[RESUELTO] Leer y generar arrays con DataArray() y dimensionarlos. Arrays de doble parentesis.

Desarrollo de Macros y programación en UNO, usar las API, llamar programas externos...
Responder
Avatar de Usuario
JoePublic
Mensajes: 36
Registrado: Dom Sep 06, 2020 5:34 pm

[RESUELTO] Leer y generar arrays con DataArray() y dimensionarlos. Arrays de doble parentesis.

Mensaje por JoePublic »

Hola,
Cuando utilizamos la funcion "getDataArray()" o "DataArray()" sobre un rango de celdas para almacenar automaticamente los valores de un rango de celdas en un Array, OOOBasic de libreOffice almacena los datos en un array pero al acceder a ellos debemos poner un parentesis para la fila y otro parentesis para la columna (es decir dos parentesis) como en el ejemplo aqui abajo:

Código: Seleccionar todo

'*** Opcion 1 ***
MsgBox valuesTable(0)(1)
Mientras que si cargo los valores manualmente de dentro de un macro, lo haces utilizando un solo parentesis entre la fila y la columna como figura aqui abajo:

Código: Seleccionar todo

'*** Opcion 2 ***
valuesTable(0,0) = 1
valuesTable(0,1) = "Jose Luis"
valuesTable(0,2) = "Madrid" 

valuesTable(1,0) = 2
valuesTable(1,1) = "Maria"
valuesTable(1,2) = "Valencia" 
¿...pero existe alguna manera de cargar un array de forma automatica con getDataArray() o con DataArray() y que al acceder a él podamos hacerlo con un único parentesis, es decir, asi: valuesTable(0,1)?

o... ¿la única manera es convertir o transformar el array automatico (de dos parentesis valuesTable(0)(1) OPCION 1) pasándolo por un bucle FOR TO ...NEXT para convertirlo en un array manual de un solo parentesis valuesTable(0,1) (OPCION 2)? (Hice una Función con for to next para ello. Esta al final).

Adjunto fotos y un archivo donde se puede ver lo que digo por si quereis ver como carga la tabla en un array de forma automatica y como extraemos informacion de un array bidimensional o multidimensional con la función DataArray() a otro array de dos dimensiones con dos parentesis, es decir, valuesTable(0)(1).

Mi problema es que al manipular arrays, luego necesito buscar informacion con ellos y si el array tiene dos parentesis se accede a la informacion de una manera determinada y si el array tiene un parenteis se lee de otra manera, con lo que siempre tengo problemas y quisiera que todos los arrays fueran iguales. No se si existe alguna funcion simple para transformar o convertir todos los arrays iguales y que no fuera transformar el array en un bucle FOR TO ... NEXT. Asi que al final veras la SOLUCION para hacerlo SIEMPRE con un array de DOS parentesis ()(), que es la forma habitual con que OOOBasic carga los arrays automaticos con DataArray() y así evitamos el bucle for to next para convertir arrays. No obstante, dejo una función para convertir un array de dos parentesis ()() a un array de un parentesis (,) para poner en ellos el indice de la fila y la columna.

GRACIAS.
Adjuntos
Vease Array automatico de dos parentesis
Vease Array automatico de dos parentesis
myData.jpg (30.82 KiB) Visto 5921 veces
Vease Array manual de un parentesis.
Vease Array manual de un parentesis.
MadridArray.jpg (32.36 KiB) Visto 5921 veces
getDataArray().ods
(64.5 KiB) Descargado 445 veces
Última edición por JoePublic el Mié Sep 20, 2023 11:28 pm, editado 7 veces en total.
Usuario apasionado de las hojas de cálculo. Novato aprendiz de macros con OOo Basic y VBA.
LibreOffice Version: 6.4.3.2 (x64) y Sistema Operativo Windows 10 Home.
FJCC-ES
Mensajes: 897
Registrado: Mié Mar 25, 2009 1:19 am
Ubicación: Colorado, USA

Re: Como leer datos array almacenado con DataArray()

Mensaje por FJCC-ES »

JoePublic escribió: Lun Ago 14, 2023 12:29 am ¿...pero existe alguna manera de cargar un array de forma automatica con getDataArray() o con DataArray() y que al acceder a él podamos hacerlo con un único parentesis, es decir, asi: valuesTable(0,1)?
Creo que no. Pero hay opciones para cargar valores manualmente usando dos parentesis.

Código: Seleccionar todo

REM	Opcion 2'  
valuesTable = Array(Array(0,0,0), Array(0,0,0))
valuesTable(0)(0) = 1
valuesTable(0)(1) = "Jose Luis"
valuesTable(0)(2) = "Madrid" 

valuesTable(1)(0) = 2
valuesTable(1)(1) = "Maria"
valuesTable(1)(2) = "Valencia" 

REM Opcion 2''
oSheet2 = ThisComponent.getSheets().getByName("Sheet2") 'Sheet2 esta vacia
oCeldas = oSheet2.getCellRangeByPosition(0,0,2,1) 'Left, Top, Right, Bottom
valuesTable = oCeldas.getDataArray()
valuesTable(0)(0) = 1
valuesTable(0)(1) = "Jose Luis"
valuesTable(0)(2) = "Madrid" 

valuesTable(1)(0) = 2
valuesTable(1)(1) = "Maria"
valuesTable(1)(2) = "Valencia" 
'Los valores de valuesTable existen solamente en el código y no en la hoja Sheet2.
Avatar de Usuario
JoePublic
Mensajes: 36
Registrado: Dom Sep 06, 2020 5:34 pm

Re: Como leer datos array almacenado con DataArray()

Mensaje por JoePublic »

Hola FJCC,
Muchas gracias por contestar. !!!
Si. Lo que comentas tambien seria buena opción cargar valores manualmente usando dos parentesis.
Yo lo he intentado antes de poner este post, pero al Dimensionar o Redimensionar el array, luego me salta un error, porque no acepta la expresion que tengo en mi función "almacenaFilasArrayBidimensional ", por eso no sabia como asignar los valores a OOOBasic.

He visto tu Opcion 2 y es buena. Declaras un rango de celdas con

Código: Seleccionar todo

oCeldas = oSheet2.getCellRangeByPosition(0,0,2,1) 'Left, Top, Right, Bottom 'Supongo que será para dimensionar el array
y luego generas el array vacio con

Código: Seleccionar todo

valuesTable = oCeldas.getDataArray()
Y despues manualmente, le vas agregando los valores. Muy bueno...
Pero este ejemplo es buen si sabes el numero de registros a añadir, y que pasa cuando no lo sabes? Es decir que vas añadiendo poco a poco.

No se como incorporar esto a mi funcion de aqui abajo. En la linea donde esta el arrayTemporal (fila,j) = arrayTable(i)(j) (Aqui es donde se asignan los valores pero en 1 parentesis, porque al poner 2 parentesis sale ERROR). Además existe el problema de que no se la dimensión del Array, ya que se va llenando poco a poco con los resultados que va encontrando, es decir que la asignación no la hace de golpe como el ejemplo que tu me has puesto, sino que va buscando los clientes de Madrid y va almacenandolos en el arrayTemporal (previamente redimensionado cada vez que encuentra un cliente de Madrid) y este punto es lo que me vuelve loco. La verdad, estos de Libre Office no se porque lo hocen tan complicado y ahora con la nueva libreria ScriptForge lo hubieran podido mejorar !!.

Podrías modificarlo tu, por favor?
Tienes el archivo de calc con la macro en el primer post para poder hacer pruebas en tu PC.
Gracias.

Código: Seleccionar todo

Function almacenaFilasArrayBidimensional (arrayTable() as Variant, ciudad as String) as Variant
'Almacena filas en un array bidimensional cuya poblacion sea Madrid.

Dim arrayTemporal(0,3) as Variant
Dim ultimaFila_A as Long
Dim ultimaColumna_A as Long
Dim poblacion as Long
Dim fila as Long

ultimaFila_A = UBound(arrayTable())
ultimaColumna_A = UBound(arrayTable(0),1) 'Para arrays de 2 parentesis

poblacion = 3 'Indice de la columna que contiene el dato Poblacion a buscar
fila = 0
For i = 0 To ultimaFila_A
	If arrayTable(i)(poblacion) = ciudad Then 'ciudad = Madrid
	Redim preserve arrayTemporal (fila, ultimaColumna_A)
		For j = 0 To ultimaColumna_A 'copia la fila con todos los datos del cliente de Madrid 
			'***** Almacena datos fila. ***********
			arrayTemporal (fila,j) = arrayTable(i)(j) 'Me gustaria poner arrayTempora()() con los dos parentesis, pero no funciona. De modo que todos los arrays serian en este formato con parentesis para fila y parentis para columnas.
		Next j 'Siguiente columna
		fila = fila + 1
	End if	
Next i 'Siguiente fila

almacenaFilasArrayBidimensional = arrayTemporal()
End Function
Última edición por JoePublic el Mar Ago 15, 2023 7:05 pm, editado 1 vez en total.
Usuario apasionado de las hojas de cálculo. Novato aprendiz de macros con OOo Basic y VBA.
LibreOffice Version: 6.4.3.2 (x64) y Sistema Operativo Windows 10 Home.
FJCC-ES
Mensajes: 897
Registrado: Mié Mar 25, 2009 1:19 am
Ubicación: Colorado, USA

Re: Como leer datos array almacenado con DataArray()

Mensaje por FJCC-ES »

Cambié getArrayTabla(), almacenaFilasArrayBidimensional(), getValuesTable()

Código: Seleccionar todo

Sub getArrayTabla()
'Coge la tabla que hay en la Hoja1 y la almacena en un array de forma automatica y en otro Array temporal almacena o filtra las personas que son de Mardid.
Dim myDataTableBidiA() as Variant
Dim sheetIndex as Long
Dim madridArray() as Variant
Dim poblacion as String
poblacion = "Madrid"
sheetIndex = 0 'Correspnde a la Hoja1
myDataCeldas = getValuesTable(sheetIndex) 'getValuesTable devuelve oRango, no oRango.DataArray
myDataTableBidiA = myDataCeldas.getDataArray()
'Msgbox ("myDataTableBidiA(2)(1) es igual a:     " & myDataTableBidiA(2)(1))

'Buscar las filas donde Poblacion = Madrid
oPoblac = myDataCeldas.getColumns.getByIndex(3)
SDesc = oPoblac.createSearchDescriptor()
SDesc.SearchString = poblacion
oRangos = oPoblac.findAll(SDesc)
'######
madridArray = almacenaFilasArrayBidimensional(myDataTableBidiA(), poblacion, oRangos.Count - 1)
MsgBox "Proceso concluido " & madridArray(1)(2)
End Sub

'***********************************************
Function almacenaFilasArrayBidimensional (arrayTable() as Variant, ciudad as String, CountNeeded as integer) as Variant
'Almacena filas en un array bidimensional cuya poblacion sea Madrid.

Dim arrayTemporal(CountNeeded) as Variant
Dim ultimaFila_A as Long
Dim ultimaColumna_A as Long
Dim poblacion as Long
Dim fila as Long

ultimaFila_A = UBound(arrayTable())
'ultimaColumna_A = UBound(arrayTable(0),1) 'Para arrays de 2 parentesis

poblacion = 3 'Indice de la columna que contiene el dato Poblacion a buscar
fila = 0
For i = 0 To ultimaFila_A
	If arrayTable(i)(poblacion) = ciudad Then
	'Redim preserve arrayTemporal (fila, ultimaColumna_A)
		'For j = 0 To ultimaColumna_A 'copia la fila con todos los datos del cliente de Madrid 
			'***** Almacena datos fila. ***********
		'	arrayTemporal (fila,j) = arrayTable(i)(j) 'Me gustaria poner arrayTempora()() con los dos parentesis, pero no funciona. De modo que todos los arrays serian en este formato con parentesis para fila y parentis para columnas.
		'Next j 'Siguiente columna
		arrayTemporal(fila) = arrayTable(i)
		fila = fila + 1
	End if	
Next i 'Siguiente fila
almacenaFilasArrayBidimensional = arrayTemporal()
End Function


'***************************************************************
Function getValuesTable(sheetIndex as Long) as Variant
'Almacena en un array los valores de una tabla.
Dim oRango as Object
Dim oSheet as Object
Dim oCell as Object

Dim Columnas as Long
Dim Filas as Long

oSheet = ThisComponent.Sheets.getByIndex(sheetIndex)
oCell =oSheet.getCellRangeByName("A1")

'*** Cogemos CurrentRegiion con el Cursor ****************
oRango = getCurrentRegion(oCell)
'**** Almacena los datos en un array atuotamaticamente.**********
'getValuesTable = oRango.DataArray() 'Asign values Table to an array
getValuesTable = oRango '.getDataArray() 'Asign values Table to an array
End Function



'*********************************************************************
'***********  CURSOR  ************* CURSOR ***************************
'*********************************************************************
Function getCurrentRegion(oRange As Object)
'Funcion que selecciona el rango de una tabla entera. Simplemente deja seleccionada una celda y CurrentRegion seleccionará la celda ENTERA. Este rango estará limitado o aislado por celdas vacías.
'Almacena el rango de celdas en un cursor. Lo que en VBA se conococe como: Range("E11").CurrentRegion.Select
   Dim oCursor As Object
   oCursor = oRange.Spreadsheet.createCursorByRange(oRange)  '.getSpreadsheet()
   ' Expand the cursor into the region containing the cells to which it currently points. A region is a cell range bounded by empty cells.
   oCursor.collapseToCurrentRegion()
   getCurrentRegion = oCursor
   'ThisComponent.currentController.Select(oCursor) 'Tambien cambia de color filas y columnas para mostrar al usuario el rango seleccionado.
   Call HighlightRange (oCursor)
End Function


'**************************************************
Sub HighlightRange (oCursor)
'How to select & highlight a range in macro
'Marca de color el rango de celdas a almacenar en un array, es decir, crea el marco para remarcarlo y que visualmente se vea coloreado, y así indicar al usuario que zona de rango esta seleccionada con lo que indica el Cursor, nada mas.

'rg = thiscomponent.sheets(0).getCellRangeByName("C5:D8")
rg = oCursor
view = thiscomponent.getCurrentController()
frame = view.getFrame()

REM necessary
frame.activate()

REM optional
win = frame.getContainerWindow()
win.toFront()

view.select(rg)
End Sub
Adjuntos
getDataArray_fjcc.ods
(60.69 KiB) Descargado 384 veces
Avatar de Usuario
JoePublic
Mensajes: 36
Registrado: Dom Sep 06, 2020 5:34 pm

Re: Como leer array generado con DataArray()

Mensaje por JoePublic »

Muchas Gracias FJCC-ES
Me has servido de gran ayuda.
Perdona no haberte contestado antes, pero con el trabajo ando liado.
En breve pondré la solución en un archivo calc y tambien script.
Usuario apasionado de las hojas de cálculo. Novato aprendiz de macros con OOo Basic y VBA.
LibreOffice Version: 6.4.3.2 (x64) y Sistema Operativo Windows 10 Home.
Avatar de Usuario
JoePublic
Mensajes: 36
Registrado: Dom Sep 06, 2020 5:34 pm

Re: Como leer array generado con DataArray()

Mensaje por JoePublic »

Gracias FJCC
Tu ejemplo me sirvio mucho y aprendi a como iterar por arrays manuales creados por uno mismo y arrays automaticos creados por la funcion getDataArray() o DataArray() de LibreOffice para hacer macros.

Gracias por ser un miembro tan activo en este foro y ayudar a tanta gente. De verdad, no sabe lo que esto supone para mi.
Le estoy muy agrdaecido. Gracias tambien a este foro he aprendido a manejarme con las funciones de OOoBasic. Y todavia me gustaría aprender más. Solo espero que no desfallezca en su labor de buen samaritano porque tengo muchas dudas que resolver e iré poniendo aqui.

Ahora con el nuevo ScriptForge, Ojala hubiera un libro con muchos ejemplos de cómo utilizar las funciones pero explicadas con varios ejemplos practicos y para tontos (dummies). La documentación que hay en la web de libreoffice esta bien, pero le falta un poco más de ejemplos por cada función. Yo aprendo con ejemplos, pero mis conocimientos son muy basicos y muchas veces me pierdo con cosas tan basicas como lo que se ha visto aqui en esta duda, no saber iterar por un array "automático" creado con getDataArray() que genera doble paréntesis o como borrar una fila, un registro de un array bidimensional sin tener que crear un bucle e iterar por todo el array.

Asi que pongo aqui la funcion que genera un array con doble parentesis. En el archivo adjunto abajo esta el ejemplo entero con las funciones para almacenar la tabla de la Hoja1 en un array bidimensional (de dos dimensiones) generado con getDataArray().
Luego iteramos por el array bidimensional y extraemos o filtramos del mismo los registros o filas cuyos ciudadanos son de Madrid y los almacenamos en otro array bidimensional, SIEMPRE con DOBLE PARENTESIS ()().

Arranca el macro llamado getArrayTabla() desde el IDE de macros de LibreOffice y pon un punto de parada o punto de interrupcion en la linea 27. Luego en la venta de inspeccion añade los arrays:
madridArray_1Parentesis
madridArray_2Parentesis
y veras como se generan los arrays con Un parentesis (,) o con doble parentesis ()(). Tal como veras en la foto. De este modo aprendes a iterar por ambos arrays.

Tambien he hecho otras dos funciones para que veas como se añade una columna a estos arrays de parentesis simples y parentesis doble.

Mira en la ventana de inspeccion los arrays siguientes y a diferencia de los de arriba, se les ha añadido una columna mas, es decir, un valor más al final.
otraColumna_1Parentesis
otraColumna_2Parentesis

GRACIAS A TODOS. !!

Código: Seleccionar todo

Function arrayBidimensional_Con_2_Parentesis (arrayTable() as Variant, ciudad as String) as Variant
'Almacena filas en un array bidimensional cuya poblacion sea Madrid.
'Pero lo almacena con doble parentesis Vease ejemplo: arrayTemporal(0)(0),  arrayTemporal(0)(1),  y asi todos y el problema
' puede venir a la hora de leer esos arrays, porque los generados por OooBasic son con doble parentesis como arrayTemporal (0)(0) 
'y los generados por ti manualmente son con un simple parentesis arrayTemporal (0,0)

Dim arrayTemporal() as Variant 'No es necesario dimensionar el array que almacena solo los clientes de Madrid.
Dim ultimaFila_A as Long
Dim poblacion as Long
Dim fila as Long

ultimaFila_A = UBound(arrayTable())

poblacion = 3 'Indice de la columna que contiene el dato Poblacion a buscar
fila = 0
For i = 0 To ultimaFila_A
	If arrayTable(i)(poblacion) = ciudad Then
		Redim preserve arrayTemporal (fila)
		arrayTemporal (fila) = arrayTable(i) 'Si el cliente es de Madrid, Coge o Almacena la fila entera del array con todos los valores de las columnas sin tener que iterar por las columnas.
		fila = fila + 1
	End if	
Next i 'Siguiente fila

arrayBidimensional_Con_2_Parentesis = arrayTemporal()
End Function
*** Funcion para tarnsformar un array de doble parentesis a un array de un simple parentesis aqui:***

Código: Seleccionar todo

Function transformArrrayBidi1Parentesis(arrayTableBidiA() as Variant) as Variant
'Transforma un array(0)(0) en un array(0,0) 

Dim arrayTemporalImporte() as Variant
Dim ultimaFila_A as Long
Dim ultimaColumna_A as Long

ultimaFila_A = UBound(arrayTableBidiA())
ultimaColumna_A = UBound(arrayTableBidiA(0),1) 'Para arrays de 2 parentesis
'ultimaColumna_A = UBound(arrayTableBidiA,2)(para arrays de 1 parentesis)
'msgbox "ultimaColumna A: " & ultimaColumna_A
'msgbox "ultimaFila A: " & ultimaFila_A
Redim  arrayTemporalImporte (ultimaFila_A, ultimaColumna_A)
'arrayTemporalImporte = arrayTableBidiA()
For i = 0 To ultimaFila_A
	For j = 0 To ultimaColumna_A 'Itera el array TableB_Bidimensional

			'***** Almacena datos fila. ***********

				arrayTemporalImporte (i,j) = arrayTableBidiA(i)(j)
'
	Next j 'Siguiente columna
Next i 'Siguiente fila

transformArrrayBidi1Parentesis() = arrayTemporalImporte()
End Function



eK56Bum6Ux.jpg
eK56Bum6Ux.jpg (41.03 KiB) Visto 5787 veces
Adjuntos
getDataArray()_Correcto.ods
Aqui el archivo calc con la solución.
(72.74 KiB) Descargado 391 veces
Usuario apasionado de las hojas de cálculo. Novato aprendiz de macros con OOo Basic y VBA.
LibreOffice Version: 6.4.3.2 (x64) y Sistema Operativo Windows 10 Home.
Responder