alberto-moyano   29-08-2023, 19:23
#1
Hola gente,

Necesito tomar una decisión y me gustaría leer la opinión de los más duchos en manejo de base de datos y manipulación de archivos, para analizar cuál camino tomar.

La cuestión es la siguiente: poseo una base de datos (es simple) ya tengo todo el Alta/Baja/Modificación (ABM) funcionando y no hay errores, tampoco con las consultas, ahora bien, los datos de una determinada consulta (cualquiera) deben ser convertidos a un archivo de texto (que en realidad es otra base de datos), la cuestión es que no sé que es más conveniente, si exportar desde SQLite directamente un archivo de texto (el resultado de la consulta) con el texto adicional inyectado (si es que esto se puede hacer, algo que desconozco) o, exportar un CSV solo con los datos (esto ya lo puedo hacer con éxito) y con una función inyectar el texto adicional al archivo CSV y darle el nuevo formato, en cualquiera de los 2 caminos voy a tener que estudiar el proceso y de ahí mi pedido de ayuda en el análisis de qué sería mejor implementar.

El archivo resultante es básicamente un archivo bibtex (que no es más que un archivo txt con extensión .bib), este es en realidad un archivo de base de datos para LaTeX, el mismo puede ser procesado con bibtex (escrito en C) o con BibLaTeX (escrito en Perl) este procesamiento genera un nuevo archivo con extensión .bbl que es el que utiliza el compilador de LaTeX para generar las diferentes salidas (PDF, ePub, html, etc.).

Como es el contenido de un archivo .bib (veamos el caso de un libro)

Código:
@Book{Metz2001, %clave identificadora
  hyphenation  = {spanish},
  author       = {Metz, Christian},
  date         = {2001},
  keywords     = {listar},
  location     = {Barcelona},
  publisher    = {Paidós},
  title        = {El significante imaginario},
  creationdate = {2023-08-04T08:08:02},
  owner        = {alberto},
}

La clave identificadora y todo el contenido entre llaves, es lo que existe en la base de datos y que viene como resultado del query.

Ustedes que camino tomarían.

Saludos
Última modificación: 29-08-2023, 19:24 por alberto-moyano.
tincho   29-08-2023, 21:35
#2
Hola Alberto.
Si estas trabajando con gambas y un "result" de la consulta lo recorrés tomando el nombre del campo y el valor de este, ya que estas trabajando con un solo registro correcto?.
Luego lo ordenas le pones las llaves y toda la parafernalia y listo.

1 Saludo.
alberto-moyano   30-08-2023, 00:34
#3
Hola Tincho,

Sí, estoy dentro de Gambas y el resultado lo obtengo con un result, el tema es que pensé que era mejor escribir el CSV en un temporal y luego formatearlo, ya que hay diferentes plantillas (tipos de datos), una para cada tipo de objeto (objeto es un tipo de referencia: @article, @book, @incollection, @thesis, etc., etc.), y la cantidad de datos sumadas todas las plantillas en juego son muchísimos, de ahí mi duda de si no era una alternativa hacerlo directamente desde SQL (pero insisto, no sé siquiera si es posible).

Gracias por tu comentario.
tincho   30-08-2023, 13:50
#4
(30-08-2023, 00:34)alberto-moyano escribió: todas las plantillas en juego son muchísimos, de ahí mi duda de si no era una alternativa hacerlo directamente desde SQL (pero insisto, no sé siquiera si es posible).

Sin ver la base de datos no puedo entrar en demasiado de talle, sin embargo te sugiero que hagas una vista para cada @OBJETO y luego desde gambas elijas la vista que corresponda con el texto que deseas generar. De esta manera tendrias los datos y las etiquetas y luego es acomodar el texto con las llaves y los espacios para dar el formato.
Para crear una vista, como sabes, se hace así:
Código:
CREATE VIEW "view_albums" AS SELECT
    albums.idx AS idx,
    albums.name AS name,
    albums.year AS year,
    artists.name AS artist
    FROM albums
LEFT JOIN artists ON albums.artist=artists.idx
ORDER BY albums.idx,albums.name ASC;
Lo de las vistas es muy potente ya que ademas de mostrar los datos, de una tabla o varias, es posible hacer recuentos, sumas y mas operaciones matemáticas entre otras cosas.
Luego para recorrer los datos:
Código:
Public con1 As New Connection    '' Conexion a la base de datos

Public Sub Button3_Click()

  con1.Type = "sqlite3"
  con1.Host = User.Home
  con1.Name = "db1.sqlite"
  con1.Open

  Print Tex("view_artist", "Artist") ' Esto lo cambias por el nombre de la vista de turno

  con1.Close

End

'' sTag es el Book, Author, etc. y sObjeto es el nombre d ela vista,  que puede ser vista_book, vista_author etc.

Public Function Tex(sObjeto As String, sTag As String) As String

  Dim Res As Result
  Dim s As String
  Dim f As ResultField
  Dim aFields As New String[]
  Dim i As Integer

  Res = con1.Exec("Select * From " & sObjeto)

  aFields.Clear
  For Each f In Res.Fields
    aFields.Add(f.Name)
  Next
  i = 0
  s = "@" & sTag & " {" & Res[aFields[i]] & ", %clave identificadora\n"

  While Res.Avalaible
    Inc i
    s &= author & " = {" & Res[aFields[i]] & "},\n"
    Res.MoveNext
  Wend
  s &= "}"

  Return s

End
Nota: Dejo el .sql de una base de datos completa para que puedas estudiar de donde provienen los campos de la vista que te di de ejemplo.
Archivos adjuntos
.gz
data.db.sql.tar.gz (Tamaño: 1.07 KB Descargas: 0)

1 Saludo.
alberto-moyano   30-08-2023, 21:52
#5
Hola Tincho,

gracias por tu aporte, lo voy a estudiar.

Mi proyecto es público, puedes acceder a él si quieres, una parte del software (70%) yo lo uso intensamente (unas 6 horas diarias) ya que está terminado, el resto es sobre lo que voy trabajando.

Lo tenía en github pero lo pase a gitlab (los motivos son largos de explicar)

https://gitlab.com/alberto.alejandro.moy...xpublisher

Aclaración: el software tiene su base en saber LaTeX (incluido PlainTeX, o sea primitivas) yo lo considero un facilitador, esto es, todo lo que se puede hacer con él, también se puede hacer sin él. El punto son sus potenciales usuarios (o posibles) que son diseñadores gráficos, correctores de texto y personas que hacen editing, es decir, gente muy por fuera de la programación, y de la consola!!!

Saludos
tincho   31-08-2023, 12:39
#6
ok, eche un vistazo a la base de datos, la vista seria algo así:
Código:
    CREATE VIEW "view_bibtext" AS SELECT
        bibtex.tipoEntrada AS type,
        bibtex.id AS id,
        bibtex.clave AS clave,
        bibtex.hyphenation As hyphenation,
        bibtex.author As author,
        bibtex.date As date,
        bibtex.keywords As keywords,
        bibtex.location As location,
        bibtex.publisher As publisher,
        bibtex.title As title,
        bibtex.fecha As creationdate,
        bibtex.editor As owner
        FROM bibtex
    ORDER BY id ASC;
Si seguí bien el flujo de gbTexPublisher en el formulario FormBib en un momento vas a apretar un botón y exportar el registro actual a este formato o bien querés hacer un batch para exportar toda la base de datos. Sea cual fuere el caso todo comenzaría con obtener el result pero desde la vista:
Res = Conn.Exec("Select * From view_bibtex")
o para solo un registro
Res = Conn.Exec("Select * From view_bibtex where id=" & txtID.Text)

Luego este código te generara el contenido .bib y también lo guardara en el directorio /tmp
Código:
Public Sub BtnExportarBIB_Click()

  Dim Res As Result
  Dim s As String
  Dim f As ResultField
  Dim aFields As New String[]
  Dim i As Integer
  Dim t As Table
  Dim w As Integer
  Dim tab As String

  Res = Conn.Exec("Select * From view_bibtex") ' Exportar todo
  'Res = Conn.Exec("Select * From view_bibtex where id=" & txtID.Text) ' Exportar el registro seleccionado

  aFields.Clear
  For Each f In Res.Fields
    aFields.Add(f.Name)
    If Len(f.Name) > w Then
      w = Len(f.Name)
    Endif
  Next

  While Res.Available
    s = "@" & Res[aFields[0]] & " {" & Res[aFields[2]] & ", %clave identificadora\n"
    For i = 3 To aFields.Max
      tab = ""
      If Len(aFields[i])[/i] < w Then
        tab = String(w - Len(aFields), " ")
      Endif
      s &= aFields & tab & " = {" & Res[aFields[i]] & "},\n"
    Next
    s &= "}"
    File.Save("/tmp/" & Res[aFields[1]] & ".bib", s)
    Res.MoveNext
  Wend

End

Tuve unos problemas con el directorio de trabajo, la base de datos y la conexión, así que te comento las cosas que cambie de tu programa:
  1. Directorio de trabajo todo en minúsculas /.gbtexpublisher ya que al cambiar la base de datos cuando cree la vista en realidad el programa apuntaba a otra base de datos.
  2. La Conexion1 la elimine del árbol del proyecto.
  3. El componente gb.sqlite3 lo deshabilite, no me queda en claro para que sirve. Con gb.db ya es suficiente para trabajar con Sqlite3.
Te hago algunas sugerencias, cosas que yo encararía de otra manera.
  1. Los nombres de los campos de las tablas todos en minúsculas a-z, 0-9 y _ (guion bajo)
  2. No usar palabras clave tales como date o year para nombrar los campos, echale un vistazo a [1].
  3. Centralizar la conexión a la base de datos en un solo lugar ya que definís "Public Conn As Connection" en cada formulario que usas la base de datos (Fmain, FormBib, Form_Busca, Form_Notas) y eso no es necesario y te puede dar problemas cuando escalas el programa o cuando trabajar en equipo con otros programadores y/o motores de base de datos.
  4. Usar la Propiedad Spacing = True dara un mejor aspecto al formulario, por ejemplo en el formulario FormBib queda mas prolija la distribución de los controles, yo uso manjaro XFCE que es GTK así que tal vez en tu sistema se ve mejor sin tener que activar esta propiedad.
  5. Usar bucles recursivos para escribir y leer el contenido de los TextBox de los formularios puede ahorrarte el escribir mucho código y permite reutilizar estos bucles para otros fines (es necesario poner un tag en cada uno con el nombre del campo)
[1] https://en.wikipedia.org/wiki/List_of_SQ...rved_words

Evidentemente hay que tener LaTex instalado para usar programa .

1 Saludo.
alberto-moyano   31-08-2023, 14:15
#7
Hola Tincho, gracias por el aporte

Tuve unos problemas con el directorio de trabajo, la base de datos y la conexión, así que te comento las cosas que cambie de tu programa:
  1. Directorio de trabajo todo en minúsculas /.gbtexpublisher ya que al cambiar la base de datos cuando cree la vista en realidad el programa apuntaba a otra base de datos.
cambiado, ok
  1. La Conexion1 la elimine del árbol del proyecto.
cambiado, ok
  1. El componente gb.sqlite3 lo deshabilite, no me queda en claro para que sirve. Con gb.db ya es suficiente para trabajar con Sqlite3.
cambiado, ok

Te hago algunas sugerencias, cosas que yo encararía de otra manera.
  1. Los nombres de los campos de las tablas todos en minúsculas a-z, 0-9 y _ (guion bajo)
Lo voy a revisar
  1. No usar palabras clave tales como date o year para nombrar los campos, echale un vistazo a [1].
Ídem anterior
  1. Centralizar la conexión a la base de datos en un solo lugar ya que definís "Public Conn As Connection" en cada formulario que usas la base de datos (Fmain, FormBib, Form_Busca, Form_Notas) y eso no es necesario y te puede dar problemas cuando escalas el programa o cuando trabajar en equipo con otros programadores y/o motores de base de datos.
Supongo que te referís a poner la conexión en un módulo, lo pensé, veré de instrumentarlo
  1. Usar la Propiedad Spacing = True dara un mejor aspecto al formulario, por ejemplo en el formulario FormBib queda mas prolija la distribución de los controles, yo uso manjaro XFCE que es GTK así que tal vez en tu sistema se ve mejor sin tener que activar esta propiedad.
En QT no hay problemas visuales con la configuración que tiene, si aplico Spacing=True, no cambia nada, así que supongo que tiene que ver con GTK, lo cambio, ok
  1. Usar bucles recursivos para escribir y leer el contenido de los TextBox de los formularios puede ahorrarte el escribir mucho código y permite reutilizar estos bucles para otros fines (es necesario poner un tag en cada uno con el nombre del campo)
No lo use nunca, lo voy a estudiar, intuyo que le puedo dar un buen uso

Gracias por el feedback

Es cierto, que tienes que instalar LaTeX y no solo eso, sino que muchos de los paquetes que uso no son de la instalación «base», por consiguiente para no perderse entre el tex-live del CTAN y el tex-live de las diferentes distros (que cambian el contenido de los metapaquetes, no entiendo por qué) siempre se termina haciendo una instalación full, lo que significa 5gb de archivos.

En unos días preparo un video que muestre como funciona una edición literada (es decir, desde un mismo archivo de LaTeX, sacar de un tirón un PDF, un ePub y un XML, por ejemplo, todos con diferentes metadatos).

Gracias nuevamente
tincho   31-08-2023, 14:21
#8
(31-08-2023, 14:15)alberto-moyano escribió: Supongo que te referís a poner la conexión en un módulo, lo pensé, veré de instrumentarlo

Si, exacto. conviene ponerlo en un módulo que marcas como clase de inicio y luego Fmain.Show() o también podes poner todo directamente en Fmain
Esto de ponerlo en un módulo de inicio separado resulta muy útil a la hora de reutilizar el código para otro programa ya que al copiar el andamiaje queda medio camino hecho ya.

(31-08-2023, 14:15)alberto-moyano escribió: No lo use nunca, lo voy a estudiar, intuyo que le puedo dar un buen uso

Sobre lo de los bucles recursivos... hice un formulario que inmita el tuyo pero con este método y lo de la centralización del la conexión.
Código:
Public Sub Form_Open()

  LoadValues()
  Me.Title = "Hacking"

End

Private Sub LoadValues()

  Dim fld As ResultField
  Dim Contenido As Result
  Dim aFields As New String[]
  Dim fname As String

  Contenido = FMain.Conn.Exec("select * from bibtex")

  If Contenido.Available Then
    Contenido.MoveFirst
    For Each fld In Contenido.Fields
      aFields.Add(fld.Name)
    Next

    For Each fname In aFields
      fwrite(Me, fname, Contenido[fname])
    Next
  Endif

End

Private Sub fwrite(ob As Object, sTag As String, sVal As String)

  Dim cls As Class
  Dim ch As Object

  Select Object.Class(ob).Parent.Name
    Case "Form", "Container"
      For Each ch In ob.Children
        fwrite(ch, sTag, sVal)
      Next
    Case "Control", "UserControl"
      If sTag = ob.Tag Then
        Select Object.Class(ob).Name
          Case "TextBox"
            ob.Text = sVal
          Case "ComboBox"
            If Not ob.ListBox.Exist(sVal) Then
              ob.Add(sVal)
            Endif
            ob.Text = sVal
        End Select
      Endif
      'Case "UserControl"
      'Print "UserControl/" & Object.Class(ob).Name
    Case Else
      Print Object.Class(ob).Parent.Name & "/" & Object.Class(ob).Name
  End Select

End

El método fwrite lo que hace es revisar un objeto y si su Tag coincide con el que viene como segundo parámetro entonces le pone el texto del tercer parámetro, si por el contrario el objeto es un contenedor entonces se llama a si mismo y vuelta a empezar pero a partir de ese contenedor.
Esto te lo llevas a cualquier formulario e incluso podes ponerlo fuera de la clase del formulario, por ejemplo en un módulo ya que los objetos se pasan siempre por referencia.

[Imagen: iWtKwwV.png]
Última modificación: 31-08-2023, 14:33 por tincho.

1 Saludo.
Shell   20-09-2023, 22:57
#9
Puede que este mensaje sea mejor moverlo al foro de base de datos. Rolleyes

"El conocimiento es la mejor inversión que se puede hacer" - Abraham Lincoln
  
Usuarios navegando en este tema: 1 invitado(s)
Powered By MyBB, © 2002-2024 MyBB Group.
Made with by Curves UI.