martes, 23 de enero de 2024

Procedimientos. Datos.

Calc. Acceder a un rango de celdas.

Ya sabemos cómo [acceder al contenido de una celda], y ahora aprenderemos a acceder al contenido de un conjunto o rango de celdas.



Para ello, y en primer lugar hay que recordar que tenemos que trabajar con [matrices de datosen sustitución de variables individuales, ya que esto facilita el desarrollo de algoritmo. Igualmente, y por las mismas razones, tendremos  que utilizar ciclos, concretamente el [ciclo For...Next].

Para ejemplificar el procedimiento, supondré una hoja en la que deseamos acceder a una colección de datos ubicados en una columna o rango unitario.

Como ya sabemos por [desarrollos anteriores], es posible (y necesario agilizar) el acceso al contenido de un conjunto de celdas (un rango) de modo que podamos pasar los datos de las mismas a una matriz de datos. Este procedimiento se resuelve de un modo relativamente simple:

  • Acedemos a la hoja -> 

oHojaFono = ThisComponent.getSheets().getByName("Fonologia")

  • Recorremos el intervalo o rango de celdas mediante un bucle For...Next 

For i=0 To 8

oCelda(i) = oHojaDatos.getCellRangeByName( "B" & i+1 )

sDatos(i) = oCelda(i).getString

Next

  • Simultaneando la "captura del contenido  en  una matriz de tipo objeto...

Dim oCelda(8) As Object  ->  oCelda(i) = oHojaDatos.getCellRangeByName( "B" & i+1 )

  • Con el paso de dicho contenido a otro matriz de tipo datos (String, por ejemplo)
Dim sDatos(8) As String -> sDatos(i) = oCelda(i).getString

Ahora ya tenemos disponible (en sDatos()) todos los contenidos del rango del celdas comprendido (en este caso) entre la celda B1 a B9 de la hoja Fonología (en este caso) del libro activo.

Para hacer más interesante y completa esta entrada, voy a suponer una segunda situación que también se dio en el proceso de conversión del soporte en docap antes indicado: ¿qué sucede si en un intervalo de datos tenemos contenidos que sí interesa capturar junto con otros que no?. UN procedimiento como el anterior nos obliga a capturar todos los datos, interesen o no, creando una matriz sobredimensionada y poco eficiente, y que puede contener mucho ruido (elementos no deseados) que después nos complicarán el tratamiento de estos mismos datos.

Esto sucede, por ejemplo, cuando un rango de datos se cumplimenta originariamente mediante un [condicional SI()], dando lugar a un listado variable, que tanto puede tener ocupadas todas sus celdas como vacías. Esto condiciona, a su vez, que la matriz de datos receptora no pueda se dimensionada previamente sin incurrir en riesgos de sobre o infra dimensionamiento.

En estos casos, suponiendo resuelto el acceso al documento y a la hoja concreta,...

oHojaFono = ThisComponent.getSheets().getByName("Fonologia")

...la solución podría pasar por desarrollar la siguiente estrategia, que implica hacer uso de funciones OOo Basic asociadas al trabajo con matrices:

  • Dimensionamos la matriz de recorrido (tipo objeto al tamaño del rango de celdas

Dim oCelda(60) As Object

  •  Pero la matriz receptora a 0

Dim sError(0) As String

  •  Creamos dos variables contador, una (i) para recorrer mediante el bucle el total de las celdas y otra (a) para ajustar condicionalmente el tamaño y el índice de posicionamiento de la matriz receptora.

Dim i As Integer, a As Integer (iniciamos a = 0)

  • Iniciamos el bucle tomando como referencia el rango a recorrer, dimensionando adecuadamente el valor inicial y final del contador i y recorremos (igual que en el caso anterior) el conjunto de las celdas...

For i=0 To 60
oCelda(i) = oHojaFono.getCellRangeByName( "G" & i+4 )
  • ... pero el paso del contenido de estas celdas a la matriz receptora queda condicionado (If) al cumplimiento de un criterio  (en este caso que la celda contenga contenido)
  If oCelda(i).getString <> "" Then
  • ... y redimensionamos (ReDim) esa matriz receptora manteniendo el contenido previo (Preserve) utilizando como referencia el valor del contador a
ReDim Preserve sError(a)

  •  ... como paso previo para pasar los datos contenidos en la celda del rango que cumpla el criterio previamente establecido...

sError(a) = oCelda(i).getString

  •  ... y, en ese mismo supuesto (no fuera de él), incrementamos en 1 el valor del contador a y cerramos el condicional (y el ciclo)

a = a +1

End If 

 Next

El resultado que obtenemos en una matriz dimensionada de modo que se ajusta a los datos realmente útiles del rango recorrido, lo que facilita el acceso funcional a los mismos y, en su caso, su posterior tratamiento.

Para facilitar la comprensión del procedimiento, te dejo a continuación el script completo explicado por partes en los párrafos anteriores. [Desde aquí] lo puedes descargar como .txt:

Sub Main

Dim oHojaFono As Object

Dim oCelda(60) As Object

Dim sError(0) As String

Dim i As Integer, a As Integer

oHojaFono = ThisComponent.getSheets().getByName("Fonologia")

a = 0

For i=0 To 60

oCelda(i) = oHojaFono.getCellRangeByName( "G" & i+4 )

If oCelda(i).getString <> "" Then

ReDim Preserve sError(a)

sError(a) = oCelda(i).getString

a = a +1

End If

Next

For i = LBound(sError()) To UBound(sError())

MsgBox sError(i)

Next

End Sub

No hay comentarios:

Publicar un comentario

Comenta esta entrada