Obteniendo datos

From Apache OpenOffice Wiki
Jump to: navigation, search


Editing.png Esta página está en estado borrador.

Leyendo datos

La forma más simple y directa de obtener el contenido de una celda, es usando el método getString, que te devuelve el contenido de la celda, tal y como se ve en la interfaz del usuario, es decir, si el contenido de la celda es texto, te lo muestra tal cual, si contiene una formula, te mostrara el resultado de dicha formula y si es fecha y tiene formato, te la devolverá como se ve en pantalla.


Sub Datos1()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
 
     If oSel.getImplementationName() = "ScCellObj" Then
         'Mostramos el contenido de la celda
         MsgBox oSel.getString()
     Else
         MsgBox "Selecciona solo una celda"
     End If
 
 End Sub


Si lo que deseas es devolver el valor de la celda, se usa el método getValue, si la celda contiene texto, este método te devolverá 0, si tiene un valor, dicho valor, si la celda contiene una formula, dependerá del tipo de resultado de esta formula, si es texto de nuevo te devolverá 0, si es un valor, este valor, si tiene un error de nuevo será 0, si la celda contiene una fecha, te devolverá el número de serie de esta fecha.


Sub Datos2()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
 
     If oSel.getImplementationName() = "ScCellObj" Then
         'Mostramos el valor de la celda
         MsgBox oSel.getValue()
     Else
         MsgBox "Selecciona solo una celda"
     End If
 
 End Sub


También puedes obtener la formula que tenga la celda con el método getFormula, si la celda contiene texto, te devolverá este texto, si es un valor, ese valor, de una fecha te devuelve el número de serie y si es formula, te devuelve dicha formula, incluyendo el signo de igual (=) con que empieza toda formula aun y cuando la formula tenga como resultado un error, también, toma en cuenta que si la formula devuelta contiene alguna función incorporada de Calc, como SUMA, BUSCARV, etc, este método te devolverá el nombre de esta función en ingles por ejemplo: SUM, VLOOKUP, etc.


Sub Datos3()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
 
     If oSel.getImplementationName() = "ScCellObj" Then
         'Mostramos la formula de la celda
         MsgBox oSel.getFormula()
     Else
         MsgBox "Selecciona solo una celda"
     End If
 
 End Sub


Si deseas obtener la formula tal y como se ve en la barra de formulas, entonces usa la propiedad FormulaLocal, que se comporta de forma muy similar a getString, excepto en las formulas, donde te las devuelve como aparecen en la barra de formulas, como en.


Sub Datos4()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
 
     If oSel.getImplementationName() = "ScCellObj" Then
         'Mostramos la formula local de la celda
         MsgBox oSel.FormulaLocal
     Else
         MsgBox "Selecciona solo una celda"
     End If
 
 End Sub


Si quieres ver las diferencias, captura valores en varias celdas, texto, números, fechas y formulas, y prueba la siguiente macro, toma en cuenta que estos métodos solo los puedes usar en celdas individuales, por ello hacemos la validación, en una de las formulas usa la función =ALEATORIO(), veras claramente las diferencias entres estos métodos.


Sub Datos5()
 Dim oSel As Object
 Dim sTmp As String
 
     oSel = ThisComponent.getCurrentSelection()
 
     If oSel.getImplementationName() = "ScCellObj" Then
         'Mostramos las diferencias entre los métodos
         sTmp = "getString : " & oSel.getString & Chr(13)
         sTmp = sTmp & "getValue : " & oSel.getValue & Chr(13)
         sTmp = sTmp & "getFormula : " & oSel.getFormula & Chr(13)
         sTmp = sTmp & "FormulaLocal : " & oSel.FormulaLocal
         'Mostramos el resultado
         MsgBox sTmp
     Else
         MsgBox "Selecciona solo una celda"
     End If
 
 End Sub


También puedes obtener el tipo de contenido de la celda con getType, que te devolverá un entero dependiendo del contenido de la celda, vacía (0), valor (1), texto (2) o formula (3), de nuevo, este método solo esta disponible es una sola celda.


Sub Datos6()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
     MsgBox oSel.getType()
 
 End Sub


Si la celda contiene una formula y esta devuelve un error, puedes saber que error es con el método getError, si la celda no contiene una formula, este método siempre te devolverá 0.


Sub Datos7()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
     MsgBox oSel.getError()
 
 End Sub


El error división entre cero, devuelve el error 532, establece este error en una formula cualquiera para que lo compruebes, también puedes probar con el error de cuando a una formula le faltan argumentos, normalmente da el error 511.


Podríamos aventurar una primera forma de usar el método correcto, de acuerdo al contenido de la celda.


Sub Datos8()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
     Select Case oSel.getType()
         Case 0
             MsgBox "La celda esta vacia"
         Case 1
             MsgBox oSel.getValue()
         Case 2
             MsgBox oSel.getString()
         Case 3
             If oSel.getError() = 0 Then
                 MsgBox oSel.FormulaLocal
             Else
                 MsgBox oSel.getError()
             End If
     End Select
 
 End Sub


Y si se convierte en función.


 Function ContenidoCelda(Celda As Object)
 Dim tmp
 
     Select Case Celda.getType()
         Case 0 : tmp = "La celda esta vacía"
         Case 1 : tmp = Celda.getValue()
         Case 2 : tmp = Celda.getString()
         Case 3
             If Celda.getError() = 0 Then
                 tmp = Celda.FormulaLocal
             Else
                 tmp = Celda.getError()
             End If
     End Select
 
     ContenidoCelda = tmp
 
 End Function


Toma en cuenta que una celda te puede devolver 532 y estar correcto, es decir que sea por ejemplo el número de alguna calle o ser el valor de alguna acción y seguir siendo correcto o ser el error 532 y como información, seguir siendo correcto, así que no tomes la función anterior como definitiva, sino tan solo como una guía para lo que realmente necesites.


Ahora solo nos resta poder llamarla desde la celda.


Sub Datos9()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
 
     MsgBox ContenidoCelda ( oSel )
 
 End Sub


Y con un poco de ingenio desde cualquier rango de celdas.


Sub Datos10()
 Dim oSel As Object
 Dim fil As Long, col As Long
 
     oSel = ThisComponent.getCurrentSelection()
     Select Case oSel.getImplementationName()
         Case "ScCellObj"
             MsgBox ContenidoCelda ( oSel )
         Case "ScCellRangeObj"
             For fil = 0 To oSel.getRows().getCount() - 1
                 For col = 0 To oSel.getColumns().getCount() - 1
                     MsgBox ContenidoCelda ( oSel.getCellByPosition(col,fil) )
                 Next col
             Next fil
     End Select
 
 End Sub


Toma en cuenta que getCellByPosition, obtiene una referencia a una sola celda, y esta, es en referencia a la selección original, te queda de tarea, obtener lo mismo pero con relación a la hoja completa, te doy dos pistas, usa el mismo método (getCellByPosition), pero toma como base de información para los ciclos la que te devuelve el método getRangeAddress.


En todos los casos anteriores, los métodos usados solo funcionan cuando hacemos referencia a una sola celda, si quieres obtener el contenido de un rango de celdas, usaremos el método getData, que te devuelve una matriz de matrices con el contenido de las celdas, pero cuidado, getData solo te devuelve las celdas con valores, además, en las celdas vacías devuelve un valor un tanto extraño, puedes verificarlo con el siguiente ejemplo, procura seleccionar un rango pequeño porque te mostrará el valor de cada celda.


Sub Datos11()
 Dim oSel As Object
 Dim mDatos
 Dim mTmp
 Dim co1 As Long, co2 As Long
 
     oSel = ThisComponent.getCurrentSelection()
 
     If oSel.getImplementationName() = "ScCellRangeObj" Then
         'Obtenemos SOLO VALORES
         mDatos = oSel.getData()
         For co1 = LBound(mDatos) to UBound(mDatos)
             'Asignamos la matriz interna a una temporal
             mTmp = mDatos(co1)
             For co2 = LBound(mTmp) to UBound(mTmp)
                 MsgBox mTmp(co2)
             Next
         Next
     End If
 
 End Sub


En vez de usar una matriz de apoyo, es más transparente obtener el número de filas y columnas del rango, un rango de celdas siempre es rectangular por lo que podemos garantizar que los índices de las matrices siempre serán correctos.


Sub Datos12()
 Dim oSel As Object
 Dim mDatos
 Dim co1 As Long, co2 As Long
 Dim Fil As Long, Col As Long
 
     oSel = ThisComponent.getCurrentSelection()
 
     If oSel.getImplementationName() = "ScCellRangeObj" Then
         'Obtenemos SOLO VALORES
         mDatos = oSel.getData()
         'Obtenemos el número de filas y columnas
         Fil = oSel.getRows.getCount() - 1
         Col = oSel.getColumns.getCount() - 1
 
         For co1 = 0 To Fil
             For co2 = 0 to Col
             'Es más claro el acceso a la matriz
             MsgBox mDatos (co1) (co2)
             Next
         Next    
     End If
 
 End Sub


Si quieres obtener el contenido sea cual sea, usa la misma estructura, pero en vez de usar getData, usa getDataArray como en.


Sub Datos13()
 Dim oSel As Object
 Dim mDatos
 Dim co1 As Long, co2 As Long
 Dim Fil As Long, Col As Long
 
     oSel = ThisComponent.getCurrentSelection()
 
     If oSel.getImplementationName() = "ScCellRangeObj" Then
         'Obtenemos todos los datos
         mDatos = oSel.getDataArray()
         'Obtenemos el número de filas y columnas
         Fil = oSel.getRows.getCount() - 1
         Col = oSel.getColumns.getCount() - 1
 
         For co1 = 0 To Fil
             For co2 = 0 to Col
             'Es más claro el acceso a la matriz
             MsgBox mDatos (co1) (co2)
             Next
         Next
     End If
 
 End Sub


Y si lo que quieres es el contenido de las celdas, como si hubieses usado en cada una el método getFormula, usas getFormulaArray.


Sub Datos14()
 Dim oSel As Object
 Dim mDatos
 Dim co1 As Long, co2 As Long
 Dim Fil As Long, Col As Long
 
     oSel = ThisComponent.getCurrentSelection()
 
     If oSel.getImplementationName() = "ScCellRangeObj" Then
         'Obtenemos todos los datos
         mDatos = oSel.getFormulaArray()
         'Obtenemos el número de filas y columnas
         Fil = oSel.getRows.getCount() - 1
         Col = oSel.getColumns.getCount() - 1
 
         For co1 = 0 To Fil
             For co2 = 0 to Col
                 'Es más claro el acceso a la matriz
                 MsgBox mDatos (co1) (co2)
             Next
         Next
     End If
 
 End Sub


De la combinación de los métodos vistos en este tema, puedes acceder a cualquier información de una celda o un rango de celdas, veamos ahora como introducir información.


Introduciendo datos

Los métodos para introducir datos en celdas, son más o menos los mismos que para obtenerlos, pero en vez de obtenerlos (get) los establecemos (set).


Para el caso de cadenas de texto, usamos setString, toma en cuenta que este método reemplazará el contenido de la celda sin preguntarte nada.


Sub Introducir1()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
 
     If oSel.getImplementationName() = "ScCellObj" Then
         'Insertamos una cadena en la celda
         oSel.setString( "Nadie esta más perdido que quien no sabe a donde va" )
     Else
         MsgBox "Selecciona solo una celda"
     End If
 
 End Sub


Para valores usamos setValue, del mismo modo que setString, simplemente reemplazará el contenido de la celda sin consultarte.


Sub Introducir2()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
 
     If oSel.getImplementationName() = "ScCellObj" Then
         'Insertamos un valor en la celda
         oSel.setValue( 34 )
     Else
         MsgBox "Selecciona solo una celda"
     End If
 
 End Sub


Ya lo habrás intuido, para las formulas podemos usar setFormula, la formula debe estar como una cadena de texto y debe ser una formula válida.


Sub Introducir3()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
 
     If oSel.getImplementationName() = "ScCellObj" Then
         'Insertamos una formula
         oSel.setFormula( "=A1+A5" )
     Else
         MsgBox "Selecciona solo una celda"
     End If
 
 End Sub


Si introduces una formula no válida, este método no te dará ningún error, pero si lo obtendrás en la interfaz del usuario, como en el siguiente ejemplo.


Sub Introducir4()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
 
     If oSel.getImplementationName() = "ScCellObj" Then
         'Insertamos una formula no valida
         oSel.setFormula( "=C2-C3+" )
     End If
 
 End Sub


Si hace uso de funciones incorporadas de OpenOffice.org, tienes que usar el nombre en ingles de la función a usar, también, los argumentos deben estar correctamente establecidos, así como los tipos de estos para que no te devuelva ningún error.


Sub Introducir5()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
 
     If oSel.getImplementationName() = "ScCellObj" Then
         'Insertamos una formula con función
         oSel.setFormula( "=SUM(A1:A10)" )
     End If
 
 End Sub


Si prefieres usar los nombres de las funciones en español, en vez de este método, usa la propiedad FormulaLocal, el siguiente ejemplo hace lo mismo que el anterior.


Sub Introducir6()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
 
     If oSel.getImplementationName() = "ScCellObj" Then
         'Insertamos una formula con función
         oSel.FormulaLocal = "=SUMA(A1:A10)"
     End If
 
 End Sub


En el Apéndice Fórmulas de Calc Español-Inglés te muestro una lista de equivalencias de las formulas que incorpora Calc en español e ingles, así puedes usar el método que quieras.


Cuando queramos introducir valores en rangos de celdas, hay que tener la precaución de establecer el rango destino, exactamente del mismo ancho y alto de la matriz origen, de lo contrario te dará un error en tiempo de ejecución.


Sub Introducir7()
 Dim oHojaActiva As Object
 Dim oRango As Object
 Dim mDatos(4)
 
     mDatos(0) = Array(1,2,3)
     mDatos(1) = Array(4,5,6)
     mDatos(2) = Array(7,8,9)
     mDatos(3) = Array(10,11,12)
     mDatos(4) = Array(13,14,15)
 
     oHojaActiva = ThisComponent.getCurrentController().getActiveSheet()
     'El rango donde se insertaran los valores, "debe"
     'ser del mismo tamaño en ancho y alto de la matriz
     oRango = oHojaActiva.getCellRangeByName("A1:C5")
     'Insertamos la matriz completa
     oRango.setData( mDatos )
 
 End Sub


También, toma nota de que con el método setData, solo puedes introducir valores, si la matriz lleva alguna cadena de texto, este método la reemplazara por 0, para valores y cadenas, debes usar setDataArray.


Sub Introducir8()
 Dim oHojaActiva As Object
 Dim oRango As Object
 Dim mDatos(4)
 
     mDatos(0) = Array("No","Nombre","Tel")
     mDatos(1) = Array(1,"Gloria",12345678)
     mDatos(2) = Array(1,"Paola",23456789)
     mDatos(3) = Array(3,"Lidia",34567891)
     mDatos(4) = Array(4,"Lizette",87654321)
 
     oHojaActiva = ThisComponent.getCurrentController().getActiveSheet()
     'El rango donde se insertaran los valores, "debe"
     'ser del mismo tamaño en ancho y alto de la matriz
     oRango = oHojaActiva.getCellRangeByName("A1:C5")
     'Insertamos la matriz completa
     oRango.setDataArray( mDatos )
 
 End Sub


Si tus datos a introducir incluyen formulas, es mejor que uses setFormulaArray.


Sub Introducir9()
 Dim oHojaActiva As Object
 Dim oRango As Object
 Dim mDatos(4)
 
     mDatos(0) = Array("No","Nombre","Tel")
     mDatos(1) = Array(1,"Gloria","=RAND()")
     mDatos(2) = Array(1,"Paola","=A3")
     mDatos(3) = Array(3,"Lidia","=SUM(A2:A4)")
     mDatos(4) = Array(4,"Lizette","=RAND()")
 
     oHojaActiva = ThisComponent.getCurrentController().getActiveSheet()
     oRango = oHojaActiva.getCellRangeByName("A1:C5")
     'Insertamos la matriz completa
     oRango.setFormulaArray( mDatos )
 
 End Sub


Borrando datos

Para borrar datos de celdas usamos el método clearContents, este método requiere un entero indicándole el tipo de contenido que deseamos borrar, por ejemplo valores (1), textos (4) o formulas (16), este método esta presente en los tres tipos de rangos vistos, por lo que solo tienes que asegurarte que efectivamente sea un rango de celdas.


En el siguiente ejemplo, se borran solo las celdas con valores, textos y formulas, de tres rangos diferentes.


Sub Borrando1()
 Dim oHojaActiva As Object
 Dim oRango As Object
 
     oHojaActiva = ThisComponent.getCurrentController().getActiveSheet()
     oRango = oHojaActiva.getCellRangeByName("A1:C5")
     'Borramos solo los valores
     oRango.clearContents( 1 )
 
     oRango = oHojaActiva.getCellRangeByName("D2:E10")
     'Borramos solo los texto
     oRango.clearContents( 4 )
 
     oRango = oHojaActiva.getCellRangeByName("G1:K100")
     'Borramos solo las formulas
     oRango.clearContents( 16 )
 
 End Sub


Puedes sumar los valores de los tipos a borrar, en el siguiente ejemplo, se borra los textos y las formulas del rango seleccionado.


Sub Borrando2()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
 
     'Borramos los textos (4) + formulas (16)
     oSel.clearContents( 20 )
 
 End Sub


Los valores permitidos para este método, están condicionados por las constantes del grupo com.sun.star.sheet.CellFlags, cuyos valores se listan en la siguiente tabla.


Constante Valor
com.sun.star.sheet.CellFlags.VALUE 1
com.sun.star.sheet.CellFlags.DATETIME 2
com.sun.star.sheet.CellFlags.STRING 4
com.sun.star.sheet.CellFlags.ANNOTATION 8
com.sun.star.sheet.CellFlags.FORMULA 16
com.sun.star.sheet.CellFlags.HARDATTR 32
com.sun.star.sheet.CellFlags.STYLES 64
com.sun.star.sheet.CellFlags.OBJECT 128
com.sun.star.sheet.CellFlags.EDITATTR 256
com.sun.star.sheet.CellFlags.FORMATTED 512


Puedes usar de forma indistinta las constantes o los valores de estas, así como cualquier combinación de ellas. El siguiente ejemplo borra todo te deja la selección como nueva.


Sub Borrando3()
 Dim oSel As Object
 
     oSel = ThisComponent.getCurrentSelection()
 
     'Borramos todo
     oSel.clearContents( 1023 )
 
 End Sub


Llenando series de datos

Llenar series es un método muy divertido de introducir datos en nuestra hoja de calculo, existen dos formas de hacerlo, en general la forma automática funcionara si se establecen correctamente los valores iniciales, observa la siguiente imagen, en la celda A1 tenemos solo un valor y en la columna C como queremos que quede nuestra serie.

El código para lograr esto es el siguiente, observa que sencillo.


Sub LlenandoSeries1()
 Dim oHojaActiva As Object
 Dim oRango As Object
 
     oHojaActiva = ThisComponent.getCurrentController.getActiveSheet()
     oRango = oHojaActiva.getCellRangeByName("A1:A15")
 
     'Llenamos hacia abajo
     oRango.fillAuto( 0, 1 )
 
 End Sub


El método fillAuto, solo requiere dos argumentos, el primero es para indicarle la dirección del llenado en nuestro ejemplo, abajo () y un entero que le indica, cuantas celdas del rango tomara como guías para determinar el algoritmo de llenado. En la siguiente tabla están las cuatro posibilidades del argumento dirección de este método.


Constante Valor
com.sun.star.sheet.FillDirection.TO_BOTTOM 0
com.sun.star.sheet.FillDirection.TO_RIGHT 1
com.sun.star.sheet.FillDirection.TO_TOP 2
com.sun.star.sheet.FillDirection.TO_LEFT 3


Si quisiéramos llenar el rango con números pares, lo haríamos así.


Sub LlenandoSeries2()
 Dim oHojaActiva As Object
 Dim oRango As Object
 
     oHojaActiva = ThisComponent.getCurrentController().getActiveSheet()
     oRango = oHojaActiva.getCellRangeByName("A1:A15")
 
     'Establecemos los valores guias
     oHojaActiva.getCellRangeByName("A1").setValue( 2 )
     oHojaActiva.getCellRangeByName("A2").setValue( 4 )
 
     'Llenamos hacia abajo, nota que ahora tomamos dos celdas como guías
     oRango.fillAuto( 0, 2 )
 
 End Sub


Por supuesto no solo con números es posible, el siguiente código establece el rango A1:L1 con los meses del año.


Sub LlenandoSeries3()
 Dim oHojaActiva As Object
 Dim oRango As Object
 
     oHojaActiva = ThisComponent.getCurrentController.getActiveSheet()
     oRango = oHojaActiva.getCellRangeByName("A1:L1")
 
     'Establecemos el valor guía
     oHojaActiva.getCellRangeByName("A1").setString( "enero" )
 
     'Llenamos a la derecha
     oRango.fillAuto( 1, 1 )
 
 End Sub


Esto es posible por que esta lista viene de forma predeterminada en OpenOffice.org, esta y otras listas, las puedes personalizar en el menú Herramientas > Opciones...> OpenOffice.org Calc > Ordenar listas.


Donde más me gusta el llenado de series, es en la forma transparente de copiar o llenar un rango con una formula deseada, por ejemplo, observa la siguiente imagen

El fin es establecer la formula para calcular la edad de cada persona, para fines didácticos daremos por buena la edad, solo restando el año actual de la de nacimiento, observa que los datos terminan en la fila 1001 pero eso no importa, pueden terminar en la 1000 o la que sea pues esto lo determinaremos por código, de la siguiente forma.


Sub LlenandoSeries4()
 Dim oHojaActiva As Object
 Dim oRango As Object
 Dim oCursor As Object
 
     oHojaActiva = ThisComponent.getCurrentController.getActiveSheet()
     oRango = oHojaActiva.getCellRangeByName("A1")
 
     'Establecemos la primer formula 
     oHojaActiva.getCellRangeByName("D2").setFormula( "=YEAR(NOW())-C2" )
 
     'Creamos un cursor a partir de la primer celda
     oCursor = oHojaActiva.createCursorByRange( oRango )
     'Expandimos a la región actual
     oCursor.collapseToCurrentRegion()
 
     'Construimos el rango a llenar
     oRango = oHojaActiva.getCellRangeByName( "D2:D" & CStr(oCursor.getRows().getCount()) )
 
     'Llenamos hacia abajo
     oRango.fillAuto( 0, 1 )
 
 End Sub


Para establecer la formula, como ya lo vimos, puedes usar también las propiedades FormulaLocal, nuestra formula de ejemplo quedaría así.



Observa como obtenemos la ultima fila del rango usado con la ayuda del cursor y el método oCursor.getRows().getCount(), y con una sola línea más, llenamos todo el rango.


Buscar y reemplazar

La búsqueda y reemplazo en OpenOffice.org es una herramienta muy poderosa, si bien tiene tantas variantes como las que puedes ver en: Editar > Buscar y reemplazar..., nos limitaremos a las opciones más comunes y generales, quedándote de tarea la investigación del resto. Usaremos para nuestras pruebas la siguiente tabla de datos, que, no es restrictiva, puedes usar la que gustes, pero esta pequeña nos permite comprobar rápidamente los resultados para verificar que funciona correctamente, después, puedes usar listados del tamaño que quieras y los recursos de tu equipo te lo permitan.


Nombre Año Edad
1 edgar 1975 33
2 gloria 1976 32
3 antonio 1965 43
4 lidia 1966 42
5 paola 1974 34
6 vanessa 1976 32
7 lizette 1975 33
8 edgar 1969 39
9 gloria 1971 37
10 antonio 1969 39
11 lidia 1973 35
12 paola 1975 33
13 vanessa 1975 33
14 lizette 1967 41
15 edgar 1975 33
16 gloria 1965 43
17 antonio 1967 41
18 lidia 1980 28


En las búsquedas, se usa un descriptor de búsqueda que no es otra cosa que una estructura donde le indicamos las características de la búsqueda y lo que estamos buscando y un lugar para buscar, que es el rango donde queremos hacer la búsqueda, por supuesto puedes buscar en toda la hoja, incluso en todas las hojas, la forma más sencilla de una búsqueda es la siguiente.


Sub Buscar1()
 Dim oHojaActiva As Object
 Dim oBuscarEn As Object
 Dim oEncontrado As Object
 Dim oSD As Object
 
     oHojaActiva = ThisComponent.getCurrentController.getActiveSheet()
 
     'Establecemos el rango donde buscaremos
     oBuscarEn = oHojaActiva.getCellRangeByName( "A1:D19" )
 
     'Creamos el descriptor de busqueda
     oSD = oHojaActiva.createSearchDescriptor
 
     'Establecemos lo que estamos buscando
     oSD.setSearchString( "33" )
 
     'Realizamos la busqueda de TODAS las coincidencias
     oEncontrado = oBuscarEn.findAll( oSD )
 
     'Si no hay coincidencias oEncontrado = Null
     If Not IsNull( oEncontrado ) Then
         'Si encuentra algo lo seleccionamos
         ThisComponent.getCurrentController.select( oEncontrado )
     Else
         MsgBox "No se encontraron coincidencias"
     End If
 
 End Sub


Y nuestra primera búsqueda nos devuelve el mensaje No se encontraron coincidencias, ¿por qué si aparentemente si tenemos valores 33 en nuestros datos?, la respuesta es que la búsqueda predeterminada se hace buscando dentro de las formulas, y todos los 33 que ves en la lista son el resultado de una formula, dicha formula es: =AÑO(AHORA())-C2, ahora, establece el valor buscado en a y realiza la búsqueda: oSD.setSearchString( "a" ).

Ahora nos pasa al revés, devolvemos demasiados resultados, ¿verdad?, la razón es la misma, la búsqueda predeterminada se hace por formulas, observa que selecciono todas las celdas de la columna B que tienen la letra a y todas las celdas de la columna C y D, la formula de la columna D ya la vimos y contiene la letra buscada, la formula de la columna C es: =ALEATORIO.ENTRE(1965;1980), como vez, también tienen la letra “a” entre su texto, por ello, la búsqueda te devuelve todo, lo cual es correcto, la búsqueda esta bien, lo que tenemos que hacer es discriminar un poco más con los criterios de búsqueda, no necesariamente tiene que ser más restrictiva, sino acorde a lo que estas buscando, y claro, lo que esperas devolver, regresemos a nuestro primer ejemplo y agreguemos una propiedad a la búsqueda, ahora, le diremos que busque por valores, para que busque en el resultado de las formulas, no dentro de las formulas, esto lo logramos con la propiedad: searchType.


Sub Buscar3()
 Dim oHojaActiva As Object
 Dim oBuscarEn As Object
 Dim oEncontrado As Object
 Dim oSD As Object
 
     oHojaActiva = ThisComponent.getCurrentController().getActiveSheet()
     oBuscarEn = oHojaActiva.getCellRangeByName( "A1:D19" )
 
     'Creamos el descriptor de busqueda
     oSD = oHojaActiva.createSearchDescriptor
     'Buscamos por valores
     oSD.searchType = 1
     'Establecemos lo que estamos buscando
     oSD.setSearchString( "33" )
     'Realizamos la busqueda de TODAS las coincidencias
     oEncontrado = oBuscarEn.findAll( oSD )
     'Si no hay coincidencias oEncontrado = Null
     If Not IsNull( oEncontrado ) Then
         'Si encuentra algo lo seleccionamos
         ThisComponent.getCurrentController.select( oEncontrado )
     Else
         MsgBox "No se encontraron coincidencias"
     End If
 
 End Sub


Mucho mejor ¿verdad?, ahora si, solo las celdas con el valor 33 son seleccionadas, prueba a establecer la búsqueda con la letra a o cualquiera que tu quieras y observa los resultados, es muy importante que sepas que el resultado es una colección de rangos, aun, cuando y solo te devuelva un solo rango, este, formará parte de dicha colección, en el tema Referencia a varios rangos de celdas, tratamos como manejar este tipo de rangos.


Como siguiente prueba, establece la búsqueda en oSD.setSearchString( "li" ) y observa el resultado.

Nota que las búsquedas las puede hacer en partes del texto, pero podemos restringirla a palabras completas con la propiedad searchWords, como en.


Sub Buscar4()
 Dim oHojaActiva As Object
 Dim oBuscarEn As Object
 Dim oEncontrado As Object
 Dim oSD As Object
 
     oHojaActiva = ThisComponent.getCurrentController.getActiveSheet()
     oBuscarEn = oHojaActiva.getCellRangeByName( "A1:D19" )
 
     oSD = oHojaActiva.createSearchDescriptor
     oSD.searchType = 1
     'Buscamos por palabras completas
     oSD.searchWords = True
     oSD.setSearchString( "li" )
 
     oEncontrado = oBuscarEn.findAll( oSD )
     If Not IsNull( oEncontrado ) Then
         ThisComponent.getCurrentController.select( oEncontrado )
     Else
         MsgBox "No se encontraron coincidencias"
     End If
 
 End Sub


La búsqueda anterior te tiene que devolver No se encontraron coincidencias, por que no hay palabras completas que sean “li”, prueba a reemplazar la cadena buscada por el nombre que más de guste de los existentes en nuestra lista, por ejemplo “lizette” y obtendremos.

Por que estamos haciendo la búsqueda por palabras completas. Podemos hacerla aun más restrictiva, si establecemos que distinga entre mayúsculas y minúsculas con la propiedad SearchCaseSensitive de la siguiente manera.


Sub Buscar5()
 Dim oHojaActiva As Object
 Dim oBuscarEn As Object
 Dim oEncontrado As Object
 Dim oSD As Object
 
     oHojaActiva = ThisComponent.getCurrentController().getActiveSheet()
     oBuscarEn = oHojaActiva.getCellRangeByName( "A1:D19" )
 
     oSD = oHojaActiva.createSearchDescriptor
     oSD.searchType = 1
     oSD.searchWords = False
     'Distinguimos mayusculas de minusculas
     oSD.SearchCaseSensitive = True
     oSD.setSearchString( "A" )
     oEncontrado = oBuscarEn.findAll( oSD )
     If Not IsNull( oEncontrado ) Then
         ThisComponent.getCurrentController.select( oEncontrado )
     Else
         MsgBox "No se encontraron coincidencias"
     End If
 
 End Sub


Observa que hemos vuelto a establecer searchWords en False para que encuentre partes de las palabras. En la búsqueda anterior, únicamente te tiene que regresar la celda C1 que contiene la palabra “Año”. Incluso, puedes realizar búsquedas dentro de las notas de las celdas si estableces la propiedad .


El reemplazo es la continuación de la búsqueda, es decir, para reemplazar algo, primero se tiene que buscar, veamos un ejemplo sencillo y después la explicación, continuamos haciendo uso de nuestra tabla usada en la búsqueda.


Sub Reemplazar1()
 Dim oHojaActiva As Object
 Dim oBuscarEn As Object
 Dim lReemplazados As Long
 Dim oRD As Object
 
     oHojaActiva = ThisComponent.getCurrentController().getActiveSheet()
     oBuscarEn = oHojaActiva.getCellRangeByName( "A1:D19" )
 
     'Creamos el descriptor de reemplazo
     oRD = oHojaActiva.createReplaceDescriptor
     'Texto a buscar
     oRD.setSearchString( "=año" )
     'Reemplazado por
     oRD.setReplaceString( "=mes" )
     'El método devuelve el numero de reemplazos que tuvieron éxito
     lReemplazados = oBuscarEn.replaceAll( oRD )
 
     If lReemplazados = 0 Then
         MsgBox "No se encontraron coincidencias"
     Else
         MsgBox "Se realizaron " & lReemplazados & " reemplazos"
     End If
 
 End Sub


Observa que ahora, en ves de un descriptor de búsqueda (createSearchDescriptor), creamos un descriptor de reemplazo (createReplaceDescriptor), establecemos el valor buscado (setSearchString) y el valor por el que se reemplazara (setReplaceString), este método (replaceAll) devuelve un entero largo (long) con el número total de reemplazos que tuvieron éxito, si es cero no encontró coincidencias. En la columna D de nuestros datos de ejemplo, teníamos la formula =AÑO(AHORA())-C2, después de ejecutar la macro anterior, deberíamos tener en esta columna la formula =MES(AHORA())-C2, como lo podemos comprobar en la siguiente imagen.

Ahora, reemplazaremos palabras completas, con el siguiente código, mi amigo Edgar no me reclamará nada si lo cambio por Nikole, de hecho me felicitará.


Sub Reemplazar2()
 Dim oHojaActiva As Object
 Dim oBuscarEn As Object
 Dim lReemplazados As Long
 Dim oRD As Object
 
     oHojaActiva = ThisComponent.getCurrentController().getActiveSheet()
     oBuscarEn = oHojaActiva.getCellRangeByName( "A1:D19" )
 
     oRD = oHojaActiva.createReplaceDescriptor
     oRD.setSearchString( "edgar" )
     oRD.setReplaceString( "nikole" )
     'Le indicamos que busque palabras completas
     oRD.searchWords = True
 
     lReemplazados = oBuscarEn.replaceAll( oRD )
 
     If lReemplazados = 0 Then
         MsgBox "No se encontraron coincidencias"
     Else
         MsgBox "Se realizaron " & lReemplazados & " reemplazos"
     End If
 
 End Sub


A veces, es conveniente hacer primero una búsqueda y comprobar que esta correcta para después hacer el reemplazo, si tus búsquedas están bien establecidas, casi puedes estar seguro de que el reemplazo lo estará.


Trabajando con notas

Las notas, en las celdas de una hoja de calculo, son muy fáciles de manejar, en el siguiente ejemplo, insertamos una nueva nota en la celda E7.


Sub Notas1()
 Dim oHojaActiva As Object
 Dim oNotas As Object
 Dim oDirCelda As New com.sun.star.table.CellAddress
 
     oHojaActiva = ThisComponent.getCurrentController.getActiveSheet()
     'Obtenemos la colección de notas de la hoja activa
     oNotas = oHojaActiva.getAnnotations()
     'La celda donde insertaremos la nota
     oDirCelda.Column = 4
     oDirCelda.Row = 6
     'Insertamos la nota
     oNotas.insertNew( oDirCelda, "Presupuesto aprobado" )
 
 End Sub


Para saber cuantas notas hay en la hoja activa.


Sub Notas2()
 Dim oHojaActiva As Object
 Dim oNotas As Object
 
     oHojaActiva = ThisComponent.getCurrentController.getActiveSheet()
     'Obtenemos la colección de notas de la hoja activa
     oNotas = oHojaActiva.getAnnotations()
     'Mostramos el total de notas en la hoja
     MsgBox oNotas.getCount()
 
 End Sub


Para mostrar la dirección de cada una de las celdas con notas y su contenido.


Sub Notas3()
 Dim oHojaActiva As Object
 Dim oNotas As Object
 Dim oNota As Object
 Dim co1 As Long
 
     oHojaActiva = ThisComponent.getCurrentController.getActiveSheet()
     oNotas = oHojaActiva.getAnnotations()
     If oNotas.getCount() > 0 Then
         For co1 = 0 To oNotas.getCount - 1
             'Obtenemos una nota
             oNota = oNotas.getByIndex( co1 )
             'Mostramos su posición y su contenido
             MsgBox DireccionCelda( oNota.getPosition ) & ": " & oNota.getString()    
         Next co1
     Else
         MsgBox "No hay notas en esta hoja"
     End If
 
 End Sub
 
 Function DireccionCelda( DirCelda As Object ) As String
 Dim oSFA As Object
 Dim mDatos
 
     'Nos apoyamos en la función de Calc DIRECCION (ADDRESS)
     oSFA = createUnoService( "com.sun.star.sheet.FunctionAccess" )
     'Construimos la matriz de datos para la función
     mDatos = Array( DirCelda.Row+1, DirCelda.Column+1, 4 )
     DireccionCelda = oSFA.callFunction("ADDRESS",mDatos())
 
 End Function


Puedes acceder a una celda primero y después a su nota para modificarla.


Sub Notas4()
 Dim oHojaActiva As Object
 Dim oCelda As Object
 Dim oNota As Object
 
     oHojaActiva = ThisComponent.getCurrentController.getActiveSheet()
     oCelda = oHojaActiva.getCellRangeByName("A1")
     'Accedemos a la nota de la celda
     oNota = oCelda.getAnnotation
     'Le cambiamos su contenido
     oNota.setString( "Cambio de texto en nota" )
 
 End Sub


Si la celda referenciada no tiene una nota, el cambio no se verá reflejado en la interfaz del usuario, por lo que tienes que asegurarte que la celda contiene una nota, puedes usar la longitud del contenido de la nota para saberlo. Si no tiene nota, tienes que insertarla primero.


Sub Notas5()
 Dim oHojaActiva As Object
 Dim oCelda As Object
 Dim oNota As Object
 
     oHojaActiva = ThisComponent.getCurrentController.getActiveSheet()
     oCelda = oHojaActiva.getCellRangeByName("A1")
     'Accedemos a la nota de la celda
     oNota = oCelda.getAnnotation
 
     If Len( oNota.getString() ) = 0 Then
         MsgBox "La celda NO tiene nota"
     Else
         MsgBox "La celda tiene nota"
     End If
 
 End Sub


También puede recorrer el conjunto de notas y comparar la dirección.


Sub Notas6()
 Dim oHojaActiva As Object
 Dim oCelda As Object
 Dim oNotas As Object
 Dim oNota As Object
 Dim co1 As Long
 
     oHojaActiva = ThisComponent.getCurrentController.getActiveSheet()
     oCelda = oHojaActiva.getCellRangeByName("E7")
     oNotas = oHojaActiva.getAnnotations()
     If oNotas.getCount() > 0 Then
         For co1 = 0 To oNotas.getCount - 1
             oNota = oNotas.getByIndex( co1 )
             'Comparamos las direcciones
             If oNota.getPosition.Column = oCelda.getCellAddress.Column And oNota.getPosition.Row = oCelda.getCellAddress.Row Then
                 MsgBox "La celda tiene nota"
                 Exit Sub
             End If
         Next co1
         MsgBox "La celda NO tiene nota"
     Else
         MsgBox "No hay notas en esta hoja"
     End If    
 
 End Sub


Podemos hacer visible una nota.


Sub Notas7()
 Dim oHojaActiva As Object
 Dim oCelda As Object
 Dim oNota As Object
 
     oHojaActiva = ThisComponent.getCurrentController.getActiveSheet()
     oCelda = oHojaActiva.getCellRangeByName("E7")
     oNota = oCelda.getAnnotation
     'La hacemos visible
     oNota.setIsVisible( True )
 
 End Sub


De nuevo, si la celda no tiene nota, el código anterior no hará nada, tampoco te dará ningún error, el siguiente ejemplo te intercambia la visibilidad de las notas de la hoja, es decir, si esta oculta la muestra y si esta visible la oculta.


Sub Notas8()
 Dim oHojaActiva As Object
 Dim oNotas As Object
 Dim oNota As Object
 Dim co1 As Long
 
     oHojaActiva = ThisComponent.getCurrentController.getActiveSheet()
     oNotas = oHojaActiva.getAnnotations()
     If oNotas.getCount() > 0 Then
         For co1 = 0 To oNotas.getCount - 1
             oNota = oNotas.getByIndex( co1 )
             'Intercambiamos su visibilidad
             oNota.setIsVisible( Not oNota.getIsVisible )
         Next co1
     Else
         MsgBox "No hay notas en esta hoja"
     End If    
 
 End Sub


Nota como hacemos el intercambio, podemos saber si la nota de la celda es visible (getIsVisible), esta propiedad nos devuelve falso (False) o verdadero (True) según este o no visible la nota, con el operador de negación (Not) invertimos este valor y por consiguiente la visibilidad.


Para borrar una nota, es preciso saber el índice de esta, por lo que hay que iterar entre el conjunto de notas.


Sub Notas9()
 Dim oHojaActiva As Object
 Dim oCelda As Object
 Dim oNotas As Object
 Dim oNota As Object
 Dim co1 As Long
 
     oHojaActiva = ThisComponent.getCurrentController.getActiveSheet()
     oCelda = oHojaActiva.getCellRangeByName("A1")
     oNotas = oHojaActiva.getAnnotations()
     If oNotas.getCount() > 0 Then
         For co1 = 0 To oNotas.getCount - 1
             oNota = oNotas.getByIndex( co1 )
             'Comparamos las direcciones
             If oNota.getPosition.Column = oCelda.getCellAddress.Column And oNota.getPosition.Row = oCelda.getCellAddress.Row Then
                 'Borramos la nota por su índice
                 oNotas.removeByIndex( co1 )
                 Exit Sub
             End If
         Next co1
         MsgBox "La celda NO tiene nota"
     Else
         MsgBox "No hay notas en esta hoja"
     End If    
 
 End Sub


También es posible acceder a la autoforma (Shape) de la nota para manipularla.


Sub Notas10()
 Dim oHojaActiva As Object
 Dim oCelda As Object
 Dim oNota As Object
 Dim oForma As Object
 Dim oTam As Object
 
     oHojaActiva = ThisComponent.getCurrentController.getActiveSheet()
     oCelda = oHojaActiva.getCellRangeByName("E7")
     'Accedemos a la nota
     oNota = oCelda.getAnnotation
     'La hacemos visible
     oNota.setIsVisible( True )
     'Accedemos a la forma
     oForma = oNota.getAnnotationShape
     'Obtenemos el tamaño actual
     oTam = oForma.getSize
     'Lo duplicamos
     oTam.Width = oTam.Width * 2
     oTam.Height = oTam.Height * 2
     'Establecemos el nuevo tamaño
     oForma.setSize( oTam )
     'Cambiamos el color de fondo de forma aleatoria
     oForma.FillColor = RGB(Rnd()*255,Rnd()*255,Rnd()*255)
 
 End Sub


Esta autoforma, tiene decenas de propiedades para manipularse, por lo que volveremos a ellas en el capítulo correspondiente a autoformas. Por ahora, tienes todos los elementos para manipular las notas de celdas a tu antojo. De tarea, crea una macro que nos haga un informe, en una hoja nueva, de todas las notas existentes en la hoja activa, nos tiene que devolver la dirección completa y su contenido, ¿vale?.



ES.Plantillas.Logo foro es.png
Si tienes dudas acerca de lo aquí explicado, tienes algún problema con AOO,
o quieres ampliar la información, no dudes en dirigirte al

Foro Oficial en español de Apache OpenOffice para Macros y API UNO

Personal tools