Datos semi-estructurados
Estrategia básica Macro-Docap
Dejamos el procedimiento ofimático de converisón de las tablas pdf, pero sobre todo doc/docx/odt expresado como tabla-registro en nuestra hoja de cálculo, pendiente de su última transformación: de vertical a horizontal, a fin de presentarse como una tabla de doble entrada en la que cada columna es un campo o variable y cada fila una colección de datos o registro. Este último paso es más que una formalidad, ya que la recuperación y el tratamiento posterior de los datos y la propia creación de la base de datos depende de ello.
Para realizar este cambio Calc dispone de la función Trasponer, el cual IA-Gemini explica del siguiente modo:
- Primero se selecciona el rango de datos que se quiere transponer
- Clic derecho + opción Copiar
- Posicionarse en la celda de destino que ocupará el primer campo de la base de datos
- Hacer clic derecho y elegir Pegado especial
- Seleccionar la opción emergente Transponer y hacer clic izquierdo en esa opción
Una vez resuelto el problema de la direccionalidad de este primer registro (y creada de paso la estructura de campos de la base de datos, la adición de nuevos registros nos obliga a procesar las celdas de la configuración vertical de un modo ligeramente diferente:
- Generamos el nuevo registro (vertical) completo (etiqueta+dato) en la hoja 1 (igual que hicimos antes
- Pero sólo seleccionamos de esta estrucura la columna de datos, siguiendo el procedimiento anterior
- En la hoja 2 (base de datos) nos posicionamos en la celda que ocupará el dato del primer campo de este nuevo registro y ejecutamos la misma secuencia de acciones que cuando creamos la base de datos
- Deberemos respetar escrupulosamente este procedimiento para evitar sustituir un registro antiguo por otro nuevo
Esta es la solución ofimática o manual, pero una vez que nuestros datos básicos ya están en una hoja de cálculo no resulta especialmente complicado automatizar la creación y la actualización de la base de datos (disposición tabular horizontal) mediante una macro y/o un script OOo Basic o la combinación de ambos. Obsérvese que lo que estoy planteando ahora supone un cambio importante respecto al procedimiento manual-ofimático anterior: ahora hablamos de automatizar el procedimiento, no de aplicar sistemática y repetidamente una secuencia de acciones.
Esta alternativa no se diferencia mucho de la que hemos aplicado a la creación de DocAp complejos de evaluación, basados en el desarrollo de un gestor sobre Calc que, entre otras funciones tiene la de recoger sistemáticamente los datos de la aplicación a modo de tabla de datos vertical y, postriormente, trasladarlos a una base de datos acumulativa diseñada en horizontal. Todo ello se basa en un conjunto de script que aquí deberán ser diferentes para cada manipulación de tablas-Word que deseemos realizar, pero como todos ellos se basan en el mismo procedimiento, no será complicado generar un código-base, el cual se ajustará lo necesario para adaptarlo a la nueva base de datos.
La automatización puede dividirse en dos fases y empezar con la selección y copia del contenido del documento .odt, pero lo fundamental se desarrolla asociado a la hoja de cálculo y se basa en un mecanismo básico de captura de datos y escritura de contenido, ambos en base a matriz y bucle. Dado que aquí no estamos desarrollando un procedimiento concretoy completo, me limitaré a construir el código básico de la automatización, el cual responde en esencia a lo que acabo de describir.
Este código está dividido en dos script que aquí creé mediante Grabar macro, en parte para ilustrar la forma más básica de automatizar el procedimiento, por decirlo de alguna manera, el procedimiento más "ofimático". El primer script genera la cabecera de la base de datos (listado de etiquetas de los campos)...
sub CrearEncabezados
rem ----------------------------------------------------------------------
rem definir variables
dim document as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem Acceder al dispatcher
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
rem Acceder a la hoja 1
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Nr"
args1(0).Value = 1
dispatcher.executeDispatch(document, ".uno:JumpToTable", "", 0, args1())
rem Seleccionar las celdas a copiar------------------------------------------
dim args2(0) as new com.sun.star.beans.PropertyValue
args2(0).Name = "ToPoint"
args2(0).Value = "$A$1:$A$20"
dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args2())
rem Copiar el contendio de esas celdas----------------------------------------
dispatcher.executeDispatch(document, ".uno:Copy", "", 0, Array())
rem Posicionarse en la hoja 2----------------------------------------------------
dim args3(0) as new com.sun.star.beans.PropertyValue
args3(0).Name = "Nr"
args3(0).Value = 2
dispatcher.executeDispatch(document, ".uno:JumpToTable", "", 0, args3())
rem Posicionarse en la celda A1-----------------------------------------------------
dim args4(0) as new com.sun.star.beans.PropertyValue
args4(0).Name = "ToPoint"
args4(0).Value = "$A$1"
dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args4())
rem Copiar (transponiendo) el contenido copiado ---------------------------------
dispatcher.executeDispatch(document, ".uno:PasteTransposed", "", 0, Array())
end sub
... y el segundo copia el contenido del registro.
sub CrearRegistro
rem ----------------------------------------------------------------------
rem definir variables
dim document as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem Acceder al dispatcher
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
rem Acceder a la hoja 1
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Nr"
args1(0).Value = 1
dispatcher.executeDispatch(document, ".uno:JumpToTable", "", 0, args1())
rem Posicionados en la hoja 1, seleccionar las celdas B1:B20-----------------
dim args2(0) as new com.sun.star.beans.PropertyValue
args2(0).Name = "ToPoint"
args2(0).Value = "$B$1:$B$20"
dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args2())
rem Copiar el contendio de esas celdas----------------------------------------
dispatcher.executeDispatch(document, ".uno:Copy", "", 0, Array())
rem Posicionarse en la hoja 2----------------------------------------------------
dim args3(0) as new com.sun.star.beans.PropertyValue
args3(0).Name = "Nr"
args3(0).Value = 2
dispatcher.executeDispatch(document, ".uno:JumpToTable", "", 0, args3())
rem Posicionarse en la celda A2-----------------------------------------------------
dim args4(0) as new com.sun.star.beans.PropertyValue
args4(0).Name = "ToPoint"
args4(0).Value = "$A$2"
dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args4())
rem Copiar (transponiendo) el contenido copiado---------------------------------
dispatcher.executeDispatch(document, ".uno:PasteTransposed", "", 0, Array())
end sub
Como puedes ver, ambos script son prácticamente el mismo, y de hecho podríamos trabajar sólo con uno, realizando las mínimas modificaciones de posicionamiento, pero me ha parecido preferible diferenciar la creación de la base de datos (en realidad, la escritura de las etiquetas de los campos) de la copia del contenido del registro. Cierto que así el primer script sólo se modifica cuando se crea el proyecto concreto (el intervalo de celdas en la Hoja1: args2(0).Value = "$A$1:$A$20"), mientras que el segundo, además del asjuste del intervalo de celdas (args2(0).Value = "$B$1:$B$20") al inicio del proyecto, es necesario modificar también la identificación de la posición de inicio de copia transpuesta en Hoja2 (args4(0).Value = "$A$2") cada vez que creamos un nuevo registro en la base de datos.
La solución anterior no está completa, ya que se puede automatizar más y mejor, pero es suficiente para ilustrar lo que intento decir, así que para este objetivo es suficiente.
Como ves, los datos semi-estructurados, una vez que es posible manejarlos desde una hoja de cálculo, también es posible automarizar su conversión en datos estructurados, al menos en términos de forma. Otra cosa es qué se puede necesitar para realizar esta automatización (en esta entrada hemos visto la forma más simple de hacerlo) y qué limpiezas posteriores requieran ya formalmente como datos estructurados. Pero estas son otras cuestiones.