Calc. Crear listados.
- La primera implicación de esta decisión es la creación del documento Hc.Calc de Bd.
- La segunda es construir sobre esta Hc la estructura de campos de la Bd, que no es otra cosa que identificar en las columnas las cabeceras de dichos campos, configurando así una tabla de doble entrada: Filas->Registros; Columnas->Campos.
Esta imagen muestra un ejemplo sencillo de la configuración de una Bd (tabla, si se prefiere) en la que se identifican un total de 18 campos (3):
- Seis de identificación del alumno
- Diez para la PD del test
- Dos para los cálculos (sumatorio PD y valoración del resultado)
- La tercera es que el docap queda determinado en cuanto al procedimiento de ejecución: desde el gestor de entrada de datos (SoportePrueba.ods) (4) se accede al documento Bd (BDPrueba.ods), con todo lo que esto implica: acceso al documento Hc previamente creado y trabajo con dicho documento.
Sub AccesoBD(Datos() As Variant)Dim sRuta As StringDim mArg()Dim oBD As Object, oHojaBD As Object, oCeldaCampo As Object, oCeldaNuevoRegistro As ObjectDim i As Integer, a As Integer, b As IntegerDim sEntrada1 As String
Fase 1. Acceso al documento externo
'Acceso a los objetos documento (BDPruebas.ods) y Hoja (DatosPrueba)sRuta = ConvertToUrl("D:\Pruebas\BDPrueba.ods")oBD = StarDesktop.loadComponentFromURL(sRuta, "_blank", 0, mArg())oHojaBD = oBD.getCurrentController.getActiveSheet()
Fase 2. Trabajo con la Bd. Registro de datos
'Búsqueda del primer registro vacíoFor i = 0 To 100oCeldaCampo = oHojaBD.getCellRangeByName("A" & CStr(i+1))sEntrada1 = oCeldaCampo.getString()If sEntrada1 = "" Thena = iExit ForEnd IfNext'Escritura de los datos en el registro vacíoFor b = 0 To UBound(Datos())oCeldaNuevoRegistro = oHojaBD.getCellByPosition(b,a)oCeldaNuevoRegistro.setString(Datos(b))Next
Fase 3. Almacenamiento de los datos del nuevo registro
'Guardar cambiosoBD.store()'Cerrar BDPruebas.odsoBD.close(True)End Sub
- Tras la declaración de las variables necesarias para el algoritmo específico de la subrutina...
Dim sRuta As StringDim mArg()Dim oBD As Object, oHojaBD As Object, oCeldaCampo As Object, oCeldaNuevoRegistro As ObjectDim i As Integer, a As Integer, b As IntegerDim sEntrada1 As String
- ... viene la primera fase, que consiste en el acceso y apertura del documento Hc.Bd...
sRuta = ConvertToUrl("D:\Pruebas\BDPrueba.ods")oBD = StarDesktop.loadComponentFromURL(sRuta, "_blank", 0, mArg())
... y a la hoja donde está construida la Bd (6)
oHojaBD = oBD.getCurrentController.getActiveSheet()
- La segunda fase es la más compleja y en ella se desarrollan dos subprocesos: la identificación del primer registro sin datos (el que sigue al último que sí contiene datos), lo que equivale y se concreta como búsqueda de la primera fila vacía y el traslado de los datos enviados desde el script principal a la subrutina mediante la asociación de parámetros (mDatos() -> Datos()). Dada la complejidad (e importancia) de estos dos subprocesos, paso a explicar detenidamente cada uno de ello.
Identificación de la primera fila (registro) vacía. Consiste en buscar mediante un bucle que recorre las filas de la hoja aquella (primera) que no contiene aun datos. Para ello creamos una estructura For...Next ...
For i = 0 To 100oCeldaCampo = oHojaBD.getCellRangeByName("A" & CStr(i+1))sEntrada1 = oCeldaCampo.getString()If sEntrada1 = "" Thena = iExit ForEnd IfNext
... con la que inicialmente repetimos el proceso un número determinado de veces (For i = 0 To 100) (7). Dicho proceso consiste en acceder al contenido de la celda (campo 1 del registro) de forma secuencial...
oCeldaCampo = oHojaBD.getCellRangeByName("A" & CStr(i+1))
... asignar ese contenido a una variable de gestión del dato...
sEntrada1 = oCeldaCampo.getString()
... y someter el mismo (presencia vs. ausencia de contenido) a un condicional If simple...
If sEntrada1 = "" Then
a = iExit For
End If
... en el que si se cumple la condición de ausencia de contenido (celda vacía)..
Si sEntrada1 = "" -> Es True
... entonces a la variable a (que se empleará en el el subproceso siguiente como referencia de la fila sobre la que trabajar) se le asigna el valor correspondiente de la variable i, que equivale al identificador numérico de la celda vacía de la primera columna ("A" & CStr(i+1)). De este modo, la variable a contendrá el valor que identifica la primera fila son datos de la tabla.
Dentro de esta estructura condicional incluimos la sentencia de cierre/cese del bucle (Exit For) para ajustar éste a la solución del problema (encontrar la celda vacía), acortando el tiempo de ejecución de algoritmo a lo estrictamente necesario (8)
Inclusión de datos en el registro. Consiste en pasar los datos contenidos en la matriz-parámetro Datos() en el registro de la Bd (en la fila de celdas vacía de contenido localizada gracias al proceso anterior)
For b = 0 To UBound(Datos())
oCeldaNuevoRegistro = oHojaBD.getCellByPosition(b,a)
oCeldaNuevoRegistro.setString(Datos(b))
Next
Empleamos para ello un segundo bucle For que trabajará con dicha matriz (9). En cada ciclo asignamos a la variable objeto oCeldaNuevoRegistro las distintas posiciones (objetos celda) de la fila (oHojaBD.getCellByPosition(b,a)) empleado como referencias las posiciones que ocupan en el entramado columna-fila (que no el nombre, como hicimos en el proceso anterior) mediante la función getCellByPosition(b,a). Observa que hace referencia a dos variables ((b,a)): primera (b) referencia cada una de las columnas que recorremos mediante el bucle y la segunda (a) referencia la fila (la primera fila vacía) (10).
Una vez identificada-seleccionada la celda, pasamos el contenido de la matriz a la celda mediante la función-método setString()) (setString(Datos(b))).
- Finalmente, en la tercera fase procedemos a grabar y cerrar el soporte.Hc (BDPrueba.ods) que hemos referenciado-asociado a la variable-objeto oBD (11). La grabación del documento lo realizamos mediante la función store() (oBD.store()) y el cierre mediante la función close() (oBD.close(True)) con valor True (12).
NOTAS
(5) Este script principal Main no es objeto de trabajo en esta entrada, ya que en ella nos centramos en el acceso y el trabajo con el documento.Hc de Bd. Para una mejor comprensión del funcionamiento global del algoritmo del que aquí se explica sólo una parte, [ver esta entrada].
(6) En este caso el documento Hc.Bd sólo consta de una hoja, pero es preferible asegurar el posicionamiento en ella como posicionamiento específico, identificado por el nombre de la hoja, y no como posicionamiento genérico (esto es, como hoja activa).
(7) Bucle de 100 repeticiones según concreto en este ejemplo, pero puede ser cualquier otro número de repeticiones. Se aconseja, no obstante, ser "generosos" al respecto, aunque el criterio de referencia para definir el tamaño del bucle es la previsión del número de registro que se espera contenga la Bd.
(8) Este sencillo procedimiento resulta de mucha utilidad: acorta el desarrollo del bucle al número de repeticiones necesario y nos da libertad para establecer éstas de forma aproximada y con el suficiente margen de seguridad, sin que la posible sobredimensión del bucle tenga un coste de tiempo de ejecución. No obstante, esto no implica que no tomemos referencias a la hora de determinar el número de repeticiones del bucle (ver nota 7)
(9) Para asegurarnos de ello utilizamos como referencia superior del recorrido el resultado de la función UBound() que identifica el último elemento de la matriz (UBound(Datos()))
(10) Recuerda que deriva del proceso previo en el que la asociamos al valor que alcanza la variable-contador i cuando se cumple el criterio que buscamos (If sEntrada1 = "" Then)
(11) En la primera fase hemos asociado dicho archivo a esta variable mediante la instrucción oBD = StarDesktop.loadComponentFromURL(sRuta, "_blank", 0, mArg()) que a su vez contiene como parámetro la variable (sRuta) que asociamos en la instrucción inmediatamente anterior al procedimiento de acceso al documento (sRuta = ConvertToUrl("D:\Pruebas\BDPrueba.ods"))
(12) Interesa destacar aquí el hecho de que ambas son funciones-métodos aplicadas sobre el objeto-documento con el que trabajamos (BDPrueba.ods), el cual, como tal, es un objeto de la clase Hoja-de-cálculo dentro del programa LibreOffice. El uso de la variable asociada a dicho documento (oBD.) es lo que nos asegura actuar sobre ese documento y no sobre (por ejemplo) la Hc.Gestor que contiene y desde la que actúa el script-subrutina AccesoBD()