Obteniendo datos
Contents
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.
Nº | 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?.
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 |