Aprendiendo_OOoBasic

March 19, 2018 | Author: pedro_coleta | Category: Programming Language, Linux Distribution, Quotation Mark, Basic, Point And Click


Comments



Description

Aprendiendo OOo BasicAutor : Correo : Fecha : Licencia : Ultima modificación : Para ayudar : Mauricio Baeza Servín mauricio (NO-SPAM) universolibre PUNTO org 15 de Septiembre del 2007 GNU Free Documentation License, v1.2 o posterior 22 de septiembre de 2009 Apoya este proyecto Copyright (c) 2007 Mauricio Baeza Servin. Se concede permiso para copiar, distribuir y/o modificar este documento bajo los términos de la Licencia de Documentación Libre de GNU, Versión 1.2 o cualquier otra versión posterior publicada por la Free Software Foundation; sin Secciones Invariantes ni Textos de Cubierta Delantera ni Textos de Cubierta Trasera. Una copia de la licencia está incluida en la sección titulada GNU Free Documentation License. Todo el código incluido en este libro esta bajo la siguiente licencia: Copyright (C) 2007 Mauricio Baeza Servín Este programa es software libre: usted puede redistribuirlo y/o modificarlo bajo los términos de la Licencia Pública General GNU publicada por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, o (a su elección) cualquier versión posterior. Este programa se distribuye con la esperanza de que sea útil, pero SIN GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública General GNU para obtener una información más detallada. Debería haber recibido una copia de la Licencia Pública General GNU junto a este programa. En caso contrario, consulte <http://www.gnu.org/licenses/>. Aprendiendo OOo Basic 3 Índice de contenido 1 - Introducción................................................................................8 2 - Conceptos iniciales....................................................................10 3 - Mi primer macro........................................................................16 4 - El lenguaje OOo Basic...............................................................23 4.1 - Declarando y usando variables................................................26 4.2 - Instrucciones y funciones en OOo Basic..................................32 4.3 - Constantes – Siempre lo mismo...............................................36 4.4 - Bifurcaciones – Tomando decisiones.......................................36 4.5 - Bucles – Repitelo otra vez........................................................39 4.6 - Matrices – Juntos pero no revueltos.........................................47 4.7 - Ámbito de variables – Ahora me ves, ahora no........................57 4.7.1 - Ámbito Local.....................................................................57 4.7.2 - Ámbito Privado.................................................................60 4.7.3 - Ámbito de Dominio Publico...............................................63 4.7.4 - Ámbito Global...................................................................63 4.8 - Funciones y subrutinas – Divide y vencerás............................63 4.9 - Operadores..............................................................................74 4.9.1 - “ ^ ” Exponenciación (aritmético)....................................74 4.9.2 - “ * ” Multiplicación (aritmético)........................................76 4.9.3 - “ / ” División (aritmético)..................................................77 4.9.4 - “ \ ” División entera (aritmético).......................................78 4.9.5 - “Mod” Resto de una división entera (aritmético)..............79 4.9.6 - “ + ” Suma (aritmético)....................................................80 4.9.7 - “ - ” Resta (aritmético)......................................................81 4.9.8 - Operadores de relación.....................................................82 4.9.9 - Not – Negación (lógico).....................................................82 4.9.10 - And – Y (lógico)...............................................................83 4.9.11 - Or – O (lógico).................................................................84 4.9.12 - Xor – O exclusiva (lógico)................................................85 4.9.13 - Eqv – Equivalencia (opuesto a Xor) (lógico)....................86 4.9.14 - Imp – Implicación (lógico)...............................................86 4 4.9.15 - Precedencia de operadores............................................87 4.10 - Control de errores..................................................................89 4.11 - Validación de datos................................................................97 4.12 - El IDE – Mucho más que un editor........................................103 5 - Trabajando con OpenOffice.org...............................................116 5.1 - Mis macros – un archivo especial...........................................117 5.2 - Asignando macros.................................................................119 5.3 - Creando nuestro primer “servicio” (objeto)...........................125 5.3.1 - Propiedades especiales de depuración...........................132 5.4 - Trabajando con documentos..................................................135 5.4.1 - Creando nuevos documentos.........................................135 5.4.2 - Rutas de archivos y directorios.......................................137 5.4.3 - Abriendo, guardando y cerrando documentos................138 5.4.4 - Exportando a PDF...........................................................146 5.4.5 - Tareas comunes en documentos....................................147 6 - Trabajando con hojas de calculo – Calc...................................150 6.1 - Trabajando con hojas.............................................................150 6.1.1 - Insertando hojas.............................................................155 6.1.2 - Borrando hojas................................................................157 6.1.3 - Moviendo hojas...............................................................158 6.1.4 - Copiando hojas...............................................................161 6.1.5 - Renombrando hojas........................................................162 6.1.6 - Ocultando y mostrando hojas.........................................164 6.1.7 - Protección y desprotección de hojas...............................165 6.2 - Referencia a rangos...............................................................166 6.2.1 - Referencia a celdas individuales.....................................166 6.2.2 - Referencia a un rango de celdas....................................168 6.2.3 - Referencia a varios rangos de celdas.............................170 6.2.4 - Referencia a filas y columnas.........................................172 6.2.5 - Referencia a la selección actual.....................................176 6.2.6 - Obteniendo información de rangos.................................178 6.2.7 - Trabajando con Cursores................................................181 6.2.8 - Selecciones especiales...................................................188 6.3 - Manipulando rangos..............................................................197 Aprendiendo OOo Basic 5 6.3.1 - Moviendo rangos............................................................197 6.3.2 - Insertando rangos...........................................................201 6.3.3 - Eliminando rangos..........................................................203 6.3.4 - Copiando rangos.............................................................205 6.4 - Manipulando datos.................................................................209 6.4.1 - Obteniendo datos ..........................................................209 6.4.2 - Introduciendo datos........................................................214 6.4.3 - Borrando datos...............................................................217 6.4.4 - Llenando series de datos................................................219 6.4.5 - Buscar y reemplazar.......................................................222 6.4.6 - Trabajando con notas.....................................................229 6.5 - Dando formato.......................................................................233 6.5.1 - Formato de celdas..........................................................233 6.5.2 - Formato de filas y columnas...........................................243 6.5.3 - Estilos y autoformato......................................................246 6.5.4 - Formato de página..........................................................254 6.5.5 - Formato condicional.......................................................272 6.6 - Imprimiendo..........................................................................277 6.7 - Rangos de datos....................................................................285 6.7.1 - Definiendo rangos...........................................................286 6.7.2 - Ordenar datos.................................................................288 6.7.3 - Filtrar datos....................................................................292 6.7.4 - Subtotales.......................................................................305 6.7.5 - Validando datos..............................................................308 6.7.6 - Agrupando datos............................................................316 6.8 - Bases de datos......................................................................323 6.8.1 - Importando datos...........................................................326 6.8.2 - Insertando nuevos datos................................................338 6.8.3 - Actualizando datos.........................................................343 6.8.4 - Borrando datos...............................................................345 6.9 - Graficando datos....................................................................346 6.10 - Trabajando con elementos gráficos.....................................371 6.10.1 - Trabajando con imágenes.............................................371 6.10.2 - Trabajando con autoformas..........................................383 6.10.2.1 - Principales propiedades de línea.................................385 6.10.2.2 - Principales propiedades de relleno.............................388 6 6.10.2.3 - Principales propiedades de sombra............................394 6.10.2.4 - Otras propiedades de las autoformas.........................395 6.10.2.5 - Agrupando y desagrupando formas............................397 6.10.2.6 - Trabajando con FontWork...........................................399 6.10.2.7 - Propiedades particulares de algunas formas..............401 6.11 - Funciones personalizadas....................................................405 6.12 - Configuración global de Calc...............................................411 7 - Trabajando con formularios.....................................................418 7.1 - Formularios (Forms)...............................................................418 7.2 - Etiquetas (Label)....................................................................422 7.3 - Cuadros de texto (TextBox)...................................................424 7.4 - Casilla de verificación (CheckBox).........................................429 7.5 - Campo formateado (FormattedField).....................................431 7.6 - Botón de comando (CommandButton)...................................432 7.7 - Botón de opción (OptionButton)............................................433 7.8 - Cuadro de lista (ListBox)........................................................436 7.9 - Cuadro combinado (ComboBox)............................................443 7.10 - Botón de selección (SpinButton)..........................................445 7.11 - Barra de desplazamiento (ScrollBar)...................................446 7.12 - Otros controles....................................................................447 7.12.1 - Botón gráfico (ImageButton)........................................448 7.12.2 - Control de imagen (ImageControl)................................449 7.12.3 - Selección de archivo (FileSelection).............................449 7.12.4 - Campo de fecha (DateField).........................................451 7.12.5 - Campo de hora (TimeField)..........................................452 7.12.6 - Campo numérico (NumericField)..................................454 7.12.7 - Campo moneda (CurrencyField)...................................455 7.12.8 - Campo enmascarado (PatternField).............................456 7.12.9 - Cuadro de grupo (GroupBox)........................................458 7.12.10 - Control de tablas (TableControl).................................458 7.12.11 - Barra de navegación...................................................459 8 - Trabajando con cuadros de dialogo.........................................461 Aprendiendo OOo Basic 7 9 - Trabajando con eventos..........................................................462 - Hemos llegado a un tema central en la programación de OOo, central por que una gran parte de la programación en OOo, tiene que responder a la pregunta ¿cuando?, ¿cuando queremos que se ejecute una macro?, ......................................................................462 10 - Apéndices..............................................................................463 10.1 - Seguridad en macros...........................................................463 10.2 - Errores más comunes en tiempo de diseño.........................465 10.3 - Instalando SDK.....................................................................476 10.4 - Mostrar información de un objeto en un archivo de Calc.....478 10.5 - Formulas de Calc español-ingles..........................................479 10.6 - Listar fuentes en un archivo de Calc....................................486 10.7 - Listar formatos en un archivo de Calc.................................488 11 - Bibliografía............................................................................490 12 - Índice Alfabético....................................................................491 8 1 Introducción 1 Introducción "Quien recibe una idea de mí, recibe instrucción sin disminuir la mía; igual que quien enciende su vela con la mía, recibe luz sin que yo quede a oscuras" Thomas Jefferson ¿Así que quieres aprender a programar en OOo Basic? Bien, pues yo también, y ese es un buen interés común y buen comienzo. No se si llegaste al lugar indicado, ya me lo contaras. Sabe de antemano que soy un programador autodidacta que reconoce que tiene vicios de los cuales tal vez no me doy cuenta, espero y deseo, que algún buen samaritano que se encuentre con estas notas me ayude a identificarlos. Estos apuntes no tienen otro propósito que compartir mi experiencia al ir experimentando con este maravilloso programa llamado OpenOffice.org y por supuesto, con su lenguaje de macros OOo Basic, una experiencia sumamente placentera. Me decidí a aventurarme a escribir, por la falta de documentación en español para programar con OOo Basic, a base de paciencia y disciplina he ido profundizado en el dominio del lenguaje, creo que puedo ayudarte a que tu curva de aprendizaje no sea tan larga como la mía, si se cumple este segundo y sencillo propósito, el tiempo y esfuerzo invertido, bien habrán valido la pena, así que, como dicen en mi pueblo -sobre advertencia no hay engaño-, adelante, empecemos... La versión de OpenOffice.org que utilizo para escribir estas notas y mostrarte los ejemplos de programación, normalmente es la ultima estable (3.1 en este momento) descargada directamente desde http://es.openoffice.org, esto es por que algunas distribuciones GNU/Linux, compilan sus propias versiones, casi todas “deberían” de trabajar de forma satisfactoria, pero te recomiendo bajar e instalar la oficial para que nos entendamos mejor. Daré por sentado que esta versión es también con la que trabajas, no te garantizo que los ejemplos mostrados aquí funcionen con otras versiones, de hecho no te garantizo que funcionen con ninguna, ojo, no me malinterpretes, es tan alta la cantidad de equipos, sistemas y configuraciones diferentes, que es cuestión software es difícil garantizar algo y si lo dudas, leete alguna de las muchas licencias de software que hay en el mercado, incluyendo por supuesto, las de software libre. Lo que si te puedo asegurar, es que cada uno de los ejemplos que te muestro los he probado más de una vez antes de darlos por buenos, así que en general espero no tengas problemas con ellos. También, es importante que sepas, que trabajo sobre GNU/Linux en varias distribuciones (por ahora) ArchLinux (http://archlinux-es.org), aunque continuamente y más seguido de lo que te imaginas cambio de distribución, pues aun no puedo abandonar esa manía de probar y experimentar (y a veces suicidarte), tanto las nuevas distribuciones como las nuevas versiones de las ya existentes, por lo que las interfaces podrían variar un poco con respecto al sistema operativo (S.O.) que usas, por ejemplo Mac/OS o Windows u otro, aunque espero que esto no sea un problema pues en si lo único que cambia es la decoración de las ventanas, lo demás, “debería” ser igual en la mayoría de los casos, no obstante no esta de más que al enviar una consulta especifiques la versión de OOo que usas y el S.O. donde trabajas, aunque claro, como no habría de recomendartelo, que esperas para probar alguna de las decenas de distribuciones GNU/Linux existentes, seguro que alguna se adapta a tu gusto y forma de trabajar, por lo menos, no dejes de intentarlo. Este documento esta en constante crecimiento, puedes verificar la ultima versión en: www.universolibre.org, como eres libre de distribuirlo, si te parece que lo merece, te invito a que hables de el y lo difundas, y si no te gusta, pues no seas chismoso. Aprendiendo OOo Basic 9 Para comentarios, notificación de errores, sugerencias, colaboraciones y dudas puedes usar las siguientes alternativas:  Presionar la tecla F1 ayuda mucho, antes de escribir para dudas, asegúrate que: • No esta resuelta en estas notas • No esta resuelta en la ayuda • No se ha comentado en las listas de correo • ¿Ya realizaste una consulta en tu buscador favorito? • Y lo más importante, que hayas tratado de resolverlo por ti mismo  De preferencia, plantea tus dudas en las listas y no a mi correo, estoy en la mejor disposición de ayudarte, pero recuerda que tu duda, tal vez otros la tengan, y si se publica en alguna lista o foro, la posible respuesta también le podrá servir a mas de uno, si aun así, deseas escribirme, procura ser lo mas claro posible en tu exposición y aunque procuro contestar siempre, no te garantizo una respuesta inmediata pues a parte de escribir estas notas, tengo otras varias actividades que tal vez no sean de tu interés, pero que consumen un poco de mi tiempo, agradezco tu comprensión al respecto.  Inscribete a cualquiera de las siguientes listas de correo, de preferencia a las dos, pues en las dos participo constantemente. Para enviar mensajes [email protected] [email protected] Para subscribirse [email protected] http://www.egrupos.net/grupo/ooobasic_es/alta Procuro participar en el foro oficial de macros: Foro de Macros en Español  Estas notas son posibles gracias a la generosidad de la gran comunidad OpenOffice.org en todo el mundo y por supuesto a la comunidad mundial del software libre, es decir, a las personas que “todos los días” desarrollan, usan y difunden el software libre. Dedico este trabajo a las personas que me aman sin su amor, no seria lo que soy... al OOo Basic. el orden y la secuencia en que queremos que lo haga. las cuales. tal vez pienses que no me gusta trabajar y estarás en lo correcto. esas tareas complejas. en estos apuntes. veras que no es tan complicado y si.org. cuando descubrí lo que se podía hacer con los lenguajes de programación. por lo cual. las llamaremos MACROS. repetitivas y tediosas (también las divertidas). a esta grabadora todavía le falta madurar un poco. a mi criterio. esas tareas complejas. crearemos nuestras macros desde cero. Las instrucciones que usamos para decirle al programa que hacer. Lo primero que tienes que aprender (y recordar) es que las macros se guardan en módulos. están contenidas dentro de documentos.org). cuando. hecho en Draw. con lo cual tendremos el siguiente diagrama. por ello. los lenguajes de programación nos permiten hacer que la computadora haga por nosotros. me refiero claro esta. por cierto. estos a su vez se guardan y organizan en bibliotecas. repetitivas y tediosas con uno de sus varios lenguajes con los que se puede programar en el.10 2 Conceptos iniciales 2 Conceptos iniciales Como soy una persona floja. . comprendí que esto es lo que necesitaba (y lo que me gustaba). estas macros podemos hacerlas de forma "semiautomática" con la Grabadora de macros (por ahora solo presente en Writer y Calc) o escribirlas nosotros desde cero (podemos crearlas desde todas las aplicaciones de OpenOffice. como. muy divertido. trataremos de aprender como hacer en OpenOffice. este seleccionado el . pero no puedes eliminarla.Aprendiendo OOo Basic 11 Todos los documentos. a esta biblioteca le puedes agregar y eliminar módulos. En la siguiente imagen puedes ver un documento (1) con una biblioteca (2). para nuestros fines usaremos el nombre "Ejemplos de macros. Te mostrara el siguiente cuadro de dialogo. un modulo (3) y dos macros (4).ods".. además de macros. mas adelante veremos y aprenderemos que los módulos también. tal como esta y el cual nos servirá para guardar las macros que vayamos creando: Abre Calc (puedes usar cualquier otra aplicación de OpenOffice.org Basic. Ve al menú Herramientas | Macros | Organizar macros | OpenOffice. y los documentos también pueden contener "diálogos". asegurate de que dentro del cuadro de lista desplegable Ubicación. presiona el botón de comando Administrar Al mostrarte el siguiente cuadro de dialogo. pueden contener "funciones". crearemos el archivo que te muestro en la imagen anterior.org) y guarda el documento nuevo en el lugar y con el nombre que consideres. da un clic en la ficha Bibliotecas. Empecemos con lo divertido.. tienen una biblioteca especial predeterminada llamada Standard. Después de dar clic en Aceptar. presiona el botón de comando Nuevo. el documento de Calc. Da un clic en el botón de comando Cerrar para regresar al anterior cuadro de dialogo. la cual llamaremos miBiblioteca. . si no lo vez. tal ves tengas que dar clic en el botón expandir representado por un signo de suma (+) a la izquierda del nombre del documento. Ejemplos de macros.ods Inmediatamente después. notaras que la nueva biblioteca se agrego a la lista. ahora. regresa a la ficha Módulos y observa que automáticamente a la nueva biblioteca se le anexo un modulo nuevo llamado Module1.12 2 Conceptos iniciales documento al que le anexaremos la nueva biblioteca. en nuestro caso. solicitando el nombre de la nueva biblioteca. tras lo cual te mostrara un cuadro de dialogo. pero se pueden cambiar cuando quieras. lo . lo que veas tiene que ser igual o muy parecido a la siguiente ilustración. Al dar clic en Editar. del mismo modo que al agregar una nueva biblioteca esta aparece con un nuevo modulo llamado de forma predeterminada Module1. para lo cual. la cual será el centro de trabajo de "todo" lo que hagamos en OOo Basic. Estos nombres vienen predeterminados. cuando agregamos un nuevo modulo. pues ella nos permitirá escribir todas las macros que nos permita nuestro tiempo e imaginación. observa que también en la lista de macros. recibe el nombre de Entorno de Desarrollo Integrado (IDE por sus siglas en ingles) y es muy “importante que te familiarices con el” lo mas posible. da un clic en el botón de comando Editar. aparece ya una con el nombre de Main (elipse roja). te abrirá una nueva ventana.Aprendiendo OOo Basic 13 Ahora. una aplicación muy especial. este crea de forma predeterminada. como lo haremos a continuación. esta nueva ventana de hecho es una nueva aplicación. esta aplicación. una macro nueva y vacía con el nombre de Main. despliega los elementos de nuestro documento. esto lo logras con el icono del símbolo mas (+) que esta a la izquierda del nombre del documento. un nombre que te resultara familiar si alguna vez programaste en C. da un doble clic a la palabra Main. afortunadamente se da como consecuencia intrínseca de programar en OOo Basic. para nuestro ejercicio le llamaremos miModulo. Main (3) Como siguiente paso. ya sea con el nombre propuesto o con el que consideres correcto. hay mas de una manera de hacer la misma acción. veremos las restricciones al respecto). Observa como nos muestra el nombre del documento en donde nos encontramos. en caso de que hubiese más. y comprueba que lo que tienes es bastante similar a la imagen siguiente. salvo un pequeño cambio (que ya notaste) quedo igual al que propusimos al inicio de estas notas. da un clic en ella y el cursor de escritura (el que parpadea) se posicionara al final del nombre actual del modulo. al terminar presiona la tecla {Enter} para aceptar el cambio o simplemente activa el área de escritura de código (3) con un clic. cambiemos el nombre del modulo. o da un clic en el conocido icono de Guardar. ahora. para continuar con nuestro ejercicio escribiremos Mi_Primer_Macro. o presiona la combinación de teclas CRTL+G. por ultimo. para ello. pero un editor con muchas características especiales que iremos conociendo poco a poco. para terminar nuestro primer ejercicio. usa. como en la mayor parte de los programas de computo. puedes cambiarlo por el que quieras. da un clic con el botón secundario de tu ratón (normalmente el botón secundario es el derecho) sobre la ficha que muestra el nombre actual (2). más adelante. nos muestra. esta área en realidad es un editor de textos. observa la macro mencionada en el inciso anterior. . ve al menú Herramientas | Macros | Organizar macros | OpenOffice... En esta misma ventana. que. ve al menú Archivo | Guardar. Por ultimo. te mostrara un menú contextual entre cuyas opciones veras Cambiar nombre. puedes reemplazar este nombre por el que quieras (bueno.14 2 Conceptos iniciales cual. así como el nombre de la biblioteca en la que estamos trabajando (1). casi por el que quieras.org Basic. nos los mostraría en fichas contiguas a este. con lo cual lograremos seleccionar la palabra completa. la que mejor te convenga o guste y guarda tu documento. el nombre del modulo activo actualmente (2). también puedes enviarme tus problemas existenciales. así que tu tarea es: •Practicar mucho •Agregar y eliminar bibliotecas a diferentes documentos de OpenOffice. impresiones. eso es todo. Para finalizar este capitulo y esta noche (ya me canse). una macro no puede ir dentro de otra. espero que si. No.. como consejo. . •Practicar mucho •Envíame tus comentarios. trata de investigar para que sirven o cual es su función. •Practicar mucho •Agregar y eliminar módulos a diferentes bibliotecas.org.Aprendiendo OOo Basic 15 ¿Te gusto el curso?. que soy un profesor que deja mucha tarea. •!Ah¡ y practica mucho. como un servicio agregado. tienen algunos controles mas. •Practicar mucho •Observar como esta estructurada nuestra primer macro y tratar de hacer mas.001% de lo que pretendo. •Practicar mucho •Los cuadro de dialogo vistos hasta ahora. con esto cubrimos el 0. no es cierto. tan tan y hasta pronto. conste que solo lo pretendo. siento mucho decirte y confesarte. quejas y dudas.. que ya lo dominas. es un documento de Calc nombrado Ejemplos de macros.org que contiene macros. que creo. daré por hecho. presiona el botón de comando Editar. por lo cual.org Basic.. tienes que cambiar el nivel de seguridad como te muestro en 7.16 3 Mi primer macro 3 Mi primer macro Ahora que ya sabes donde crearemos nuestras macros. escribir código. Con la acción anterior. inmediatamente después de seleccionar la macro que lleva por nombre Mi_Primer_Macro. si has seguido estas notas. De forma predeterminada.. te abrirá el Entorno de desarrollo (de aquí en adelante IDE) y este es el punto interesante y el más divertido. decirle al programa que . Por supuesto. Esta serie de acciones. cuando abres un archivo de OpenOffice. te mostrara el siguiente aviso de seguridad. es la forma que usaremos para acceder a la edición de cualquier macro vista en estas notas. nuestro archivo. Abre tu archivo de trabajo. si este es tu caso.ods. Ve al menú Herramientas | Macros | Organizar macros | OpenOffice. es bastante claro.. tu biblioteca y tu modulo.1 Seguridad en macros.y navega hasta tu documento. empecemos con ellas. de aquí en adelante. es decir. Puede ser que no te muestre este mensaje y te abra el archivo directamente con las macros deshabilitadas. para poder trabajar correctamente tienes que habilitar las macros. más adelante aprenderemos a evitar este mensaje para los archivos que sabemos son seguros.. muestra un "mensaje" en un cuadro de dialogo. es decir. en conjunto con el IDE. que el lenguaje. presiona el botón de ejecución (circulo rojo en la imagen anterior) o presiona la tecla {F5} y listo.Aprendiendo OOo Basic 17 haga lo que queramos. empezaremos con un clásico.. solo te falta el saber el "porque". reconoce de modo especial y "realiza". ¡Felicidades!. para no salirnos de los "santos cánones" de la programación. agrega la siguiente linea a la macro. asegurate de escribirla o copiarla tal cual: MsgBox "¡¡Hola Mundo!!" De modo que quede de la siguiente manera: Ahora. no eres todavía un programador completo. para "ejecutar" la macro. pues ya sabes el "como". cuando queramos y como queramos.. "ejecuta". como habrás notado (por que de aquí en adelante tendrás que ser muy observador). solo OOo Basic la puede usar) MsgBox... el hombre practico sabe el "cómo". ya eres todo un programador. una tarea especifica. lo ideal es saber "como" y "por qué". pero espera. ¿que mensaje?. el mensaje que muestra es . es decir. por que “solo” OOo Basic puede hacer uso de ella. recuerda esto bien. "hace". en el caso de esta "palabra clave o reservada" (llamada así. para lograr lo que decía mi entrañable profesor de topografía: El hombre teórico sabe "por qué". es una "instrucción" de OOo Basic. analicemos la linea que acabamos de agregarle a nuestra macro: MsgBox "¡¡Hola Mundo!!" La primer palabra. que realice su trabajo. Y para lograrlo. tendrás que ver el cuadro de mensaje que te mostré lineas arriba. una palabra especial. Para entender el "¿por qué?". pero como nosotros somo “amateur” haremos caso omiso de ese comentario. y que. como te recomiendo que sea. así como todos los programadores con los que compartas tu código. así: REM Muestra un mensaje en un cuadro de dialogo MsgBox "¡¡Hola Mundo!!" Los comentarios. podemos agregarlos..18 3 Mi primer macro el que "nosotros" le indicamos delante de ella. pues como dijo alguna vez Ling Yu Tan -me gusta la gente amateur-. Ahora veamos la linea donde inicia nuestra macro: Sub Mi_Primer_Macro ... no tendrías que haber modificado: REM ***** BASIC ***** La primer palabra . sobre todo. asume esta recomendación.. tu memoria te lo agradecerá. ¿y con fechas o algun otro valor?. comentar las lineas de código es una practica sumamente útil. "casi". es decir. es decirle al programa (nuestra macro). el lenguaje se lo saltara olímpicamente sin hacerle caso. ¿sucederá lo mismo con números?. -siempre comenta tus lineas de código-. de dialogo Reitero. como una regla. y sencillamente lo que "hace". y como es una "cadena" de texto. que todo lo haya después de esta palabra. es un comentario. procura comentar la mayor parte de tu código. cuando las macros van creciendo de tamaño y complejidad. también es una palabra clave de OOo Basic.. de modo que te quede. MsgBox 1234567890 MsgBox 15/01/1974 MsgBox 1dfgdfh245 Realiza todos los experimentos que quieras y me cuentas que sucede. Observa la primer linea de la macro que acabas de hacer. lo tenemos que hacer entre comillas y separada de la instrucción por un espacio. Así que ve al código de nuestra macro y comenta la linea que le agregaste. si has seguido al pie de la letra. así que. si decides que sea software libre. por ahí leí en algún foro que un código bien escrito y profesional no necesitaba comentarios.dialogo MsgBox "¡¡Hola Mundo!!" 'Muestra un mensaje. al final de la linea de código: MsgBox "¡¡Hola Mundo!!" REM Muestra un mensaje.. también puedes establecerlos con una comilla simple (') 'Muestra un mensaje en un cuadro de dialogo MsgBox "¡¡Hola Mundo!!" Ademas. pero recuerdalo para más adelante. Inform. aquí. si lo haces.Aprendiendo OOo Basic 19 Como se que eres observador. quiere decir: sintaxis. o sea. le asignamos un nombre. 2. •NO •NO puede iniciar con un número. para identificarla. de συντάσσειν. efectivamente. la cual nos sirve para definir una "subrutina". f. (Del lat. dentro del modulo en que se declara. la palabra importante es. no analizaremos. si tratas de hacer lo anterior. Parte de la gramática que enseña a coordinar y unir las palabras para formar las oraciones y expresar conceptos. . no puede haber dos que se llamen igual. syntaxis. te mostrara el siguiente mensaje de error: •NO Observa la primer linea de los mensajes de las dos imágenes anteriores. y este del gr. si nos atenemos a lo que dice la Doña Real Academia Española. 1. es una palabra clave de OOo Basic. ya habrás deducido que la primer palabra. Conjunto de reglas que definen las secuencias correctas de los elementos de un lenguaje de programación. te mostrara el siguiente mensaje de error: debe repetirse el nombre de la macro. si lo hace. en nuestro caso le pusimos: Mi_Primer_Macro. σύνταξις. al ejecutar. Gram. que. que por ahora. te mostrara un mensaje. coordinar). como también se les conoce a las macros. si. nombre que: puede llevar espacios. f. "sintaxis". las dos son iguales -Error de sintaxis de BASIC-. "Ejemplo " & _ "de linea larga" End Sub Y ahora si. las dos son palabras claves del lenguaje y también. son bastante explicitas. lo confieso. esto es muy útil cuando se esta programando. el IDE nos informa muchas veces cuando implementamos mal. 0 . pero recuerda que sigue siendo la misma sentencia: Sub LineasLargas() MsgBox "Estas es una linea larga de codigo. la que nos interesa es la numero dos. si las separas con dos puntos. "subrutina" o "macro". para terminar este capitulo. como en: Sub VariasSentencias() MsgBox "Estas es una sentencia" : MsgBox "Esta es otra sentencia" End Sub En sentencias largas. analicemos la ultima y muy sencilla linea de nuestra macro: End Sub Si. no son tantas. este conjunto de reglas. cuando comúnmente hacemos mal uso de la “sintaxis” de Ooo Basic. las cuales. puedes tener varias sentencias en una sola línea. Para finalizar este capitulo. observa que el IDE nos muestra diferentes colores en las palabras. cada línea de código y. como en el siguiente ejemplo. se puede dividir " & _ "usando el guion bajo. es decir. nos indican el final de nuestro "programa".20 3 Mi primer macro Real Academia Española © Todos los derechos reservados De estas definiciones. Entonces. trata de recordarla -Conjunto de reglas que definen las secuencias correctas de los elementos de un lenguaje de programación-. que es el guion bajo _. como en este ejemplo". te confesaré. como las llamaremos de aquí en adelante. como una herencia del VBA (aunque también pesa el hecho de tener una macro ya hecha que convierte estos colores en formato HTML). pero por puro gusto y también. uso la siguiente combinación de colores: Azul para las palabras claves Verde para los comentarios • Rojo para los números Rojo obscuro para las cadenas de texto • Negro para todo lo demás • • • Aquí un ejemplo de como se mostraría el código con esta combinación de colores: Option Explicit Rem Pruebas de comentario Sub Pruebas(ByVal Pal As String) ' comentario Dim intNum As Integer intNum = 10 + 10 . el lenguaje lo reconocerá como una sentencia de OOo Basic. hasta donde se encuentre un salto de línea. puedes usar el carácter de continuación de línea. pues en las siguientes páginas. creo. ni tan complejas y como seguro habrás notado. trataremos de aprender e implementar este conjunto de reglas. es indistinto el uso de MAYUSCULAS o minúsculas. tienes que recordar que para OOo Basic. para terminar este capitulo. en OpenOffice. decidirás si es así como te gusta. "debería" de funcionar igual con: •minúsculas sub mi_primer_macro msgbox "¡¡Hola Mundo!!" end sub •MAYUSCULAS SUB MI_PRIMER_MACRO MSGBOX "¡¡Hola Mundo!!" END SUB •Combinación de ambas.Aprendiendo OOo Basic 21 MsgBox "Prueba" End Sub 'comentario Para configurar estos u otros colores que sean de tu agrado. es decir. Esta es la de a de veras. Sub Mi_Primer_Macro MsgBox "¡¡Hola Mundo!!" End Sub . gusten o simplemente te den la gana que para eso es la libertad. si no...org escoge Representación. como nuestro original. para que quede de la siguiente manera Recuerda que esto es solo una recomendación. con el uso y la practica. nuestra macro. o una combinación de ambas. que es la forma mas común y la forma que yo usare a todo lo largo de estas notas. no dudes ni un momento en establecer los colores que más te agraden. ahora si. tu. ve al menú Herramientas | Opciones. no hace una autocorrección de las palabras. Envíame tus comentarios. presionar {F1} "ayuda" mucho. así que: • • • • • Practica mucho. aportes y dudas. a ser mejor observador. no te iguala las palabras a mayúsculas o minúsculas (todavía). Investiga mas acerca de la instrucción MsgBox. pero esto. Practica mucho.22 3 Mi primer macro El IDE. . te ayuda mucho a mejorar tu mecanografía. Practica mucho. a OOo Basic se le denomina un "lenguaje interpretado".. ¿ya?. ¿verdad?. aquí esta: Sub Mi_Segunda_Macro 'Algo más interesante MsgBox "¡Hola Nena!" End Sub Y ya encarrilados. por que cada nueva instrucción que aprendamos. es correcto. "solo". Claro. ya no use guiones para separar las palabras. por ello.Aprendiendo OOo Basic 23 4 El lenguaje OOo Basic OOo Basic. esta es más que suficiente. solo se ejecutara la que se llama Mi_Primer_Macro. respuesta. esto es importante que lo domines bien. daré por entendido que así es. esta es la forma en que de aquí en adelante. así que para que no haya excusas. presiona {F5} y observa muy bien que sucede. El IDE. no entraremos aquí en disquisiciones filosóficas de su historia o diferencia con otros "sabores" Basic. para nuestros fines. ser buen observador es una excelente virtud en un programador): En la tercer macro. si tienes como primer macro alguna otra.. cada vez que "ejecutamos" la macro. Supongo que has ido probando cada macro. me limitare a mostrarte el uso de su sintaxis lo mas claramente que me sea posible. El IDE. la tienes que probar "dentro" de una macro. se encarga de revisar la correcta "sintaxis" (recordando que sintaxis es un "conjunto de reglas") de cada línea que nosotros escribamos. su facilidad y sencillez. forma parte de la familia de lenguajes Basic. procurando que los ejemplos sean tu principal fuente de consulta. comparte con ellos la mayor parte de su sintaxis. creo que es bastante obvio ¿por que?. por que revisa la sintaxis. solamente te mostrara: . Y cada vez que trates de ejecutar. ejecuta la primer macro que este en el módulo activo. si no es así. ¿es correcto?. así que si tienes las tres macros que hemos hecho. escribiré todo mi código. agrega una tercer macro: Sub MiTercerMacro 'Lo que quieras MsgBox "OOo Basic es fácil y divertido" End Sub Observaciones (¿recuerdas que íbamos a ser observadores?. como nombrarla y como ejecutarla. así que esta bien escrito MiTercerMacro. por ahora. ahora es el momento. repacemos una vez mas esto. si. uno de los requisitos es que el nombre "no" lleve espacios. La estructura básica para una macro es: Sub Nombre_de_la_Macro REM Aquí van todas las instrucciones que queramos End Sub Por supuesto existen más variantes. en el nombre. es muy sencilla la explicación. Ahora ya conoces donde inicia y donde termina una macro. vamos a escribir nuestra segunda macro. esta será la que se ejecute. en la que usamos la técnica denominada de "camello". ya la habrás deducido. pues que de aquí en adelante. escoges la macro que desees y presiona el botón Ejecutar. ahora si vemos lo que queremos ver: . ve a la barra de herramientas y da un clic en el icono Seleccionar macro. esto me parece bien.24 4 El lenguaje OOo Basic En algunas distribuciones Linux. pero todavía no esta implementado en la distribución oficial. Como diría un buen amigo -ansina si-. he notado que la macro que se ejecuta al presionar F5. es la macro donde este el cursor de escritura en ese momento. Para ejecutar la macro que quieras. Del cuadro de dialogo que te muestra. "llamar" a las otras. así quedarían nuestras macros: REM ***** BASIC ***** Sub Pruebas Mi_Primer_Macro End Sub Sub Mi_Primer_Macro 'Todo un clásico MsgBox "¡Hola Mundo!" End Sub Sub Mi_Segunda_Macro 'Algo mas interesante MsgBox "¡Hola Nena!" End Sub Sub MiTercerMacro 'Lo que quieras MsgBox "OOo Basic es fácil y divertido" End Sub Y esto. Sub Pruebas Mi_Primer_Macro . y. desde esta. es que puedes "llamar" a más de una macro.. es algo que tendrás que dominar muy bien.Aprendiendo OOo Basic 25 Y la tercera también: Otra técnica para ejecutar la macro que sea. Lo interesante. desde otra. Sub Pruebas Mi_Primer_Macro End Sub Para llamar a la segunda macro seria así: Sub Pruebas Mi_Segunda_Macro End Sub Tu haces la tercera. observa como es tan sencillo como escribir el nombre correcto de la macro que deseamos "llamar". desde otra. por ejemplo.. "llamar" a una macro. es crear una primer macro que se llame por ejemplo: Pruebas. cumple el flujo anterior. es usando la instrucción Call. tal vez podríamos obtener además del número de letras o palabras: •El día de la semana en que nació •Cuantos días lleva vivo •Cuantos años tiene •Cuantas vocales tiene el nombre •¿Se te ocurren otra “información” que puedas obtener? Observa como con solo dos datos. de la siguiente manera. podemos obtener mucha “información”. veras que en mayor o menor medida. más adelante. de uno que no lo es. manipulan eficientemente los datos para darnos “información” y entre el flujo de los . los buenos programas. cuando aprendamos más opciones de como declarar y usar macros. pero recuerda que solo es de prueba.26 Mi_Segunda_Macro End Sub 4 El lenguaje OOo Basic Otra forma de "llamar" a otras macros. veamos un sencillo ejemplo: •Solicitamos que el usuario capture su nombre completo (Entrada) •Contamos el número de letras (o palabras) que contiene (Proceso) •Mostramos el resultado obtenido (Visualización) Ahora. el resultado es el mismo: Sub Pruebas Call Mi_Primer_Macro Call Mi_Segunda_Macro End Sub Se que tendríamos que escribir el nombre de la macro a llamar para probar la que deseamos cada vez que la necesitamos. Descartes -todo lo complejo. pero esa división tu mismo la iras notando y desglosando conforme profundices en este o cualquier otro lenguaje. esta sencilla ecuación hace la diferencia entre un programa eficiente. recuerda el siguiente sencillo diagrama: Si analizas cada programa de computo que usas. puede dividirse en partes simples- 4. ademas. cada uno de estos tres pasos los podemos dividir en muchos más. que pasa si ademas del nombre solicitamos que capture su fecha de nacimiento. veras que este ultimo método de pruebas es mejor que el primero y que esto nos sirve como afirmación de lo que decía el Sr.1 Declarando y usando variables Cada vez que programes tus macros. sabe que una función. pero lo más común es llamarlo “variable”. No pienses que estoy desvariando. con lo cual tenemos esta primer sencilla ecuación. algunos textos también la nombran como “marcador”. Variable = Dato Veamos un ejemplo de esto. Entonces. normalmente solo provee de “velocidad” y tu. existen dos entes que son determinantes para la calidad de la información obtenida. ya sea traerlos de algún lado o solicitarlos al usuario. el programador.Aprendiendo OOo Basic 27 datos a la “información”. es la que permite tomar las decisiones. a esta área que estamos nombrando. no en nuestra memoria. aunque sea de forma temporal. le llamaremos “variable”. resumiendo. en la llamada memoria RAM. al servicio del proceso de convertir los datos en “información”. uno es la computadora. veamos cual es. es en memoria. veamos algunos ejemplos de nombres de variables: . sino en la de la computadora. tendremos que darle un nombre a una porción de dicha memoria. que como sabes. mostrando el nombre de una novia que tuve: Sub MostrarNombre 'Asignamos un valor a una variable Nombre = "Nicole Kidman" 'Mostramos el valor de la variable MsgBox Nombre End Sub Observa como en la linea: Nombre = "Nicole Kidman" Estamos asignando el “dato” "Nicole Kidman”. es obtener los datos. así que no desesperes si ves que vamos algo lento. nos regresa un valor. lo cual lograremos con la “función” InputBox. al igual que el nombre de las macros. otra vez. retorna un valor. a la “variable” Nombre. pero estos temas iniciales son determinantes para comprender todo lo que venga después. Recuerda que primero hay que saber caminar para después correr. retomando el sencillo ejemplo con el que empezamos este capitulo. para ello. unos mas otros menos. en el caso de nuestra macro. que iremos ampliando según vayamos avanzando en nuestro curso. recuerdalo bien “variable”. vamos a solicitarle al usuario que nos proporcione su nombre. que pone toda su inteligencia. la cual. el primer lugar donde tenemos que aprender a guardar datos. por supuesto. el nombre de las variables. precisamente por que su valor o contenido puede variar durante los procesos que haga nuestra macro. tendremos que poner en algún lugar para poder tenerla disponible y para poder manipularla. ademas de no poder llevar caracteres especiales. los datos que obtengamos los guardamos “temporalmente” en variables. “normalmente”. De acuerdo a los dos diagramas anteriores. el inicio de toda “macro” (o programa). todo este “rollo” lleva un fin. ojo con la palabra “función” ya que es importante. creo que casi cualquier persona que usa computadoras. que. no pueden llevar espacios y no pueden empezar con un número. esto es importante. conforme tus macros se hacen más grandes y complejas. hay una palabra clave para ello. “declaración explícita”. aquí el ejemplo: Sub DeclarandoVariables 'Declaramos cuatro variables Dim Direccion Dim Telefono2 Dim FechaNacimiento Dim Edad 'Mas código End Sub De esta forma. se puede guardar cualquier “tipo” de dato (texto. esta forma de usar variables se conoce como. “declaración implícita”. en el caso de la variable Direccion. le estamos diciendo -oye mi hermano. no es nada recomendable. en vez de usar variables tipo “Variant”. el lenguaje reserva el espacio en memoria para su uso. junto con Dim y el tipo de variable. por eso. en la variable FechaNacimiento una fecha y en la variable Edad un número. esta forma de usar las variables. normalmente guardara un texto. esta segunda forma de usar las variables se denomina. fecha. el hacer uso de las variable de esta forma se vuelve (y no exagero) una verdadera locura. por que al asignarle un valor por primera vez a una variable. nosotros somos los que le indicamos al lenguaje. para ello. se llama Dim y su uso es muy sencillo. simplemente con usar el nombre correcto de una variable. Observa que el nombre de las variables inmediatamente nos da una idea acerca del dato que guardaremos en ella. se usa la palabra clave As. apartame un cachito de memoria que se llame Direccion para que yo la use-. etc) en ella. y efectivamente. veamoslo con un ejemplo: Sub VariablesTipoVariant Dim UnDato UnDato MsgBox UnDato MsgBox UnDato MsgBox End Sub = "Esto es un texto" UnDato = 12345678 UnDato = "15/01/1974" UnDato 'Guardamos un texto 'Guardamos un numero 'Guardamos una fecha La recomendación es que. numero. OOo Basic hace uso de ella. de esta forma. por ejemplo: Sub Dim Dim Dim DeclaracionExplicitaDeVariables Direccion As String 'Variable tipo texto Edad As Integer 'Variable tipo numero entero Fecha As Date 'Variable tipo fecha . es más eficiente y mucho más claro si le dices al lenguaje. a este tipo de variables se le conoce como “variant”. de la forma como están declaradas las variables. que variables son las que usaras para que reserve la memoria necesaria. que variables son las que usaremos.Numero 4. el lenguaje lo hará para nosotros. en contraste. pero (dicen que siempre hay un pero). desde el inicio de tu macro.28 •Direccion •Telefono2 •FechaDeNacimiento •Correo electronico •3Fax •Áéíóú •Calle.1 Declarando y usando variables - Correcto Correcto Correcto Incorrecto (tiene un espacio) Incorrecto (inicia con número) Incorrecto (no se permiten caracteres especiales) Incorrecto (no se permiten comas ni puntos) Como notaste. con la instrucción Dim. le indiquemos explicitamente al lenguaje que tipo de datos guardaremos en una variable. puedes copiarla: Sub DameTuNombre Dim Nombre As String 'Otra de mis novias Nombre = "Miranda Otto" MsgBox Nombres End Sub ¿Que pasa al ejecutarla?.402823 x 10E38 a 1.535 caracteres Enteros entre 0 y 255 Enteros entre -32768 y 32767 Enteros entre -2147483648 y 2147483647 Precisión simple y coma flotante (3.5808 y +922337203685477. la lista completa del tipo de variables que puedes usar en OOo Basic: Tipo Descripción Valores que puede contener String Byte Integer Long Single Double Currency Texto Entero Entero Entero largo Simples Dobles Moneda Hasta 65.401298 x 10E-45). cualquier variable antes de usarla.Aprendiendo OOo Basic 29 Direccion = "Parque San Andres N° 14" Edad = 32 MsgBox Direccion MsgBox Edad End Sub Aquí. esto es por que. debe hacerse como primer linea de cualquier modulo (solo una vez por modulo). Precisión doble y coma flotante (1. de modo que nuestra anterior macro quedara así: Option Explicit Sub DameTuNombre Dim Nombre As String . asegúrate de transcribirla tal cual o mejor aun. existe una instrucción que nos ayuda a ello. esto no es tan evidente a simple vista.5807 Solo puede contener valores True (verdadero) o False (falso) Cualquier valor. tipo de declaración predeterminado Para hacer referencias a objetos Boolean Date Variant Object Lógica Fecha Variante Objeto Veamos este nuevo ejemplo de una macro. es diferente de la variable Nombres y a la variable Nombres no le hemos asignado ningún valor todavía. para minimizar este tipo de errores. Almacena valores entre -922337203685477. no nos muestra nada en el cuadro de mensaje. efectivamente. cuando se use. la variable Nombre. Option Explicit. a pesar de que en este ejemplo es bastante evidente nuestro error (una pequeña “s” de diferencia). esta instrucción. cuando se programa y haces uso de unas cuantas decenas de variables declaradas. que nos obliga a declarar con la instrucción Dim. para el lenguaje.79769313486232 x 10E308 a 4.94065645841247 x 10E-324) Máximo de 15 números antes del signo decimal y cuatro después de el. es decir. otra recomendación que tienes que tomar como regla -siempre usa Option Explicit al programar-. también veíamos que este dato o datos se guardan temporalmente en variables (generalmente). veamos un ejemplo de la función InputBox. La segunda variante que veremos para asignarle un valor a una variable y que servirá como preámbulo para los siguiente capítulos es la siguiente: Variable = Funcion En donde Funcion. empieza con la solicitud de algún dato al usuario (generalmente). mas adelante veremos que otras herramientas implementa el IDE para ayudarnos con la localización de errores y la depuración de nuestras macros. la instrucción básica para ello era: Variable = Dato y como ejemplo mostramos: Sub MostrarNombre 'Asignamos un valor a una variable Nombre = "Nicole Kidman" 'Mostramos el valor de la variable MsgBox Nombre End Sub Lo cual funciona. pero no es muy versátil que digamos.1 Declarando y usando variables 'Otra de mis novias Nombre = "Miranda Otto" MsgBox Nombres End Sub Vuelve a ejecutar esta macro y observa que pasa. El inicio de este tema. así que. nos muestra el siguiente mensaje: Como ves el mensaje es muy claro: Variable no definida. no hemos usado la instrucción Dim para declararla. es cualquier instrucción que nos “retorne” una valor. creo que terminara por cansarnos. que aunque bello. mencionábamos que una macro (o programa). siempre nos mostrara el mismo nombre. así es. Sub MiNombre Dim Nombre As String . usando esta instrucción te volverás un poco menos loco cuando busques ¿por que? no funciona tu macro. observa en la imagen (el subrayado rojo). es decir. además.30 4. que el IDE nos indica con una flecha la línea donde ocurrió el error. no se me olvida dejarte tarea: •Practica mucho mas de la función InputBox. entonces. Ni modo. esto lo logramos con la función Len. •Envíame •Practica mucho. te mostrara lo que hayas escrito: Para cerrar el circulo. nuestra macro completa quedaría así: Sub MiNombre Dim Nombre As String Dim NumeroDeLetras As Integer Nombre = InputBox( "¿Cual es tu nombre?" ) NumeroDeLetras = Len( Nombre ) MsgBox NumeroDeLetras End Sub 'Entrada de datos 'Proceso de datos 'Visualización de resultado Observa como se cumple el flujo del diagrama mostrado al inicio de este capítulo. y comprobar que si funciona el primer diagrama de este capitulo. veamos cuantas letras tiene. “hagamos algo” con el dato.Aprendiendo OOo Basic 31 Nombre = InputBox("¿Cual es tu nombre?") MsgBox Nombre End Sub Al ejecutar. que nos dice cuantos caracteres tiene una cadena. aportes y dudas. •Investiga •Practica mucho tus comentarios. se que es un gran simplificación pero nos es bastante útil para nuestros propósitos. . te tendrá que mostrar el siguiente cuadro de dialogo: Y al escribir tu nombre y dar clic en Aceptar. Usaremos una instrucción que ya conoces. es necesario o requerido. el IDE nos muestra el siguiente error. con este argumento es más que suficiente para que trabaje. por que esta “haciendo” algo. MsgBox Efectivamente. MsgBox. prueba la siguiente línea de código y observa el resultado. por ejemplo. son de un “tipo de dato”). es decir. no puedes crear una macro que se llame MsgBox u Option. recibe el nombre de “parámetro” o “argumento”.32 4. para mostrarte las diferencias entre las instrucciones y las funciones.2 Instrucciones y funciones en OOo Basic 4. Veamos la siguiente linea de código. al igual que las variables. se llaman así por que solo OOo Basic puede hacer uso de ellas?. es crucial para el entendimiento y desarrollo óptimo de los siguientes capítulos. como primer aproximación a una definición útil. nos muestra un mensaje en pantalla. no. la linea del error. por ello. recuerdalo bien. el texto. ¿verdad que lo recuerdas?. en este caso.2 Instrucciones y funciones en OOo Basic ¿Recuerdas que mencionamos que las palabras claves o reservadas de OOo Basic. no trabajara mientras no lo incorporemos a la linea de código. las instrucciones y las funciones. tampoco puedes declarar variables con alguna de estas palabras. MsgBox "Estoy aprendiendo OOo Basic". esta cadena de texto. ¿que?. con lo cual se deduce fácilmente que el argumento Mensaje. que le indicamos entre comillas. Y nos señalara con la flecha que ya conoces. las podemos dividir en dos grandes grupos. pues esta palabra clave tiene la particularidad de poder usarse como una u otra dependiendo de nuestras necesidades. Estas palabras clave. diremos que: Las instrucciones “hacen” algo Las funciones “devuelven” algo La diferencia entre una y otra. pero eso si. 16 . MsgBox "Estoy aprendiendo OOo Basic" Estamos usando MsgBox como una instrucción. de aquí en adelante “cadena de texto”. que es de tipo “cadena de texto” (ojo con esto. ¿que muestra?. recibe el nombre de “argumento”. los argumentos. la linea con la instrucción MsgBox. que. puede llevar más argumentos. ¿necesita algún otro?. ¿Has probado a intentar ejecutar esta instrucción sin ningún argumento?. 16. ¿verdad?. nunca me creas completamente hasta no haberlo comprobado por ti mismo. MsgBox "Estoy aprendiendo OOo Basic". el cual permite personalizar el titulo del cuadro de dialogo. "Icono de exclamación" MsgBox "Estoy aprendiendo OOo Basic". "Icono de pregunta" MsgBox "Estoy aprendiendo OOo Basic". espero que si. Mensaje. "Icono de información" Y observa el resultado. que te muestro aquí: La instrucción MsgBox. todas dicen soffice. por lo cual. si quieres que te muestre un icono con la señal de “stop”. prueba las siguientes lineas de código. que como notas en las cuatro imágenes anteriores. tiene un tercer argumento opcional que se llama Titulo. existen otro dos iconos que puedes mostrar. Sigamos. "Icono de Stop" MsgBox "Estoy aprendiendo OOo Basic". 48. Tipo y Titulo. la sintaxis completa y correcta de esta instrucción es: MsgBox Mensaje As String. para hacerlo. compruébalo. solo de la segunda linea: Creo que todavía mantengo tu confianza. Estos son los tres argumentos que puede usar la instrucción MsgBox. [Tipo As Integer].Aprendiendo OOo Basic 33 Y ahora esta: MsgBox "Estoy aprendiendo OOo Basic". [Titulo As String] . en esta caso. el icono de exclamación (48) y el icono de información (64). para el primer caso un 16 y para el icono de interrogación ponemos un 32. debes de agregarle un segundo argumento que se llama Tipo. es un número entero. 64. 32. el cual. 32 Entonces. y veamos que también podemos establecer los botones de comando que queramos se muestren en el cuadro de dialogo. es muy importante que la variable donde guardemos el valor sea del “mismo tipo” del valor que esperamos nos devuelva la función. 36. Mostrar los botones Sí y No. por lo cual. para empezar. En las funciones. "OOo Basic" Que nos mostrara: Y apuesto a que ya te hiciste la pregunta interesante. los argumentos que lleve la función. Repetir y Ignorar. No y Cancelar. para ello tienes que recordar que: una función devuelve un valor. Mostrar los botones Repetir y Cancelar. "Instrucción MsgBox" Cuando quieras mostrar una combinación de botones e iconos. como función. 2. Integer. van siempre entre paréntesis y. Y una muestra: MsgBox "Estoy aprendiendo OOo Basic".2 Instrucciones y funciones en OOo Basic Lo importante aquí es que aprendas a distinguir la estructura o sintaxis de una instrucción. "OOo Basic" MsgBox "Estoy aprendiendo OOo Basic. guardaremos en una variable. 4 + 32. usaremos MsgBox pero ahora. las dos lineas siguientes son equivalentes: MsgBox "Estoy aprendiendo OOo Basic. ¿quieres continuar?". aquí esta la lista completa de estas opciones: 0 1 2 3 4 5 Mostrar sólo el botón Aceptar. el cual. la respuesta es sencilla. es muy importante. ¿como sabemos que botón es el que presiono el usuario?. pasarle a un argumento un tipo de dato que NO es el que espera. las funciones. y muy importante. ¿quieres continuar?". observa como los argumentos se separan por comas y los argumentos opcionales se encierran entre corchetes. observa que se especifica el tipo de dato que se espera se use en el argumento. simplemente establece el argumento Tipo. Mostrar los botones Sí. al devolver un valor. esto. segundo. puede producir errores o resultados imprevisibles. como una suma de los valores que quieres mostrar. Muestre los botones Cancelar. Regresemos al argumento Tipo. etc). como van asignadas a una .34 4. también es de un tipo especifico (String. Mostrar los botones Aceptar y Cancelar. ademas. por ahora. no olvides de: . ¿como saber cual? y actuar en consecuencia. o en su defecto. en la documentación de OOo Basic. la estructura completa de la función MsgBox seria: Variable As [Titulo As String]) Integer = MsgBox (Mensaje As String. completo. es que en la variable Respuesta. lo importante y relevante al programar. solo te paso la lista completa de los valores que puede retornar la función MsgBox. es tema de otro capitulo. tendremos el valor del botón que el usuario haya presionado. Entre más conozcas y domines las instrucciones y funciones de OOo Basic. con esto. que solo son referencia. lo verdaderamente importante es que “aprendas a reconocer la sintaxis y estructura de cualquier instrucción o función”. es que aprendas a consultar esta documentación. Lo realmente importante. de modo que la excelencia no es un acto sino un habitoMás adelante aprenderemos a crear nuestras propias instrucciones que aquí llamaremos “subrutinas” y también nuestras propias funciones. así. "OOo Basic" ) MsgBox Respuesta End Sub Por supuesto. por supuesto. Veamos el ejemplo anterior. más rápido y productivo serás. el resto es solo consultar la documentación del lenguaje. necesitamos usar el signo igual. como resultado. Recordando. viendo estructuras como las que te he mostrado. la ayuda del programa o manuales como este. espero me alcancen las ganas de mostrarte todas las funciones que usa OOo Basic. ya con su variable de retorno: Sub InstruccionesYFunciones Dim Respuesta As Integer Respuesta = MsgBox ( "Estoy aprendiendo OOo Basic.Aprendiendo OOo Basic 35 variable. 1 Aceptar 2 Cancelar 3 Cancelar 4 Repetir 5 Ignorar 6 Sí 7 No No creas que esta mal la lista. devuelve un entero (Integer). pero la gran diferencia. [Tipo As Integer]. para hacer real lo que decía Don Aristoteles. como saber que tipo de valor de retorno tendrás. no veras mucha diferencia. la lógica. por ahora. en el caso de las funciones. 36. por lo que la variable donde guardes el valor de retorno debes de declararla como tipo entera (Integer) y así para cada valor de retorno de cada función que uses. dependiendo de con que otros botones se muestre. eso. te mostrara el mismo cuadro de dialogo. Y un nuevo capitulo ha llegado a su fin. es decir. que la variable debe ser declarada del mismo tipo del valor que esperamos devuelva la función. puede regresar un valor 2 o 3. así que sigue leyendo. la función MsgBox. espero que si. en este caso en especifico. pero recuerda que no es necesario aprenderse de memoria todo esto. ¿quieres continuar?". no debes de tener duda alguna de como se usan las que incorpora OOo Basic. normalmente viene especificado este valor de retorno para cada función. -somos lo que hacemos día con día. ya que es muy importante. pero para ello. el botón Cancelar. saber que argumentos necesita y de que tipo. solo se logra con la practica diaria. debes de ser capas de hacer uso de cualquier función o instrucción. 36 4. pero habrá ocasiones. Dependiendo del tamaño de tu proyecto. ICONO_PREGUNTA + BOTONES_SINO. es una buena practica de programación. visto en el capitulo anterior. si esta llega a cambiar. que un valor será constante durante toda la ejecución de una macro. y en las macros no nos salvamos de ellas.4 Bifurcaciones – Tomando decisiones ¿Te has puesto a pensar cuantas decisiones tomas al día?. "OOo Basic" Para nombrar a las constantes. •Enviarme tus dudas. •No te deben de quedar dudas. es sustituir el uso de los enteros en el argumento Tipo de la instrucción MsgBox. el uso de constantes es muy sencillo y nos evita tener que estar recordando valores específicos. otro valor agregado de las constantes. es muy importante para los siguientes capítulos. Afortunadamente en OOo Basic es mucho más sencillo que en la vida. tomamos uno u otro camino. usar un modulo único para declarar variables y constantes. declarar las constantes con MAYUSCULAS. •Prueba a combinar los diferentes valores •Practicar mucho.2 Instrucciones y funciones en OOo Basic •Practicar mucho.3 Constantes – Siempre lo mismo Hemos visto como guardar un dato temporalmente en una variable. este tema del argumento Tipo. usamos la palabra clave Const de la siguiente manera: Const I = 100 Aunque lo más recomendable. comentarios y aportes. Un buen ejemplo del uso de constantes. 4. •Practicar mucho. Para declarar una constante. 4. es que. veamos como hacerlo. pero a fin de cuentas tu gusto y criterio son los que mandan. casi siempre hay que estar decidiendo algo y en base a esta decisión. o eso dicen. por lo que no las repetiremos aquí. aunque esto no es una regla. aplican las mismas reglas vistas para nombrar a las macros y a las variables.1416 Es una practica común en los programadores. la vida esta hecha de decisiones. veamos como: Const ICONO_PREGUNTA As Integer = 32 Const BOTONES_SINO As Integer = 4 MsgBox "Estoy aprendiendo OOo Basic". te encontraras muy seguido con esta forma de declarar constantes. . es también establecer el tipo de constante: Const PI As Single = 3. solo tenemos que cambiar su valor una vez en la sección donde la declaramos. . 32 + 4. simplemente no lo sabemos.. pero que tal que dice que “si”. "Novios" ) 'Evaluamos la respuesta. actuaremos en consecuencia. un 7 es igual No If Respuesta = 7 Then MsgBox "De lo que te pierdes" Else 'Cualquier otro valor diferente del que se evalúa en la condición MsgBox "Que inteligente eres" End If End Sub Notaras al ejecutar. Sub Novios2 Dim Respuesta As Integer 'La pregunta importante Respuesta = MsgBox( "¿Quieres ser mi novia?". significa “cualquier” otro valor o caso o condición. 32 + 4. para solventar esto. veamoslo con un ejemplo: Sub DiaDeLaSemana Dim Dia As Integer 'Solicitar un numero digamos entre 1 y 10 Dia = InputBox( "¿Que dia quieres saber (1 a 10)?" ) If Dia = 1 Then MsgBox "Este dia es Domingo" Else MsgBox "Este dia NO es Domingo" End If . si el valor de la variable Respuesta era 7.Then. para ello te presento una nueva instrucción que te acompañara (esta sí) para el resto de tu programación. preguntemosle: Option Explicit Sub Novios Dim Respuesta As Integer Respuesta = MsgBox( "¿Quieres ser mi novia?". la ejecución continua en la línea inmediata. pero cuando se presiona el botón “Si”. en nuestro ejemplo. si la variable tiene “cualquier” otro valor o condición. recuerda. "Novios" ) MsgBox Respuesta End Sub Copia y ejecuta la macro anterior y observa como únicamente estamos obteniendo la información del botón que selecciono el usuario: un 6 para el botón “Si” y un 7 para el botón “No”.. que ahora si sabemos cuando se presiono cada uno de los botones de nuestro cuadro de dialogo.. checa la siguiente macro: Sub Novios3 Dim Respuesta As Integer 'La pregunta importante Respuesta = MsgBox( "¿Quieres ser mi novia?". de acuerdo a los valores mostrados en la sección 2. 32 + 4. Señoras y señores. con Ustedes. Debes de poner atención a algo importante. es decir. "Novios" ) 'Evaluamos la respuesta. entonces hace lo segundo. la instrucción If. recuerda. dependiendo de la respuesta. Veamos su uso.Aprendiendo OOo Basic 37 Un pregunta importante: ¿Quieres ser mi novia?. un 7 es igual No If Respuesta = 7 Then MsgBox "De lo que te pierdes" End If End Sub Observa que solo logramos saber cuando se presiono el botón de “No”. la instrucción Else. si dice que “no” ¿que hago?. Ahora.Else. Else es: If CONDICION Then 'Código si condición es verdadera [ElseIf CONDICION_2 Then] 'Código si condición 2 es verdadera [Else] 'Cualquier otro valor End If Recuerda que las opciones que están entre corchetes son “opcionales”... no te importe como esta construida. Resumiendo: la estructura general de la instrucción If. en ocasiones. usaremos una variante de la instrucción If. ahora.. es como se nos informa que es Domingo. veamos como: Sub DiaDeLaSemana2 Dim Dia As Integer 'Solicitar un numero digamos entre 1 y 10 Dia = InputBox( "¿Que dia quieres saber (1 a 10)?" ) If Dia = 1 Then MsgBox "Este dia es Domingo" ElseIf Dia = 2 Then MsgBox "Este dia es Lunes" Else MsgBox "NO se que dia es" End If End Sub De esta manera. Como pista.. que por ahora. pero veras que más adelante aprenderemos a hacer. ElseIf bolHayComillas = False And (strPalabra = "'" Or UCase(strPalabra) = "REM") Then ElseIf EsPalabraClave(strPalabra) And bolHayComillas = False Then Volviendo al ejemplo de los días de la semana.Else.Case.. [TAREA] completa la macro para que nos de todo los días de la semana y en caso de otro valor nos informe que no es un día de la semana.38 End Sub 4. veamos un ejemplo: Sub DiaDeLaSemana3 Dim Dia As Integer Dia = InputBox( "¿Que día quieres saber (1 a 10)?" ) Select Case Dia Case 1 MsgBox "Este día es Domingo" Case 2 MsgBox "Este día es Lunes" . sobre todo cuando se compara la misma variable varias veces. sino tan solo quiero mostrarte un caso “diferente” de condición.. aprenderás a usar Select.4 Bifurcaciones – Tomando decisiones Observa como “solamente” con el valor de 1. Si quisiéramos saber que día de la semana corresponde a otro valor.Then. En CONDICION.. es posible usar otra instrucción de bifurcación. puede ir “cualquier” instrucción susceptible de ser evaluada como verdadera o falsa y puede ser tan sencilla como las vistas hasta ahora o compleja como el siguiente ejemplo. podemos hacer tantas comparaciones como queramos.. cualquier otro valor nos muestra el segundo mensaje. pero veras que casi siempre así será. puedes usar tantos ElseIf como quieras.Then.. no necesariamente tienes que usarlas. Loop. las condición a evaluar puede ser muy sencilla o compleja.Then. 4.. tenlas siempre a la mano. necesitamos repetir bloques de código las veces que queramos o cuando (o hasta) que se cumpla una condición especifica. son el pan nuestro de cada día en la programación. están son: For.. Para ello... muy seguido) es necesario realizar el mismo paso una y otra vez.5 Bucles – Repitelo otra vez En ocasiones (de hecho. día de trabajo" Case Else MsgBox "NO se que día es" End Select End Sub ¿Verdad que es fácil? Al igual que con la instrucción If. si en eso entonces hubiese sabido programar (y conste que cuando iba a la primaria ya existían las computadoras) le hubiese entregado a la maestra el siguiente código: Option Explicit Sub PortarseBien Dim Contador As Integer 'Inicia el contador con los limites especificados For Contador = 1 To 2 'Este es el código que se ejecuta el numero de veces 'especificado con los limites en nuestro caso 2 veces MsgBox "Tengo que portarme bien" .. veamos ejemplos de cada una... puede usar varios valores a evaluar o rangos de valores. Ademas. así que. por ejemplo: Sub DiaDeLaSemana4 Dim Dia As Integer Dia = InputBox( "¿Que día quieres saber (1 a 10)?" ) Select Case Dia 'Aquí evaluamos si es sábado o domingo Case 1. pero las dos. 7 MsgBox "Por fin a descansar" 'Y aquí si es entre semana.Else.Next y Do. de Lunes a Viernes Case 2 To 6 MsgBox "Que horror.Aprendiendo OOo Basic Case 3 39 MsgBox "Este día es Martes" Case 4 MsgBox "Este día es Miércoles" Case Else MsgBox "NO se que día es" End Select End Sub Observa que fácil es esta instrucción. vamos a conocer dos nuevas estructuras para hacer bucles o repeticiones. es decir.. te acuerdas cuando te portabas mal y la maestra te dejaba escribir cien veces -Tengo que portarme bien-. es necesaria una variable de apoyo. Para hacer uso de la estructura For. te dejo de tarea que te quede muy presentable y bonito. J y subsecuentes como contadores. pero tu eres libres de elegir y usar la variable que más te plazca. la letra M es muy bonita. es más común usar el símbolo de ampersan (&) como concatenador de cadenas de texto: Sub Dim Dim Dim Dim TuNombre2 Nombre As String Apellido1 As String Apellido2 As String NombreCompleto As String Nombre = InputBox( "¿Cual es tu Nombre?") Apellido1 = InputBox( "¿Cual es tu primer Apellido?") Apellido2 = InputBox( "¿Y el segundo?") NombreCompleto = Nombre & Apellido1 & Apellido2 MsgBox "Tu nombre completo es: " & NombreCompleto End Sub Por supuesto habrás notado que el nombre completo sale todo pegado. por ejemplo: Sub Dim Dim Dim Dim TuNombre Nombre As String Apellido1 As String Apellido2 As String NombreCompleto As String Nombre = InputBox( "¿Cual es tu Nombre?") Apellido1 = InputBox( "¿Cual es tu primer Apellido?") Apellido2 = InputBox( "¿Y el segundo?") NombreCompleto = Nombre + Apellido1 + Apellido2 MsgBox "Tu nombre completo es: " + NombreCompleto End Sub Observa como solicitamos el nombre y apellido y al final lo mostramos en una sola línea de texto.40 Next End Sub 4.. probemos primero con 10: Sub PortarseBien2 Dim Contador As Integer Dim Texto As String For Contador = 1 To 10 Texto = Texto & "Tengo que portarme bien" . pero para establecer valores más grandes.. la B también es muy linda. que son las indicadas por el limite inferior y superior del contador especificadas con 1 To 2. si bien funciona con el operador +. Ahora si. con frecuencia te encontraras que algunos programadores usan la letra I. Observa que solo te mostrara el mensaje dos veces. por ejemplo.Next. podemos hacer nuestro bucle más grande. para nuestro caso. en programación a la “suma” de cadenas de texto se le conoce como “concatenar” y no es otra cosa que pegar cadenas de texto una con otra. pero mejor lo explicamos para que no haya ninguna duda y ningún pretexto de como aplicarlo más adelante. no te puse cien por que tendrías que dar cien clics para terminar la macro. escogimos la variable Contador. aprovecharemos para ver como “sumar” cadenas de texto.5 Bucles – Repitelo otra vez Se que esta muy claro. Tengo que portarme bien" & Chr(13) Next MsgBox Texto End Sub . ¿verdad?. ¿Y que te parecería si lo mejoramos agregándole el número a cada línea?: Sub PortarseBien4 Dim Contador As Integer Dim Texto As String For Contador = 1 To 10 Texto = Texto & Contador & ".Aprendiendo OOo Basic Next MsgBox Texto End Sub 41 Rápido pero no nos gusta todo el texto junto. le agregaremos un saldo de línea al final de cada una. Para mejorarlo un poco.. así: Sub PortarseBien3 Dim Contador As Integer Dim Texto As String For Contador = 1 To 10 Texto = Texto & "Tengo que portarme bien" & Chr(13) Next MsgBox Texto End Sub ¿Recuerdas como decía mi amigo? -ansina si-. de tres en tres o en el rango que necesitemos. en este caso Step. cuando podemos ir de dos en dos. ojo.42 4. Sub PortarseBien5 Dim Contador As Integer Dim Texto As String For Contador = 1 To 20 Step 2 Texto = Texto & Contador & ".. ni positivo. Los limites inferior y superior no necesariamente tienen que ser positivos: For Contador = -5 To 5 Tampoco tienen por que ir de uno en uno.5 Bucles – Repitelo otra vez Mucho mejor. ¿no crees?. Por supuesto observaste que le agregamos un argumento a la instrucción. para indicarle que salto queremos y este salto no necesariamente tiene que ser ni entero.Tengo que portarme bien" & Chr(13) Next MsgBox Texto End Sub Esto se esta poniendo divertido. For Contador = 100 To 10 Step -10 . mucho ojo con esto. el mismo nombre de la variable que este usando como contador. muchas veces el uso de la sangría es suficiente para distinguir unos de otros. decidirás si lo usas o no. pero no esta de más como ayuda. por ejemplo: For Contador = 0 To 1 Step 0. claro que el IDE de indica si falta alguno. es un poco complejo saber donde termina uno. Sub PortarseBien6 Dim Contador As Integer Dim Texto As String For Contador = 0 To 1 Step 0.. hay una instrucción que no hemos visto. Observa que debajo de la linea de comentario. de nuevo. de “a deveras” para finalizar. que de eso se trata la libertad. esta nos sirve para salir anticipadamente de un ciclo For... es decir en el momento que quieras.Tengo que portarme bien" & Chr(13) Next MsgBox Texto End Sub Como ultimo comentario de esta instrucción.1 'Aquí va código Next Contador Esto es sumamente útil cuando tienes varios bucles de repetición anidados.Aprendiendo OOo Basic 43 Y aquí te lo dejo para que hagas todas las pruebas que quieras y nos las cuentes en el foro o lista de correo.1 Texto = Texto & Contador & ". a fin de cuentas. tu y solo tu. se trata de: Exit For. puedes usar después de la palabra clave Next. sobre todo cuando hay muchas líneas de código entre ellos. La siguiente macro tiene un pequeño error. co2 As Integer For co1 = 1 To 5 For co2 = 1 To 10 Next co2 Next co1 End Sub Ahora si. veamos un ejemplo divertido de su uso: Option Explicit Sub Dim Dim Dim Dim Usando_Exit_For() co1 As Integer sLetra As String sVocales As String sConsonantes As String For co1 = 1 To 100 sLetra = Chr( Rnd() * 25 + 65 ) . pero en otras ocasiones. Sub BuclesAnidados Dim co1 As Integer. tu tarea es indicarme cual es. recuerda bien la estructura de esta instrucción: For Variable = Inicio To Fin [Step Salto] 'codigo [Exit For] Next [Variable] Y recuerda que lo que esta entre corchetes es opcional.Next. en el capitulo de variables puedes encontrar ayuda. "O". es decir.. 0. "E". si es la letra S o si es una consonante. nos apoyaremos en una estructura ya vista: Sub DameTuNombre2 .44 4. "U" sVocales = sVocales & " " & sLetra Case "S" Exit For Case Else sConsonantes = sConsonantes & " " & sLetra End Select Next MsgBox "El ciclo termino en: " & co1 & Chr(13) & Chr(13) & _ "Vocales: " & sVocales & Chr(13) & _ "Consonantes: " & sConsonantes. en este caso un nombre Loop While Nombre = "" 'Continuamos el bucle “mientras” la condición sea VERDADERA End Sub 'Finalizamos la macro Habrás notado que de esta forma. también nos sirve para hacer repeticiones. mostramos el valor del contador para saber si termino el ciclo o salio antes. pero en vez de usar un contador. Al tipo de ciclo usado en For.Next. es mis pruebas curiosamente salio varias veces en 1 y lo máximo fue 98. por ello es que con la línea sLetra = Chr( Rnd() * 25 + 65 ) Obtenemos un valor aleatorio entre 65 y 90 y Chr nos devuelve dicha letra. ya me contaras como te va a ti con tus pruebas. después evaluamos si es una vocal. "Ejemplo Exit For" End Sub La función Chr(valor) nos devuelve el carácter ASCII correspondiente a dicho valor. recuerda que es deseable. forzamos al usuario a escribir un valor en el cuadro de dialogo. solo en el caso de que la letra devuelta sea una S (de Salida). la letra A tiene un valor de 65 y la letra Z tiene un valor de 90.Loop. pues dependen de una o unas condiciones para empezar o terminar el ciclo. algunos autores le llama “determinado” pues sabemos donde empieza y donde termina.Next se interrumpe y sale con Exit For. proporcionar casi siempre una forma de cancelar o interrumpir el bucle. "I". nunca termino el ciclo. el ciclo For.. hay otro tipo de ciclos llamados “indeterminados”. a ellos nos atenemos: Sub DameTuNombre Dim Nombre As String Do Nombre = InputBox( "¿Cual es tu Nombre?") Loop While Nombre = "" End Sub Analicemos línea por línea la macro anterior: Sub DameTuNombre 'Iniciamos la macro Dim Nombre As String 'Declaramos una variable de texto Do 'Iniciamos el bucle Nombre = InputBox( "¿Cual es tu Nombre?") 'Solicitamos un valor. si bien es posible. para probar una primer alternativa para ello. al final.. Como creo que es más claro con ejemplos. se usa una condición para saber cuando terminar un bucle e incluso cuando empieza o tal vez nunca empezar.. veamos cuales son: La instrucción Do..5 Bucles – Repitelo otra vez Select Case sLetra Case "A". validación. esa es tu tarea. . Para continuar. "Salir" ) 'Recuerda que un 6 significa que el usuario presiono el botón SI If Respuesta = 6 Then 'Establecemos la variable con cualquier cosa para que termine el bucle Nombre = "cualquier cosa" End If End If Loop While Nombre = "" End Sub Ahora sí. es el pan nuestro de cada día al programar. "Salir" ) 'Recuerda que un 6 significa que el usuario presiono el botón SI If Respuesta = 6 Then 'Establecemos la variable con cualquier cosa para que termine el bucle Nombre = "cualquier cosa" End If End If Loop While Nombre = "" End Sub Recuerda siempre de ir probando el código. Parece que funciona bien la macro anterior. veremos una variante de esta estructura que nos permite invertir la lógica de la condición. te presento a la instrucción Trim. en negritas) que la variable Nombre. ¿realmente quieres salir?". 32 + 4. lo que hicimos fue cambiar un argumento y el operador de la condición. haremos uso de una función integrada en OOo Basic que nos sirve para eliminar los espacios vacíos al inicio y al final de una cadena. recuerda esta palabra muy bien. sea “diferente” de vacía. observa como ahora le decimos “hasta” (con la instrucción Until. nota que la condición tiene que seguir siendo verdadera para que el bucle termine. 32 + 4. con validación y todo. contenga algo. ¿realmente quieres salir?". ¿se te ocurren más alternativas por “prever” o mejorar?. que se usa de la siguiente forma: Sub DameTuNombre3 Dim Nombre As String Dim Respuesta As Integer Do Nombre = InputBox( "¿Cual es tu Nombre?" ) Nombre = Trim( Nombre ) If Nombre = "" Then Respuesta = MsgBox( "Al parecer no escribiste nada. Ahora.Aprendiendo OOo Basic Dim Nombre As String Dim Respuesta As Integer Do 45 Nombre = InputBox( "¿Cual es tu Nombre?" ) If Nombre = "" Then Respuesta = MsgBox( "Al parecer no escribiste nada. lo siento. es decir. veamos como: Sub DameTuNombre4 Dim Nombre As String Do Nombre = InputBox( "¿Cual es tu Nombre?") Loop Until Nombre <> "" End Sub Se muy atento. la macro completa. prueba a introducir puros espacios y veras que sale inmediatamente. para subsanar este inconveniente. ojo. funciona mejor. pero hay una simple forma de “engañarla”. También. la cuestión se enriquece. es casi seguro que unas se adaptaran rápidamente a tu forma de razonar. necesitamos forzosamente que se cumpla una condición. simplemente pasamos la instrucción al inicio de la estructura. ejecuta el código entre Do. si la variable es diferente de vacía Do While Nombre <> "" 'Formamos una lista de los nombres introducidos Lista = Lista & " . sea un buen momento para ampliar tus horizontes. Recuerda que no todos tenemos el mismo modo de “razonar”. la primera de forma directa y la segunda de forma anidada. te debe de resultar muy familiar si eres un usuario medio/avanzado de cualquier hoja de calculo. "Salir" ) 'Recuerda que un 6 significa que el usuario presiono el boton SI If Respuesta = 6 Then 'Establecemos la variable con cualquier cosa para que termine el bucle Nombre = "cualquier cosa" End If End If Loop Until Nombre <> "" End Sub Tal vez. Aquí nota las dos formas en que hacemos uso de la instrucción InputBox. detente un momento y trata de entender la forma “diferente” de razonar del otro." & Nombre 'Solicitamos otro nombre Nombre = Trim( InputBox( "¿Dame otro Nombre?") ) Loop 'Si la lista contiene algo lo mostramos If Lista <> "" Then MsgBox Lista End If End Sub Fácil. hay más de una forma de hacer las cosas. En casi todo y más en la programación. pero al haber varias maneras de resolver el mismo problema. con justa razón. observa como las dos variantes de la estructura vista. Habrá ocasiones en que necesitemos o queramos que no se ejecute ni una sola vez. ¿realmente quieres salir?".. Para hacer esto. otras no. tal vez.5 Bucles – Repitelo otra vez Nombre = InputBox( "¿Cual es tu Nombre?") Nombre = Trim( Nombre ) If Nombre = "" Then Respuesta = MsgBox( "Al parecer no escribiste nada.Loop. Y sí. te preguntaras.46 Sub DameTuNombre5 Dim Nombre As String Dim Respuesta As Integer Do 4. Y hablando de variedad. ¿verdad?. Anidar funciones. conocimiento que te resultara muy útil en programación ya que es muy recurrida. al menos una vez. de la siguiente forma: Sub DameTuNombre6 Dim Nombre As String Dim Lista As String 'Solicitamos un dato Nombre = InputBox( "¿Dame un Nombre?") 'Le quitamos los espacios sobrantes al inicio y al final Nombre = Trim( Nombre ) 'Iniciamos el bucle. ¿por ejemplo?. 32 + 4. así que la próxima vez que estés pronto a prejuzgar. pues hay . imagina que para entrar en el bucle. ¿porque dos formas de hacer lo mismo?. a los fundamentalistas de cualquier extremo y color se les reconoce fácilmente por su “pensamiento” uniforme y negación a ver otro o al otro. te mostrare la instrucción para finalizar anticipadamente un ciclo Do. pues muchas estructuras de OpenOffice. Para finalizar este tema de los bucles. las matrices pueden ser de mucha utilidad o convertirse en un verdadero galimatias si no se manejan correctamente. estarás en lo cierto. Empieza a pensar en como automatizarías esos pasos tan repetitivos y tediosos que siempre haces. una condición mal planteada te puede dejar dentro de un ciclo infinito.y solo la practica diaria te dará el dominio de la herramienta para obtener de ella el mejor provecho. estas palabras clave son: Exit Do y se usan de la siguiente manera: Option Explicit Sub Usando_Exit_Do() Dim sClave As String Dim sTmp As String sClave = "mellon" Do sTmp = Trim(InputBox("Habla amigo y entra")) If sTmp = "mellon" Then MsgBox "Y se abren las puertas de Moria" Exit Do End If Loop Until sTmp = "salir" End Sub Observa como tenemos dos formar de terminar el bucle. la cual consiste en que logres el mismo propósito. si crees que estoy tratando de influenciarte para que practiques mucho. en vez de While.. La sintaxis más sencilla para una matriz es la siguiente: Dim Nombre_Matriz( Tamaño As Integer ) As Tipo . recuerda lo que decía un hombre que practicaba y experimentaba mucho. como dice el dicho -la practica hace al maestro. con solo leer estas notas o cualquiera otra documentación que encuentres o adquieras (y te lo digo por experiencia) no es suficiente para que resuelvas tus problemas informáticos. Ten cuidado con los ciclos indeterminados. “casi” todo lo que se hace en programación responde aproximadamente bien a el.6 Matrices – Juntos pero no revueltos En el cual veremos como manipular muchos datos en una sola variable. que te hagas llamar programador. muchas cosas. ya se pueden hacer muchas. Para ello. mucho menos. "El genio es 1% de inspiración y 99% de transpiración" Thomas Alva Edison 4. una. mantén siempre en tu mente el diagrama que vimos en el capitulo 4.Loop.1. si el usuario escribe correctamente la palabra clave y salimos con Exit Do.. eso quiero hacer y para terminar este capitulo.org vienen implementadas en matrices.Aprendiendo OOo Basic 47 tarea. no te engañes. y la otra. Me creerás que con los elementos vistos hasta ahora. pero con la palabra clave Until. es importante que aprendas a utilizarlas. la que ya conoces en la condición final. una simple lista sería así: ● ● ● ● ● ● ● Domingo Lunes Martes Miércoles Jueves Viernes Sábado Para guardar esto en una matriz. podemos forzar a que las matrices empiecen en 1 (uno). el indicarte que sea un tipo Integer (Entero) es más indicativo que restrictivo. sería así: Sub Ejemplo_Matrices1 Dim miSemana(6) As String miSemana(0) = "Domingo" miSemana(1) = "Lunes" miSemana(2) = "Martes" miSemana(3) = "Miércoles" miSemana(4) = "Jueves" miSemana(5) = "Viernes" miSemana(6) = "Sábado" MsgBox miSemana( 3 ) End Sub Y observa que con un simple bucle. de la siguiente manera: . en este caso. 64. tal vez quiera decir que es hora de pasar a usar bases de datos. he hecho la prueba con valores más grande que un Integer (Entero). en mis pruebas estoy casi seguro que esta condicionado más por el limite de la memoria Ram del equipo donde se ejecute que de otra causa. pero no me imagino una macro que use tantos elementos y si lo hay. Tamaño se refiere al número de elementos que contendrá la matriz. experiencia y pruebas el limite de elementos a usar. que es la forma predeterminada. "Toda la semana" Next End Sub Nota que la matriz empieza en 0 (cero).6 Matrices – Juntos pero no revueltos En donde para Nombre_Matriz tiene que cumplir las mismas condiciones que para nombrar las macros y las variables vistas anteriormente. Te resultara muy fácil pensar en las matrices con una lista de valores en su presentación más sencilla. Te dejo a tu criterio. o en una tabla de filas y columnas en las mas compleja. por ejemplo: los días de la semana. podemos acceder a toda la matriz Sub Ejemplo_Matrices2 Dim miSemana(6) As String Dim co1 As Integer miSemana(0) miSemana(1) miSemana(2) miSemana(3) miSemana(4) miSemana(5) miSemana(6) = = = = = = = "Domingo" "Lunes" "Martes" "Miércoles" "Jueves" "Viernes" "Sábado" For co1 = 0 To 6 MsgBox miSemana( co1 ).48 4. No he encontrado documentación al respecto del limite de este valor. usando la palabra clave Option Base. Dim Nombre_Matriz( Inicio As Tipo To Fin As Tipo ) As Tipo En donde Inicio puede ser incluso un valor negativo como en los ejemplos siguientes: Sub Ejemplo_Matrices4 Dim misNumeros(5 To 14) As Integer Dim misColores(-5 To 4) As String misNumeros(5) = 123 misNumeros(6) = 345 misNumeros(7) = 567 misNumeros(8) = 890 misNumeros(9) = 135 misNumeros(10) = 246 misNumeros(11) = 147 misNumeros(12) = 258 misNumeros(13) = 369 misNumeros(14) = 951 misColores(-5) = "Azul" misColores(-4) = "Verde" misColores(-3) = "Morado" misColores(-2) = "Rojo" misColores(-1) = "Blanco" misColores(0) = "Rosa" misColores(1) = "Violeta" misColores(2) = "Gris" misColores(3) = "Negro" misColores(4) = "Oro" MsgBox misNumeros( 9 ). "Toda la semana" Next End Sub Option Base “no” puede ir dentro de una macro. Si te es necesario un inicio y un fin diferentes pues usar la siguiente variante para la declaración de matrices. 64. así que usaremos este valor de inicio como predeterminado en todo el libro. tiene que ir al inicio de un modulo en el área de declaración de variables. 64. La mayoría de las estructuras de OpenOffice. 64.Aprendiendo OOo Basic Option Explicit Option Base 1 Sub Ejemplo_Matrices3 Dim miSemana(7) As String Dim co1 As Integer miSemana(1) miSemana(2) miSemana(3) miSemana(4) miSemana(5) miSemana(6) miSemana(7) = = = = = = = "Domingo" "Lunes" "Martes" "Miércoles" "Jueves" "Viernes" "Sábado" 49 For co1 = 1 To 7 MsgBox miSemana( co1 ). "Colores" End Sub . "Números" MsgBox misColores( 0 ).org inician en 0 (cero). cuando queremos recorrer una matriz con un bucle. y por ultimo la función Str que convierte en cadena de texto el argumento pasado.58.35. Usando estas dos ultimas funciones. LBound que nos devuelve el limite inferior de una matriz y UBound que nos devuelve el limite superior. pero muy bien podemos combinar datos si declaramos la matriz como Variant.35.48. ni siquiera tenemos que enterarnos de los limites de una matriz.16 ) MsgBox "Limite Inferior = " & Str( LBound( misdatos() )) MsgBox "Limite Superior = " & Str( UBound( misdatos() )) For co1 = LBound( misdatos() ) To UBound( misDatos() ) MsgBox misDatos( co1 ).51. como en el siguiente ejemplo: Sub Ejemplo_Matrices5 Dim misDatos(5) As Variant Dim co1 As Integer misDatos( 0 ) = "Mauricio Baeza" misDatos( 1 ) = 1974 misDatos( 2 ) = "Miguel Angel 64" misDatos( 3 ) = "Mexico" misDatos( 4 ) = "D. hemos establecido los valores superior e inferior de la matriz declarada previamente. no sera posible conocer los valores de inicio y fin de una matriz.58. cuenta con dos funciones muy útiles para conocer estos valores: Sub Ejemplo_Matrices6 Dim misDatos() As Integer Dim co1 As Integer misDatos() = Array( 87.F.26. "Mis datos" Next End Sub Notaras que en los casos vistos hasta ahora. 64. las matrices tienen los mismos diez elementos. 25. "Prueba". "Hola". 30. que nos permite crear una matriz introduciendo directamente los valores que contendrá.12. cada uno separado por una coma. Puedes declarar una matriz de un determinado tamaño y usar Array para llenar la matriz sin que necesariamente correspondan el número de elementos. "Hola" ) MsgBox "Limite Inferior = " & Str( LBound( misdatos2() )) & Chr( 13 ) & _ "Limite Superior = " & Str( UBound( misdatos2() )) 'Con mas elementos . "Mis datos" Next End Sub En este ejemplo aprendemos cuatro nuevas funciones de OOo Basic. en una guardamos números y en la otra texto. 15 ) MsgBox "Limite Inferior = " & Str( LBound( misdatos1() )) & Chr( 13 ) & _ "Limite Superior = " & Str( UBound( misdatos1() )) 'Con menos elementos misDatos2() = Array( "Paola". 64. en estos casos. 45. en muchos casos.98.50 4.26.6 Matrices – Juntos pero no revueltos Observa como en los dos casos. OOo Basic. Array. como en los siguiente ejemplos: Sub Dim Dim Dim Dim Ejemplo_Matrices7 misDatos1(5) As Variant misDatos2(5) As Variant misDatos3(3) As Variant co1 As Integer 'Llenamos la primer matriz con el numero exacto de elementos declarados misDatos1() = Array( "Lizet"." misDatos( 5 ) = 37000 For co1 = 0 To 5 MsgBox misDatos( co1 ). 64. claramente notamos que la matriz se “redimenciona” con el número de elementos que tenga la función Array. "Mis amigos" Next Redim misAmigos(4) misAmigos(3) = "Lidia": misAmigos(4) = "Anita" For co1 = LBound( misAmigos() ) To UBound( misAmigos() ) MsgBox Str( co1 ) & " . 18. "Mis amigos" Next End Sub Ahora si. 27. se logra agregando una simple palabra clave: Sub Ejemplo_Matrices9 Dim misAmigos(2) As String Dim co1 As Integer misAmigos(0) = "Edgar": misAmigos(1) = "Gloria" : misAmigos(2) = "Toñito" For co1 = LBound( misAmigos() ) To UBound( misAmigos() ) MsgBox Str( co1 ) & " ." & misAmigos( co1 ).7." & misAmigos( co1 ). se llama ReDim y se usa de la siguiente manera: Sub Ejemplo_Matrices8 Dim misAmigos(2) As String Dim co1 As Integer misAmigos(0) = "Edgar": misAmigos(1) = "Gloria" : misAmigos(2) = "Toñito" For co1 = LBound( misAmigos() ) To UBound( misAmigos() ) MsgBox Str( co1 ) & " . esto es por que al redimencionar la matriz con ReDim. es una tarea habitual de programación." & misAmigos( co1 ). te mantiene los valores previos. esta. pero tiene el inconveniente de que ni aun usando Preserve. también sirve para disminuirlos. esto. "Mis números" . "Mis amigos" Next ReDim Preserve misAmigos(4) misAmigos(3) = "Lidia": misAmigos(4) = "Anita" For co1 = LBound( misAmigos() ) To UBound( misAmigos() ) MsgBox Str( co1 ) & " .3. no importándole el valor con el que hayamos declarado la matriz. 64.4. 64. por supuesto que en ocasiones desearemos mantener los valores que existan. borra los valores que hayamos introducido previamente en la matriz. "Mis amigos" Next End Sub Se que eres muy observador y ya notaste que en el segundo bucle.Aprendiendo OOo Basic 51 misDatos3() = Array( "Mariana". "Hola".2.9. como lo demuestra el siguiente ejemplo: Sub Ejemplo_Matrices10 Dim misNumeros(9) As Integer Dim co1 As Integer misNumeros() = Array( 1. solo nos muestra los valores de los indices 3 y 4.8. "Prueba" ) MsgBox "Limite Inferior = " & Str( LBound( misdatos3() )) & Chr( 13 ) & _ "Limite Superior = " & Str( UBound( misdatos3() )) End Sub Al observar los valores inferior y superior que nos devuelve cada matriz. 64. por ello existen varias alternativas para lograr este propósito. 64.6. Pero ReDim no solo sirve para aumentar elementos." & misAmigos( co1 ).5.10 ) For co1 = LBound( misNumeros() ) To UBound( misNumeros() ) MsgBox misNumeros( co1 ). todo se mantiene con la palabra clave Preserve. OOo Basic cuenta con una instrucción especifica para lograr esto. Cambiar de tamaño o de cantidad de elementos que puede contener una matriz de forma dinámica durante la ejecución de una macro. que hace exactamente lo mismo. es una tarea idónea para convertirla en una subrutina o si lo deseas en una función como se ve en el tema 4. ByVal Tamano As Integer) Dim mTmp() As Variant Dim co1 As Integer If Tamano > UBound( Matriz() ) Then ReDim Preserve Matriz( Tamano ) ElseIf Tamano < UBound( Matriz() ) Then ReDim mTmp( Tamano ) For co1 = LBound( mTmp() ) To UBound( mTmp() ) mTmp( co1 ) = Matriz( co1 ) Next Redim Matriz( Tamano ) Matriz() = mTmp() Erase mTmp End If End Sub Como una función. Como es una tarea habitual (el disminuir de tamaño una matriz y desear mantener los valores restantes).7. si es igual la deja tal cual: Sub RedimencionarMatriz( Matriz() As Variant. seguro que si.8 Funciones y subrutinas . ByVal Tamano As Integer) As Variant . "Mis números" Next End Sub Una primera solución es la propuesta siguiente: Sub Dim Dim Dim Ejemplo_Matrices11 misNumeros(9) As Integer mTmp() As String co1 As Integer 'Llenamos la matriz con 10 números misNumeros() = Array( 1. "Mis números" Next 'Borramos la memoria usada por la matriz temporal Erase mTmp End Sub ¿Se te ocurre alguna otra?. si es menor. si es mayor solo redimensiona.6. Aquí las dos formas y tu decides cual usar. 64.10 ) 'Redimencionamos la matriz temporal Redim mTmp(4) 'Pasamos los valores a la matriz temporal For co1 = LBound( mTmp() ) To UBound( mTmp() ) mTmp( co1 ) = misNumeros( co1 ) Next 'Redimencionamos la matriz original Redim misNumeros(4) 'Copiamos loa valores temporales misNumeros() = mTmp() 'Verificamos que esten los datos For co1 = LBound( misNumeros() ) To UBound( misNumeros() ) MsgBox misNumeros( co1 ). 64.5. en donde le pasamos la matriz a redimensionar y el nuevo tamaño que tendrá.Divide y vencerás.52 4.2. copia los valores a mantener y redimenciona. Como una subrutina.9. Function FuncionRedimencionarMatriz( Matriz() As Variant.4. excepto que devuelve el valor en vez de manipular el parámetro pasado.8.6 Matrices – Juntos pero no revueltos Next ReDim Preserve misNumeros(4) For co1 = LBound( misNumeros() ) To UBound( misNumeros() ) MsgBox misNumeros( co1 ).3. observa el paso de argumentos. 15 ) 'Asignamos un valor al indice 12 misNumeros(12) = 12 'Verificamos que lo haya guardado MsgBox misNumeros(12) 'Llamamos de nuevo a la funcion. crecemos la matriz misNumeros() = FuncionRedimencionarMatriz( misNumeros(). "Mis números" Next End Sub OOo Basic es muy noble en el manejo de las matrices.3.2.7.Aprendiendo OOo Basic Dim mTmp() As Variant Dim co1 As Integer 53 If Tamano > UBound( Matriz() ) Then ReDim Preserve Matriz( Tamano ) ElseIf Tamano < UBound( Matriz() ) Then ReDim mTmp( Tamano ) For co1 = LBound( mTmp() ) To UBound( mTmp() ) mTmp( co1 ) = Matriz( co1 ) Next Redim Matriz( Tamano ) Matriz() = mTmp() Erase mTmp End If FuncionRedimencionarMatriz = Matriz() End Function Pero para que no quede duda.3.10 ) Call RedimencionarMatriz( misNumeros(). 64.10 ) 'Llamamos a la funcion.8. observa que sencillo es copiar una matriz en otra MatrizDestino() = MatrizOrigen() .8. 5) 'Verificamos que estén los datos For co1 = LBound( misNumeros() ) To UBound( misNumeros() ) MsgBox misNumeros( co1 ). esta vez la disminuimos misNumeros() = FuncionRedimencionarMatriz( misNumeros(). 64. tanto como subrutina y como función: 'Usándola como subrutina Sub Ejemplo_Matrices12 Dim misNumeros(9) As Variant Dim mTmp() As String Dim co1 As Integer misNumeros() = Array( 1. 15) misNumeros(12) = 12 MsgBox misNumeros(12) Call RedimencionarMatriz( misNumeros(). "Mis números" Next End Sub 'Usándola como función Sub Ejemplo_Matrices13 Dim misNumeros(9) As Variant Dim mTmp() As String Dim co1 As Integer 'Llenamos la matriz misNumeros() = Array( 1.9.5.9.5.6.6. 5 ) 'Verificamos que estén los datos For co1 = LBound( misNumeros() ) To UBound( misNumeros() ) MsgBox misNumeros( co1 ).2.7.4.4. veamos su uso. 2 ) = "1-2" mDatos( 2. llenamos una matriz de 10 x 10 elementos y la llenamos con valores aleatorios de entre 1 y 100. Sub Matrices_Multidimension2 Dim mNumeros( 9. Hasta ahora. hemos visto la declaración y el uso de matrices de una sola dimensión. creo que es más por mis limites y flojera que no lo he comprobado. 0 ) = "0-0" mDatos( 0. 1 ) 2. 9 ) As Integer Dim co1 As Integer. 2 ) = "0-2" mDatos( 1. en lo personal matrices con más de tres dimensiones se me hacen complicadas de manipular. 1 ) = "2-1" mDatos( 2. procura mantener el control de la cantidad de memoria que usas en tus macros. 2 ) Piensa en las matrices de dos dimensiones como en una hoja de calculo formada por filas y columnas. 2 ) = "2-2" 'Mostramos los MsgBox mDatos( MsgBox mDatos( MsgBox mDatos( End Sub datos 0.54 4. 0 ) = "2-0" mDatos( 2. es posible declarar y usar matrices de más de una dimensión veamos como se hace.6 Matrices – Juntos pero no revueltos También. la matriz anterior quedaría así: 0 0 1 2 0-0 0-1 0-2 1 1-0 1-1 1-2 2 2-0 2-1 2-2 Por supuesto puedes declarar y usar matrices de más de dos dimensiones ¿hasta cuantas?. 1 ) = "1-1" mDatos( 1. no obstante. 0 ) = "1-0" mDatos( 1. Sub Matrices_Multidimension1 Dim mDatos( 2. parece ser que el limite esta determinado una vez más por la cantidad de memoria ram que contenga la maquina donde se ejecute la macro. 0 ) 1. 2 ) As String 'Llenamos los datos mDatos( 0. así que te invito a que hagas tus pruebas con muchas dimensiones y las compartas conmigo. co2 As Integer . le indicamos dos tamaños separados por una coma. La sintaxis para declarar matrices multidimensionales es la siguiente: Dim Nombre_Matriz( Tamaño As Integer. 1 ) = "0-1" mDatos( 0. observa el uso de la palabra clave Erase para borrar de memoria las matrices dinámicas que ya no usemos. Tamaño As Integer) As Tipo Observa como ahora. si bien ahora la mayoría de las maquinas disponen de muchos megas de ram. un ejemplo es más ilustrativo. Otro ejemplo divertido. 1 ) End Sub Pero lo interesante y divertido es darle la oportunidad al usuario de ir capturando estos datos e ir creciendo la matriz según las necesidades de este. pero OJO. 0 ) = "Gloria" mTelefonos( 0. 1 ) = "87654321" mTelefonos( 2. 1 ) As String mTelefonos( 0.Aprendiendo OOo Basic 55 'Recuerda que por default los indices de las matrices empieza en cero For co1 = 0 To 9 For co2 = 0 To 9 mNumeros( co1. observa el uso de la funcion Trim para quitar espacios sobrantes Nombre = Trim( InputBox( "Escribe un nombre". 0 ) = "Lidia" mTelefonos( 2. 4 ) End Sub Observa el uso de la función Rnd(). 0 ) = "Antonio" mTelefonos( 1. "Nombre" ) ) Telefono = Trim( InputBox( "Ahora su telefono". 1 ) = "32458924" MsgBox "El telefono de " & mTelefonos( 2. veamos como: Sub Dim Dim Dim Dim Dim Dim Matrices_Multidimension4 mDirectorio( 0. 0 ) & " es " & mTelefonos( 2. 0 ) = Nombre mDirectorio( co1. solo la primer dimension Redim Preserve mDirectorio( co1. que nos devuelve un número aleatorio entre 0 y 1 que al ser multiplicado por el valor superior que nos interesa y sumarle el valor inferior que nos interesa. 1 ) = "12345678" mTelefonos( 1. veamos un sencillo ejemplo: Sub Matrices_Multidimension3 Dim mTelefonos( 2. 1 ) As String Nombre As String Telefono As String iContinuar As Integer co1 As Integer sTmp As String Do 'Solicitamos el nombre. 0 ) & " es " & mDirectorio( co1. nos da dicho número aleatorio entre estos dos y sin querer tienen ahora el “algoritmo” para que devuelvas un número aleatorio entre dos valores dados. 4 + 32. "Telefono" ) ) 'Redimencionamos la matriz. 1 ) 'Guardamos los datos en el nuevo indice mDirectorio( co1. Con las matrices de dos dimensiones podemos simular el uso de una pequeña base de datos o el uso de una hoja de calculo donde guardamos una serie de datos en columnas que se denominan “campos” y filas que se denominan “registros”. co2 ) = Rnd() * 100 + 1 Next Next 'Comprobamos un indice cualquiera MsgBox mNumeros( 4. "Continuar" ) Loop While iContinuar = 6 . 1 ) = Telefono 'Vamos construyendo nuestro directorio sTmp = sTmp & "El telefono de " & mDirectorio( co1. 1 ) & Chr(13) 'Incrementamos nuestro contador de registros co1 = co1 + 1 'Preguntamos si desea continuar iContinuar = MsgBox( "¿Deseas capturar mas datos?". 6 Matrices – Juntos pero no revueltos Observa atentamente que hacemos un poco de trampa al ir guardando los valores introducidos por el usuario en un variable temporal (sTmp). algunas funciones y estructuras de OpenOffice. Obliga al usuario a introducir un nombre y teléfono."Pino".56 'Mostramos nuestro directorio MsgBox sTmp End Sub 4."Gato". y por supuesto."Oso"."Tiburon". como en el ejemplo siguiente: MsgBox Ubound( mDirectorio. tienes que encontrar la manera de preguntarle al usuario si quiere borrar un registro. pero esta dentro de lo posible y confío en tus capacidades."Potasio". de ahí la importancia de que las conozcas. si le estableces un número superior al de dimensiones que tiene la matriz. Otra variante del uso de las matrices."Caoba". así que. con lo cual. 1 ) En donde nos mostrara el indice superior de la primer dimensión y así sucesivamente."Plata". tener dentro de una matriz otra matriz."Fresno") mDatos(2) = Array("Cobre". como una matriz dentro de otra. Te muestre tu directorio completo. llenando la variable sTmp “después” de salir del bucle. para corroborarlo. Por ultimo. es decir. si. a trabajar. pero ya lo notaste. te dará un error. ingeniatelas para poder darle la oportunidad al usuario de borrar un registro."Burro") mDatos(1) = Array("Cedro". veamos su uso: Sub Matrices_Matrices1 Dim mDatos(2) As Variant Dim mTmp As Variant mDatos(0) = Array("Perro". borrarlo efectivamente."Fierro") mTmp = MsgBox mTmp = MsgBox mTmp = MsgBox End Sub mDatos(0) mTmp(0) mDatos(1) mTmp(1) mDatos(2) mTmp(2) Observa el uso de una variable temporal (mTmp) para asignar la matriz interna y así poder acceder a sus valores. 2. es decir. Si. algunos autores a estas le llamas matrices escalares. es decir. pero con una pequeña variante. están implementadas de estar forma. de tarea tienes que modificar la macro para que: 1."Manganeso". no estamos muy seguros de que efectivamente los datos estén siendo guardados dentro de la matriz. su uso es muy sencillo.org que veremos más adelante. para resolver esto tienes que hacer uso de la función UBound vista más arriba. veamos un ejemplo divertido de los que me gustan: Sub Dim Dim Dim Dim Matrices_Matrices2 mDatos(3) As Variant mTmp As Variant co1 As Integer sCaracter As String . es tener matrices de matrices. que no estén vacíos estos campos 3. reconozco que el punto tres no esta nada fácil cuando uno va empezando. le tienes que indicar de que dimensión quieres saber su limite superior."Azufre". es decir. las variables también se crean y fenecen.1 Ámbito Local . queda a tu curiosidad e imaginación buscarle sus aplicaciones practicas y las no tan practicas."."+"."N".Aprendiendo OOo Basic Dim sContra As String 57 'Llenamos los datos."r". a esta visibilidad y tiempo de vida se le conoce como ámbito de la variable. ahora no Como todo en esta vida. tienes tarea.7."W"."B" ."!" ."h" ."I" . el nivel más bajo y básico ya lo conoces pues."X". veamos cual es: 4.7 Ámbito de variables – Ahora me ves."y".". dar por completo un tema es un poco aventurado. a estas alturas ya te habrás dado cuenta de la cantidad de variantes que se pueden tener con unas cuantas instrucciones de OOo Basic por lo cual."ñ"."7". letras mayusculas."U". UNO de los cuatro grupos mTmp = mDatos( CInt( Rnd() * 3 ) ) 'Seleccionamos aleatoriamente."Q"."t"."n". casi completo."¿"."s"."F" ."Z") mDatos(2) = Array("1"."2"."e" ."%" . pero todas lo hacen."}".".". que a veces. observa como tenemos cuatro grupos."0") mDatos(3) = Array( "\" ."[") 'Nuestra contraseña sera de 10 caracteres For co1 = 1 To 10 'Seleccionamos aleatoriamente."<".". lo damos por concluido."{". numeros y caracteres especiales mDatos(0) = Array( "a". letras minusculas. si."l" . son las más divertidas."c" ."w". bueno."k". unas duran más otras menos."k" . UN elemento del grupo."¡". lo cual aprenderemos en este capitulo. "b" ."]". la buena noticia es que nosotros decidimos cuando y cuanto."5"."x"."Ñ"."R"."P"."H" ."(" ."Y"."d" . modifica la macro de modo que le pregunte al usuario de cuantos caracteres quiere su contraseña."/" .">"."V". aquellas que no sirven para nada."m"."$" . observa como usamos la funcion Rnd y la multiplicamos por el indice superior del grupo seleccionado sCaracter = mTmp( CInt( Rnd() * UBound(mTmp) ) ) 'Vamos juntando los caracteres de la contraseña sContra = sContra & sCaracter Next 'Mostramos la contraseña MsgBox "Tu contraseña es: " & sContra End Sub Analizala y veras que no es tan complejo como parece y si."6"."C" . si has seguido estos apuntes.")" ."4"."&" . digamos entre 5 y 50 caracteres Y sin querer tenemos un nuevo capitulo completo."S"."L" ."z") mDatos(1) = Array( "A" ."9"."j" ."|" . ponle un rango mínimo y máximo que pueda escoger."?" .". los has venido usando desde el inicio de estas notas."i" . este capitulo."_"."o". entendiendo por tiempo de vida."J" ."O"."=" ."v"."T". ¡Feliz programación! 4."u"."K" . el tiempo que esta disponible para poder acceder y manipular su contenido."·" ."G" .":"."M". lo siento."-"."D" . determinara su “visibilidad” y tiempo de vida."f" . El lugar donde declares una variable y como lo hagas. pero para fines prácticos."3"."E" ."g" ."p"."8". para comprobar que efectivamente. el IDE de solo te mostrara un error. solo esta macro puede “ver” a la variable iEdad. no hemos definido la variable para “esa macro” dentro de esa macro. en resumen. te recomiendo que nunca olvides de usar.7 Ámbito de variables – Ahora me ves. ojo. crea una segunda macro desde donde intentemos usar esta variable: Sub Variables_Locales2 'Intentamos mostrar el valor de la variable iEdad MsgBox iEdad End Sub Por supuesto. lo cual.58 4. todas la variables declaradas dentro de macros. Veamos un ejemplo más. te evitara muchos dolores de cabeza. como en: Option Explicit Sub Variables_Locales1 Dim iEdad As Integer 'Mostramos el valor de la variable MsgBox iEdad 'Cambiamos su valor iEdad = 34 'Mostramos de nuevo el valor de la variable MsgBox iEdad End Sub Ejecuta varias veces la macro anterior para que observes como “siempre” el valor inicial de la variable es cero. tienen ámbito local. si tienes la precaución de usar la palabra clave Option Explicit. tienes que ejecutar la macro que se llama Variables_Locales3: Option Explicit Sub Variables_Locales3 Dim sTmp As String sTmp = "Aquí no soy nadie" Call Soy_Filosofo Call Soy_Divertido MsgBox sTmp End Sub . si ejecutas la segunda macro. te tiene que dar un error como el de la siguiente imagen: Observa la flecha en el margen izquierdo que nos indica la línea donde se produjo el error y observa también el mensaje que es muy claro. Entonces. ahora no Estas variables son las que se declararan dentro del cuerpo de una macro o función y se crean al invocar a esta y se destruyen al finalizar. pero esta segunda versión donde llamamos varias veces a la macro Contar: Option Explicit Sub Variables_Locales4 Call Contar() Call Contar() Call Contar() End Sub Sub Contar Static iContador As Integer iContador = iContador + 1 MsgBox iContador End Sub . específicamente en la declaración de la variable y volvemos a ejecutar la macro Variables_Locales4. vamos a hacer un pequeño cambio a la macro Contar.Aprendiendo OOo Basic Sub Soy_Filosofo Dim sTmp As String sTmp = "Ahora soy un filosofo" MsgBox sTmp End Sub Sub Soy_Divertido Dim sTmp As String sTmp = "Ahora soy divertido" MsgBox sTmp End Sub 59 Tienes que ser muy observador para que notes como la variable toma el valor asignado en cada macro. siempre te muestra el valor 1. es decir. Copia las dos macros siguientes y ejecuta la que se llama Variables_Locales4 varias veces: Option Explicit Sub Variables_Locales4 Call Contar() End Sub Sub Contar Dim iContador As Integer iContador = iContador + 1 MsgBox iContador End Sub Siempre lo mismo. ¿que pasará si llamamos a la macro varias veces como en el ejemplo siguiente?: Option Explicit Sub Variables_Locales4 Call Contar() Call Contar() Call Contar() End Sub Sigue igual. ¿verdad?. ¿verdad?. cada una es diferente y se inicializa y termina con la macro donde se declara. ahora. tu decides. dice el maestro Savater. ejecutando varias veces la macro Variables_Locales4. por que llamamos a la macro Contar tres veces y esta. Option Explicit Sub Variables_Locales5 Dim iRespuesta As Integer Do Call Contar() iRespuesta = MsgBox( "¿Continuar contando?".7.60 4. pero continuamente te invito a experimentar y a que tomes tus propias decisiones y te forjes tus propios criterios para tu programación. para que nos avise siempre si no hemos declarado una variable. corresponde a las variables declaradas en la cabecera de un modulo usando la palabra clave Private. te recuerdo. aunque estemos declarando la variable iContador como Static. si lo prefieres. pero ahora. Option Explicit Sub Variables_Locales4 Call Contar() Call Contar() Call Contar() 'La siguiente linea “deberia” darte un error MsgBox iContador End Sub ¿Verdad que es muy divertido?. -nos vienen bien las enseñanzas de los maestros. no por ello deja de ser una variable de ámbito local. con lo que le estamos indicando que conserve el valor entre las llamadas a la macro. el siguiente cambio en la macro te debería dar un error de -variable no definida-. para que cuente hasta que le digamos que “No”. incrementa el valor de la variable una unidad cada vez. recuerda que la cabecera es el inicio de un modulo. aquí como en la vida.2 Ámbito Privado Este segundo nivel. usamos la palabra clave Static. ahora no ¿Lo notaste?. pues eso. pero te aseguro que lo agradecerás más de una vez. donde “siempre” tienes que agregar la otra importante palabra clave Option Explicit. no es obligatorio. puedes crear otra macro para que la anterior quede tal cual. "Continuar") 'Recuerda que si el usuario presiona Si. Observa el ejemplo siguiente: Option Explicit 'Observa que en vez de Dim estamos usando Private Private intContador As Integer Sub Sumar_y_Restar 'Llamamos a la macro Sumar . le haremos un pequeño cambio a la macro Variables_Locales4. dentro de la macro Contar. esto. como puedes comprobarlo fácilmente tratando de mostrar su valor desde la macro Variables_Locales4. en nuestro caso.7 Ámbito de variables – Ahora me ves. observa como declaramos la variable iContador en la macro Contar. en vez de usar la palabra clave Dim. Espero que lo hayas notado. como podrás demostrarlo. OJO. estamos solos para decidir-. el valor máximo siempre es tres. este valor lo conservara mientras se ejecute la macro que llamo a la macro donde esta declarada la variable Static. 4+32. el valor que devuelve MsgBox es 6 Loop While iRespuesta = 6 End Sub 4. pero al final. la variable intContador. es “visible” y manipulable por cualquier macro o función declarada en el modulo. . ojo. vamos a adelantarnos un poquito en los temas y veremos como agregar un segundo modulo a nuestra biblioteca para agregar más macros y demostrar como las variables declaradas a nivel modulo con Private son visibles por cualquier otro modulo. solo son visibles para el modulo donde se declaran. 3. da un clic con el botón secundario de tu ratón (normalmente el derecho) sobre la etiqueta del modulo actual donde estés trabajando. "Sumar y Restar") Select Case iRes Case 6 Call Sumar() Case 7 Call Restar() End Select MsgBox intContador Loop Until iRes = 2 End Sub Ahora si.1 End Sub Nota como ahora. seleccionas Insertar y después Modulo BASIC como te muestro en la siguiente imagen. pero en mis pruebas TAMBIEN son visibles en otros módulos. la teoría dice que estas variables. veamos una variante de la macro anterior para seguir sumando y restando: Option Explicit Private intContador As Integer Sub Sumar_y_Restar2 Dim iRes As Integer Do iRes = MsgBox( "Para sumar presiona SI" & Chr(13) & "Para restar presiona NO" & _ Chr(13) & "Para salir presiona CANCELAR".Aprendiendo OOo Basic 61 Call Sumar() 'Mostramos el valor de la variable MsgBox intContador 'Llamamos a la macro Restar Call Restar() 'Mostramos de nuevo el valor de la variable MsgBox intContador End Sub Sub Sumar 'Aquí aumentamos la variable en dos unidades intContador = intContador + 2 End Sub Sub Restar 'y aquí restamos a la variable una unidad intContador = intContador . para ello. antes de demostrarte esto. esta acción te tiene que mostrar un menú contextual. de este. pues de este modo. vamos a renombrarla y trataremos de acceder a la variable intContador declarada y usada en el modulo uno. te dejo a tu criterio que lo hagas. notaras en el menú contextual anterior. la variable es accedida desde otras bibliotecas del archivo. lo cual espero se arregle en futuras versiones.62 4. copia y ejecuta la siguiente macro: Option Explicit Private intContador As Integer Sub ValorVariable intContador = 100 'Llamamos a la macro del modulo 2 Call MostrarValor() End Sub Creo que es bastante claro que la variable se puede manipular y acceder desde cualquier otro modulo. pero observa como “no” nos da error. en mis pruebas. este agrega la declaración de una nueva macro. como se que eres observador. aun y cuando se declare con Private. pues toma la declaración de la variable del modulo 1. de forma predeterminada. que es cero. Te . nos basta tener dos módulos para pruebas como en: Nota que al insertar un modulo. usar Private y Dim es indistinto y el siguiente tema no tiene razón de ser. como dice la teoría. Volvamos al modulo 1. ahora no Tienes que ver el nuevo modulo al lado del anterior. incluso. por ahora. veamos que pasa: Option Explicit Sub MostrarValor() MsgBox intContador End Sub Nota que la macro anterior esta en el modulo 2 y al ejecutarla nos muestra el valor de la variable.7 Ámbito de variables – Ahora me ves. pues recuerda que el valor inicial de toda variable numérica es cero. tienes la opción de cambiar el nombre del modulo. aun y cuando ya termino la ejecución de la macro. al ser de ámbito local. aun y cuando se termina la macro.3 Ámbito de Dominio Publico En este ámbito. declaradas con la palabra clave Static.Aprendiendo OOo Basic 63 agradeceré si haces tus pruebas y si notas algo diferente o te funciona como “debería” me lo hagas saber. debe ser declarada en la cabecera de un módulo con la palabra clave Global de la siguiente manera: Option Explicit Global intgContador As Integer Sub Variable_Global() intgContador = intgContador + 100 MsgBox intgContador End Sub Al ejecutar varias veces la macro anterior. El decidir que variables usar y con que ámbito no es un tema menor y cuando uno va empezando se convierte casi en un problema existencial. Su uso podría compararse en función a las variables de ámbito local. pero a nivel global de todas las macros del archivo. 4. que las variables declaradas a nivel cabecera de modulo usando la palabra clave Dim. pero no te preocupes.7. Para que una variable sea de ámbito global.7. pero difiere en cuanto a su función. pues esta guarda su ultimo valor. pero en mis pruebas es visible hasta por los módulos de otras bibliotecas del archivo y se comporta exactamente del mismo modo que las variables de ámbito privado vistas en el tema anterior. la recomendación para este tema es procurar usar lo más posible variables de ámbito local y después de ámbito publico. esto es por que conforme ya no uses una variable. esta se destruye y se libera la memoria usaba por ella al concluir la macro donde se use. te sea más fácil aprender a decidir lo mejor en cada caso. por supuesto esto no es restrictivo solo tu practica y experiencia te dirán cual es la mejor opción. 4.4 Ámbito Global Este ámbito es igual al de dominio publico en cuanto a su visibilidad. por lo que no lo repetiré aquí.8 Funciones y subrutinas – Divide y vencerás “Todo lo complejo puede dividirse en partes simples” . solo esperemos que pronto se arregle y funcione como dicen que debe hacerlo. Option Explicit Dim intContador As Integer 4. notaras como guarda el valor. se supone. son visibles para cualquier modulo de la biblioteca. Y con esto terminamos un tema más. esperemos que con los muchos ejemplos que mostramos. "Aprendiendo OOo Basic" MsgBox "Solo acabamos este tema". 48. por lo que lo único que cambia es la cadena mostrada. Es decir “haga” algo. "Aprendiendo OOo Basic" MsgBox "Es fácil y divertido". comencemos con los ejemplos y después las explicaciones. entonces. esto no es requisito. En estos casos. 48. analizar o mejorar. En este capitulo veremos como declararlas y usarlas. las siguiente líneas son equivalentes: . "Aprendiendo OOo Basic" End Sub Lo importante es que aprendas como llamamos a una macro con argumentos y que es muy importante que. vimos algunos conceptos que nos serán muy útiles en este. este caso es idóneo para que hagamos una subrutina. como en otros más que tal vez se te presenten.64 4. 48. y sigamos con nuestras suposiciones. "Aprendiendo OOo Basic" MsgBox "Ya tengo sueño". “necesitamos” pasarle una variable. supongamos que de nuestros mensajes. que no es más que una macro creada por nosotros a la que comúnmente (no es obligatorio) se le pasa un/unos parámetro(s) o argumento(s) y realice una tarea. en otras ocasiones. siempre son los mismos. no nos son suficientes para resolver algún problema planteado o su complejidad nos obliga a pensar en otra alternativa. sino que sea de tipo String. el código se vuelve tan largo que se vuelve difícil de leer.8 Funciones y subrutinas – Divide y vencerás Rene Descartes En ocasiones.2 Instrucciones y funciones en OOo Basic . "Aprendiendo OOo Basic" End Sub Ahora tenemos dos macros que hacen cosas muy similares. no tiene nada de extraordinario. pero nos resultara muy útil para nuestros propósitos. los argumentos pasados sean del mismo tipo de los esperados. En el tema 4. al llamarla. el icono mostrado y el titulo del cuadro de dialogo. 48. 48. 48. También observa que usamos la palabra clave Call para llamar a la macro. "Aprendiendo OOo Basic" End Sub Si. recurrimos a crear nuestras propias funciones y subrutinas. las funciones e instrucciones incorporadas del lenguaje. observa como la macro MuestraMensaje “necesita” un argumento llamado Mensaje que es de tipo String. 48. "Aprendiendo OOo Basic" MsgBox "Ya voy a medio camino". no importa el nombre. Vamos a suponer una segunda macro similar a la anterior: Sub MostrarMensaje2() MsgBox "Es un poco tarde". copia y ejecuta la siguiente macro: Option Explicit Sub MostrarMensaje1() MsgBox "Estoy aprendiendo OOo Basic". Copia la siguiente macro y modifica las dos primeras macros para que queden de la siguiente manera: Option Explicit Sub MostrarMensaje3() Call MuestraMensaje( Call MuestraMensaje( Call MuestraMensaje( Call MuestraMensaje( Call MuestraMensaje( Call MuestraMensaje( End Sub "Estoy aprendiendo OOo Basic" ) "Es facil y divertido" ) "Ya voy a medio camino" ) "Es un poco tarde" ) "Ya tengo sueño" ) "Solo acabamos este tema" ) Sub MuestraMensaje(Mensaje As String) MsgBox Cadena. en lo personal.Aprendiendo OOo Basic 65 Sub MostrarMensaje3() Call MuestraMensaje( "Estoy aprendiendo OOo Basic" ) MuestraMensaje( "Estoy aprendiendo OOo Basic" ) MuestraMensaje "Estoy aprendiendo OOo Basic" End Sub Observa como en la primera usamos Call y paréntesis. es decir 'no hemos podido cambiar su valor en la subrutina MsgBox sMensaje End Sub 'Observa el cambio en la declaracion del argumento usando ByVal . por lo cual. Cuando pasamos los argumentos por valor. En lo personal el uso de Call solo lo uso para saber que es una subrutina personalizada. cuando los argumentos se pasan por referencia. el valor de este argumento solo se puede usar “dentro” de la subrutina que la usa. también. una es por valor y otra por referencia. en la segunda omitimos Call y en la tercera quitamos Call y los paréntesis. El uso de paréntesis como abras notado también es opcional. 48. en el siguiente ejemplo: Option Explicit Sub PasoPorValor() Dim sMensaje As String 'Asignamos una cadena a la variable sMensaje = "El trabajo es el refugio de los que no tienen nada que hacer" 'Llamamos a la subrutina y le pasamos el argumento Call NoCambiaValor( sMensaje ) 'Mostramos la variable que nos muestra lo mismo. Ahora. no así. la diferencia es muy sencilla pero es de suma importancia esta diferencia. como muchas instrucciones que usa OpenOffice. pero ya sabes. cambiado en la subrutina MsgBox sMensaje End Sub Sub CambiaValor(Cadena As String) 'Mostramos el mensaje con la cadena pasada MsgBox Cadena. se le pueden pasar los argumentos o parámetros de dos maneras. veremos un tema importante. a una subrutina. en realidad lo que se hace es pasarle una “copia” del valor de la variable. en cambio. modificamos el argumento pasado y el cambio se ve reflejado en la variable origen. queda a tu criterio su uso u omisión. podemos modificar su valor “dentro” de la subrutina. tienes la ultima palabra. "Cadena Original" 'Modificamos el argumento pasado Cadena = "Eso lo dijo Lao Tse" End Sub Observa como en este caso. por lo cual.org hacen uso de los paréntesis. hago uso de ellos. lo que estamos haciendo es pasarle la “ubicación” de la variable en la memoria. comprobemoslo con un ejemplo: Option Explicit Sub PasoPorReferencia() Dim sMensaje As String 'Asignamos una cadena a la variable sMensaje = "La travesia de mil kilometros comienza con un paso" 'Llamamos a la subrutina y le pasamos el argumento Call CambiaValor( sMensaje ) 'Mostramos la variable con el nuevo valor. por el momento. la variable origen quedo intacta. Todas las subrutinas que tengan argumentos tienen que ser invocadas (llamadas) desde otra macro.org por ejemplo.66 Sub NoCambiaValor( ByVal Cadena As String ) 'Mostramos el mensaje con la cadena pasada MsgBox Cadena. leí que una macro. se pasa por valor. salvo que se indique lo contrario. algunos programadores opinan que todos los argumentos deberían pasarse por referencia. si es no... se las vamos a dejar a grandes proyectos. procedimiento o subrutina. tienes que usar la palabra clave ByVal “antes” del nombre del argumento. los argumentos se pasan por referencia. pues al pasar la dirección de la variable en memoria. Las preocupaciones del uso de la memoria. pero observa la diferencia en la declaración de la subrutina.8 Funciones y subrutinas – Divide y vencerás Ahora. escribir . no recuerdo donde. "Cadena Original" 'Intentamos modificar el argumento pasado Cadena = "Eso lo dijo Oscar Wilde" End Sub 4. Una pregunta que nos ayuda a saber si declaramos una variable por valor o referencia es: ¿necesito manipular su valor en la subrutina?. para pasar un argumento por valor. para nuestros fines prácticos. donde están involucradas millones de líneas de código. He observado que hay dos criterios encontrados en el uso de los argumentos por valor o referencia. no estamos usando más memoria a este criterio podría argumentarse que los equipos actuales tienen mucha más memoria. si la respuesta es si se pasa por referencia. 48. pues una subrutina tiene que ser como una unidad completa por si misma. Por default. te dará el siguiente error: Y si la intentas ejecutar desde la interfaz del usuario. cierta ocasión. desde el menú Herramientas | Macros | Ejecutar macro. esto por supuesto es sumamente subjetivo.. tu decides. no “debería” tener más de una página de líneas. te dará el siguiente error: Las subrutinas nos ayudan a dividir nuestro código en bloques lógicos o más manejables. otros dicen que todos los argumentos deberían pasarse por valor. si intentas ejecutar directamente una subrutina con argumentos desde el IDE. como OpenOffice. y la memoria usada se libera al finalizar la subrutina. es decir. si pasas los argumentos en subrutinas y funciones por valor o referencia. argumentan que la “validación de datos” (no se te olvide esta frase). algunos autores no recomiendan el uso de la instrucción Exit Sub. Habrá ocasiones. sale inmediatamente de la macro con la instrucción Exit Sub. veamos su uso: Option Explicit Sub Ejemplo_ExitSub() Dim sFrase As String sFrase = Trim(InputBox("Escribe una frase")) Call ContarLetras( sFrase ) End Sub Sub ContarLetras( Cadena As String) If Cadena = "" then Exit Sub Else MsgBox "Hay" & Str(Len(Cadena)) & " letras en la cadena" & Chr(13) & Chr(13) & Cadena End If End Sub Observa como en la subrutina ContarLetras si el argumento pasado esta vacío. que estas “deberían” hacer solo su trabajo y pasarle los datos correctos. observa las modificaciones a las macros anteriores: Sub Ejemplo_ExitSub2() Dim sFrase As String sFrase = Trim(InputBox("Escribe una frase")) If sFrase <> "" Then Call ContarLetras2( sFrase ) End If End Sub Sub ContarLetras2( Cadena As String) MsgBox "Hay" & Str(Len(Cadena)) & " letras en la cadena" & Chr(13) & Chr(13) & Cadena End Sub Nota que la validación la hacemos con la linea: If sFrase <> "" Then . por supuesto queda a tu criterio y experiencia su uso. es decir. la practica diaria te dictara los mejores argumentos para programar. existe una instrucción que se llama Exit Sub. incluso. no “debería” necesitar salidas “forzadas”. en que quieras salir anticipadamente de una subrutina. una vez más. en “teoría” una subrutina “debería” ser completa. para ello. para ejemplificar esto. se tiene que hacer “antes” de llamar a una subrutina. es decir. por ejemplo.Aprendiendo OOo Basic 67 “código compacto” no es sinónimo de “código eficiente”. la subrutina anterior podría quedar así: Sub ContarLetras1( Cadena As String) If Cadena <> "" then MsgBox "Hay" & Str( Len(Cadena) ) & " letras en la cadena" & Chr(13) & Chr(13) & Cadena End If End Sub Observa como solo ejecutamos el código si el argumento Cadena “no” esta vacío. algunos autores más exigentes. "Area de un circulo". no es común usar subrutinas para manipular variables y argumentos. Veamos otro ejemplo de una subrutina. despues convertimos el valor a tipo Single. garantizar que sean correctos. que es el tipo de variable esperado sRadio = CSng( Trim( InputBox( "¿Cual es el radio?". es decir. lo más usual. sus defensores y sus detractores. un gran porcentaje de errores en muchos programas es por una deficiente validación de datos y también. si se quiere “devolver” un valor. "1" ) ) ) 'Solo si tenemos valores mayores a cero If sRadio > 0 Then dArea = PI * ( sRadio ^ 2 ) MsgBox "El area de un circulo de radio = " & Str(sRadio) & " es =: " & Str(dArea) End If End Sub Si creamos una subrutina. Solo te digo. "1" ) ) ) . es usar una función en vez de una subrutina. ya le estamos pasando un dato validado. correcto. por que dentro de la subrutina no es necesario hacer ninguna validación. ya te darás cuenta. usando una función. es “validar tus datos”. dArea ) MsgBox "El area de un circulo de radio " & Str(sRadio) & " es =: " & Str(dArea) End If End Sub Sub DevuelveAreaCirculo( Radio As Single. "Area de un circulo".1416 'Solicitamos el radio del circulo a calcular. por supuesto esto tiene sus pros y sus contras. quedaría de la siguiente manera: Option Explicit Sub CalcularAreaCirculo3() Dim dArea As Double Dim sRadio As Single sRadio = CSng( Trim( InputBox( "¿Cual es el radio?". Area As Double ) Const PI As Single = 3. que un gran porcentaje de código. observa que primero limpiamos los espacios 'con Trim. otra vez lo repito. se nos va.8 Funciones y subrutinas – Divide y vencerás Por lo que al llamar a la macro ContarLetras2. aplica tu criterio que la experiencia y la practica serán tus mejores aliadas.68 4. "1" ) ) ) If sRadio > 0 Then Call DevuelveAreaCirculo( sRadio. la macro anterior. no importa donde lo hagas pero validalos. Supongamos que nos piden hacer una macro que solicite el radio de un circulo y se calcule su área: Option Explicit Sub CalcularAreaCirculo1() Dim dArea As Double Dim sRadio As Single Const PI As Single = 3. podría ser algo así: Option Explicit Sub CalcularAreaCirculo2() Dim dArea As Double Dim sRadio As Single sRadio = CSng( Trim( InputBox( "¿Cual es el radio?". validando datos. Lo que si nunca. "Area de un circulo". nunca debes de dejar de hacer.1416 Area = PI * ( Radio ^ 2 ) End Sub Si bien lo anterior funciona. "Circulo". "1" ) ) ) If sRadio > 0 Then 'Aqui usamos la funcion SIN el argumento opcional dArea = Circulo( sRadio ) 'Y aqui usamos la funcion CON el argumento opcional dPeri = Circulo( sRadio. ahora. Otro cambio importante es que para devolver el valor dentro de la función.1416 'Comprobamos si el parametro se paso o no If IsMissing( Perimetro ) Then 'Si no se paso le asignamos el valor por default Perimetro = False End If If Perimetro Then Circulo = PI * ( Radio * 2 ) Else Circulo = PI * ( Radio ^ 2 ) .1416 'Observa como usamos el nombre de la función para devolver al valor AreaCirculo = PI * ( Radio ^ 2 ) End Function Observa el modo de declarar una función. tiene otra posibilidad muy interesante. es decir. en vez de usar otro argumento o variable. el paso de argumentos opcionales. El paso de argumentos en subrutinas y funciones. como el paso por valor o referencia. en vez de usar la palabra clave Sub. usamos una nueva palabra clave Function. la declaración de los argumentos tiene las mismas características usadas en las subrutinas.Aprendiendo OOo Basic 69 If sRadio > 0 Then 'Observa como usamos la funcion y asignamos el resultado a una variable dArea = AreaCirculo( sRadio ) MsgBox "El area de un circulo de radio = " & Str(sRadio) & " es =: " & Str(dArea) End If End Sub Function AreaCirculo( Radio As Single ) As Double Const PI As Single = 3. le agregaremos un argumento opcional para saber si lo que queremos calcular es el perímetro: Option Explicit Sub Dim Dim Dim CalcularCirculo dArea As Double dPeri As Double sRadio As Single sRadio = CSng( Trim( InputBox( "¿Cual es el radio?". por supuesto. "Circulo" End If End Sub Function Circulo( Radio As Single. continuemos con nuestro ejemplo del circulo. True ) MsgBox "Area = " & Str(dArea) & chr(13) & _ "Perimetro = " & Str(dPeri). también pueden devolver el tipo por default de las variables que es Variant pero la recomendación es especificar siempre que te sea posible el tipo de valor que esperas devuelva la función. usamos el mismo nombre de la función como destino y para finalizar. en “todas” las declaraciones de Function. supongamos que ahora se nos pide hacer una macro que calcule ya sea el área o el perímetro de un circulo. debemos cerrarlas con End Function. sino. en vez de usar End Sub como hasta ahora. para usar la misma función. pero un cambio importante. las funciones también devuelven un “tipo” especifico de valor. Optional Perimetro As Boolean ) As Double Const PI As Single = 3. 64. es el tipo de valor “devuelto” por una función. te dará un error. matrices.50.80. el punto importante es que “compruebes” si se paso o no el argumento para que en su defecto. veamos un ejemplo de uno y otro: Option Explicit Sub Sumando Dim mDatos(9) As Integer Dim co1 As Integer 'Llenamos la matriz con datos aleatorios entre 1 y 100 For co1 = LBound( mDatos() ) To UBound( mDatos() ) mDatos( co1 ) = Rnd() * 100 + 1 Next MsgBox "La suma de la matriz es = " & Str( SumaMatriz( mDatos() ) ) End Sub Function SumaMatriz ( Datos() As Integer ) As Integer Dim co1 As Integer For co1 = LBound( Datos() ) To UBound( Datos() ) SumaMatriz = SumaMatriz + Datos( co1 ) Next End Function Observa como se declaro la matriz tipo Integer. intentemos usar una matriz.8 Funciones y subrutinas – Divide y vencerás Nota el uso de la palabra clave Optional. verdadera o falsa (Boolean).40. tienes siempre que declararlos como Variant si para llenar dicha matriz usas la función Array. Por supuesto. ¿que es lo que desea calcular? Y por supuesto. ahora. puedes usar el mismo tipo con que declares tu matriz. solo muestra el valor del calculo solicitado. para verificar si se paso o no un argumento usas la función de OOo Basic IsMissing( Argumento ). haciendo uso de la función Array y veamos que pasa: Option Explicit Sub Sumando2() Dim mDatos() As Integer Dim iSuma As Integer 'Llenamos la matriz con la funcion Array mDatos() = Array(10. en otros casos. puedes declarar tantos argumentos opcionales como necesites. tanto la variable en la macro como el argumento en la declaración de la función.60. lo único que tienes que considerar es que los argumentos esperados como matrices.20. como se ve en el ejemplo anterior. pero en tus funciones puede declarar al igual que los otros argumentos. le asignes un valor por default a dicho argumento.70.30. para fines de lo que se nos pide usamos una variable tipo boleana. De tarea.90) 'Intentamos sumar la matriz iSuma = SumaMatriz( mDatos() ) MsgBox Str( iSuma ) End Sub Function SumaMatriz ( Datos() As Integer ) As Integer Dim co1 As Integer .70 End If End Function 4. del tipo que necesites. a las funciones también es posible pasarle como argumentos. modifica la macro para que le preguntes al usuario. Correo. Function SumaMatriz ( Datos() As Variant ) As Integer Dim co1 As Integer For co1 = LBound( Datos() ) To UBound( Datos() ) SumaMatriz = SumaMatriz + Datos( co1 ) Next End Function Observa como cambiamos a tipo Variant el tipo de matriz que espera con lo cual. necesites asignarle un valor predeterminado diferente ValidarCorreo = False Exit Function Else 'Buscamos la posicion de la arroba con la función InStr pos = InStr( 1.Aprendiendo OOo Basic 71 For co1 = LBound( Datos() ) To UBound( Datos() ) SumaMatriz = SumaMatriz + Datos( co1 ) Next End Function Nos da un error. también es posible hacer uso de la instrucción Exit. solo validaremos que el correo tenga 'el obligado símbolo de arroba (@) y que no sea ni el primer 'ni el ultimo carácter Function ValidarCorreo( Correo As String ) As Boolean Dim pos As Integer 'Si el argumento Correo esta vacío. tan solo te muestro un sencillo ejemplo de su uso: Option Explicit Sub Correo() Dim sCorreo As String sCorreo = Trim(InputBox("Dame tu correo")) If ValidarCorreo( sCorreo ) Then MsgBox "Correo Valido" Else MsgBox "Correo NO valido" End If End Sub 'Para fines didácticos. siempre. claro. ya no nos da error. salimos de la función If Correo = "" Then 'Si lo deseas esta linea la puedes omitir. pues al salir con Exit Function 'la función devuelve Falso. Corrige la declaración de la función y ahora si. esto es por que la función Array. En las funciones. aquí usaremos Exit Function. siempre devuelve una matriz tipo Variant. ¿verdad?. la razón es que la función espera una matriz de tipo Integer y se le esta pasando una matriz de tipo Variant. "@" ) 'No debe ser ni el primero ni el ultimo carácter 'en el siguiente tema aprenderemos más de los operadores lógicos If pos > 1 And pos < Len(Correo) Then ValidarCorreo = True Else ValidarCorreo = False End If End If End Function . pero tal vez en otros casos que no sea booleana 'la respuesta. debe de funcionar. no importa como hayas declarado la matriz. tiene las mismas consideraciones que te comente para la instrucción Exit Sub. así que no ahondare en ello. veamos el ejemplo de una función que hace uso de una función incorporada del lenguaje que es muy bonita. como sabes. no es una actividad que digamos muy placentera. Chr(13) ) End Function . para ello. que es el valor ASCII para el salto de linea. por ejemplo. el siguiente: Option Explicit Sub MostrarMensajes1() Dim sMensaje As String sMensaje = "Por favor escoge una opcion: CANCELAR = Sales del programa " & _ "REPETIR = Intenta de nuevo IGNORAR = No hace nada" MsgBox sMensaje. de la siguiente manera: Sub MostrarMensajes2() Dim sMensaje As String sMensaje = "Por favor escoge una opcion:" & Chr(13) & Chr(13) & _ "CANCELAR = Sales del programa" & Chr(13) & _ "REPETIR = Intenta de nuevo" & Chr(13) & _ "IGNORAR = No hace nada" MsgBox sMensaje. 2. que. nuestro cuadro de mensaje tiene mucha mejor presentación Pero imaginate que tienes que mostrar múltiples mensajes con diferentes cadenas y estar concatenando los saltos de linea en cada una. la estética no es muy bonita que digamos: Mejoremos un poco la vista de nuestro cuadro de mensaje.8 Funciones y subrutinas – Divide y vencerás Para terminar este tema. se hace usando la función Chr pasandole el argumento 13. "Opcion" End Sub Como podrás notar. "Opcion" End Sub Ahora si. Supongamos que tenemos que mostrar muchos mensajes al usuario. insertando unos saltos de linea. hagamos una función que lo haga por nosotros Function InsertarSaltos( Datos() ) As String InsertarSaltos = Join( Datos(). 2.72 4. espera como argumentos."IGNORAR = No hace nada") 'Llamamos a la funcion que inserta los saltos de linea sMensaje = InsertarSaltos( mMensajes() ) 'Mostramos el mensaje MsgBox sMensaje. por ahora."CANCELAR = Sales del programa". la función Join de OOo Basic. 2.""."REPETIR = Intenta de nuevo". es una función que me gusta mucho. "Opcion" End Sub Dividir nuestro código en subrutinas y funciones.Aprendiendo OOo Basic 73 Observa que función más sencilla y que útil y linda es. juntamos en una cadena unos números separados por un guion: Sub JuntarDatos() Dim mDatos() As Variant Dim sCadena As String mDatos() = Array(100.400. una matriz y un carácter separador. es el pan nuestro de cada día.300. "-") MsgBox sCadena End Sub La función InsertarSaltos la usamos de la siguiente manera: Sub MostrarMensajes3() Dim mMensajes() As Variant Dim sMensaje As String 'Recuerda que la funcion Array SIEMPRE devuelve una matriz Variant mMensajes() = Array("Por favor escoge una opcion:". !!Feliz programación¡¡ .200. en el ejemplo siguiente.500) sCadena = Join( mDatos(). no debes de tener duda pues más adelante las usaremos frecuentemente. lo que hace es juntar cada elemento de la matriz separados por el carácter separador. otro tema a llegado a su fin. el resultado no cabe en la variable iResul declarada como Integer.1 “ ^ ” Exponenciación (aritmético) a Se usa para elevar un número llamado base a otro llamado exponente. por ejemplo. es decir.9 Operadores 4.74 4. n 4. tal vez te resulte familiar: Option Explicit Sub Dim Dim Dim Potencias1() iNum1 As Integer iNum2 As Integer iResul As Integer iNum1 = 2 iNum2 = 10 'Base 'Exponente iResul = iNum1 ^ iNum2 MsgBox Str(iResul) End Sub En general con todos los operadores. debes de tener la precaución de proveer lo mejor posible que el resultado de la operación no exceda el “tamaño” de la variable destino. Sub Dim Dim Dim Potencias2() iNum1 As Integer iNum2 As Integer iResul As Integer iNum1 = 3 iNum2 = 10 'Base 'Exponente iResul = iNum1 ^ iNum2 MsgBox Str(iResul) End Sub .9 Operadores OOo Basic soporta los siguiente operadores aritméticos. de relación y lógicos.9. El número resultante del siguiente ejemplo. la siguiente operación te tiene que dar un error de desbordamiento. pero según tus necesidades podría ser incluso más grande. lo que hace el lenguaje.53 iNum2 = 5. Dim iResul As Long La base y el exponente no tienen por que ser enteros. el signo de la potencia lo determinará el exponente. observa el cambio de declaración de las variables: Sub Dim Dim Dim Potencias3() iNum1 As Single iNum2 As Single iResul As Double iNum1 = 2. invierte la base para que el exponente sea positivo. en este caso Long. de acuerdo a las leyes de los signos que ya conoces desde la escuela elemental.54 'Base 'Exponente iResul = iNum1 ^ iNum2 MsgBox Str(iResul) End Sub Tampoco tienen por que ser positivos. . si es impar será negativa. como lo dictan las matemáticas. cuando la base es negativa. si este es par será positiva. como se comprueba en los siguiente ejemplos: Sub Dim Dim Dim Potencias4() iNum1 As Single iNum2 As Single iResul As Double iNum1 = -2 'Base iNum2 = 4 'Exponente iResul = iNum1 ^ iNum2 MsgBox Str(iResul) 'Resultado positivo iNum1 = -2 'Base iNum2 = 5 'Exponente iResul = iNum1 ^ iNum2 MsgBox Str(iResul) 'Resultado negativo End Sub En el caso de que el exponente sea negativo.Aprendiendo OOo Basic 75 La solución es cambiar la variable iResul por una más grande. 2 “ * ” Multiplicación (aritmético) La multiplicación es la operación aritmética que nos permite hacer una suma abreviada.9 Operadores 2 = −3 1 1 = =0. debe ser lo suficientemente grande para contenerlo. positivos y negativos. Option Explicit Sub Dim Dim Dim Multiplicacion2() iNum1 As Integer iNum2 As Integer iResul As Integer iNum1 = 11 iNum2 = 56 iResul = iNum1 * iNum2 MsgBox Str(iResul) iNum1 = -11 iNum2 = 56 iResul = iNum1 * iNum2 MsgBox Str(iResul) iNum1 = 11 iNum2 = -56 iResul = iNum1 * iNum2 MsgBox Str(iResul) iNum1 = -11 . las leyes de los signos aplican correctamente. al resultado se le llama producto y los números multiplicados factores: Option Explicit Sub Dim Dim Dim Multiplicacion1() iNum1 As Integer iNum2 As Integer iResul As Integer 'Factores iNum1 = 365 iNum2 = 34 iResul = iNum1 * iNum2 MsgBox Str(iResul) End Sub Recuerda que la variable donde asignes el resultado.76 Sub Dim Dim Dim Potencias5() iNum1 As Single iNum2 As Single iResul As Double iNum1 = 2 'Base iNum2 = -3 'Exponente iResul = iNum1 ^ iNum2 MsgBox Str(iResul) End Sub 4. en este caso. que puedes multiplicar valores enteros y no enteros.125 3 2 8 4.9. Es la operación inversa a la multiplicación. podría decirse. Option Explicit Sub Dim Dim Dim Division1() iNum1 As Single iNum2 As Single iResul As Double iNum1 = 123456790 iNum2 = 123 iResul = iNum1 / iNum2 MsgBox Str(iResul) End Sub Sub Dim Dim Dim Division2() iNum1 As Integer iNum2 As Integer iResul As Integer iNum1 = 589 'Dividendo iNum2 = -25 'Divisor iResul = iNum1 / iNum2 MsgBox Str(iResul) 'Dividendo 'Divisor . una resta abreviada.3 “ / ” División (aritmético) Operación aritmética para saber cuantas veces cabe un número en otro. negativos y positivos.Aprendiendo OOo Basic iNum2 = -56 iResul = iNum1 * iNum2 MsgBox Str(iResul) End Sub 77 Recuerda que en las multiplicaciones el orden de los factores no altera el producto (propiedad conmutativa): Sub Dim Dim Dim Multiplicacion3() iNum1 As Integer iNum2 As Integer iResul As Long iNum1 = 12345 iNum2 = 18 iResul = iNum1 * iNum2 MsgBox Str(iResul) iNum1 = 18 iNum2 = 12345 iResul = iNum1 * iNum2 MsgBox Str(iResul) End Sub 4. al otro “divisor”. al resultado entero se le llama “cociente” y si no es exacta la división a lo que resta se le llama “residuo”. las leyes de los signos aplican de la misma forma que en la multiplicación. El número a dividir se llama “dividendo”. es.9. Puedes dividir numero enteros y no enteros. 78 4. cuando el valor decimales es muy cercano al siguiente entero.9 Operadores End Sub En el caso de la división.4 “ \ ” División entera (aritmético) Con este operador obtenemos solo la parte entera de una división: Option Explicit Sub Dim Dim Dim Division_Entera1() iNum1 As Single iNum2 As Single iResul As Single iNum1 = 100 iNum2 = 15 iResul = iNum1 / iNum2 MsgBox Str(iResul) 'Devuelve solo la parte entera iResul = iNum1 \ iNum2 MsgBox Str(iResul) End Sub En algunos casos. este operador te devuelve el siguiente entero. el orden de los operandos si importa. como en: Sub Dim Dim Dim Division_Entera2() iNum1 As Single iNum2 As Single iResul As Single iNum1 = 100 iNum2 = 25.9. es muy diferente que un número sea dividendo que divisor como podemos verlo en el siguiente ejemplo: Sub Dim Dim Dim Division3() iNum1 As Single iNum2 As Single iResul As Double iNum1 = 98765 iNum2 = 321 iResul = iNum1 / iNum2 MsgBox Str(iResul) iNum1 = 321 iNum2 = 98765 iResul = iNum1 / iNum2 MsgBox Str(iResul) End Sub 4.1 iResul = iNum1 / iNum2 MsgBox Str(iResul) . mejor usa la función Int(valor) que te devuelve solo la parte entera del valor pasado.1 iResul = iNum1 / iNum2 MsgBox Str(iResul) iResul = iNum1 \ iNum2 MsgBox Str(iResul) iResul = Int( iNum1 / iNum2 ) MsgBox Str(iResul) End Sub 4.9.5 “Mod” Resto de una división entera (aritmético) Este operador nos devuelve el residuo entero de una división entera: Option Explicit Sub Dim Dim Dim Resto_Division1() iNum1 As Single iNum2 As Single iResul As Single iNum1 = 100 iNum2 = 15 iResul = iNum1 Mod iNum2 MsgBox Str(iResul) End Sub 15 6 100 10 El siguiente ejemplo hace uso de los operadores “Mod” y ”\” (división entera) para convertir un número decimal en binario: Sub Dim Dim Dim Decimal_Binario() iDec As Integer sBin As String iBase As Integer 'Número entero a convertir iDec = 100 'El sistema binario es base 2 iBase = 2 . como te muestro aquí: Sub Dim Dim Dim Division_Entera3() iNum1 As Single iNum2 As Single iResul As Single iNum1 = 100 iNum2 = 25.Aprendiendo OOo Basic 79 iResul = iNum1 \ iNum2 MsgBox Str(iResul) End Sub Si quieres asegurarte que “siempre” te regrese “solo” la parte entera. 55 iResul = iNum1 + iNum2 MsgBox Str( iResul ) End Sub Por su propiedad conmutativa.9 Operadores 4.80 'Hasta que el número sea menor que la base Do Until iDec < iBase 'Obtenemos el residuo y lo vamos concatenando sBin = (iDec Mod iBase) & sBin 'Obtenemos la división entera y reasignamos el numero 'si no haces esto. el orden de los sumandos no altera la suma: Sub Dim Dim Dim Sumas2() iNum1 As Single iNum2 As Single iResul As Single iNum1 = 1974 iNum2 = 34 iResul = iNum1 + iNum2 MsgBox Str( iResul ) iNum1 = 34 iNum2 = 1974 iResul = iNum1 + iNum2 MsgBox Str( iResul ) End Sub .25 iNum2 = 489. te quedaras en un ciclo infinito iDec = iDec \ iBase Loop 'Por ultimo concatenamos el ultimo cociente sBin = iDec & sBin 'Mostramos el valor en binario MsgBox sBin End Sub 4. A dichas cantidades se les llama sumandos y al resultado suma: Option Explicit Sub Dim Dim Dim Sumas1() iNum1 As Single iNum2 As Single iResul As Single iNum1 = 159. es la operación aritmética que nos permite combinar dos cantidades para obtener una sola.9.6 “ + ” Suma (aritmético) La adición. al primero se le llama minuendo y al segundo sustraendo. Es la operación inversa de la suma.9. la suma tendrá el signo del mayor sumando: Sub Dim Dim Dim Sumas3() iNum1 As Single iNum2 As Single iResul As Single iNum1 = 4268 iNum2 = -258 iResul = iNum1 + iNum2 MsgBox Str( iResul ) iNum1 = -5689 iNum2 = 197 iResul = iNum1 + iNum2 MsgBox Str( iResul ) End Sub 4. si intercambias el minuendo y el sustraendo. pero fijate que curioso resultado: Sub Dim Dim Dim Restas2() iNum1 As Single iNum2 As Single iResul As Single iNum1 = 562 iNum2 = 956 iResul = iNum1 .7 “ .iNum2 MsgBox Str( iResul ) End Sub 'Minuendo 'Sustraendo La resta no tiene propiedad conmutativa.Aprendiendo OOo Basic 81 Por leyes de los signos.iNum2 MsgBox Str( iResul ) iNum1 = 956 . no te dará el mismo resultado.” Resta (aritmético) La sustracción o resta es la operación aritmética que nos permite conocer la diferencia entre dos números. Option Explicit Sub Dim Dim Dim Restas1() iNum1 As Single iNum2 As Single iResul As Single iNum1 = 5000 iNum2 = 2125 iResul = iNum1 . es decir. el resultado de la expresión a la derecha del signo se asigna a la variable a la izquierda del signo. este ejemplo es más claro pues esta entre paréntesis: bResul = ( iNum1 = iNum2 ) 4. el segundo signo igual (en negritas y rojo) es usado como operador de relación entre dos términos.9 Not – Negación (lógico) Cambia el valor de la expresión de falso a verdadero y viceversa.iNum2 MsgBox Str( iResul ) End Sub 4. siempre devuelven un valor verdadero (True) o falso (False).9 Operadores 4. Option Explicit Sub Dim Dim Dim Operadores_Relacion() bResul As Boolean iNum1 As Integer iNum2 As Integer iNum1 = 99 iNum2 = 19 bResul = iNum1 = iNum2 MsgBox "Son iguales? " & bResul bResul = iNum1 <> iNum2 MsgBox "Son distintos? " & bResul bResul = iNum1 < iNum2 MsgBox "Menor que? " & bResul bResul = iNum1 > iNum2 MsgBox "Mayor que? " & bResul bResul = iNum1 <= iNum2 MsgBox "Menor o igual? " & bResul bResul = iNum1 >= iNum2 MsgBox "Mayor o igual? " & bResul End Sub Ten cuidado de no confundir los signos de igual (=). el primero de izquierda a derecha es el signo igual usado como asignación.9. un valor booleano.8 Operadores de relación Estos operadores nos permiten comparar el valor de dos expresiones o términos. Se aplica a solo un operador. es decir.9. .82 iNum2 = 562 iResul = iNum1 . devuelve falso (False).9. cualquier otro valor.Aprendiendo OOo Basic Option Explicit Sub Negacion() Dim bValor As Boolean 'Valor original Verdadero bValor = True Msgbox bValor 'Le aplicamos el operador bValor = Not bValor Msgbox bValor 'Valor original Falso bValor = False Msgbox bValor 'Le aplicamos el operador bValor = Not bValor Msgbox bValor End Sub 83 Su tabla de verdad es muy sencilla. siendo esta una herramienta para conocer los posibles valores de una expresión cuando se le aplican operadores lógicos. A Not A V F F V 4. Ahora. devuelve verdadero (True) solo en el caso de que los dos operadores sean verdaderos (True). primero te muestro su tabla de verdad y después los ejemplos: A B A And B V V F F V F V F V F F F Option Explicit Sub Dim Dim Dim Conjuncion() bValor1 As Boolean bValor2 As Boolean bResul As Boolean 'Solo en caso de que los dos sean verdaderos 'el resultado sera verdadero .10 And – Y (lógico) Se aplica a dos operadores. 84 bValor1 = True bValor2 = True bResul = bValor1 And bValor2 Msgbox bResul bValor1 = True bValor2 = False bResul = bValor1 And bValor2 Msgbox bResul bValor1 = False bValor2 = True bResul = bValor1 And bValor2 Msgbox bResul bValor1 = False bValor2 = False bResul = bValor1 And bValor2 Msgbox bResul End Sub 4. Su tabla de verdad es: A B A Or B V V F F Option Explicit Sub Dim Dim Dim V F V F V V V F Disyuncion() bValor1 As Boolean bValor2 As Boolean bResul As Boolean bValor1 = True bValor2 = True bResul = bValor1 Or bValor2 Msgbox bResul bValor1 = True bValor2 = False bResul = bValor1 Or bValor2 Msgbox bResul bValor1 = False bValor2 = True bResul = bValor1 Or bValor2 Msgbox bResul . devuelve falso (False).9 Operadores 4. Si los dos operadores son falsos (False).11 Or – O (lógico) Se aplica a dos operadores.9. cualquier otro valor devuelve verdadero (True). Aprendiendo OOo Basic bValor1 = False bValor2 = False bResul = bValor1 Or bValor2 Msgbox bResul End Sub 85 4.9. si son diferentes devuelve verdadero (True).12 Xor – O exclusiva (lógico) Se aplica a dos operadores. Su tabla de verdad es: A B A Xor B V V F F Option Explicit Sub Dim Dim Dim V F V F F V V F Operador_Xor() bValor1 As Boolean bValor2 As Boolean bResul As Boolean bValor1 = True bValor2 = True bResul = bValor1 Xor bValor2 Msgbox bResul bValor1 = True bValor2 = False bResul = bValor1 Xor bValor2 Msgbox bResul bValor1 = False bValor2 = True bResul = bValor1 Xor bValor2 Msgbox bResul bValor1 = False bValor2 = False bResul = bValor1 Xor bValor2 Msgbox bResul End Sub . Si los dos operadores son iguales devuelve falso (False). 9 Operadores Eqv – Equivalencia (opuesto a Xor) (lógico) Se aplica a dos operadores. Si los dos operadores son iguales devuelve verdadero (True).13 4.14 Imp – Implicación (lógico) Se aplica a dos operadores. cualquier otro valor. devuelve verdadero (True).9. Su tabla de verdad es: A B A Imp B V V F F V F V F V F V V . Su tabla de verdad es: A B A Eqv B V V F F Option Explicit Sub Dim Dim Dim V F V F V F F V Operador_Eqv() bValor1 As Boolean bValor2 As Boolean bResul As Boolean bValor1 = True bValor2 = True bResul = bValor1 Eqv bValor2 Msgbox bResul bValor1 = True bValor2 = False bResul = bValor1 Eqv bValor2 Msgbox bResul bValor1 = False bValor2 = True bResul = bValor1 Eqv bValor2 Msgbox bResul bValor1 = False bValor2 = False bResul = bValor1 Eqv bValor2 Msgbox bResul End Sub 4.9.86 4. Si el primer operador es verdadero (True) y el segundo es Falso (False) devuelve falso (False). si son diferentes devuelve Falso (False). mayor o igual que Negación Y O O exclusiva Equivalencia (opuesto a Xor) Implicación Operación Tipo Aritmético Aritmético Aritmético Aritmético Aritmético Relacionales Lógico Lógico Lógico Lógico Lógico Lógico . son los siguientes. tiene el mismo nivel de precedencia Operador ^ *. están ordenados de mayor a menor precedencia. Los operadores que están en la misma linea./ \ Mod +.= . distinto. la prioridad que les asigna el lenguaje cuando en una sentencia están implicados dos o mas operadores. <> .Aprendiendo OOo Basic Option Explicit Sub Dim Dim Dim Operador_Imp() bValor1 As Boolean bValor2 As Boolean bResul As Boolean bValor1 = True bValor2 = True bResul = bValor1 Imp bValor2 Msgbox bResul bValor1 = True bValor2 = False bResul = bValor1 Imp bValor2 Msgbox bResul bValor1 = False bValor2 = True bResul = bValor1 Imp bValor2 Msgbox bResul bValor1 = False bValor2 = False bResul = bValor1 Imp bValor2 Msgbox bResul End Sub 87 4. >= Not And Or Xor Eqv Imp Exponenciación Multiplicación y división División entera Resto de una división entera Suma y resta Igual. menor que. es decir.9. mayor que. < . menor o igual que.15 Precedencia de operadores En resumen. los operadores que puedes usar en OOo Basic. > <= . se ejecutan de izquierda a derecha ● La precedencia se puede “romper” (cambiar) usando paréntesis.9 Operadores La prioridad de ejecución es muy importante. toma en cuenta las siguiente reglas: ● La precedencia va de mayor a menor. .88 4. sin los paréntesis da un resultado 'totalmente diferente num = 45 * 56 / 10 ^ 3 + 125 MsgBox num End Sub Los paréntesis nos ayudan a determinar el orden en que queramos hacer una operación cuando la precedencia de operaciones no es muy clara. es que tu determines el orden de las operaciones. ya sea en sucesivas líneas como en el primer ejemplo o usando paréntesis como en el segundo ejemplo: Sub Precedencia_Operadores2() Dim num As Double num = 45 * 56 num = num / 10 num = num ^ 3 num = num + 125 MsgBox num num = (((45 * 56) / 10) ^ 3) + 125 MsgBox num 'Observa como. tienen prioridad los más internos y hacia afuera Option Explicit Sub Precedencia_Operadores1() Dim num As Double 'Observa como la prioridad va de izquierda a derecha '4 16 1 3 num = 2 ^ 2 * 4 Mod 3 + 2 MsgBox num 'Y ahora va de derecha a izquierda '16 32 34 num = 2 + 2 * 4 ^ 2 MsgBox num End Sub Lo más sencillo. es que mantengas el control de tu código. te puede dar resultados diferentes a los esperados. es decir. se ejecutan primero los operadores de mayor jerarquía ● Si los operadores tienen la misma precedencia. pues si no la utilizas correctamente. Mi recomendación como casi siempre lo notaras. En general podríamos hablar de tres tipos de errores dependiendo de cuando se producen o en que contexto. te muestro una lista de los errores en tiempo de diseño más frecuentes 2) Errores lógicos: estos errores. el siguiente código. Únicamente la experiencia y la practica te ayudaran a minimizar este tipo de errores. muy comúnmente son errores de sintaxis. sabemos que esto no es así. 1) Errores en tiempo de diseño: son aquellos que se cometen cuando se esta codificando. los errores son evidentes-. entre más grande y complejo sea tu código. programando.2.por ejemplo. Hay una frase que se le atribuye (no he podido comprobarlo) a Linus Torvalds que dice -ante los ojos de muchos. esto solo puede suceder con el software libre.10 Control de errores En teoría. te deberá mostrar el siguiente mensaje de error que es muy claro: Option Explicit Sub Errores1() En el apéndice A punto 7. en la practica. 3) Errores en tiempo de ejecución: estos errores se producen durante el tiempo que se esta ejecutando tu programa o código. por supuesto. como el que tu y yo usamos. escribiendo nuestro código. generalmente son detectados por el IDE en cuanto tratamos de ejecutar el código y normalmente nos muestra un mensaje indicándonos el tipo de error cometido. OOo Basic cuenta con instrucciones y palabras claves para controlar este tipo de errores y son los que aprenderemos en este capitulo. sino simplemente el código “no hace” las tareas para las que se supone esta desarrollado o “no devuelve” los valores esperados. pues solo en el tenemos a nuestra disposición el código fuente que es la única forma de verificar que un software haga lo que dice que hace. un programa no debería tener errores o no necesitaría de un control de errores. Copia y ejecuta la siguiente macro: Option Explicit Sub Manejo_Errores1() Dim sRutaArchivo As String .Aprendiendo OOo Basic 89 4. son los más difíciles de detectar y corregir pues frecuentemente no te dan un mensaje o no se detiene el código. ¿verdad?. la probabilidad de que tenga errores lógicos aumenta considerablemente. recordando que sintaxis es: -Conjunto de reglas que definen las secuencias correctas de los elementos de un lenguaje de programación. devuelve una cadena vacía. no tienes la seguridad que esos recursos estarán “siempre” disponibles. te “debe” dar el mensaje de error y nota que el ultimo mensaje con MsgBox ya “no” se muestra: Claro. "Borrar archivo" End If End Sub En la validación anterior estamos usando una función de OOo Basic que tal vez no conozcas.10 Control de errores Si escribes la ruta de un archivo que no existe. otros procesos pueden acceder y manipularlos.90 sRutaArchivo = Trim(InputBox("Escribe la ruta del archivo a borrar")) Kill sRutaArchivo MsgBox "El archivo " & sRutaArchivo & " se borro correctamente" End Sub 4. Considera que cuando accedes a recursos externos. si “no” encuentra el archivo. me refiero a la función Dir(valor). considera la utilización de un controlar de errores como en el ejemplo siguiente: Option Explicit Sub Manejo_Errores3() Dim sRutaArchivo As String On Error Goto CONTROLAERRORES sRutaArchivo = Trim(InputBox("Escribe la ruta del archivo a borrar")) Kill sRutaArchivo MsgBox "El archivo " & sRutaArchivo & " se borro correctamente" Exit Sub CONTROLAERRORES: . donde valor puede ser una ruta de archivo. en este y otros casos. por ello. estarás pensando que es más fácil y más eficiente el validar antes que exista el archivo y estarás en lo correcto: Sub Manejo_Errores2() Dim sRutaArchivo As String sRutaArchivo = Trim(InputBox("Escribe la ruta del archivo a borrar")) If sRutaArchivo<>"" And Dir(sRutaArchivo)<>"" Then Kill sRutaArchivo MsgBox "El archivo " & sRutaArchivo & " se borro correctamente" Else MsgBox "Ruta invalida o archivo no existe". 0. en el caso de los archivos. salga de la macro “sin” ejecutar el controlador de errores. esto es para que si. Case Else MsgBox "Ocurrió el error numero: " & Err & Chr(13) & Error & _ Chr(13) & "En la linea " & Erl . la descripción del error (variable Error) y la línea donde este ocurrió (variable Erl). que esta termina en dos puntos (:) . son indispensables para que no te muestre el siguiente mensaje de error en tiempo de diseño: Inmediatamente después de la declaración de la etiqueta. Después de declarar la macro y las variables a usar. esta variable tendrá valor 0 si no ocurrió ningún error. observa que usamos la instrucción Exit Sub. es exactamente igual a la usada en la declaración del controlador de errores. es una variable tipo Long de OOo Basic que contiene el número de error que se haya provocado. 48 En caso de que ocurra un error no especificado o desconocido. Ahora si. observa como declaramos la etiqueta usada en la declaración del controlador de errores. Enseguida. Después de iniciar el controlador de errores. sabemos que si no se encuentra un archivo.Aprendiendo OOo Basic 91 Select Case Err Case 0 Case 53 MsgBox "No se encontró la ruta especificada" & Chr(13) & Chr(13) & sRutaArchivo. observa que iniciamos un Select Case con la variable Err. mostramos el número de error (variable Err). En nuestro ejemplo. nota que esta etiqueta. nuestro código se ejecuta sin problemas. tenemos propiamente el código de nuestra macro. tenemos una nueva instrucción: On Error Goto CONTROLAERRORES La sintaxis general de esta instrucción es: On Error Goto NombreEtiqueta En donde NombreEtiqueta es cualquier palabra que cumpla las características vistas para nombrar a las variables y literalmente significa -En caso de error salta (o va) a NombreEtiqueta. estos. cuya valiosa información nos ayudara a corregirlo. ocurre el error 53. también nota. muy importante. 48 Case Else MsgBox "Ocurrió el error numero: " & Err & Chr(13) & Error & _ Chr(13) & "En la linea " & Erl End Select On Error Goto 0 End Sub Veamos todas las partes del código anterior. esta. excepto por que es indistinto las mayúsculas y minúsculas. el cual manipulamos con la linea: Case 53 MsgBox "No se encontró la ruta especificada" & Chr(13) & Chr(13) & sRutaArchivo. tan solo corregirlos en tu código.92 4. Error y Erl. no es la única pero es la que generalmente se usa. afortunadamente.10 Control de errores Después de cerrar la estructura Select Case con End Select. En caso de que quieras establecer un control de errores genérico. tenemos la linea: On Error Goto 0 Que no hace otra cosa que reinicializar las variables de error. La estructura de control o administración de errores que acabamos de ver. Códigos de error Nº 2 3 4 5 6 7 8 9 10 11 12 13 14 Descripción Error de sintaxis no especificado Return sin Gosub Restaurar desde el principio Llamada a procedimiento no válida Desbordamiento Memoria agotada Matriz ya dimensionada Sunbíndice fuera de rango Definición duplicada División por cero Variable no definida Discordancia de tipo Parámetro no válido Nº 70 71 73 74 75 76 91 93 94 Descripción Permiso denegado Disco no preparado Prestación no implementada Imposible cambiar nombre con unidad distinta Error de acceso a ruta/archivo Ruta no encontrada Variable de objeto no definida Cadena de secuencia no válida Uso de Null no válido 323 Imposible cargar módulo 341 Índice de objeto no válido 366 No hay documento o vista activos 380 Valor de propiedad incorrecto . veamos algunas. toma en cuenta que algunos de estos errores “solo” ocurren en tiempo de diseño y varios de ellos “no” puedes interceptarlos. es decir Err. hay algunas variantes que a criterio puedes usar. podrías usar: Sub Manejo_Errores4() On Error Goto CONTROLAERRORES 'Aqui va todo tu codigo Exit Sub CONTROLAERRORES: If Err <> 0 Then MsgBox "Ocurrio el error numero: " & Err & Chr(13) & Error & Chr(13) & "En la linea " & Erl End If On Error Goto 0 End Sub Puedes simular el error que quieras simplemente asignando el número de error a la variable Error de la siguiente manera: 'Aqui va todo tu codigo Error(12) Esta es la lista de valores de errores que puedes usar en la variable Error o que en algún momento te pueden aparecer. por supuesto. es decir. nos permite regresar.Aprendiendo OOo Basic 93 Códigos de error Nº 18 20 28 35 48 49 51 52 53 54 55 57 58 59 61 62 63 67 68 Descripción Interrupción de usuario Continuar sin error Espacio de pila agotado Sub o Function no definidos Error al cargar DLL Convención de llamada a DLL incorrecta Error interno Nombre de archivo o número incorrectos Archivo no encontrado Modo de archivo incorrecto Archivo ya abierto Error de E/S de dispositivo Archivo ya existente Longitud de registro incorrecta Disco lleno Entrada más allá del final del archivo Número de registro incorrecto Demasiados archivos Dispositivo no disponible Nº Descripción 382 Propiedad de sólo lectura 394 Propiedad de sólo escritura 420 Referencia de objeto no válida 423 Propiedad o método no encontrados 424 Objeto necesario 425 Uso de objeto no válido 430 La clase no admite OLE 438 El objeto no admite este método 440 Error de automatización OLE 445 El objeto no admite esta acción 446 El objeto no admite argumentos con nombre 447 El objeto no admite la configuración de entorno local actual 448 Argumento mencionado no encontrado 449 Argumento no opcional 450 Número de argumentos incorrecto 451 Objeto no es una colección 452 Ordinal no válido 453 Función DLL especificada no encontrada 460 Formato de portapapeles no válido OOo Basic cuenta con una instrucción que complementa el uso de un controlador de errores. de la primer forma. esta instrucción es Resume. básicamente tiene tres posibles usos. volver a intentar ejecutar la línea que provoco el error. esto es recomendable ya que se hayan corregido o atendido las causas del error. por ejemplo: Option Explicit Sub Manejo_Errores5() Dim sRutaArchivo As String Dim iRes As Integer On Error Goto CONTROLAERRORES sRutaArchivo = Trim(InputBox("Escribe la ruta del archivo a borrar")) Kill sRutaArchivo MsgBox "El archivo " & sRutaArchivo & " se borro correctamente" Exit Sub CONTROLAERRORES: Select Case Err . puedes quedar en un bucle infinito entre la linea que provoco el error y el controlador de errores. La segunda forma.10 Control de errores iRes = MsgBox ("No se encontro la ruta especificada" & Chr(13) & Chr(13) & sRutaArchivo & Chr(13) & Chr(13) & "¿Deseas intentarlo de nuevo?". en donde NombreEtiqueta tiene las mismas consideraciones vistas al inicio de este tema. preguntamos al usuario si desea volver a intentarlo: Case 53 iRes = MsgBox ("No se encontro la ruta especificada" & Chr(13) & Chr(13) & sRutaArchivo & Chr(13) & Chr(13) & "¿Deseas intentarlo de nuevo?". La ultima forma es usar la instrucción Resumen NombreEtiqueta. te permite continuar la ejecución de tu código en la línea siguiente a la que provoco el error. tu tarea es corregir eso. aun y cuando este no se hizo efectivamente. ejemplo: Sub Manejo_Errores7() . 32 + 4 ) If iRes = 6 Then Resume End If Case Else MsgBox "Ocurrio el error numero: " & Err & Chr(13) & Error & _ Chr(13) & "En la linea " & Erl End Select On Error Goto 0 End Sub Observa como dentro del bloque donde controlamos el error. 32 + 4 ) If iRes = 6 Then Resume End If Si no haces lo anterior.94 Case 0 Case 53 4. por ejemplo: Sub Manejo_Errores6() Dim sRutaArchivo As String Dim iRes As Integer On Error Goto CONTROLAERRORES sRutaArchivo = Trim(InputBox("Escribe la ruta del archivo a borrar")) Kill sRutaArchivo MsgBox "El archivo " & sRutaArchivo & " se borro correctamente" Exit Sub CONTROLAERRORES: Select Case Err Case 0 Case 53 iRes = MsgBox ("No se encontro la ruta especificada" & Chr(13) & Chr(13) & sRutaArchivo & Chr(13) & Chr(13) & "¿Deseas continuar?". usando Resume Next. 32 + 4 ) If iRes = 6 Then Resume Next End If Case Else MsgBox "Ocurrio el error numero: " & Err & Chr(13) & Error & _ Chr(13) & "En la linea " & Erl End Select On Error Goto 0 End Sub Aquí lo importante es que notes como nos muestra el mensaje de confirmación de borrado. la idea 'es salir de forma controlada de tu macro MsgBox "Se saldra correctamente" End Sub Nota también que en vez de usar Exit Sub. 48 Resume SALIDACONTROLADA Case Else MsgBox "Ocurrio el error numero: " & Err & Chr(13) & Error & _ Chr(13) & "En la linea " & Erl End Select On Error Goto 0 SALIDACONTROLADA: 'Aqui va todo el codigo que quieras. aunque el uso más común es redirigir a un segundo bloque donde se sale de la macro de forma controlada. 32 + 4 ) If iRes = 6 Then Resume REINTENTARLO End If Case Else MsgBox "Ocurrio el error numero: " & Err & Chr(13) & Error & _ Chr(13) & "En la linea " & Erl End Select On Error Goto 0 End Sub No dejes de observar la declaración de la etiqueta correspondiente a donde va a saltar la instrucción Resume. por ejemplo: Sub Manejo_Errores8() Dim sRutaArchivo As String On Error Goto CONTROLAERRORES sRutaArchivo = Trim(InputBox("Escribe la ruta del archivo a borrar")) Kill sRutaArchivo MsgBox "El archivo " & sRutaArchivo & " se borro correctamente" Goto SALIDACONTROLADA CONTROLAERRORES: Select Case Err Case 0 Case 53 MsgBox "No se encontro la ruta especificada" & Chr(13) & Chr(13) & sRutaArchivo & Chr(13) & Chr(13) & "El programa terminara". por ejemplo 'cierre de archivos y bases de datos. para saltar directamente a . usamos la instrucción Goto NombreEtiqueta. “antes” de la etiqueta y código de controlador de errores.Aprendiendo OOo Basic Dim sRutaArchivo As String Dim iRes As Integer On Error Goto CONTROLAERRORES 95 REINTENTARLO: sRutaArchivo = Trim(InputBox("Escribe la ruta del archivo a borrar")) Kill sRutaArchivo MsgBox "El archivo " & sRutaArchivo & " se borro correctamente" Exit Sub CONTROLAERRORES: Select Case Err Case 0 Case 53 iRes = MsgBox ("No se encontro la ruta especificada" & Chr(13) & Chr(13) & sRutaArchivo & Chr(13) & Chr(13) & "¿Deseas intentarlo de nuevo?". 96 4.10 Control de errores la etiqueta de salida. Estas opciones son solo variantes, una vez más tu decidirás que es lo que mejor se acomoda a tu forma de trabajar y de razonar, la recomendación es que no abuses de los saltos con Resume o Goto, por claridad, limitate en su uso lo más posible. Para terminar este tema, te muestro otra instrucción para “omitir” errores, me refiero a la instrucción On Error Resume Next, que significa -En caso de error, continua el la siguiente línea-, y se usa de la siguiente manera: Sub Manejo_Errores9() Dim sRutaArchivo As String On Error Resume Next sRutaArchivo = Trim(InputBox("Escribe la ruta del archivo a borrar")) Kill sRutaArchivo MsgBox "El archivo " & sRutaArchivo & " se borro correctamente" End Sub Intentemos controlar el error Sub Manejo_Errores10() Dim sRutaArchivo As String On Error Resume Next sRutaArchivo = Trim(InputBox("Escribe la ruta del archivo a borrar")) Kill sRutaArchivo If Err = 0 Then MsgBox "El archivo " & sRutaArchivo & " se borro correctamente" End If End Sub Notaras que no es posible, no importa el número de errores que sucedan Sub Manejo_Errores11() Dim sRutaArchivo As String On Error Resume Next Error(2) Error(3) Error(4) Error(5) Error(6) If Err = 0 Then MsgBox "No ocurrio ningun error" End If End Sub Puedes tener juntas una después de otra las dos instrucciones para controlar errores: On Error Resume Next On Error Goto CONTROLAERRORES Aprendiendo OOo Basic 97 Pero tendrá prioridad On Error Resume Next, por lo que no es aconsejable, de hecho, no te recomiendo el uso de On Error Resume Next a menos que estés seguro de lo que haces. 4.11 Validación de datos Con la experiencia te darás cuenta que hacer una macro o programa libre de errores no es tema menor y que entre más grande sea tu código, la probabilidad de que tenga errores aumenta considerablemente. Una fuente frecuente de errores, son los datos que un usuario alimenta a un programa, por supuesto, es nuestra responsabilidad como programadores el minimizar este tipo de errores, esto lo logramos filtrando los datos que el usuario alimenta, es decir “validando” los datos, no se te olvide, VALIDANDO LOS DATOS, veras que la validación de datos, consume bastante líneas de código, a veces, muchas más que el proceso en si de estos, por ello es un tema muy importante en programación. OOo Basic cuenta con algunas funciones que nos ayudan a validar datos, otras, tienes que programartelas (e ingeniertales) tu mismo, veamos algunas de ellas, pero recuerda que son solo guías, pues las opciones son tantas y tan variadas como programadores las implementen. Para el mejor aprovechamiento de este tema, tienes que saber que los lenguajes Basic son muy nobles en al conversión de datos de un tipo a otro, muchas de estas conversiones las puede hacer el lenguaje de forma directa, a esta conversión se se llama implícita, pero lo recomendable es que nosotros controlemos, siempre que sea posible, estas conversiones, a esta forma se le llama explicita y nos apoyamos en varias funciones de OOo Basic para hacer estas conversiones. Como sabes, la instrucción MsgBox, espera como parámetro “requerido” un argumento llamado Mensaje de tipo String, es decir, una cadena de texto. MsgBox Mensaje As String, [Tipo As Integer], [Titulo As String] Veamos los siguientes ejemplos: Option Explicit Sub Dim Dim dim Mensajes1() dFecha As Date iNumero As Integer bOpcion As Boolean dFecha = DateSerial(74,1,15) iNumero = 2008 bOpcion = True MsgBox dFecha MsgBox iNumero MsgBox bOpcion End Sub Observa como, aunque le pasemos un número o una fecha o incluso un valor booleano, la instrucción MsgBox sigue trabajando, esto es por que el lenguaje, hace internamente (de forma implícita) una conversión de tipos, mientras le sea posible, convierte del tipo que reciba, a una cadena de texto (string), lo ideal, es que nosotros hagamos esta conversión de forma explicita, como en el siguiente ejemplo: 98 Sub Dim Dim dim Mensajes2() dFecha As Date iNumero As Integer bOpcion As Boolean dFecha = DateSerial(74,1,15) iNumero = 2008 bOpcion = True MsgBox CStr( dFecha ) MsgBox CStr( iNumero ) MsgBox CStr( bOpcion ) End Sub 4.11 Validación de datos Observa como hacemos uso de la función CStr(valor) que convierte el tipo de “valor” a una cadena de texto (String). De esta forma, “casi” podemos estar seguros de que no nos dará un error inesperado. OOo Basic cuenta con funciones para convertir a la mayoría de los tipos de variables posibles: Función CStr(valor) CByte(valor) CInt(valor) CLng(valor) CSng(valor) CDbl(valor) CBool(valor) CDate(valor) Convierte a tipo Byte Convierte a tipo entero (Integer) Convierte a tipo entero largo (Long) Convierte a tipo simple (Single) Convierte a tipo doble (Double) Convierte a tipo booleano (Boolean) Convierte a tipo fecha (Date) Descripción Convierte a cadena de texto (String) OOo Basic cuenta con otras funciones que nos ayudan a saber que tipo de dato tiene una variable, veamos las siguientes: Cuando necesites saber si una variable contiene un número usamos IsNumeric: Option Explicit Sub EsNumero() Dim sDato As String sDato = Trim( InputBox( "Introduce un numero" ) ) If IsNumeric( sDato ) Then MsgBox "Es un numero" Else MsgBox "No es un numero" End If End Sub Cuando necesites saber si una variable contiene una fecha usamos IsDate: Sub EsFecha() Dim sDato As String sDato = Trim( InputBox( "Introduce una fecha" ) ) Aprendiendo OOo Basic If IsDate( sDato ) Then MsgBox "Es una fecha" Else MsgBox "No es una fecha" End If End Sub 99 Y cuando necesites saber si una variable es una matriz usamos IsArray: Sub EsMatriz() Dim mDato As Variant If IsArray( mDato() ) Then MsgBox "Es una matriz" Else MsgBox "No es una matriz" End If mDato = Array(1,2,3,4,5) If IsArray( mDato() ) Then MsgBox "Es una matriz" Else MsgBox "No es una matriz" End If End Sub Veamos algunos ejemplos de validaciones comunes, como dicen en mi pueblo -ni son todas las que están, ni están todas las que son-, solo pretendo que te sea de referencia y las adaptes y complementes a tus necesidades. Obligamos al usuario a introducir un dato, el que sea, la única condición es que no sea una cadena vacía: Sub Validar1() Dim sDato As String Dim bSalir As Boolean Do sDato = Trim( InputBox("Introduce los datos") ) If sDato <> "" Then bSalir = True End If Loop Until bSalir End Sub Habrás observado en el ejemplo anterior, que aun cuando el usuario presione Cancelar, de todos modos no le hacemos caso y lo obligamos a introducir un dato, si bien lo podemos hacer, no es común, lo habitual es proporcionar siempre al usuario una forma de cancelar un proceso: Sub Dim Dim Dim Validar2() sDato As String bSalir As Boolean iRes As Integer sDato = Trim( InputBox("Introduce los datos") ) If sDato <> "" Then 'Aqui va tu codigo para manipular los datos bSalir = True Else Do 100 4.11 Validación de datos iRes = MsgBox( "Parece que no escribiste nada, ¿Deseas salir?", 32 + 4, "Salir" ) If iRes = 6 Then bSalir = True End If End If Loop Until bSalir End Sub Ahora, obligamos al usuario a introducir una cadena de texto, que “no” sea número ni fecha: Sub Dim Dim Dim Validar3() sDato As String bSalir As Boolean iRes As Integer Do sDato = Trim( InputBox("Introduce los datos") ) If sDato <> "" Then If Not(IsDate(sDato)) And Not(IsNumeric(sDato)) Then 'Aqui va tu codigo para manipular los datos MsgBox "Es una cadena" & Chr(13) & Chr(13) & sDato bSalir = True Else MsgBox "Valor NO valido" End If Else iRes = MsgBox( "Parece que no escribiste nada, ¿Deseas salir?", 32 + 4, "Salir" ) If iRes = 6 Then bSalir = True End If End If Loop Until bSalir End Sub Que solo introduzca números: Sub Dim Dim Dim Validar4() sDato As String bSalir As Boolean iRes As Integer Do sDato = Trim( InputBox("Introduce un numero") ) If sDato <> "" Then If IsNumeric(sDato) Then 'Aqui va tu codigo para manipular los datos MsgBox "Es un numero" & Chr(13) & Chr(13) & sDato bSalir = True Else MsgBox "Valor NO valido" End If Else iRes = MsgBox( "Parece que no escribiste nada, ¿Deseas salir?", 32 + 4, "Salir" ) If iRes = 6 Then bSalir = True End If End If Loop Until bSalir End Sub Que introduzca una fecha: Sub Validar5() Aprendiendo OOo Basic Dim sDato As String Dim bSalir As Boolean Dim iRes As Integer Do 101 sDato = Trim( InputBox("Introduce una fecha") ) If sDato <> "" Then If IsDate(sDato) Then 'Aqui va tu codigo para manipular los datos MsgBox "Es una fecha" & Chr(13) & Chr(13) & sDato bSalir = True Else MsgBox "Valor NO valido" End If Else iRes = MsgBox( "Parece que no capturaste nada, ¿Deseas salir?", 32 + 4, "Salir" ) If iRes = 6 Then bSalir = True End If End If Loop Until bSalir End Sub Un número, con un rango definido, digamos, entre 50 y 100: Sub Dim Dim Dim Validar6() sDato As String bSalir As Boolean iRes As Integer Do sDato = Trim( InputBox("Introduce un numero") ) If sDato <> "" Then If IsNumeric(sDato) And Val(sDato)>=50 And Val(sDato)<=100 Then 'Aqui va tu codigo para manipular los datos MsgBox "Es un numero, en el rango 50-100" & Chr(13) & Chr(13) & sDato bSalir = True Else MsgBox "Valor NO valido" End If Else iRes = MsgBox( "Parece que no capturaste nada, ¿Deseas salir?", 32 + 4, "Salir" ) If iRes = 6 Then bSalir = True End If End If Loop Until bSalir End Sub Una fecha que no sea fecha futura: Sub Dim Dim Dim Validar7() sDato As String bSalir As Boolean iRes As Integer Do sDato = Trim( InputBox("Introduce una fecha") ) If sDato <> "" Then If IsDate(sDato) Then If CDate(sDato) <= Date() Then 'Aqui va tu codigo para manipular los datos MsgBox "Es una fecha valida" & Chr(13) & Chr(13) & sDato 102 bSalir = True Else MsgBox "Es una fecha futura" End If Else MsgBox "Valor NO valido" End If Else 4.11 Validación de datos iRes = MsgBox( "Parece que no capturaste nada, ¿Deseas salir?", 32 + 4, "Salir" ) If iRes = 6 Then bSalir = True End If End If Loop Until bSalir End Sub El siguiente ejemplo es muy divertido, le pedimos al usuario que introduzca solo vocales, pero ya sabes como son los usuarios, seguro capturan lo que se les da la gana, así que filtraremos su texto, dejando solo las vocales: Sub Dim Dim Dim Dim Dim Dim Dim Validar8() sDato As String bSalir As Boolean iRes As Integer co1 As Integer sLetra As String sTmp As String pos As Integer Do sDato = Trim( InputBox("Introduce solo vocales") ) If sDato <> "" Then If Not(IsDate(sDato)) And Not(IsNumeric(sDato)) Then 'Aqui va tu codigo para manipular los datos For co1 = 1 To Len(sDato) 'Tomamos una por una cada letra capturada sLetra = Mid(sDato,co1,1) 'Averiguamos si es una vocal mayuscula o minuscula pos = InStr(1,"aeiouAEIOU",sLetra) 'Si encuentra la letra en la lista de vocales InStr te 'devuelve la posicion, con que sea mayor a cero sabemos 'que ha sido encontrada If pos > 0 Then sTmp = sTmp & sLetra End If Next MsgBox sTmp bSalir = True Else MsgBox "Valor no valido" End If Else iRes = MsgBox( "Parece que no capturaste nada, ¿Deseas salir?", 32 + 4, "Salir" ) If iRes = 6 Then bSalir = True End If End If Loop Until bSalir End Sub Aprendiendo OOo Basic 103 No quiero que se te olvide, la VALIDACION de los datos que introduce el usuario es “muy importante” y si conjugas esto con el control de errores, te aseguro que podrás minimizar el riesgo de fallos en tus aplicaciones, sino un 100%, si en un porcentaje bastante alto. Si tienes una validación interesante y que este al nivel básico que venimos manejando, puedes enviármela para incluirla aquí o en su defecto, si tienes problemas con alguna validación, planteala en las listas de correo y si es lo suficientemente ilustrativa, también la incluiremos aquí. !!Feliz programación¡¡ 4.12 El IDE – Mucho más que un editor A estas alturas ya habrás notado la gran utilidad del IDE, te colorea las palabras dependiendo de su contexto y te muestra mensajes preventivos o de error siempre que sea posible, en este capitulo, veremos algunas otras características del IDE que nos pueden ayudar a depurar nuestras macros, entendiendo por depurar, las técnicas que nos ayudan a encontrar más fácilmente un error, sobre todo, lógico, que son, a veces, los más complicados de encontrar. Para empezar demos un repaso a nuestro centro de trabajo, es decir, al IDE y sus diferentes partes: 1. 2. 3. 4. 5. 6. 7. 8. Barra de titulo Barra de menús Barras de herramientas Ventana de edición Ventana de observador Ventana de llamadas Barra de desplazamiento de módulos y diálogos Barra de estado 104 4.12 El IDE – Mucho más que un editor Algunas de estas ya te serán muy familiares, otras son nuevas pero las veremos en este capitulo. Como ya mencionamos, el IDE, es solo otra aplicación de OpenOffice.org, que nos permite crear y editar nuestras macros, la barra de titulo y la de menús es consistente con las demás aplicaciones que integran la aplicación, por lo que no las veremos aquí, Las barras de herramientas las veremos a continuación: La primer barra de herramientas se llama MacroBar, por lo que supongo que en castellano será, Barra de macros, ya que el nombre no aparece en su barra de titulo, como si lo hace en la mayoría de las barras de herramientas: El primer control que es un cuadro de lista desplegable (control ComboBox) te permite seleccionar el archivo que este abierto y la biblioteca que quieras editar: 4. te das cuenta que línea es la siguiente a ejecutar por una flecha amarilla en el margen izquierdo del editor. pero ya vimos las técnicas para ejecutar las demás macros. en la barra de desplazamiento de módulos. así como del archivo especial Mis macros y los integrados en OpenOffice. compártela conmigo. es mejor usar “puntos de ruptura”. normalmente se usa junto con el “Observador” para encontrar errores. 2. si seleccionas esta opción. que es lo que se supone hace este icono. Icono de ejecutar: Este icono ejecuta “solo” la primer macro del módulo activo. . si tu la vez o la sabes. pero en mis pruebas no veo ninguna diferencia.Aprendiendo OOo Basic 105 Observa como la primer opción es Todos. Icono entrar en el proceso: Realiza la misma acción del icono 4. te mostrara “todos” los módulos y diálogos de todos los archivos abiertos. equivale a presionar la tecla F8 5. normalmente se usa en conjunción con los iconos 4 y 5. los iconos 4 y 5. por lo que esta opción te podría llegar a mostrar varias decenas de módulos dependiendo de cuantos archivos tengas abiertos y de cuantos módulos tengas con código. Icono de compilar: Me gustaría mucho que el código de nuestras macros se pudiese compilar. por lo que para depurar macros. solo se ejecutan en la primer macro del modulo activo. Icono pasar al siguiente: Permite ejecutar línea a línea el código de nuestra macro. equivale a presionar la tecla F5. muy útil para depurar y encontrar errores. 3. Icono de detener macro: Solo esta activo cuando ejecutamos una macro. El resto de los botones son los siguientes: 1.org. 7. también puede eliminar el punto de interrupción que quieras tan solo seleccionándolo y presionando el botón Eliminar. con este icono activamos (mostramos) y desactivamos (ocultamos) los puntos rojos que son puntos de ruptura en la línea actual donde este el cursor de escritura. recuerda que el cursor de escritura es la raya vertical negra de todo editor de texto. pero lo mejor es agregar los puntos desde el editor. puedes agregar el que quieras.106 4. Observa en la siguiente imagen los puntos rojos. Icono salir de proceso: Cuando ejecutamos una macro línea por línea. así mismo. Cada punto de ruptura estará indicado por la línea en donde se encuentre y podrás seleccionar y desactivar el punto que quieras. es decir. Icono de activar/desactivar puntos de ruptura: Un punto de ruptura es una “señal” que le indica al IDE que detenga la ejecución en la linea indicada por un punto rojo en el margen izquierdo de nuestro editor.12 El IDE – Mucho más que un editor 6. tan solo indicando el numero de línea donde deseas establecerlos y presionar el botón nuevo. eliminar o desactivar puntos de ruptura en un cuadro de dialogo. dentro del margen izquierdo del editor. exactamente en la línea que quieras. . Icono gestionar puntos de ruptura: Nos permite administrar los puntos de ruptura existentes en nuestro modulo actual. nos permite agregar. con lo cual el punto rojo pasará a ser un punto gris. este icono nos permite continuar la ejecución de la macro normalmente. pero muy importante. 8. también puedes activar y desactivar puntos de ruptura con la tecla F9 o dando un doble clic en la línea que quieras. equivale a presionar la tecla F5. módulos y macros disponibles. Icono catalogo de objetos: Nos muestra un cuadro de dialogo que nos permite navegar en forma de árbol entre los archivos abiertos y dentro de sus bibliotecas. con un doble clic sobre la macro seleccionada nos lleva a ella o usando el botón Mostrar (circulo rojo en la imagen): .Aprendiendo OOo Basic 107 9. te permite abrir. muy útil sobre todo en funciones anidadas donde se pierden los paréntesis. guardar. más adelante veremos a detalle esta herramienta 10. pegar. y es muy similar a la mayoría de las barras estándar de las demás aplicaciones. Icono de insertar código Basic: Permite. esta ventana normalmente se usa ejecutando la macro línea a línea (F8) o junto con puntos de ruptura para poder observar el valor de las variables. Icono de guardar código Basic: Nos permite exportar a un archivo de texto con extensión BAS el código seleccionado o todo el modulo si no hay nada seleccionado. etc. Icono de buscar paréntesis: Con el cursor de escritura posicionado “antes” de un paréntesis de apertura o cierre. 12. 1. copiar. salvo por los tres iconos siguientes solo disponibles en el IDE. Icono de habilitar inspección: Permite agregar la variable seleccionada a la ventana de observador para visualizar el valor de dicha variable durante la ejecución de una macro. imprimir. La siguiente barra de herramientas se llama Estándar. 11. nos permite seleccionar todo el texto dentro de dichos paréntesis e incluyendo los paréntesis. a partir de un archivo de texto (normalmente con extensión BAS) insertar el código Basic que contengo en el modulo actual en la posición del cursor de escritura actual. por lo que no veremos aquí estas opciones. una opción muy interesante y poderosa es “Asignar” una macro. pero también podemos editar y eliminarlas. . que se verá más adelante. sus bibliotecas y sus módulos.12 El IDE – Mucho más que un editor 2.108 4. por ahora. Icono de seleccionar macro: Nos muestra un cuadro de dialogo para administrar nuestras macros. nos permite también navegar entre los archivos abiertos. principalmente la hemos usados para ejecutar la macro que queramos. Icono seleccionar modulo: Nos muestra un cuadro de dialogo que nos permite administrar módulos. la ventana de observador y la ventana de llamadas a depurar nuestras macros. Veamos ahora como nos pueden ayudar los puntos de ruptura. lo importante es seguir la secuencia correcta de los pasos siguientes. por ejemplo. la ejecución línea a línea. el siguiente . agregarlos y eliminarlos entre otras opciones como agregar una contraseña a una biblioteca. Puedes usar cualquier macro de las que hayamos desarrollado en estos apuntes o cualquiera que tengas. diálogos y bibliotecas. Observa la llave al lado izquierdo de miBiblioteca que nos indica que esta biblioteca tiene establecida una contraseña para su visualización. la cual te solicitara si intentas editarla.Aprendiendo OOo Basic 109 3. pos1+1.sNombre.sNombre. "Nombre" )) 'Vamos a suponer una fecha correcta. presiona F8.12 El IDE – Mucho más que un editor código. el RFC es un dato personal y unico en Mexico y digo seudo 'por que no es tan simple como lo pongo aqui. asegurate de que sea la “primer” macro de dicho módulo de código: Option Explicit 'Construimos un seudo-RFC. por ahora no haremos verificacion 'OJO solo por ahora.2) & Mid(sNombre.1) & Mid(sNombre. pos2 As Byte Dim RFC As String 'Vamos a suponer que capturamos un nombre estandar Nombre Paterno Materno 'por ejemplo Vanessa Bauche Chavira sNombre = Trim( InputBox( "Escribe tu nombre completo". copialo en la parte superior de cualquier módulo. es decir. continua presionando F8 y nota como la flecha amarilla va avanzando línea por línea en nuestro código. asi que prueba fechas correctas dNacimiento = CDate( InputBox( "Ahora tu fecha de nacimiento". nota como aparece una flecha amarilla en el margen izquierdo de nuestro editor. . pero nos sirve muy bien de ejemplo 'Primeras dos letras del apellido paterno 'Primera letra del apellido materno 'Primera letra del nombre 'Año de nacimiento de dos digitos 'Mes de nacimiento de dos digitos 'Dia de nacimiento de dos digitos Sub ObtenerRFC1() Dim sNombre As String Dim dNacimiento As Date Dim pos1 As Byte. por supuesto nuestra macro se ejecutara de forma normal." ") RFC = UCase( Mid(sNombre.pos2+1. Ahora. presiona la tecla F5."00" ) 'Mostramos el RFC construido MsgBox RFC End Sub Tienes que ser muy observador. continua así hasta terminar de ejecutar la macro. "Fecha" )) 'Encontramos la posicion del primer espacio pos1 = InStr(1. captura los datos solicitados correctamente y verifica que el resultado sea el esperado.1. empezando por la primer línea de nuestra macro.2) & Format(Month(dNacimiento).1) ) & _ Right(CStr(Year(dNacimiento))." ") 'Encontramos la posicion del segundo espacio pos2 = InStr(pos1+1.110 4."00" ) & _ Format(Day(dNacimiento). pos1+1.1) & Mid(sNombre. muy bien. en cualquier momento puedes continuarla de forma normal presionando F5 o de plano detener la macro con el botón Detener Macro o presionando Ctrl+Shift+Q.Aprendiendo OOo Basic 111 Vuelve a empezar presionando F8. observa como el IDE nos muestra el valor almacenados en cada una de las variables en un pequeño cuadro de texto amarillo que desaparece en cuanto movemos el cursor. muy bien. para ver el valor de las variables. que si copiaste el código anterior. tendrás razón. . RFC = UCase( Mid(sNombre. pos2 y RFC. repite este proceso con todas las restantes variables y ve observando como en la ventana del observador se van listando las variables."00" ) & _ Format(Day(dNacimiento). Con justa razón te preguntaras. No esta de más aclararte que la imagen siguiente esta editada para mostrarte el valor de todas la variables."00" ) Posiciona el cursor sobre cada una de las variables sNombre. detente exactamente en la línea siguiente. ¿esto no es muy practico cuando tenemos decenas de variables? Y si. ¿que notas?. ahora para ello. tiene que ser la línea 28 aproximadamente.2) & Format(Month(dNacimiento).pos2+1.2) & Mid(sNombre.1. pos1. Selecciona una variable y presiona el icono “Habilitar inspección” o presiona la tecla F7 que tiene el mismo efecto. mientras estas ejecutando el código línea por línea. usaremos la ventana del observador de la siguiente manera.1) ) & _ Right(CStr(Year(dNacimiento)). pero ahora. dNacimiento. También observa que. en vez de ejecutar nuestro código línea a línea. “muy importante”. veo que eres un alumno atento. primero posicionamos el cursor sobre la línea donde nos interese establecer el punto de interrupción. vuelve a ejecutar la macro paso a paso. son señales que le dejamos al IDE para que se detenga en la línea indicada. tienes que ver algo muy similar a: Mira que lindo. puede ser que una variable no tenga o no obtenga los datos que necesitamos. como vimos más atrás.12 El IDE – Mucho más que un editor Ahora. línea a línea y ve observando la ventana de inspección. al llegar a la línea donde construimos el RFC. Agrega un punto de interrupción en la linea donde construimos el RFC de modo que te quede de la siguiente manera: . Para agregarlos usamos el icono “activar/desactivar puntos de ruptura” o presionamos la tecla F9. he ahí su importancia. es decir. que. además. Y surge una nueva pregunta. estos cambios los podrás ir analizando en la ventana del observador. tenemos el valor de todas nuestras variables. usaremos puntos de interrupción. una frecuente fuente de errores. muy buena pregunta. pero. ¿y si tenemos decenas o centenas de líneas de código?. por supuesto si estas variables cambian su valor en el transcurso de ejecución de nuestra macro.112 4. te muestra el tipo de variable que es. para estos casos. ¿tenemos que ejecutar nuestro código línea a línea para poder ver los valores de las variables?. es precisamente que en ocasiones al procesar los datos tan rápido. puedes establecer tantos puntos de interrupción como quieras o necesites. "15/01/74" )) 'Los procesamos Call ObtenerIniciales( sNombre. "Nombre". solo selecciona la variable que quieras quitar en la ventana del observador y la eliminas de esta con el icono que esta inmediatamente encima de estas. modifica el código anterior para dividirlo en una subrutina y en una función. puedes continuar ejecutando línea a línea (F8) o continuar normalmente (F5). de modo que quede de la siguiente manera: Option Explicit Sub Dim Dim Dim Dim ObtenerRFC2() sNombre As String dNacimiento As Date RFC As String mDatos(2) As String 'Obtenemos los datos sNombre = Trim( InputBox( "Escribe tu nombre completo". ejecuta la macro con F5 y observa como después de alimentar los datos. Para terminar este tema tan divertido."Vanessa Bauche Chavira" )) dNacimiento = CDate( InputBox( "Ahora tu fecha de nacimiento". mDatos) Dim pos1 As Byte. Ahora. "Fecha". pos2 As Byte . En cualquier momento puedes quitar los puntos de interrupción con F9 sobre la línea donde esta el punto de interrupción o las variables de la ventana del observador.Aprendiendo OOo Basic 113 Observa como aun tenemos las variables en la ventana del observador. para esto. el código se detiene exactamente en la línea que establecimos. si cierras tu archivo los perderás. mDatos() ) RFC = Join(mDatos(). ahora."") RFC = RFC & FechaRFC( dNacimiento ) 'Mostramos el resultado MsgBox RFC End Sub Sub ObtenerIniciales(ByVal Nombre As String. veamos para que sirve la ventana de llamadas y veamos como la ventana de observador también nos puede mostrar el valor de una matriz de datos. Las variables que agregues a la ventana del observador y los puntos de interrupción que establezcas. solo estarán disponibles en tu sesión actual. para tener algo muy similar a la siguiente imagen: Tal vez en la ventana del observador tendrás que darle un clic al símbolo del signo más a la izquierda del nombre de la variable para que te despliegue el contenido de la matriz.2)) mDatos(1)=UCase(Mid(Nombre.1)) End Sub Function FechaRFC(ByVal Nacimiento As Date) As String FechaRFC= Right(CStr(Year(Nacimiento)). que.1)) mDatos(2)=UCase(Mid(Nombre. esta vacía.1. en esta caso.114 4.Nombre.pos1+1.Nombre." ") pos2 = InStr(pos1+1. detente en la primer línea donde aparece la variable sNombre." ") mDatos(0)=UCase(Mid(Nombre. después agrega la variable mDatos a la ventana del observador (F7) y ejecuta el código paso a paso (F8)."00" ) & _ Format(Day(Nacimiento).pos2+1. Continua ejecutando paso a paso (F8) y detente en: .2) & _ Format(Month(Nacimiento).12 El IDE – Mucho más que un editor pos1 = InStr(1."00" ) End Function Ejecuta el código primero (F5) para verificar que obtenemos los resultados esperados. para ejecutar paso a paso otras macros. Y sin querer queriendo dimos un breve repaso a varios temas vistos anteriormente. tanto como puedas !!Feliz programación¡¡ .Aprendiendo OOo Basic 115 Reitero. tienes que ser muy observador. No me resta más que decirte. así como el valor de las variable en la ventana del observador. establece primero un punto de ruptura en la linea que te interese dentro de dicha macro y después ejecutas la macro de forma normal para que se detenga en el punto de ruptura establecido.. practica mucho. No se te olvide que las teclas F5 y F8 solo tienen efecto en la primer macro declarada en el modulo activo. Continua paso a paso hasta el inicio de la función FechaRFC y observa la ventana de llamadas que una vez más muestra la función y sus valores pasados: Termina la ejecución de la macro (F5) y observa que la pila de llamadas se vacía. observa la ventana de llamadas como te muestra el nombre de la subrutina y además. Continua la ejecución paso a paso y detente en: Observa como ahora la matriz ya tiene datos y estos se muestran en la ventana del observador. los valores que se le están pasando. a partir de ahí ya puedes usar F8 para continuar paso a paso. muy útil para saber si estamos estableciendo correctamente los valores. nota como al llegar a la línea donde llamamos a la subrutina.. el código salta a dicha subrutina y muy importante. a través de OOo Basic.org. ya que este sera el nombre que usaremos de aquí en adelante. podemos profundizar óptimamente en las entrañas de OpenOffice. eso es OpenOffice.org. envíame lo mas claramente posible.116 5 Trabajando con OpenOffice. de hecho. el famoso juego de construcción con piezas de plástico. no confundas estos "módulos". con los vistos en el capitulo 2. etc. C++. A su vez. pero que se puede embonar perfectamente bien con miles de piezas más para "armar" y "crear" nuevos componentes.org es un LEGO.org A mi juicio. que no se te olvide "servicio". pero estoy en la mejor disposición de ayudarte a resolver tus dudas.org precisamente. entender como esta construido OpenOffice. vuelve a leer el tema. es la diferencia entre aprovechar todo el potencial que tiene OOo Basic o perderte en un laberinto infranqueable por andar buscando "similitudes" con "otros" programas. hay forma de saber que "servicios" implementa un componente. no dejes de mencionarlo.org 5 Trabajando con OpenOffice. así que solo como conocimiento recuerdalo y concentrate en los "servicios". pero ojo.org (Java. por lo que si sabes usar un "servicio" y este esta implementado en otro componente. sabiendo "preguntar" lo correcto y consultando el lugar correcto. no así para los que usan otros lenguajes con OpenOffice. lo cual. es enseñarte a "preguntarle" a los "servicios" la información necesaria para ponerlos a trabajar. Cada pieza del LEGO es un pieza completa. si aun queda alguna. no continuar con los siguientes capítulos. que es lo que no queda claro. estos "servicios".org se le denomina "servicio". que si no sabes que es. para que recuerdes que "no hay que estar adivinando" nada. hasta no haber comprendido cabalmente este. pueden contener otros "servicios". a su vez. .). mi propósito en este capitulo. te estas perdiendo de un maravilloso juego.org. esta forma de organización no tiene mayor relevancia para los que programamos en OO Basic. estos "servicios" se organizan en "módulos". doy por sentado que no tienes dudas de lo visto y explicado en capítulos anteriores. En OpenOffice. a cada una de estas partes. se que mis herramientas pedagógicas no son las mejores. por supuesto. puedes aplicar tus conocimientos de este "servicio" en el nuevo componente sin ningún problema. Tal vez pecando de un excesivo reduccionismo. esta divido en una finita y conocida cantidad de partes. NOTA MUY IMPORTANTE Te sugiero ampliamente. le podemos llamar "objeto". así mismo. así que anda. pero en el lenguaje de OpenOffice. OpenOffice. por su importancia y por la falta de documentación en español es lo que trataremos de aprender a hacer de la mejor forma. también. si tienes algún aporte para ayudar a transparentar este tema. si tienes alguna. Como se que eres observador.Aprendiendo OOo Basic 117 5. aparte del archivo que estuvieras usando. .. uno de Calc y otro de Writer. guardarlos con el nombre que quieras. el organizador de macros te mostraba o bien. aunque muy bien pudiste haber usado un archivo de Writer. la mayoría de las macros que hemos desarrollado y probado. por ejemplo: Option Explicit Sub Mensaje_Calc() MsgBox "Estoy en mi archivo de Calc" End Sub Sub Mensaje_Writer() MsgBox "Estoy en mi archivo de Writer" End Sub Toma nota de que son dos macros en “dos” archivos diferentes. si has seguido estas notas desde el inicio. Para empezar a clarificar esto. observa como solo nos muestra el archivo de Writer y no el de Calc. Ahora. intentemos primero con la macro que esta en el archivo de Writer. agregales una macro de prueba que nos muestre un mensaje.1 Mis macros – un archivo especial. veamos en que casos te mostraba uno y en que casos lo otro. crea dos nuevos archivos. esta diferencia es importante para el desarrollo de los siguientes temas.. todos los archivos que tienes abiertos o solo el archivo activo para ejecutar una macro. Hasta ahora. las hemos escrito “dentro” de un documento de OpenOffice. seguro habrás notado cada vez que habrías tu archivo para editar las macros o ejecutabas alguna..org. propusimos un archivo de Calc. trata de ejecutar cada macro desde el menú Herramientas | Macros | Ejecutar macros. que nos mostrará: Ahora si. optamos por ir al menú Herramientas | Macros | Organizar macros | OpenOffice. Para que tengamos disponibles nuestras macros con cualquier archivo y poder ejecutarlas desde Herramientas | Macros | Ejecutar macros. si... Ahora la macro que esta en el archivo de Calc y observa como solo nos muestra el archivo de Calc y no el de Writer.. podemos optar por usar el archivo especial que se llama Mis macros.1 Mis macros – un archivo especial.org Basic. Por supuesto.. que puedes ver aquí: . en vez de ir al menú Herramientas | Macros | Ejecutar macros. observa como nos muestra todos los archivos abiertos y podemos tanto editar las macros que contenga o ejecutarlas.118 5. podemos “forzar” que nos muestre todos los archivos abiertos...... openoffice. claro. así como los diálogos que aprenderemos a crear y programar más adelante. hemos ejecutado todas nuestras macros desde el IDE o llamándolas desde el menú herramientas. esto. por ejemplo. veamos algunos ejemplos de como hacer esto. cuando abrimos un archivo.org. pero también podemos asignar las macros para ejecutarlas. por supuesto. es sumamente útil y poderoso.org/3/user/basic. 64. algo tan sencillo como mostrar la fecha y hora actuales. si dentro de archivos individuales o dentro de Mis macros."Hoy es" .2 Asignando macros Hasta ahora. "dddd dd \d\e mmmm \d\el yyyy " & Chr(13) & _ "y \son la\s HH \ho\ra\s con mm \minuto\s" MsgBox sMensaje. a menús. puedes crear todas las bibliotecas que quieras y todos los módulos que quieras. Este archivo se encuentra en el directorio del usuario dentro de la carpeta oculta de OpenOffice. combinaciones de teclas e incluso asignarlas a sucesos de la aplicación.Aprendiendo OOo Basic 119 Dentro de el. A partir de aquí. hay que escribir la macro que nos interesa asignar. es muy útil respaldar de vez en cuando esta carpeta. por ejemplo: /home/USUARIO/. 5. barras de herramientas. En este directorio podrás ver como carpetas las bibliotecas que vayas agregando y dentro de ellas los módulos creados. con un poco de formato para que sea vea bien: Sub MostrarFechayHora() Dim sMensaje As String sMensaje = Format( Now(). como primer paso. queda a tu criterio decidir donde guardas tus macros. hemos seleccionado CTRL + SHIFT + M (5). despliega su contenido y seleccionar “user” que se refiere al archivo especial “Mis Macros”.. Pero observa que tienes una amplia gama de opciones de donde escoger. están en gris desactivadas. veamos primero lo más sencillo. . para nuestro ejemplo. esto es por que estas teclas no puedes reasignarlas. para nuestro ejemplo se llama MostrarFechayHora (7). desde cualquier aplicación de OpenOffice. El siguiente paso es que escojas la combinación de teclas que quieres asignar a nuestra macro.org. así como mostrar las Combinaciones de teclas de OpenOffice. para nuestro ejemplo. ve al menú Ver | Barra de herramientas | Personalizar. también notaras que algunas teclas. tienes que decidir “cuando” o “como” quieres ejecutarla.org. para ello. hagamos que se ejecute con una combinación de teclado. por que delante de ellas tienen la tarea asignada (4). como por ejemplo la tecla F1. el siguiente paso es seleccionar la macro que deseamos ejecutar con esta combinación de teclas. te va a dar cuenta las que ya están en uso. para ello. primero desplazate en el cuadro de lista Área (6) hasta encontrar la opción Macros de OpenOffice. solo te resta seleccionar la biblioteca y el modulo donde esta la macro a asignar. que te mostrara el siguiente cuadro de dialogo: Asegurate de que este seleccionada la ficha Teclado (1). cuidate de seleccionar una que este libre.120 End Sub 5..org (2). desplazate en el cuadro de lista Combinación de teclas (3) y escoge la que más te guste.2 Asignando macros Ahora. Aprendiendo OOo Basic 121 Observa como tienes opción de cargar combinaciones de teclas guardadas. . presiona el botón de comando Modificar (8) que asigna finalmente la combinación de teclas (9) a la macro seleccionada (10). Como ultimo paso. Para terminar. presiona el botón de comando Aceptar. así como de guardar las actuales y restablecer las predeterminadas. te queda de tarea “jugar” y experimentar con estas opciones. a un suceso del sistema. desde cualquier documento. 64. solo nos resta probar que funcione. presiona la combinación de teclas seleccionada (Ctrl+Shift+M) y si todo esta correcto.122 5."Creando documento" End Sub . Ahora veamos como asignar una macro a un evento. para ello.2 Asignando macros Ahora. te tiene que mostrar: Con un poco de imaginación puedes crear tus accesos directos para probar todas las macros que quieras de una forma sencilla. vamos a crear una sencilla macro de ejemplo: Sub MostrarMensaje() Dim sMensaje As String sMensaje = "No te olvides de guardar tu documento" MsgBox sMensaje. . la biblioteca y el modulo que contiene la macro deseada.Aprendiendo OOo Basic 123 Ve al menú Ver | Barra de herramientas | Personalizar. te desplegara un cuadro de dialogo que ya conoces. Para nuestro ejemplo seleccionaremos el “evento” Crear documento (3) que se ejecuta cada vez que creamos un nuevo documento. selecciona la ficha Eventos (1) y asegurate de seleccionar OpenOffice.. Observa como delante del “evento” queda seleccionada la macro. selecciona la macro. (4)... con el botón de comando Macro. presiona Aceptar y listo.org (2) para guardar la asignación que hagamos.. crea tantos nuevos documentos como quieras. solo te resta presionar el botón de comando Aceptar y probar la macro. solo te resta navegar dentro del archivo. esta vez. Ahora. . . Asignar una macro a un menú o a una barra de herramientas es trivial.124 5. pues puede ser tan sencillo como nuestros ejemplos.2 Asignando macros Con cada nuevo documento creado. más adelante profundizaremos en algunas de sus opciones. de cualquier aplicación de OOo. así que te queda de tarea intentar hacerlo. te tiene que mostrar el mensaje: Asignar macros a eventos no es un tema menor. conectarte a una base de datos o a una página web y muchas cosas más. existe una palabra clave que nos da acceso inmediato a este “servicio”.star. pero aquí empieza lo divertido e interesante. de la siguiente manera. “necesitas” asignarlo a una variable de objeto.Desktop" ) appOpenOffice = StarDesktop Ejecutando la macro anterior. por ello. “StarDesktop” por lo que. modifica la macro para que quede de la siguiente manera: Option Explicit Sub AccediendoAOpenOffice2() Dim appOpenOffice As Object Dim oActivo As Object 'Inicializamos una variable con el servicio com.Identifier End Sub Ahora si.sun. por ahora. pues nos permite acceder a “toda” la aplicación y sus componentes.star.Desktop appOpenOffice = StarDesktop 'Obtenemos una referencia al componente activo oActivo = appOpenOffice. tal vez te muestre este otro: .frame. Para crear. Sub AccediendoAOpenOffice1() Dim appOpenOffice As Object appOpenOffice = createUnoService( "com.CurrentComponent 'Mostramos el tipo de componente MsgBox oActivo.sun. no veras ningún efecto.frame.Desktop" ) End Sub El servicio com.frame.Desktop es usado muy frecuentemente. vamos a explorar por dentro del OpenOffice. Dim NombreVariable As Object E inicializarla para poder usarla.star. acceder y manipular un servicio.org.star. la siguientes dos líneas son equivalentes: appOpenOffice = createUnoService( "com. al ejecutar te tiene que mostrar el siguiente mensaje: Pero.3 Creando nuestro primer “servicio” (objeto).sun. para ello. usamos la función createUnoService.Aprendiendo OOo Basic 125 5.frame.sun. star. es decir. es una “propiedad” lo que esta mal.sun. En el tema anterior vimos como llamar a una macro desde donde queramos. Ejecuta la macro anterior desde cada uno de estos documentos.126 5. Todos excepto la base de datos te tienen que mostrar el mensaje correctamente y en el caso de la base de datos.sun. Abre seis archivos.sheet.sun.SpreadsheetDocument" MsgBox "Soy una hoja de calculo" Case "com.star. Incluso tal vez el siguiente: ¿Por que? Porque dependerá desde donde “llames” (ejecutes) la macro.drawing. pero no estaría de más por que los vamos a usar en repetidas ocasiones. o tal vez la llamaste desde una hoja de calculo o desde un archivo de texto.star.3 Creando nuestro primer “servicio” (objeto).CurrentComponent 'Mostramos el tipo de componente Select Case oActivo.org (hoja de calculo. queda a tu criterio. documento de texto.frame.DrawingDocument" MsgBox "Soy un dibujo" .star. presentación.Desktop appOpenOffice = StarDesktop 'Obtenemos una referencia al componente activo oActivo = appOpenOffice. En este caso. te tiene que mostrar el error siguiente: Aprendete muy bien estas dos nuevas palabras “propiedad” y “método”.PresentationDocument" MsgBox "Soy una presentacion" Case "com. las vas a usar de aquí en adelante y siempre que programes en OOo Basic. verifícalo. la propiedad Identifier.presentation. podríamos empezar a proponer una macro genérica para saber que tipo de documento es el activo. aunque lo más practico para los siguientes ejemplos es que programes tus macros dentro de archivo Mis macros.Identifier Case "com.sun. uno por cada tipo de documento que podemos manejar en OpenOffice. tal vez la ejecutaste directamente desde el IDE. base de datos y formula) no necesariamente tienes que guardarlos. probemos con la siguiente: Sub AccediendoAOpenOffice3() Dim appOpenOffice As Object Dim oActivo As Object 'Inicializamos una variable con el servicio com. no la implementan las bases de datos. Sabiendo esto. dibujo. ImplementationName End Sub Esta vez si nos muestra un mensaje en todos los documentos. aquí el resumen de lo que tendrías que obtener en cada caso: Aplicación Writer Calc Impress Draw Base Math Tipo de documento Documento de texto Hoja de calculo Presentaciones Dibujo Base de datos Formula Propiedad ImplementationName SwXTextDocument ScModelObj SdXImpressDocument SdXImpressDocument com. implementar un controlador de errores pero por ahora no lo haremos. Todos los objetos admiten un método que nos permite preguntar si dicho objeto soporta un servicio en especial. ¿Y si en vez de devolver un cadena de texto. es decir.supportsService( Nombre_del_Servicio As String) Veamoslo trabajando en el siguiente ejemplo: . si quieres.sun.sheet.TextDocument" MsgBox "Soy un documento de texto" End Select End Sub Ejecuta la macro anterior desde cada uno de los seis archivos.SpreadsheetDocument”. en este caso. y cada documento soporta un tipo de servicio diferente. puedes. este método se llama supportsService y hay que pasarle como argumento el nombre del servicio que queremos validar y nos devolverá verdadero (True) o falso (False) según soporte o no el servicio. no resulta muy idónea para diferenciar a cada uno.Aprendiendo OOo Basic 127 Case "com.sun.star. busquemos otra alternativa.comp. por lo que la sintaxis competa de este método es: Variable As Boolean = Objeto. le preguntamos a cada componente si son lo que dicen ser?.sun. a pesar de estar implementada en todos los tipos de documentos.CurrentComponent 'Mostramos el tipo de componente MsgBox oActivo.star.math. probemos ahora la propiedad ImplementationName y veamos que pasa: Sub AccediendoAOpenOffice4() Dim oActivo As Object 'Obtenemos una referencia al componente activo oActivo = StarDesktop.comp. por lo que esta propiedad.start. nota el valor devuelto en las hojas de calculo y como las presentaciones y los dibujos devuelven el mismo resultado. excepto desde la base de datos pues te dará un error.ODatabaseDocument com.start.star. claro. una hoja de calculo implementa propiedades y métodos (servicios) para manipular hojas de calculo.sun. por ejemplo.FormulaProperties" MsgBox "Soy una formula" Case "com. pero notaras que esta propiedad en algunos documentos no es muy clara.dba. por ejemplo.text.sun.FormulaDocument ¿Te fijas que interesante?.formula. este servicio se llama "com. star.supportsService("com.star.script.sheet.text.supportsService("com.sdb.sun.PresentationDocument") Then MsgBox "Soy una presentacion" ElseIf oActivo.star. es muy importante para minimizar el riesgo de errores y para consultar directamente las propiedades y métodos que implementa dicho servicio sin tener que estar “adivinando” nada y precisamente para no estar adivinando.star. esta propiedad se llama SupportedServiceNames y su sintaxis es: Variable As Array = Objeto.sheet.drawing.DrawingDocument") Then MsgBox "Soy un dibujo" ElseIf oActivo.star. simplemente consultando si soporta su respectivo “servicio”: Sub AccediendoAOpenOffice6() Dim oActivo As Object oActivo = StarDesktop.CurrentComponent If oActivo.supportsService("com.SupportedServiceNames Como siempre.BasicIDE") Then MsgBox "Soy el editor de codigo IDE" Else MsgBox "NO se que tipo de documento soy" End If End Sub Ahora si.sun. no hay como los ejemplos: Sub Dim Dim Dim AccediendoAOpenOffice7() oActivo As Object mServicios() As String co1 As Byte .3 Creando nuestro primer “servicio” (objeto).star.sun.FormulaProperties") Then MsgBox "Soy una formula" ElseIf oActivo.sun.sun. Saber si un objeto implementa un determinado servicio.sun. bImplementaServicio = oActivo.presentation.star.supportsService("com.supportsService("com.star.CurrentComponent 5.supportsService("com.SpreadsheetDocument") If bImplementaServicio Then MsgBox "Soy una hoja de calculo" Else MsgBox "NO soy una hoja de calculo" End If End Sub Y prueba desde todos nuestros documentos que funciona correctamente por lo que ya podemos implementar una macro mejor para saber que tipo de documento tenemos activo. existe una propiedad que nos devuelve una matriz (array) con los servicios que soporta un objeto.SpreadsheetDocument") Then MsgBox "Soy una hoja de calculo" ElseIf oActivo.128 Sub AccediendoAOpenOffice5() Dim oActivo As Object Dim bImplementaServicio As Boolean oActivo = StarDesktop.formula. ya podemos discriminar correctamente los documentos.sun.supportsService("com.supportsService("com.sun.TextDocument") Then MsgBox "Soy un documento de texto" ElseIf oActivo.OfficeDatabaseDocument") Then MsgBox "Soy una base de datos" ElseIf oActivo. drawing.DrawingDocument com.GenericDrawingDocument com.sun.drawing.star.document.document.drawing.supportsService("com.star. tienes que obtener la siguiente lista de servicios en cada uno: Aplicación Tipo de documento Writer Documento de texto Propiedad SupportedServiceNames com.DrawingDocumentFactory com.OfficeDatabaseDocument com.OfficeDocument com.GenericTextDocument com.star.star.star.OfficeDocument com.sun. que.sheet.sun.OfficeDocument).sun.OfficeDocument") If bImplementaServicio Then MsgBox "Verdad que si esta implementado el servicio" Else MsgBox "NO esta implementado el servicio" End If .sun.sun.CurrentComponent bImplementaServicio = oActivo.sun.star.drawing.star.sun.CurrentComponent 'Obtenemos una matriz con los servicios que implementa mServicios() = oActivo. en todos los demás documentos también te funcionara.sun.star.sheet.star.PresentationDocument com.formula.sun. es común a todos los documentos.sun.sdb.document.OfficeDocument com.sun.sun.SpreadsheetDocumentSettings com.text.sun.sun.star.sun.start.star. podemos demostrar que lo implementa con el siguiente ejemplo que tienes que ejecutar desde cualquier hoja de calculo.text.star.SupportedServiceNames 'Y mostramos el nombre de cada servicio For co1 = LBound( mServicios() ) To UBound( mServicios() ) MsgBox mServicios( co1 ) Next End Sub Y si ejecutas la macro anterior desde cada uno de nuestros seis documentos abiertos.OfficeDocument com.TextDocument com.document.sun.document. pero recuerda que solo queremos comprobar si la hoja de calculo implementa este servicio: Sub AccediendoAOpenOffice8() Dim oActivo As Object Dim bImplementaServicio As Boolean oActivo = StarDesktop.sun.Aprendiendo OOo Basic 129 'Obtenemos una referencia al componente activo oActivo = StarDesktop.star.star.DrawingDocumentFactory com.document.document.OfficeDocument com.drawing.GenericDrawingDocument com.star.star.SpreadsheetDocument com.presentation.star. pero no creas que la hoja de calculo no lo implementa.star. excepto en la hoja de calculo.FormulaProperties Calc Impress Hoja de calculo Presentaciones Draw Dibujo Base Math Base de datos Formula Nota como Impress y Draw implementan casi los mismos servicios y observa como hay un servicio (com.sun. casi todos los métodos tienen su correspondencia en una propiedad. en la medida de lo posible. también es muy usado e importante como más adelante podrás comprobarlo. cuando se les pasan argumentos y cuando devuelven un valor se ven afectados por estas consideraciones. los objetos son como los sustantivos. hemos accedido a un solo documento.nextElement() 'Mostramos el tipo de documento MsgBox "Soy un documento de " & TipoDocumento( oDocumento ) Loop End Sub Function TipoDocumento(ByRef Documento As Object) As String Dim sAplicacion As String . pero en OOo Basic. Por ahora. el uso como método y como propiedad.getComponents() 'Enumeramos cada uno oEnumeraDocumentos = oDocumentos. principalmente cuando vimos variables y funciones.hasMoreElements() 'Nos desplazamos al siguiente elemento y lo asignamos oDocumento = oEnumeraDocumentos. pero ve que no hemos usado la propiedad SupportedServiceNames. diferenciados por el prefijo get y los paréntesis. sino el método getSupportedServiceNames(). por lo que reitero. Hasta ahora. End Sub Este servicio común a todos los documentos. así mismo los métodos. copia y prueba la siguiente macro: Option Explicit Sub Dim Dim Dim Controlando_OpenOffice1() oDocumentos As Object oDocumento As Object oEnumeraDocumentos As Object 'Accedemos a todos los documentos actualmente abiertos oDocumentos = StarDesktop. así mismo y muy importante. te mostrare. más adelante me limitare a usar métodos y tu usaras el que más de agrade. por lo que tienes que tener las mismas consideraciones (y precauciones) vistas en varios temas atrás.130 5. las propiedades son adjetivos y los métodos son verbos.3 Creando nuestro primer “servicio” (objeto).createEnumeration() 'hasMoreElements devuelve verdadero (True) mientras haya elementos Do While oEnumeraDocumentos. los dos hacen lo mismo. integer. A lo largo de este capitulo. si te es útil. Sub Dim Dim Dim AccediendoAOpenOffice9() oActivo As Object mServicios() As String co1 As Byte oActivo = StarDesktop. las propiedades siempre son de un tipo de dato soportado por OOo Basic (string. array.getSupportedServiceNames() For co1 = LBound( mServicios() ) To UBound( mServicios() ) MsgBox mServicios( co1 ) Next End Sub Notaras que trabaja exactamente igual que la anterior.CurrentComponent mServicios() = oActivo. etc. recuerda tus clases elementales de español.).org. copia la siguiente macro y pruebala de nuevo con todos los documentos. ten cuidado con los tipos de datos que usas. pero podemos acceder a todos los documentos actualmente abiertos en OpenOffice. nextElement(). .sun.sun.DrawingDocument") Then sAplicacion = "Draw" ElseIf Documento.text.sdb. para saber si el documento ha sido modificado. el método .sun.org.supportsService("com.sun. como dicen en mi pueblo -sobre advertencia no hay engaño-.script.hasMoreElements() nos sirve para saber si todavía hay elementos y el método .SpreadsheetDocument") Then sAplicacion = "Calc" ElseIf Documento.supportsService("com. así que la estructura de la macro anterior la podrías usar con frecuencia. Empecemos con código un poco más divertido. es como un listado de objetos.star.supportsService("com. Sub Dim Dim Dim Dim Controlando_OpenOffice2() oDocumentos As Object oDocumento As Object oEnumeraDocumentos As Object co1 As Integer oDocumentos = StarDesktop. te cerrara “todos” los archivos de Calc que no tengan cambios por guardar.star. si ejecutas la siguiente macro desde un archivo de Calc podrías cerrarte el archivo con resultados inesperados.sun.sun. te cerrará el archivo sin preguntarte nada.Aprendiendo OOo Basic 131 If Documento.isModified() Then 'el metodo dispose cierra el archivo oDocumento.getComponents() oEnumeraDocumentos = oDocumentos. Una “enumeración”.BasicIDE") Then sAplicacion = "Basic" Else sAplicacion = "Desconocido" End If TipoDocumento = sAplicacion End Function Toma nota de como hemos convertido una macro usada anteriormente en una función que nos devuelve el tipo de documento abierto. Observa como usamos la propiedad isModified().dispose() co1 = co1 + 1 End if End If Loop MsgBox "Se cerraron un total de " & CStr(co1) & " archivos de Calc" End Sub Ten mucho cuidado con el método dispose.nextElement() 'Verificamos que sea un archivo de Calc If TipoDocumento( oDocumento ) = "Calc" Then 'Si no ha sido modificado o los cambios ya estan guardados 'el metodo isModified devolvera False If Not oDocumento. usalo con conocimiento de causa.createEnumeration() Do While oEnumeraDocumentos. la siguiente variante de la macro anterior.drawing.star.star.star.star.presentation.sheet.FormulaProperties") Then sAplicacion = "Math" ElseIf Documento.OfficeDatabaseDocument") Then sAplicacion = "Base" ElseIf Documento. permite movernos al siguiente elemento de la enumeración.sun.supportsService("com.supportsService("com.TextDocument") Then sAplicacion = "Writer" ElseIf Documento. Muchos objetos en OpenOffice. se crean con el método createEnumeration(). CUIDADO.formula.supportsService("com.star.PresentationDocument") Then sAplicacion = "Impress" ElseIf Documento.hasMoreElements() oDocumento = oEnumeraDocumentos. solo son accesibles creando una “enumeración”.supportsService("com. tenga o no tenga cambios guardados. html También puedes descargarla y después consultarla fuera de línea para su acceso inmediata o si no tienes conexión permanente a Internet. También vimos el uso del método getSupportedServiceNames() que nos devuelve una matriz con los nombres de los servicios que implementa el objeto. este cuenta con tres propiedades que nos informan de todas las propiedades. método o propiedad estamos buscando. pero en OOo Basic no tiene importancia por que accedemos directamente a las propiedades y métodos de los servicios. para nuestros fines es perfectamente valido que los llamemos “servicios”. .Dbg_Methods MsgBox StarDesktop. pero tiene el inconveniente de que tenemos que saber anticipadamente el nombre de dicho servicio. Para una consulta óptima de esta documentación. Dbg_Properties 3.Dbg_Properties MsgBox StarDesktop. La Interfaz de Programación de la Aplicación (API por sus siglas en ingles) proporciona.Dbg_SupportedInterfaces End Sub No te me confundas con esto de las “interfaces”. Dbg_SupportedInterfaces 2. lo cual a veces es un poco complicado.1 Propiedades especiales de depuración Ya vimos en el tema anterior como saber con el método “supportsService” si un objeto soporta un determinado servicio. lo ideal es saber de forma anticipada que servicio.3. la puedes consultar en linea (por ahora solo en ingles) dentro de la página www.3 Creando nuestro primer “servicio” (objeto). métodos e “interfaces” que implementa dicho objeto.openoffice. veamos cuales son. para ello. todos los objetos cuentan con unas propiedades especiales que nos dan mucha información. estas propiedades son tres: 1. 5.132 5. Dbg_Methods Las tres son de tipo texto (string) y se usan de la siguiente manera: Sub ConsultandoObjetos1() Dim sDatos As String MsgBox StarDesktop. en el Apéndice B te muestro como hacerlo.openoffice.org http://api. Para obtener toda la información de un objeto.org. decenas incluso centenas de servicios con métodos y propiedades para controlar y manipular OpenOffice.org/docs/common/ref/com/sun/star/module-ix. simplemente piensa en las interfaces como una forma de organizar servicios. Aprendiendo OOo Basic 133 La pequeña macro anterior. te tiene que mostrar un cuadro de mensaje con las propiedades del objeto: Sus métodos: . nota que se nos muestra el tipo de valor que puedes obtener de las propiedades y que será el mismo tipo para establecerla si la propiedad es de escritura. si vamos a su documentación. SbxSTRING getURL ( void ) .getCurrentComponent(). te darás cuenta que solo tiene un método loadComponentFromURL. por ejemplo y siguiendo en la suposición de que nos informamos de una hoja de calculo. lo cual veremos al terminar este tema..Dbg_SupportedInterfaces End Sub Esta vez nos muestra muchos más datos.org/docs/common/ref/com/sun/star/frame/XComponentLoader.object). pues nos permite crear documentos nuevos o abrir archivos existentes. otra una cadena (2. Ahora. Ahora probemos con los datos del documento activo: Sub ConsultandoObjetos2() Dim sDatos As String MsgBox StarDesktop.string) y por ultimo un objeto (3. pero un método muy importante. Por ejemplo.getCurrentComponent().Dbg_Properties MsgBox StarDesktop. SbxOBJECT Sheets Tenemos una propiedad que devuelve un array (1).. ¿verdad?. en las propiedades.3 Creando nuestro primer “servicio” (objeto).Dbg_Methods MsgBox StarDesktop. si ejecutamos la macro anterior desde una hoja de calculo podremos ver entre sus propiedades las siguientes: 1.html). Y sus interfaces (servicios): Observa el servicio señalado con una flecha. SbxSTRING Location 3. en línea (http://api.134 5.getCurrentComponent(). tenemos: 1. SbxARRAY Printer 2.openoffice. en los métodos también nos muestra información valiosa. observa de que forma tan simple podemos obtener mucha información.html) o local (file:///opt/openoffice/sdk/docs/common/ref/com/sun/star/frame/XComponentLoader. en el Apéndice B te muestro como hacerlo.star. 5. la macro se llama WritedbgInfo y solo hay que pasarle el objeto del cual queremos obtener su información.Aprendiendo OOo Basic 135 2. nos escriba la información en una hoja de calculo.sun.datatransfer.star. existe una en especial que te escribe la información de las tres propiedades vistas en un nuevo documento de Writer. crearlos y guardarlos. muestra la información necesaria para ir a la documentación del API y saber que otros servicios soporta. existen varias que nos ayudan a depurar nuestras macros. SbxARRAY ) 3. veamoslo con un ejemplo: Sub ConsultandoObjetos3() BasicLibraries.4 Trabajando con documentos En donde veremos como manipular documentos de OpenOffice.XTransferable 2. 1. dentro de las macros que trae OpenOffice. 5.org. aunque la puedes ejecutar siempre y cuando la variable pasada apunte “efectivamente” a una variable de objeto.sun. el método que nos permite crear nuevos documentos se llama loadComponentFromURL y es un método del servicio “com.getCurrentComponent() ) End Sub Prueba la macro anterior.sheet. veamos primero los ejemplos y después las explicaciones: Option Explicit . el método storeAsURL requiere una cadena (string) y un array como argumentos (2). Por ultimo. Para terminar este tema.star.frame.sun.LoadLibrary( "Tools" ) Call WritedbgInfo( StarDesktop. com. com.star.sun. com. solo hay que hacer las preguntas y búsquedas correctas.1 Creando nuevos documentos Como ya dijimos. Por ahora lo importante es saber reconocer la sintaxis de esta información para usarla en nuestras macros. El trabajo común a la mayoría de los documentos. SbxINTEGER resetActionLocks ( void ) En este caso tenemos el método getUrl que devuelve una cadena (string) y no necesita argumentos (1). para el tema que estamos tratando. que métodos y que propiedades.XSpreadsheetDocument Creo que con esto queda demostrado que no hay que estar adivinando nada.view. devuelve un entero (integer) y no necesita argumentos (3). pero no devuelve ningún valor y por ultimo el método resetActionLocks. llamándola desde diferentes documentos.org. Con unas pequeñas variantes podemos hacer que en vez de un documento de Writer.XComponentLoader”. cualquiera de los servicios mostrados.XPrintable 3. SbxVOID storeAsURL ( SbxSTRING.4. 0. 0. "_default".loadComponentFromURL( sRuta. mArg() ) End Sub Y los demás tipos de documentos: Sub Dim Dim Dim CreandoNuevosDocumentos3() sRuta As String mArg() oNuevoDocumento As Object sRuta = "private:factory/simpress" oNuevoDocumento = StarDesktop. creamos una nueva hoja de calculo. probemos: Sub Dim Dim Dim CreandoNuevosDocumentos4() sRuta As String mArg() oNuevoDocumento As Object sRuta = "private:factory/sbase" oNuevoDocumento = StarDesktop. "_default". y si.loadComponentFromURL( sRuta. solo hay que hacer unos pequeños cambios para crear un documento de texto: Sub Dim Dim Dim CreandoNuevosDocumentos2() sRuta As String mArg() oNuevoDocumento As Object sRuta = "private:factory/swriter" oNuevoDocumento = StarDesktop.loadComponentFromURL( sRuta. lo deduces bien. mArg() ) sRuta = "private:factory/smath" oNuevoDocumento = StarDesktop. 0. 0. mArg() ) End Sub ¿Y una base de datos?. "_default". muy fácil ¿no?.136 5. mArg() ) End Sub ¿Ya la probaste?.loadComponentFromURL( sRuta.loadComponentFromURL( sRuta. "_default". mArg() ) sRuta = "private:factory/sdraw" oNuevoDocumento = StarDesktop. mArg() ) End Sub Nos da un error ¿verdad? . 0.4 Trabajando con documentos Sub Dim Dim Dim CreandoNuevosDocumentos1() sRuta As String mArg() oNuevoDocumento As Object sRuta = "private:factory/scalc" oNuevoDocumento = StarDesktop.loadComponentFromURL( sRuta. "_default". "_default". 0. no te preguntara nada.ods" . así que ten cuidado de no usar una ruta o nombre de una base importante que tengas y segundo. no quedara “registrada” en OpenOffice.4. pasarle la ruta en formato Url. de los demás documentos podemos crear tantos nuevos documentos como queramos sin tener que guardar nada.ods Toma en cuenta que este formato hace uso de los caracteres 0-9.star. si queremos trabajar con ella.2 Rutas de archivos y directorios OpenOffice. solo pasa con las bases de datos. en el formato URL. esto. tenemos que guardar primero la base de datos: Option Explicit Sub Dim Dim Dim Dim CreandoBaseDeDatos1() oBDServicio As Object oBDNueva As Object sRuta As String mArg() 'Ruta y nombre donde quedara guardada la base de datos sRuta = "/home/mau/Mi_Base_Datos.org. es decir. Para saber por que nos da un error.Aprendiendo OOo Basic 137 No esta soportado. y cualquier otro carácter será convertido y mostrado con su respectivo código.storeAsURL( sRuta. si ya existe. casi como una regla. simplemente lo reemplazara.odb" 'Creamos el servicio que nos permite manipular bases de datos oBDServicio = createUnoService( "com. por ejemplo.createInstance() 'Establecemos el tipo de base oBDNueva. con lo que no tendrás acceso desde otros programas de la aplicación. para ello. los espacios los reemplazara con %20. Siempre que le pases una ruta de archivo a cualquier servicio de OpenOffice.sun. del mismo modo que lo hacemos desde la interfaz de usuario.ods file:///d:/datos/miarchivo. la base de datos así creada. por ejemplo: file:///home/usuario/datos/miarchivo. OOo Basic cuenta con dos funciones muy útiles que hacen el trabajo ConvertToUrl y ConvertFromUrl. procura. mArg() ) End Sub Toma en cuenta dos cosas muy importantes en la macro anterior. hace uso de las rutas de archivos y directorios. el asistente nos “obliga” primero a guardarla con un nombre y después ya podemos manipularla.URL = "sdbc:embedded:hsqldb" 'Y la guardamos oBDNueva.org. a-z y A-Z. observa como primero.org. más adelante veremos como registrar una base de datos por código. al ser multiplataforma.DatabaseContext" ) 'Creamos una nueva instancia de una base de datos oBDNueva = oBDServicio. la respuesta es sencilla. intenta abrir una base de datos nueva. el nombre que uses. entonces ¿como creamos una nueva base de datos?. 5.DatabaseDocument.sdb. veamos como se usan: Sub RutasDeArchivos1() Dim sRuta As String 'Establecemos una ruta sRuta = "/home/mau/Mi archivo de Calc. getURL() 'Convertimos la ruta URL en formato local sRutaCompleta = ConvertFromUrl( sRutaURL ) 'Obtenemos solo el nombre del archivo sNombre = FileNameOutOfPath( sRutaURL ) 'Obtenemos el directorio donde esta el archivo sRuta = DirectoryNameoutofPath(sRutaCompleta.ods" ) 'Y vemos el resultado MsgBox sRuta 'Regresamos al formato local sRuta = ConvertFromUrl( sRuta ) 'Y comprobamos que es correcto MsgBox sRuta End Sub 5. GetPathSeparator()) 'Mostramos los resultados MsgBox sRutaCompleta & Chr(13) & Chr(13) & sNombre & Chr(13) & Chr(13) & sRuta End Sub El objeto ThisComponent. veremos la importancia de usar las rutas de archivos y directorios en formato Url y recuerda que en S.138 'Y la mostramos MsgBox sRuta 'La convertimos al formato URL sRuta = ConvertToUrl( "/home/mau/Mi archivo de Calc. Estas y otras útiles funciones se encuentran dentro de la biblioteca Tools de OpenOffice. es una palabra clave especial que designa al documento desde el cual llamamos a nuestra macro. que te regresa solo el directorio de la ruta del archivo pasada. Observa que hacemos uso de algunas funciones incorporadas de OpenOffice. comprobar siempre a que tipo de documento esta apuntando ThisComponent. sea el que esperas. es buena practica de programación.4. guardando y cerrando documentos . no es lo mismo si ejecutas una macro desde la interfaz del usuario. a que lo hagas desde el IDE.4 Trabajando con documentos Abre varios documentos existentes y ejecuta la siguiente macro desde cada uno: Sub Dim Dim Dim Dim DocumentoActivoMostrarDatos() sRutaURL As String sRutaCompleta As String sRuta As String sNombre As String 'Referencia al documento activo sRutaURL = ThisComponent. Linux. y aun desde el IDE. 5.org.O. que te devuelve de la ruta pasada solo el nombre del archivo y DirectoryNameoutofPath. así que siempre verifica que el objeto apuntado con ThisComponent.3 Abriendo. dependerá si haces referencia a el desde un archivo cualquiera o desde el archivo especial Mis Macros.org En nuestro siguiente tema. estas son: FileNameOutOfPath. se tiene en cuenta la diferencia entre mayúsculas y minúsculas. PropertyValue" oDoc As Object mOpciones(0). si el valor es falso (False).sun.Aprendiendo OOo Basic 139 Abrir archivos existentes es sumamente sencillo.Name = "AsTemplate" mOpciones(0).Value = True sRuta = ConvertToUrl( "/home/mau/Mi archivo de Writer. le estamos indicando que queremos abrir la plantilla para editarla.PropertyValue" esta conformada por un par de valores. en caso contrario (True) abrirá una copia de la plantilla.Name = "AsTemplate" mOpciones(0). "_blank".star. en este caso.odt" ) oDoc = StarDesktop. es decir. prueba el siguiente código con algún archivo existente que no sea plantilla: Sub Dim Dim Dim AbriendoDocumentos4() sRuta As String mOpciones(0) As New "com. Lo interesante de esta propiedad es que perfectamente la puedes aplicar a archivos existentes. le especificamos la ubicación del archivo a abrir de la siguiente manera: Sub Dim Dim Dim AbriendoDocumentos1() sRuta As String mArg() oDocumento As Object 'Reemplaza esta ruta por la ruta de tu archivo sRuta = ConvertToUrl( "/home/mau/Mi archivo de Calc. por ejemplo. observa como se declara la variable mOpciones: Sub Dim Dim Dim AbriendoDocumentos3() sRuta As String mOpciones(0) As New "com. te abrirá una copia de dicha plantilla: sRuta = ConvertToUrl( "/home/mau/miplantilla.loadComponentFromURL( sRuta. mOpciones() ) End Sub La estructura "com. es decir. pero en el parámetro ruta.Value = False sRuta = ConvertToUrl( "/home/mau/miPlantilla. un nombre y un valor y es muy frecuentemente usada cuando se programa en OOo Basic.org que las requieran Si abres una plantilla.beans. le indicamos en las opciones de apertura esto.sun. "_blank". mArg() ) End Sub Si tu archivo existe. esta se comportara de forma normal. 0. 0. 0. En la macro anterior le estamos indicando la propiedad AsTemplate (que seria algo así como Es Plantilla).loadComponentFromURL( sRuta.star. mArg() ) Pero también podrías querer abrir la plantilla para editarla. observa como la matriz de la variable mOpciones la hemos inicializado en 0. “siempre” utiliza ConvertToUrl cuando uses rutas de archivos o directorios en funciones de OpenOffice.loadComponentFromURL( sRuta.PropertyValue" oDoc As Object mOpciones(0). 0. con esta propiedad podemos forzarlos a comportarse como plantillas.ots" ) oDoc = StarDesktop.star. pero muy bien puede tener más opciones como veremos más adelante. "_blank". mOpciones() ) . es decir. "_blank".sun. solo contendrá un par de valores.beans. el código anterior lo abrirá.loadComponentFromURL( sRuta.beans. archivos que “no” necesariamente sean plantillas.ott" ) oDocumento = StarDesktop. usamos el mismo método usado para crear nuevos documentos.ods" ) oDocumento = StarDesktop. Otras propiedades interesantes son ReadOnly (Solo Lectura) para abrir un archivo como solo lectura y Password (Contraseña) para abrir archivos con contraseña: Sub Dim Dim Dim AbriendoDocumentos5() sRuta As String mOpciones(0) As New "com.beans. mOpciones() ) End Sub Por supuesto puedes combinar cualquier cantidad de opciones siempre y cuando no entren en conflicto: Sub Dim Dim Dim AbriendoDocumentos7() sRuta As String mOpciones(1) As New "com.sun.loadComponentFromURL( sRuta.Name = "ReadOnly" mOpciones(0).140 5.star.loadComponentFromURL( sRuta.beans. "_blank".star. por supuesto.Name = "Password" .odt" ) oDoc = StarDesktop.PropertyValue" oDoc As Object mOpciones(0).PropertyValue" oDoc As Object mOpciones(0).sun.loadComponentFromURL( sRuta. 0. 0. "_blank".Value = "abrete" sRuta = ConvertToUrl( "/home/mau/Mi archivo de Draw. mOpciones() ) End Sub Prueba a poner la contraseña incorrecta y observa el mensaje.sun. pero con la propiedad AsTemplate.Name = "Password" mOpciones(1).PropertyValue" oDoc As Object 'La contraseña más segura mOpciones(0).Value = True sRuta = ConvertToUrl( "/home/mau/Mi archivo de Writer.beans.Value = True mOpciones(1).Name = "Password" mOpciones(0).4 Trabajando con documentos End Sub Observa como el archivo es un documento de texto normal (ODT).star. forzamos su apertura como una plantilla.odg" ) oDoc = StarDesktop. podemos solicitarle al usuario la contraseña y no esta demás verificar que el archivo exista: Sub Dim Dim Dim Dim AbriendoDocumentos8() sRuta As String mOpciones(0) As New "com.beans.Name = "ReadOnly" mOpciones(0).PropertyValue" oDoc As Object sContra As String sContra = Trim( InputBox( "Introduce la contraseña de apertura" ) ) mOpciones(0).Value = "abrete" sRuta = ConvertToUrl( "/home/mau/Mi archivo de Draw. "_blank".odg" ) oDoc = StarDesktop. mOpciones() ) End Sub Sub Dim Dim Dim AbriendoDocumentos6() sRuta As String mOpciones(0) As New "com.sun.star. 0. en el siguiente ejemplo.loadComponentFromURL( sRuta.star. mOpciones() ) End Sub .star.beans. de forma predeterminada lo abre con las macros desactivadas.Name = "MacroExecutionMode" mOpciones(0).org.PropertyValue" oDoc As Object sRuta = ConvertToUrl( "/home/mau/Campamentos. 0. 0.Name = "StartPresentation" mOpciones(0). mOpciones() ) sRuta = ConvertToUrl( "/home/mau/Renacimiento.xls" ) oDoc = StarDesktop.beans. "_blank".loadComponentFromURL( sRuta.htm" ) oDoc = StarDesktop. "_blank". 0.loadComponentFromURL( sRuta. 0.sun.PropertyValue" oDoc As Object mOpciones(0). "_blank".Value = True sRuta = ConvertToUrl( "/home/mau/Mi archivo de Impress. un Htm y un Xls: Sub Dim Dim Dim AbriendoDocumentos9() sRuta As String mOpciones(0) As New "com. "_blank". 0. "_blank". mOpciones() ) End Sub Cuando abres un archivo por código y este contiene macros. mOpciones() ) sRuta = ConvertToUrl( "/home/mau/datos.odg" ) 'Verificamos que exista el archivo If Len(Dir(sRuta)) > 0 Then oDoc = StarDesktop.loadComponentFromURL( sRuta. tu puedes establecer si se abre con las macros activadas.ods" ) oDoc = StarDesktop.beans. lo podrás abrir con el método loadComponentFromURL.sun.sun.Aprendiendo OOo Basic mOpciones(0). mOpciones() ) Else MsgBox "El archivo no existe" End If End Sub Mientras un tipo de archivo sea soportado por OpenOffice.Value = sContra 141 sRuta = ConvertToUrl( "/home/mau/Mi archivo de Draw. "_blank". es la que nos permite abrir una presentación e iniciarla inmediatamente: Sub Dim Dim Dim AbriendoDocumentos11() sRuta As String mOpciones(0) As New "com.PropertyValue" oDoc As Object mOpciones(0).odp" ) oDoc = StarDesktop.star. así que solo nos resta saber como abrirlo con las macros activadas: Sub Dim Dim Dim AbriendoDocumentos10() sRuta As String mOpciones(0) As New "com.loadComponentFromURL( sRuta.doc" ) oDoc = StarDesktop. mOpciones() ) End Sub Otra opción interesante. abrimos un archivo tipo Doc.loadComponentFromURL( sRuta.Value = 4 sRuta = ConvertToUrl( "/home/mau/Mi archivo de Calc. 0. PropertyValue" oDoc As Object sRuta = "private:factory/scalc" oDoc = StarDesktop. otros. También tenemos una propiedad que nos ayuda a saber si un documento ha sido modificado o no. como debe ser. 0.loadComponentFromURL( sRuta.sun. unos abrelos y modificalos antes de ejecutarla.PropertyValue" . mOpciones() ) MsgBox oDoc.loadComponentFromURL( sRuta.4 Trabajando con documentos Por supuesto. mOpciones() ) MsgBox oDoc.hasLocation() End Sub El primer mensaje debe mostrarte Falso (False) y el segundo Verdadero (True). Los documentos tienen una propiedades que no ayudan a saber si un documento ya esta guardado o no: Sub Dim Dim Dim AbriendoGuardandoDocumentos2() sRuta As String mOpciones(0) As New "com.beans.142 5.sun.star. mOpciones() ) 'AQUI va todo el codigo que quieras para manipular el archivo MsgBox "Archivo abierto y modificado correctamente. veamos como guardar los cambios realizados y cerrar el archivo: Sub Dim Dim Dim AbriendoGuardandoDocumentos1() sRuta As String mOpciones(0) As New "com.sun. "_blank".beans.close(True) End Sub El código anterior funcionara con un archivo existente.ods" ) oDoc = StarDesktop. la idea general de abrir un archivo es para obtener datos de el o para manipularlo.ods" ) oDoc = StarDesktop. llamándola desde diferentes documentos.beans.hasLocation() sRuta = ConvertToUrl( "/home/mau/Mi archivo de Calc. 0.star.PropertyValue" oDoc As Object sRuta = ConvertToUrl( "/home/mau/Mi archivo de Calc. 0. compruébalo.store() 'Cerramos el archivo oDoc. presione Aceptar para guardar y cerrar" 'Guardamos los cambios oDoc. "_blank". "_blank". te dará un error.star.loadComponentFromURL( sRuta.isModified() End Sub Y otra más que nos informa si el documento es de solo lectura: Sub AbriendoGuardandoDocumentos3() Dim sRuta As String Dim mOpciones(0) As New "com. por supuesto no me creas. ejecuta la siguiente macro. ya sea un documento nuevo o uno existente. pero con uno nuevo no. solo abrelos y ejecutala para que notes la diferencia: Sub EstaModificado() MsgBox ThisComponent. loadComponentFromURL( sRuta. "_blank". mOpciones() ) MsgBox oDoc.star. 0.ods" ) oDoc = StarDesktop. la ruta del archivo y una matriz de propiedades. "_blank". 0.storeAsURL( sRuta. "_blank".loadComponentFromURL( sRuta. Toma nota de que si el archivo ya existe lo reemplazara sin avisarte por lo que es buena practica de programación verificar esto: Sub Dim Dim Dim AbriendoGuardandoDocumentos5() sRuta As String mOpciones(0) As New "com.sun.sun. "_blank".Name = "ReadOnly" mOpciones(0). mOpciones() ) End Sub Observa como requiere dos parámetros. Veamos algunas propiedades interesantes para guardar archivos.PropertyValue" oDoc As Object sRuta = "private:factory/scalc" oDoc = StarDesktop.beans.isReadOnly() End Sub Ya te imaginaras que útil es saber. mOpciones() ) sRuta = ConvertToUrl( "/home/mau/Archivo de Calc. mOpciones() ) Else MsgBox "El archivo ya existe. antes de guardar un archivo.storeAsURL( sRuta. antes de ver trabajando juntas todas estas propiedades. veamos como guardar un archivo nuevo con el método storeAsUrl: Sub Dim Dim Dim AbriendoGuardandoDocumentos4() sRuta As String mOpciones(0) As New "com.ods" ) 'Guardamos el archivo oDoc. mOpciones() ) MsgBox oDoc. no se ha guardado el nuevo archivo" End If End Sub Te queda de tarea implementar la pregunta al usuario para reemplazar o no el archivo.loadComponentFromURL( sRuta. algunas de las cuales veremos a continuación.ods" ) If Len( Dir( sRuta )) = 0 Then 'Guardamos el archivo oDoc. mOpciones() ) 'Establecemos la ruta y nombre donde se guardara el archivo sRuta = ConvertToUrl( "/home/mau/Archivo de Calc.loadComponentFromURL( sRuta.star. si ha sido modificado o si ya ha sido guardado.beans. 0.PropertyValue" oDoc As Object sRuta = "private:factory/scalc" oDoc = StarDesktop. por ejemplo.isReadOnly() mOpciones(0). 0. si este es de solo lectura.Value = True sRuta = ConvertToUrl( "/home/mau/Mi archivo de Calc.Aprendiendo OOo Basic Dim oDoc As Object 143 sRuta = "private:factory/scalc" oDoc = StarDesktop. guardar con contraseña: Sub AbriendoGuardandoDocumentos6() . permitamos que el usuario escoja la ruta y el archivo desde un cuadro de dialogo.sun.star. por ejemplo.star. OpenOffice. soporta la importación/exportación de múltiples formatos de archivos. mOpciones() ) End Sub El método storeAsURL también lo puedes usar para abrir un archivo existente y guardarlo con otro nombre: Sub Dim Dim Dim AbriendoGuardandoDocumentos8() sRuta As String mOpciones(0) As New "com.storeAsURL( sRuta. mOpciones() ) End Sub Como sabes.storeAsURL( sRuta.Name = "FilterName" mOpciones(0). "_blank". que nos permite hacer esto. veamos como: Sub Dim Dim Dim Dim Dim AbrirArchivo1() oDlgAbrirArchivo as Object mArchivo() As String mOpciones() sRuta As String oDoc As Object 'Creamos el servicio necesario oDlgAbrirArchivo = CreateUnoService ("com.star.ods" ) oDoc.beans. "_blank".ui.dialogs. 0.ui. usaremos el servicio com.FilePicker. en formato DOC: Sub Dim Dim Dim AbriendoGuardandoDocumentos7() sRuta As String mOpciones(0) As New "com. "_blank". para ello.storeAsURL( sRuta.sun.Name = "Password" mOpciones(0).PropertyValue" Dim oDoc As Object 5.beans.Value = "MS Word 97" sRuta = ConvertToUrl( "/home/mau/Archivo de Word.dialogs.PropertyValue" oDoc As Object sRuta = ConvertToUrl( "/home/mau/Mi archivo de Calc.sun.loadComponentFromURL( sRuta.org.star. mOpciones() ) End Sub Para terminar esta capitulo.PropertyValue" oDoc As Object sRuta = "private:factory/swriter" oDoc = StarDesktop. 0. 0.star.sun. veamos como guardar. vamos a hacer un poco más interactivo la apertura y guardado de archivos.sun. mOpciones() ) 'Como vez no tengo mucha imaginacion mOpciones(0).ods" ) oDoc.beans.loadComponentFromURL( sRuta.doc" ) oDoc.144 Dim sRuta As String Dim mOpciones(0) As New "com.4 Trabajando con documentos sRuta = "private:factory/scalc" oDoc = StarDesktop.Value = "abrete" sRuta = ConvertToUrl( "/home/mau/Archivo de Calc.FilePicker") .ods" ) oDoc = StarDesktop. mOpciones() ) 'Establecemos el filtro a documentos tipo DOC mOpciones(0).loadComponentFromURL( sRuta. mOpciones() ) sRuta = ConvertToUrl( "/home/mau/Nuevo archivo Calc. dialogs.Execute() Then 'De forma predeterminada.FilePicker") oDlgAbrirArchivo.setTitle("Selecciona los archivos a abrir") 'Establecemos que se puedan seleccionar mas de un archivo oDlgAbrirArchivo.setMultiSelectionMode(True) If oDlgAbrirArchivo. 0.getSelectedFiles() 'Mostramos los archivos seleccionados For co1 = LBound( mArchivos() ) To UBound( mArchivos() ) MsgBox ConvertFromUrl( mArchivos(co1) ) Next 'Te queda de tarea abrir todos los archivos 'oDoc = StarDesktop.setTitle("Selecciona el archivo a abrir") 'Con el metodo .loadComponentFromURL( sRuta. para permitir al usuario seleccionar carpeta y nombre de archivo donde guardar su archivo: Sub Dim Dim Dim Dim GuardarArchivo1() oDlgGuardarArchivo as Object mDlgOpciones() mArchivo() As String mOpciones() 'Usamos el mismo servicio para abrir archivos.sun.star.sun.getFiles() 'El primer elemento de la matriz es el archivo seleccionado sRuta = mArchivo(0) 'Y lo abrimos oDoc = StarDesktop. pues es el mismo cuadro de dialogo oDlgGuardarArchivo = CreateUnoService ("com.Initialize ( mDlgOpciones() ) . mOpciones() ) Else 'Si el usuario presiona Cancelar MsgBox "Proceso cancelado" End If End Sub Si quieres abrir más de un archivo a la vez.ui.Execute() mostramos el cuadro de dialogo 'Si el usuario presiona Abrir el metodo devuelve 1 que podemos evaluar como Verdadero (True) 'Si presiona Cancelar devuelve 0 If oDlgAbrirArchivo.star. mostramos el cuadro de dialogo Guardar Como. "_blank". 0.dialogs. usa: Sub Dim Dim Dim Dim AbrirArchivo2() oDlgAbrirArchivo as Object mArchivos() As String mOpciones() co1 As Integer oDlgAbrirArchivo = CreateUnoService ("com.star.sun. mOpciones() ) Else MsgBox "Proceso cancelado" End If End Sub Ahora.loadComponentFromURL( sRuta. solo se puede seleccionar un archivo 'pero devuelve una matriz de todos modos con la ruta completa 'del archivo en formato URL mArchivo() = oDlgAbrirArchivo.dialogs.Aprendiendo OOo Basic 145 'Establecemos el titulo del cuadro de dialogo oDlgAbrirArchivo.ui.ui. "_blank".Execute() Then mArchivos() = oDlgAbrirArchivo.FilePicker") 'Establecemos que nos muestre el cuadro de dialogo Guardar Como con las 'casillas de verificacion Autoextension y guardar con contraseña 'com.TemplateDescription.FILESAVE_AUTOEXTENSION_PASSWORD = 2 mDlgOpciones() = Array(2) With oDlgGuardarArchivo 'Iniciamos el cuadro de dialogo con las opciones seleccionadas . esta función ya la usamos sTipoDoc = TipoDocumento( oDoc ) 'Solo se pueden exportar (por ahora) Select Case sTipoDoc 'los siguiente documentos Case "Calc".146 5. por ahora.AppendFilter( "Hoja de calculo ODF (. "*.4 Exportando a PDF Exportar a PDF desde OpenOffice. "*.Execute() Then mArchivo() = oDlgGuardarArchivo. usamos el mismo directorio 'y nombre del archivo.ods" ) End With 'Lo mostramos If oDlgGuardarArchivo.getUrl ) & ". te queda de tarea intentar adaptarla para archivos nuevos: Sub Dim Dim Dim dim ExportarPDF() oDoc As Object sTipoDoc As String mOpciones(0) As New "com.odt)". .AppendFilter( "All files (*.org es muy sencillo.4 Trabajando con documentos 'Agreamos filtros de archivos .sun.storeToURL( sRuta. lo es también con OOo Basic.ods)".4.*" ) .*)".Value = LCase(sTipoDoc) & "_pdf_Export" 'Construimos la ruta correcta.star. te devuelve toda la ruta pero sin la extensión del archivo. solo agregamos la extension PDF sRuta = GetFileNameWithoutExtension( oDoc.beans. asegurate de que los archivos ya estén guardados antes de exportar.pdf" 'Guardamos el archivo oDoc. "Draw". "*. de la ruta pasada. mOpciones() ) Case Else MsgBox "Aplicacion no soportada" End Select End Sub La función GetFileNameWithoutExtension viene integrada en las macros de OpenOffice.getFiles() 'Solo te muestro la ruta y nombre de archivo seleccionado 'Solo te resta guardar el archivo MsgBox ConvertFromUrl( mArchivo(0) ) Else MsgBox "Proceso cancelado" End If End Sub 5.odt" ) .Name = "FilterName" 'Contruimos el filtro correcto PDF para cada aplicacion mOpciones(0).org.LoadLibrary( "Tools" ) 'Referencia al documento desde donde se llama la macro oDoc = ThisComponent 'Obtenemos el tipo de documento. "Math" 'Establecemos el tipos de filtro mOpciones(0).PropertyValue" sRuta As string BasicLibraries.AppendFilter( "Documento de Texto ODF (. "Writer". "Impress". prueba la siguiente macro desde diferentes documentos. por ejemplo. como en el siguiente ejemplo: Sub ControlarAplicacion3() Dim oBarraEstado As Object Dim co1 As Integer .hasMoreElements() 'Nos desplazamos al siguiente elemento y lo asignamos oDocumento = oEnumeraDocumentos.nextElement() 'Obtenemos acceso a la ventana oVentana = oDocumento.getFrame. también observa que esta vez “no” hemos usado storeAsUrl.Aprendiendo OOo Basic 147 observa como solo le agregamos la extensión PDF. para saber el titulo del documento activo. ahondaremos en las características especificas de cada tipo de documento.getComponents() 'Enumeramos cada uno oEnumeraDocumentos = oDocumentos.getTitle End Sub Para activar el documento que quieras. en donde activamos durante un segundo y medio cada documento de OOo abierto.createEnumeration() 'hasMoreElements devuelve verdadero (True) mientras haya elementos Do While oEnumeraDocumentos. 5. Sub Dim Dim Dim Dim ControlarAplicacion2() oDocumentos As Object oDocumento As Object oVentana As Object oEnumeraDocumentos As Object 'Accedemos a todos los documentos actualmente abiertos oDocumentos = StarDesktop. sino storeToUrl para exportar el archivo. sobre todo por la opción de poder mostrar una barra de progreso.getCurrentController 'El titulo MsgBox oControlador. se usa el método setFocus de la siguiente manera.4. pero creo que tenemos los elementos para empezar a automatizar nuestras tareas diarias.setFocus() 'Esperamos 1.getCurrentController.5 Tareas comunes en documentos Veamos algunas tareas comunes a la mayoría de los documentos de OOo. Te habrás dado cuenta de que las variantes pueden ser inmensas. usamos: Sub ControlarAplicacion1() Dim oDoc As Object Dim oControlador As Object 'El documento desde donde se llama esta macro oDoc = ThisComponent 'El controllador del documento actual oControlador = oDoc. en los siguientes capítulos.getComponentWindow() 'Le enviamos el foco para activarla oVentana. es la de controlar la barra de estado de las aplicaciones.5 segundos para pasar al siguiente documento Wait 1500 Loop End Sub Una posibilidad interesante. 4 Trabajando con documentos 'Referencia a la barra de estado del documento activo oBarraEstado = ThisComponent.setValue( co1 ) 'Esperamos un segundo Wait 1000 Next 'Es importante finalizar la barra de estado para devolverle el control a la aplicación oBarraEstado.CurrentZoom" 'El valor deseado. en este caso 150% mOpc(0).148 5.setText( "Procesando la línea: " & co1 ) 'Esperamos un segundo Wait 1000 Next 'Es importante finalizar la barra de estado para devolverle el control a la aplicación oBarraEstado.Frame 'El despachador de instrucciones a nivel usuario oDH = createUnoService("com.executeDispatch(oDoc.beans.start( "Procesando Líneas ". ". 0.start( "Contando ".star.star.getCurrentController. 10 ) For co1 = 1 To 10 'Establecemos el valor de la barra de progreso oBarraEstado.sun.StatusIndicator 'Establecemos el texto inicial y el limite de la barra de progreso oBarraEstado.Name = "ZoomSlider.setValue( co1 ) 'Y el texto oBarraEstado. Sub Dim Dim dim ControlarAplicacion5() oDoc As Object oDH As Object mOpc(0) As New com.end() End Sub Otra opción es cambiar el zoom de la vista del documento. 10 ) For co1 = 1 To 10 'Establecemos el valor de la barra de progreso oBarraEstado.DispatchHelper") 'El método que deseamos ejecutar mOpc(0). por lo que tienes que validar en su caso si es necesario.PropertyValue 'Acceso al marco del documento oDoc = ThisComponent. "".Value = 150 'Ejecutamos la orden oDH.StatusIndicator 'Establecemos el texto inicial y el limite de la barra de progreso oBarraEstado. funcionará en todas las aplicaciones. también puedes cambiar el texto durante el progreso para dar más información al usuario.sun. como en: Sub ControlarAplicacion4() Dim oBarraEstado As Object Dim co1 As Integer 'Referencia a la barra de estado del documento activo oBarraEstado = ThisComponent. excepto en Base.frame.getCurrentController.uno:ZoomSlider".end() End Sub La macro anterior.CurrentController. mOpc() ) End Sub . Calc. Impress y Draw. pero no te dará ningún error si llamas a la macro desde estas aplicaciones. Base y Math no lo implementan. Writer. . solo funcionará en las aplicaciones que soporten zoom. simplemente ignorará la instrucción.Aprendiendo OOo Basic 149 La opción anterior. getSheets() 'Obtenemos una matriz con los nombres de todas las hojas mNombresHojas() = oHojas. por citar solo un ejemplo. aprenderemos más detalles del manejo de la hoja de calculo con código OOo Basic que se basan en el servicio: com.star. como aprenderemos en este capítulo. pues si no sabes que es un formato condicional. de ahora en adelante. 6. apunta efectivamente a un documento de hoja de calculo como se vio más arriba.1 Trabajando con hojas Para acceder a todas las hojas de un documento de hoja de calculo. te recomiendo siempre verificar que ThisComponent.SpreadsheetDocument. así que te invito a repasar tus apuntes de hoja de calculo. en este. abrir y guardar archivos de Calc y otros tipos de documentos.sheet.getSheets() 'Mostramos cuantas son MsgBox oHojas. doy por sentado que eres un usuario medio de hoja de calculo.getCount() Else MsgBox "No es un documento de hoja de calculo" End If End Sub Asegurate de llamar a la macro anterior desde una hoja de calculo. si estas usando el archivo especial Mis Macros.150 6 Trabajando con hojas de calculo – Calc 6 Trabajando con hojas de calculo – Calc En el capitulo anterior aprendiste a crear.getLocation() ) & _ Chr(13) & "tiene las siguientes hojas" & Chr(13) & Chr(13) sMensaje = sMensaje & Join( mNombresHojas(). usamos: Sub TodasLasHojas1() Dim oDoc As Object Dim oHojas As Object 'Acceso al documento desde donde se llama a esta macro oDoc = ThisComponent 'Nos aseguramos de que sea una hoja de calculo If oDoc.LoadLibrary( "Tools" ) oDoc = ThisComponent oHojas = oDoc.supportsService("com. te será más complicado establecerlo por código.BasicLibraries. Chr(13) ) .star. Podemos acceder a los nombres de todas las hojas Sub Dim Dim Dim Dim TodasLasHojas2() oDoc As Object oHojas As Object mNombresHojas() As String sMensaje As String GlobalScope.SpreadsheetDocument") Then 'Referencia a TODAS las hojas del documento oHojas = oDoc.sun.getElementNames() 'Contruimos el mensaje sMensaje = "El archivo " & FileNameOutOfPath( oDoc. daré por hecho que lo sabes y tu determinaras si haces la validación o no.sun.sheet. org y nos devuelve solo el nombre del archivo de la ruta pasada.getByName( sNombreHoja ) MsgBox oHoja.getName() End Sub Pero si la hoja no existe.getSheets().getByName("Datos Agosto") 'Solo comprobamos que es la hoja correcta MsgBox oHoja.hasByName( sNombreHoja ) then 'Accedemos a una hoja por su nombre oHoja = oHojas.getSheets() 'Obtenemos una matriz con los nombres de todas las hojas mNombresHojas() = oHojas.getElementNames() For co1 = LBound( mNombresHojas() ) To UBound( mNombresHojas() ) MsgBox mNombresHojas(co1) Next End Sub Podemos devolver solo la hoja que nos interesa por su nombre: Sub UnaHoja1() Dim oDoc As Object Dim oHoja As Object oDoc = ThisComponent 'Accedemos a una hoja por su nombre oHoja = oDoc.getName() & " .existe en el documento" Else MsgBox "La hoja -" & sNombreHoja & ". También podemos mostrar los nombres de las hojas una a una: Sub Dim Dim Dim Dim TodasLasHojas3() oDoc As Object oHojas As Object mNombresHojas() As String co1 As Integer oDoc = ThisComponent oHojas = oDoc. el método hasByName es muy útil para saber si una hoja existe.no existe" .getSheets() sNombreHoja = "Datos Agosto" 'Comprobamos que la hoja exista para poder acceder a ella If oHojas. lo cual es indispensable para acceder a ella: Sub Dim Dim Dim Dim UnaHoja2() oDoc As Object oHojas As Object oHoja As Object sNombreHoja As String oDoc = ThisComponent oHojas = oDoc. la macro anterior te dará un error.Aprendiendo OOo Basic 151 'Lo mostramos MsgBox sMensaje End Sub La función FileNameOutOfPath. viene incorporada en OpenOffice. getName() End Sub Del mismo modo que por el nombre. Podemos acceder a una hoja por su índice. si tratas de acceder a una hoja por un índice que no exista. te dará un error.152 End If End Sub 6. también por su índice: Sub Dim Dim Dim Dim TodasLasHojas4() oDoc As Object oHojas As Object oHoja As Object co1 As Integer oDoc = ThisComponent oHojas = oDoc. la numeración empieza de izquierda a derecha. es el total de hojas menos uno.getSheets() iNumeroHoja = 1 'Comprobamos que la hoja exista If iNumeroHoja < oHojas.org empiezan en cero.getSheets() 'Accedemos a la hoja por el indice oHoja = oHojas.getSheets() 'Nota que el limite.getCount() Then 'Accedemos a la hoja por el indice oHoja = oHojas.1 Trabajando con hojas Nota que el método hasByName es un método del conjunto de las hojas (getSheets) y te devolverá verdadero (True) en caso de que la hoja exista y falso (False) en caso de que no. recuerda que los índices en OpenOffice.getByIndex( 1 ) MsgBox oHoja. en las hojas.getName() Else MsgBox "Numero de hoja no existe" End If End Sub Por lo que podemos acceder a cada hoja de un documento. Este método no distingue entre mayúsculas y minúsculas. por que comienza en 0 For co1 = 0 To oHojas.getCount()-1 .getByIndex( iNumeroHoja ) MsgBox oHoja. Sub Dim Dim Dim UnaHoja3() oDoc As Object oHojas As Object oHoja As Object oDoc = ThisComponent oHojas = oDoc. lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas: Sub Dim Dim Dim Dim UnaHoja4() oDoc As Object oHojas As Object oHoja As Object iNumeroHoja As Integer oDoc = ThisComponent oHojas = oDoc. así que siempre comprueba que exista una hoja antes de intentar acceder a ella.getActiveSheet() Msgbox oHoja. una primera aproximación podría ser: Option Explicit Sub SaberSiExisteHoja() MsgBox ExisteHoja( "Hoja3" ) End Sub 'Saber si una hoja existe Function ExisteHoja(ByVal NombreHoja As String) As Boolean Dim oHojas As Object oHojas = ThisComponent.getSheets() ExisteHoja = oHojas.getCurrentController.getByIndex( co1 ) MsgBox oHoja.getName() Next End Sub Toma en cuenta que si mueves una hoja de posición en relación con las demás. no así su nombre.sun. pero el nombre es susceptible de ser cambiado por el usuario.hasByName(NombreHoja) End Function Podemos hacerla incluso más genérica pasándole el documento donde se desea comprobar la existencia de la hoja y comprobando que sea una hoja de calculo: Option Explicit Sub SaberSiExisteHoja2() MsgBox ExisteHoja2( ThisComponent.Aprendiendo OOo Basic 153 oHoja = oHojas.star. su índice cambiara. "Hoja3" ) End Sub 'Saber si una hoja existe Function ExisteHoja2(Documento As Object.getSheets() ExisteHoja2 = oHojas. ya puedes crearte tus útiles funciones para trabajar con hojas.sheet.hasByName(NombreHoja) End If . una función que nos devuelva falso o verdadero según exista o no el nombre de la hoja pasado como argumento. Otra opción es devolver la hoja activa: Public Sub HojaActiva() Dim oHoja As Object 'Hacemos una referencia a la hoja activa oHoja = ThisComponent. por ejemplo. ByVal NombreHoja As String) As Boolean Dim oHojas As Object 'Si no es una hoja de calculo devuelve falso (False) If Documento.getName() End Sub Ahora.supportsService("com.SpreadsheetDocument") Then oHojas = Documento. 1 Trabajando con hojas End Function Ahora devolvemos la hoja: Option Explicit Sub DevuelveReferenciaAHoja1() dim oHoja As Object oHoja = DevuelveHoja1( "Datos" ) If IsNull(oHoja) Then MsgBox "La hoja no existe" Else MsgBox oHoja. esto lo puedes hacer directamente o usando la función creada más arriba.getByName(NombreHoja) End If End Function De nuevo. "Datos" ) If IsNull(oHoja) Then MsgBox "La hoja no existe" Else MsgBox oHoja.hasByName(NombreHoja) Then DevuelveHoja2 = oHojas.getName() End If End Sub 'Saber si existe la hoja y regresarla.getSheets() If oHojas.getName() End If End Sub 'Saber si existe la hoja y regresarla.SpreadsheetDocument") Then oHojas = Documento. ByVal NombreHoja As String) As Object Dim oHojas As Object If Documento.sheet. puedes pasarle el documento del cual te interesa devolver la hoja.supportsService("com. si lo deseas. si llamas a esta funcion.getByName(NombreHoja) End If End If End Function . 'tienes que verificar que se devolvio algo con IsNull Function DevuelveHoja2(Documento As Object. 'tienes que verificar que se devolvio algo con IsNull Function DevuelveHoja1(ByVal NombreHoja As String) As Object Dim oHojas As Object oHojas = ThisComponent. si llamas a esta funcion.154 6.sun.hasByName(NombreHoja) Then DevuelveHoja1 = oHojas.star. observa como comprobamos también que la hoja exista. queda a tu criterio: Sub DevuelveReferenciaAHoja2() dim oHoja As Object oHoja = DevuelveHoja2( ThisComponent.getSheets() If oHojas. con la referencia es suficiente. querer “activar” toda hoja que se quiera manipular.getSheets() 'Verificamos si ya existe la hoja If Not oHojas. si no.hasByName(sNombre) Then 'Si no existe la insertamos al final oHojas.getSheets() If Not oHojas. 0) End If 'Referencia a la nueva hoja o a la existente oHoja = ThisComponent.insertNewByName( sNombre.getSheets.insertNewByName(sNombre. oHojas. la mayor parte de las veces. pues no puedes tener dos hojas con el mismo nombre. tenemos que verificar si la hoja existe o no: Sub Dim Dim Dim InsertarNuevaHoja2() oHojas As Object oHoja As Object sNombre As String 'Solicitamos un nombre para la nueva hoja sNombre = Trim(InputBox("Nombre de la nueva hoja")) 'Verificamos que no este vacio If sNombre <> "" Then 'Referencia a todas las hojas oHojas = ThisComponent. La ultima linea para activar la hoja no es necesaria para que la manipules. entonces.getCount() ) End If .getCurrentController. solo hacemos una referencia a ella. 0) End Sub Ejecuta la macro anterior dos veces y notaras que te dará un error.getByName(sNombre) 'La activamos ThisComponent.1 Insertando hojas Para insertar nuevas hojas.getSheets() oHojas. puedes omitirla. Es sumamente frecuente en programadores noveles. solo en caso de que quieras que el usuario haga o manipule algo en ella. También podemos agregar la hoja al final de todas las demás: Sub Dim Dim Dim InsertarNuevaHoja3() oHojas As Object oHoja As Object sNombre As String sNombre = Trim(InputBox("Nombre de la nueva hoja")) If sNombre <> "" Then oHojas = ThisComponent. usamos el método insertNewByName(Nombre.hasByName(sNombre) Then 'Si no existe la insertamos el inicio oHojas.setActiveSheet(oHoja) End If End Sub Observa que si la hoja ya existe.1. esto no es necesariamente así. de hecho.insertNewByName("Datos Sep". Posicion). la siguiente macro agrega una hoja nueva al inicio de las demás: Sub InsertarNuevaHoja1() Dim oHojas As Object oHojas = ThisComponent.Aprendiendo OOo Basic 155 6. en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos. getByIndex(co1) If oHoja.156 oHoja = ThisComponent.getName() then MsgBox "El indice de la hoja activa es: " & co1 Exit For End If Next End Sub Que podemos convertir a una función: Function BuscarIndiceHoja(ByVal NombreHoja As String) As Integer Dim co1 As Integer dim oHoja As Object For co1 = 0 To ThisComponent.getCurrentController.getCount() .getActiveSheet() For co1 = 0 To ThisComponent.getName()) oHojas.getSheets.setActiveSheet(oHoja) End If End Sub 6.getByIndex(co1) If oHoja.getSheets. no te dará error y la insertara al final de las demás hojas.getSheets. lo cual hay que evaluar en caso necesario.getCurrentController.insertNewByName( sNombre. pos ) End If .getSheets.1 oHoja = ThisComponent.getSheets() oHojaActiva = ThisComponent.getSheets.getCurrentController.hasByName(sNombre) Then 'Buscamos el indice de la hoja activa pos = BuscarIndiceHoja(oHojaActiva.1 oHoja = ThisComponent.getName() = NombreHoja then BuscarIndiceHoja = co1 Exit Function End If Next BuscarIndiceHoja = -1 End Function Observa que si no la encuentra el valor devuelto es -1. primero tienes que encontrar el índice de la hoja activa: Sub Dim Dim dim IndiceHojaActiva() co1 As Integer oHojaActiva As Object oHoja As Object oHojaActiva = ThisComponent. Si quieres insertar la hoja antes o después de la hoja activa.getName() = oHojaActiva. Para insertar antes de la hoja activa usamos: Sub Dim Dim Dim Dim Dim InsertarNuevaHoja4() oHojas As Object oHoja As Object oHojaActiva As Object sNombre As String pos As Integer sNombre = Trim(InputBox("Nombre de la nueva hoja")) If sNombre <> "" Then oHojas = ThisComponent.1 Trabajando con hojas Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por getCount() pero incluso si es mayor a este valor.getByName(sNombre) ThisComponent.getCount() .getActiveSheet() If Not oHojas. getCurrentController. esa.getByName(NombreHoja) End If End Function Nota como estamos obteniendo el índice de la hoja activa.getSheets. 6.getSheets() oHojaActiva = ThisComponent.Aprendiendo OOo Basic 157 oHoja = ThisComponent.setActiveSheet(oHoja) End If End Sub Para insertar después de la hoja activa. ByVal Posicion As Integer) As Object Dim oHojas As Object Dim oHojaActiva As Object Dim iPos As Integer If NombreHoja <> "" Then oHojas = ThisComponent.getRangeAddress().org. con lo cual nos evitamos tener que hacer un ciclo por las hojas del documento.Sheet + 1 Case Else : iPos = 0 End Select If Not oHojas. es que muchas de las acciones que hacemos por código.hasByName(NombreHoja) Then oHojas. no esta de más recomendarte usar con cuidado el borrado de hojas.getSheets. Puedes mejorar esta función para insertar la hoja en cualquier otro documento. así como ingeniártelas para pedirle al usuario el número de hojas nuevas que quiera insertar e insertarlas por supuesto.getCount() Case 3 : iPos = oHojaActiva. el borrado de hojas es una de ellas. es tu tarea. son susceptibles de deshacerse de forma normal con la barra de herramientas o con CTRL+Z.getByName(sNombre) ThisComponent.getCurrentController. usamos el método removeByName(Nombre).Sheet Case 4 : iPOs = oHojaActiva. solo sumas uno al valor devuelto por la función BuscarIndiceHoja: pos = BuscarIndiceHoja(oHojaActiva.insertNewByName(NombreHoja.getRangeAddress(). iPos) End If getNuevaHoja = ThisComponent. donde Nombre es el nombre de la hoja que queremos borrar. compruébalo: Sub BorrarHoja1() Dim oHojas As Object .1. aunque algo que me gusta mucho de OpenOffice.getName()) + 1 Podemos aventurar una primera versión de una función genérica para insertar una nueva hoja de calculo donde quieras: 'Como funcion regresamos la nueva hoja insertada o la existente en su caso 'Posicion: 1 = Inicio ' 2 = Final ' 3 = Antes de la hoja activa ' 4 = Despues de la hoja activa Function getNuevaHoja(ByVal NombreHoja As String.2 Borrando hojas Para borrar hojas.getActiveSheet() Select Case Posicion Case 1 : iPos = 0 Case 2 : iPos = oHojas. hasByName( sNombre ) Then oHojas. valida que siempre quede más de una: Sub BorrarHoja3() Dim oHojas As Object Dim sNombre As String sNombre = Trim( InputBox( "Nombre de la hoja a borrar" )) If sNombre <> "" Then oHojas = ThisComponent.getSheets() oHojas. claro.getCount()>1 Then oHojas.3 Moviendo hojas . para evitar el error que te da al tratar de borrar la ultima hoja.1.getSheets() If oHojas.getSheets() If oHojas.1 Trabajando con hojas oHojas = ThisComponent.158 6.getActiveSheet() oHojas = ThisComponent.getName() ) End Sub Ejecuta la macro anterior hasta que no quede ni una.getSheets() 'Borramos la hoja por su nombre oHojas.removeByName( oHojaActiva.removeByName( sNombre ) Else MsgBox "La hoja no existe o solo queda una" End If End If End Sub 6.removeByName( "Hoja11" ) End Sub Por supuesto no puedes borrar una hoja que no exista.hasByName( sNombre ) And oHojas. no te dejara por que un documento de hoja de calculo por lo menos debe de tener una hoja.removeByName( sNombre ) Else MsgBox "La hoja no existe" End If End If End Sub Puedes borrar la hoja activa: Sub BorrarHojaActiva() Dim oHojas As Object Dim oHojaActiva As Object oHojaActiva = ThisComponent. así que verifícalo: Sub BorrarHoja2() Dim oHojas As Object Dim sNombre As String sNombre = Trim( InputBox( "Nombre de la hoja a borrar" )) If sNombre <> "" Then oHojas = ThisComponent.getCurrentController. org y usa el método de burbuja para ordenar la lista pasada."v".) 'Mostramos los datos desordenados MsgBox Join( mDatos().org/wiki/Bubblesort También puedes crearte tu versión de este algoritmo."e".Aprendiendo OOo Basic 159 Para mover hojas usamos el método moveByName(NombreHoja. usa siempre getCount() para asegurarte. Chr(13) ) End Sub La función BubbleSortList. como ya sabemos obtener los nombres e indices de cada hoja."e".getSheets() 'Movemos la hoja especificada al inicio oHojas.getSheets() 'Movemos la hoja especificada al final oHojas. viene incorporada a las macros de OpenOffice."o". hagamos una macro que nos ordene alfabéticamente nuestras hojas.org/issues/show_bug. para ello nos apoyaremos en una función que ordena la matriz que le pasemos: Sub PruebaOrdenar1() Dim mDatos() GlobalScope."f".1."h". aquí esta la mía."d"."o".wikipedia. PosicionNueva). 0 ) End Sub Ahora.openoffice. puedes ordenar de forma ascendente o descendente: Sub PruebaOrdenar2() Dim mDatos() mDatos() = Array("5".1).moveByName( "Hoja2". si quieres saber más de este algoritmo visita: http://es. no es el algoritmo más eficiente.BasicLibraries."y". donde NombreHoja tiene que ser el nombre de una hoja existente: Sub MoverHoja1() Dim oHojas As Object oHojas = ThisComponent. ten cuidado con mover tus hojas “no más allá de la ultima hoja”. Chr(13) ) .moveByName( "Hoja2"."y". aun así.) 'Mostramos los datos desordenados MsgBox Join( mDatos(). este error (bug) se reporto en su momento (http://www."d". y ha sido arreglado a partir de esta versión (3. y ahora hemos aprendido a mover hojas. oHojas.cgi?id=92477)."h". pero en listas pequeñas y dada su sencillez de implementación es perfectamente válida para nuestros fines.getCount() ) End Sub Si usas una versión anterior a la 3."l".LoadLibrary( "Tools" ) mDatos() = Array("5". Vamos a hacer algo muy divertido."u". la movemos al final: Sub MoverHoja2() Dim oHojas As Object oHojas = ThisComponent."v". pues te puede provocar un error en toda la aplicación. Chr(13) ) 'Ordenamos los datos mDatos() = BubbleSortList( mDatos() ) 'Mostramos los datos ordenados MsgBox Join( mDatos()."f"."u"."l". 1) End If End If Next co2 Next co1 End Sub 'Macro para intercambiar un par de valores Sub Intercambio(ByRef Dato1 As Variant. co2 As Long NumDatos = UBound(Datos) For co1 = 1 To NumDatos For co2 = NumDatos To co1 Step -1 If Orden = 1 Then If Datos(co2) < Datos(co2 . nuestra macro para ordenar hojas en acción. 1 ) 'Mostramos los datos ordenados MsgBox Join( mDatos().1) End If Else If Not (Datos(co2) < Datos(co2 . crearte tu propia versión: Option Explicit 'Ordenamos las hojas por orden alfabetico Sub OrdenarHojas() Dim oHojas As Object Dim mNombres() As Variant Dim aTmp As Variant Dim co1 As Integer Dim oHoja As Object 'Referencia a todas las hojas del documento oHojas = ThisComponent.1 Trabajando con hojas 'Ordenamos los datos Call OrdenarBurbuja( mDatos(). puedes usar la función o macro que prefieras para ordenar la matriz de nombres obtenida. ByRef Dato2 As Variant) Dim sTmp As Variant sTmp = Dato1 Dato1 = Dato2 Dato2 = sTmp End Sub Ahora si. Datos(co2 . Datos(co2 . Chr(13) ) End Sub ' Datos = matriz de datos a ordenar ' Orden = 1 ascendete ' 2 descendente Sub OrdenarBurbuja(ByRef Datos() As Variant.getElementNames() 'Ordenamos la matriz Call OrdenarBurbuja( mNombres(). incluso.160 6.1)) Then Call Intercambio Datos(co2).1) Then Call Intercambio Datos(co2).getSheets() 'Matriz con los nombres de todas las hojas mNombres() = oHojas. ByVal Orden As Integer) Dim NumDatos As Long Dim co1 As Long. 1 ) 'Recorremos la matriz For co1 = LBound( mNombres() ) To UBound( mNombres() ) . copyByName( "Hoja2". lo mejor.getSheets() 'Solo copia la hoja. sNombreNuevo.hasByName(sNombreNuevo)) Then oHojas.moveByName( mNombres(co1).getSheets() 'Nombre de la hoja activa .Aprendiendo OOo Basic 161 'El índice en la matriz. "Nueva Hoja2". es evaluarlo antes: Sub Dim Dim Dim CopiarHoja2() oHojas As Object sNombre As String sNombreNuevo As String sNombre = "Datos" sNombreNuevo = "Datos nuevos" oHojas = ThisComponent. tomando como base el nombre actual de la hoja. 0 ) End Sub Por supuesto el nombre de la hoja a copiar “debe” de existir y el nombre nuevo de la hoja “no debe” existir.hasByName(sNombre) And (Not oHojas. Posicion ) de la siguiente manera: Sub CopiarHoja1() Dim oHojas As Object oHojas = ThisComponent. oHojas. sera el mismo de la posición oHojas.4 Copiando hojas Para copiar hojas usamos el método copyByName ( NombreHoja.getSheets() 'Copiamos la "hoja2" como "Nueva Hoja2" al inicio oHojas.copyByName( sNombre. co1 ) Next co1 End Sub 6.1. si la hoja a copiar existe y el nombre nuevo no existe If oHojas. por ejemplo: Sub Dim Dim Dim Dim Dim CopiarHojaActiva() oHojas As Object oHoja As Object sNombre As String sNombre2 As String co1 As Long 'Referencia a todas las hoja oHojas = ThisComponent. NombreNuevo.getCount() ) Else MsgBox "No se copio la hoja" End If End Sub Podemos intentar copiar una hoja y asegurarnos de que el nombre no exista. 162 sNombre = ThisComponent.getCurrentController.getCurrentController.. oHojas.getByIndex( 0 ).getByName("Hola").setActiveSheet(oHoja) End Sub Solo te resta preguntarle al usuario cuantas nuevas hojas quiere e insertar ese número de hojas nuevas.1.getName() 6.1 Trabajando con hojas 'Contador para construir el nuevo nombre co1 = 1 'El nuevo nombre es igual mas un guion bajo y un numero sNombre2 = sNombre & "_" & Format(co1) 'Hace el ciclo mientras el nuevo nombre exista Do While oHojas.getByName(sNombre2) 'Y la activamos ThisComponent. por “Prueba” oHojas.getSheets() oHojas.setName( "Gastos" ) End Sub Es recomendable validar que la hoja a renombrar exista y que el nuevo nombre no: ..getCount()) 'Referencia a la nueva hoja oHoja = ThisComponent.hasByName( sNombre2 ) 'Si ya existe incrementamos el contador co1 = co1 + 1 'y construimos el nuevo nombre sNombre2 = sNombre & "_" & Format(co1) Loop 'Sale del ciclo cuando el nuevo nombre no exista.copyByName(sNombre. de la siguiente manera: Sub CambiarNombreHoja1() Dim oHojas As Object oHojas = ThisComponent.5 Renombrando hojas Para renombrar hojas usamos el método setName. pero. sNombre2.getSheets() 'Cambiamos el nombre de la hoja “Hola”. esa es tu tarea: 6.getActiveSheet. entonces 'podemos copiar la hoja al final (o donde quieras) oHojas.getSheets.setName( "Prueba" ) End Sub También puedes usar el índice para referirte a la hoja: Sub CambiarNombreHoja2() Dim oHojas As Object oHojas = ThisComponent. Aprendiendo OOo Basic Sub Dim Dim Dim CambiarNombreHoja3() oHojas As Object sNombreActual As String sNombreNuevo As String sNombreActual = "Resumen" sNombreNuevo = "Terminado" oHojas = ThisComponent.getSheets() 163 'Validamos que la hoja exista y el nuevo nombre no If oHojas.hasByName(sNombreActual) And (Not oHojas.hasByName(sNombreNuevo)) Then oHojas.getByName( sNombreActual ).setName( sNombreNuevo ) Else MsgBox "No se renombro la hoja" End If End Sub Solo para divertirnos, cambiamos los nombres de las hojas por números: Sub CambiarNombreHoja4() Dim oHojas As Object Dim co1 As Integer oHojas = ThisComponent.getSheets() For co1 = 1 To oHojas.getCount() oHojas.getByIndex( co1-1 ).setName( co1 ) Next End Sub Ahora por letras, el código siguiente podría fallarte si tienes más de 25 hojas en tu documento, tu tarea es decirme ¿porqué? y corregirlo, en algunos casos, “el cambio de nombre no tendrá efecto”, también, te toca averiguar ¿porqué? Sub CambiarNombreHoja5() Dim oHojas As Object Dim co1 As Integer oHojas = ThisComponent.getSheets() For co1 = 1 To oHojas.getCount() oHojas.getByIndex( co1-1 ).setName( Chr( co1+64 ) ) Next End Sub O los meses del año: Sub Dim Dim Dim Dim CambiarNombreHoja6() oHojas As Object co1 As Integer Limite As Byte sMes As String oHojas = ThisComponent.getSheets() 'Para que solo cambie las primeras 12 If oHojas.getCount() > 12 Then Limite = 12 Else 'O las que haya si son menos de 12 Limite = oHojas.getCount() 164 End If For co1 = 1 To Limite 'Obtenemos el nombre del mes sMes = Format( DateSerial(Year(Date),co1,1) ,"mmmm") oHojas.getByIndex( co1-1 ).setName( sMes ) Next End Sub 6.1 Trabajando con hojas Te queda de tarea lograr completar los meses para que sean los doce del año, es decir, tienes que insertar los meses que te hagan falta si el documento tiene menos de las hojas necesarias, si tiene más de doce borra las sobrantes. 6.1.6 Ocultando y mostrando hojas Mostrar y ocultar hojas es muy sencillo, solo hay que establecer su propiedad isVisible en verdadero (True) o falso (False) según se requiera de la siguiente manera: Sub OcultarHoja1() Dim oHojaActiva As Object oHojaActiva = ThisComponent.getCurrentController.getActiveSheet() oHojaActiva.isVisible = False End Sub La macro anterior te ocultara la hoja activa, si la ejecutas varias veces te ira ocultando tus hojas hasta que solo quede una, si solo hay una no te dará error, pero la dejará visible por que, como sabes, tiene que haber al menos una hoja visible en un documento de Calc. También puedes ocultar una hoja por medio de su índice, como en: Sub OcultarHoja2() Dim oHoja As Object oHoja = ThisComponent.getSheets().getByIndex(1) oHoja.isVisible = False End Sub Toma en cuenta que: el índice de la hoja “debe” existir, sino te dará un error, así mismo, si ocultas una hoja, esta no cambia de índice por lo que puedes usar el mismo para acceder a ella, aunque este oculta, la siguiente macro alterna entre mostrar y ocultar la primer hoja del documento: Sub OcultarHoja3() Dim oHoja As Object oHoja = ThisComponent.getSheets().getByIndex(0) oHoja.isVisible = Not oHoja.isVisible Aprendiendo OOo Basic 165 End Sub Como ya habrás intuido, para mostrar una hoja oculta simplemente hay que establecer esta propiedad en verdadero (True) Sub OcultarHoja4() Dim oHoja As Object oHoja = ThisComponent.getSheets().getByIndex(1) oHoja.isVisible = True End Sub El siguiente código te oculta todas las hojas, excepto la hoja activa: Sub Dim Dim Dim OcultarHoja5() oHojaActiva As Object oHojas As Object co1 As Long oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() oHojas = ThisComponent.getSheets() For co1 = 0 To oHojas.getCount() - 1 If oHojas.getByIndex(co1).getName <> oHojaActiva.getName() Then oHojas.getByIndex(co1).isVisible = False End If Next End Sub Tu tarea es hacer la función inversa, muestra todas las hojas ocultas. 6.1.7 Protección y desprotección de hojas Para terminar este capítulo, veamos como proteger una hoja, es decir, establecer una contraseña para evitar modificaciones a la misma, además, recuerda que para que la protección de celdas individuales sea efectiva, la hoja debe estar protegida. Para proteger una hoja, usamos el método Protect, pasándole como argumento, la contraseña que queremos establecer, por supuesto, puedes pasarle una contraseña vacía, con lo que la hoja no estará muy protegida que digamos, pero creeme, muchos usuarios no saben desproteger una hoja, aun sin contraseña. Sub ProtegerHoja1() Dim oHojaActiva As Object oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() 'Para que veas que si me ocurren otras contraseñas oHojaActiva.Protect( "letmein" ) End Sub Y para desproteger, usamos el método unProtect, si la hoja tiene contraseña, hay que pasársela como argumento, si no es correcta, el método no te devolverá ningún error como en la interfaz del usuario que te avisa que la contraseña es incorrecta, para saber si tuvo éxito o no la 166 6.1 Trabajando con hojas desprotección, hay que verificar la propiedad isProtected, si es verdadera (True) la hoja sigue protegida, si es falsa (False), la hoja esta desprotegida. Sub ProtegerHoja2() Dim oHojaActiva As Object oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() If oHojaActiva.isProtected Then MsgBox "La hoja esta protegida" 'Intentamos desprotegerla oHojaActiva.unProtect( "letmein" ) 'Verificamos si tuvo exito la desprotección If oHojaActiva.isProtected Then MsgBox "La contraseña no es correcta" Else MsgBox "Hoja desprotegida correctamente" End If Else MsgBox "La hoja NO esta protegida" End If End Sub Te queda de tarea modificar la macro para solicitar al usuario la contraseña, verificar si es correcta o no y darle solo tres intentos para ingresarla. Fácil, ¿verdad?. Como comentarios finales, si intentas proteger una hoja que ya tiene contraseña, no obtendrás ningún error, pero la hoja permanecerá con la contraseña original, para cambiarla, primero tienes que desprotegerla y después cambiarla. Cuando proteges una hoja e intentas hacer modificaciones a esta, por ejemplo, escribir en una celda, tampoco retornará ningún error, pero no será efectiva la modificación, procura usar la propiedad para saber si una hoja esta o no protegida (isProtected), para actuar en consecuencia. 6.2 Referencia a rangos Seguro que sabes, si eres usuario habitual de una hoja de calculo, que el trabajo con rangos es esencial en estos documentos, por lo mismo, el trabajo con rangos desde código OOo Basic es igualmente importante, ya vimos como aseguramos que estamos trabajando en una hoja de calculo, así que dejo a tu criterio esta validación. En la siguientes secciones nos centraremos en aprender como hacer referencia a distintos tipos de rangos para después poder manipularlos, darles formato o hacer con ellos lo que queramos. 6.2.1 Referencia a celdas individuales Podemos acceder a las celdas de una hoja de calculo de varias maneras, principalmente por su nombre o por su posición, pero muy importante, primero tienes que acceder a la hoja donde están las celdas que te interesa manipular, como acceder a hojas es un tema que Aprendiendo OOo Basic 167 ya hemos tratado, pero en cada ejemplo podrás notar que repasamos estos conocimientos, la forma más simple de hacer referencia a una celda es por su nombre: Sub AccesoCeldas1() Dim oHojaActiva As Object Dim oCelda As Object 'Referencia a la hoja activa oHojaActiva = ThisComponent.getCurrentController.getActiveSheet() 'Referencia a la celda E5 oCelda = oHojaActiva.getCellRangeByName( "E5" ) 'Mostramos el contenido de la celda MsgBox oCelda.getString() 'Mostramos la hoja, columna y fila correspondiente a esta celda MsgBox "Hoja: " & oCelda.getCellAddress.Sheet & Chr(13) & _ "Columna: " & oCelda.getCellAddress.Column & Chr(13) & _ "Fila: " & oCelda.getCellAddress.Row End Sub Observa como comprobamos en la ultima linea, que efectivamente hemos hecho referencia a la celda que nos interesa, es decir a la celda E5, que en columna y fila es la 4, por que recordamos que los número de columna y fila empiezan en 0, observa la estructura getCellAddress, esta, es muy importante pues a muchos métodos para manipular celdas, se les tienen que pasar estructuras como esta, solo tiene tres propiedades, la hoja (valor tipo integer, este, también empieza en 0) donde esta la celda referenciada, la columna (long) y la fila (long) de esta celda. Ahora accedemos a una celda por su posición, recuerda que los índices de inicio desde código empiezan en 0, por lo que para hacer referencia a la celda E5, tenemos que poner la columna 4 y fila 4, el primer valor es para la columna y el segundo para la fila, no esta de más comentarte que tengas cuidado de no establecer una posición fuera de la hoja, pues te dará un error, por ejemplo, establecer el valor de la columna en 256 o superior si trabajos con la versión 2.x de OpenOffice.org, en la versión 3.x tenemos 1024 columnas para trabajar, por supuesto, si el valor de la fila y columna se la solicitas al usuario, “deberías” de validar que los valores proporcionados son correctos. Sub Dim Dim Dim Dim AccesoCeldas2() oHojaActiva As Object oCelda As Object Col As Long Fil As Long oHojaActiva = ThisComponent.getCurrentController.getActiveSheet() 'Nos aseguramos que sea un valor con Val y que sea positivo con Abs Col = Abs(Val(InputBox("Dame la columna"))) Fil = Abs(Val(InputBox("Dame la fila"))) 'Nos aseguramos que esten dentro de los rangos correctos If Col < oHojaActiva.Columns.Count And Fil < oHojaActiva.Rows.Count Then 'Accedemos a la celda oCelda = oHojaActiva.getCellByPosition( Col,Fil ) MsgBox oCelda.getString() Else MsgBox "Valores de celda incorrectos" End If End Sub 168 6.2 Referencia a rangos Es frecuente que el acceso por nombre a una celda se use para establecer valores preestablecidos, como títulos de campos por ejemplo, y el acceso por posición es muy útil para realizar ciclos, como el ejemplo siguiente que inserta el año como titulo en la celda A1 y los meses del año de la celda A2 a la A13. Sub Dim Dim Dim AccesoCeldas3() oHojaActiva As Object oCelda As Object co1 As Integer oHojaActiva = ThisComponent.getCurrentController.getActiveSheet() 'Referencia a celda por nombre oCelda = oHojaActiva.getCellRangeByName( "A1" ) oCelda.setString( Year(Date) ) For co1 = 1 To 12 'Referencia a celda por posicion oCelda = oHojaActiva.getCellByPosition( 0,co1 ) oCelda.setString( Format( DateSerial(Year(Date),co1,1) ,"mmmm") ) Next End Sub Observa que hemos estado usando el método getString() para obtener el contenido de una celda y setString(Valor As String) para establecerlo, más adelante veremos todas las posibilidades que tenemos para introducir u obtener datos de las celdas de nuestra hoja de calculo, así como sus diferencias. 6.2.2 Referencia a un rango de celdas Podemos acceder a un rango de celdas por su nombre, usando el mismo método usado para acceder a una celda: Sub AccesoRango1() Dim oHojaActiva As Object Dim oRango As Object oHojaActiva = ThisComponent.getCurrentController.getActiveSheet() 'Referencia al rango A1:E5 oRango = oHojaActiva.getCellRangeByName( "A1:E5" ) 'Y lo seleccionamos ThisComponent.getCurrentController.select(oRango) End Sub Para acceder a un rango de celdas por su posición, hay que usar un método diferente: getCellRangeByPosition, que requiere de cuatro argumentos. Sub AccesoRango2() Dim oHojaActiva As Object Dim oRango As Object oHojaActiva = ThisComponent.getCurrentController.getActiveSheet() Aprendiendo OOo Basic 169 'Seleccionamos el rango B1:B10 oRango = oHojaActiva.getCellRangeByPosition( 1,0,1,9 ) 'Y lo seleccionamos ThisComponent.getCurrentController.select(oRango) End Sub Observa que ahora usamos el método getCellRangeByPosition, los argumentos pasados a este método son cuatro, la columna y fila donde empieza nuestro rango y la columna y fila donde termina, recuerda que los números de fila y columna empiezan en 0, algunos piensan que los dos últimos argumentos son el ancho y alto del rango a usar, no es así, estos argumentos también son números de índices de columna y fila respectivamente y tienes que tener la precaución de establecer los segundos iguales o mas grandes que los primeros, sino, te dará un error en tiempo de ejecución y por supuesto sin sobrepasar el máximo de filas y columnas de la hoja de calculo. Observa también, como en la ultima línea seleccionamos el rango referenciado. Otra posibilidad, es usar nombres definidos de rangos, es decir, aquellos que establecemos desde el “Cuadro de nombre” en la hoja de calculo, ya sabes, ese cuadro de lista desplegable (combobox) que esta al lado de la barra de formulas, que también puedes establecer desde el menú Insertar | Nombres | Definir... cuya teclas de acceso rápido son Ctrl+F3. En el siguiente ejemplo, seleccionamos el rango de celdas llamado Datos. Toma nota de que si el rango no existe en al hoja desde donde se intenta referenciar, te dará un error. Sub AccesoRango3() Dim oHojaActiva As Object Dim oRango As Object oHojaActiva = ThisComponent.getCurrentController.getActiveSheet() 'Seleccionamos el rango por su nombre definido oRango = oHojaActiva.getCellRangeByName( "Datos" ) 'Y lo seleccionamos ThisComponent.getCurrentController.select(oRango) End Sub Por supuesto, si el nombre del rango no existe, te dará un error en tiempo de ejecución, este método no es sensible a mayúsculas o minúsculas. Para hacer referencia a la hoja correcta donde exista el rango con nombre, observa como obtenemos la hoja donde se encuentra. Si el usuario es el que proporciona el nombre del rango, como siempre, es mejor validar que el rango exista. Sub Dim Dim Dim Dim AccesoRango4() oHoja As Object oRango As Object oRangosPorNombre As Object sNombreRango As String 'Referencia a todos los rangos con nombre en la hoja de calculo oRangosPorNombre = ThisComponent.NamedRanges() sNombreRango = Trim( InputBox( "Escribe el nombre del rango a seleccionar" ) ) 'Comprobamos que el rango exista If oRangosPorNombre.hasByName( sNombreRango ) Then oHoja = ThisComponent.getSheets.getByIndex(oRangosPorNombre.getByName(sNombreRango).getReferredCells.getRangeAd dress.Sheet) 'Seleccionamos el rango por su nombre definido oRango = oHoja.getCellRangeByName( sNombreRango ) 'Y lo seleccionamos ThisComponent.getCurrentController.select(oRango) 170 Else 6.2 Referencia a rangos MsgBox "El rango " & sNombreRango & " no existe en el documento" End If End Sub No confundas estos nombres de rangos, con los que puedes establecer en el menú Datos | Definir rango..., ya que estos últimos se refieren a rangos considerados como una tabla de datos, de hecho, puedes tener un mismo nombre para un rango de celdas y para un rango de datos, pero son dos cosas diferentes, los segundos, los veremos más adelante. De los rangos de celdas, también es posible obtener información, para ello se hace uso de la estructura CellRangeAddress a travez del método getRangeAddress que te devuelve información de: la hoja donde esta el rango, la columna y fila donde comienza y la columna y fila donde acaba. Sub Dim Dim Dim Dim AccesoRango5() oHojaActiva As Object oRango As Object oDirCelda As Object sTmp As String oHojaActiva = ThisComponent.getCurrentController.getActiveSheet() oRango = oHojaActiva.getCellRangeByName( "Nombres" ) 'Obtenemos la información de la dirección oDirCelda = oRango.getRangeAddress() 'Construimos el texto informativo sTmp = "El rango esta en la hoja: " & oDirCelda.Sheet & Chr(13) & _ "Columna Inicio: " & oDirCelda.StartColumn & Chr(13) & _ "Fila Inicio: " & oDirCelda.StartRow & Chr(13) & _ "Columna Fin: " & oDirCelda.EndColumn & Chr(13) & _ "Fila Fin: " & oDirCelda.EndRow MsgBox sTmp End Sub Esta estructura también es usada por varios métodos para manipular rangos que veremos más adelante, por lo que es importante que la tengas presente. 6.2.3 Referencia a varios rangos de celdas Cuando en la interfaz del usuario, hacemos la selección de un rango y mantenemos presionada la tecla Ctrl y hacemos un segunda selección de un rango y así sucesivamente, estamos hablando de un conjunto de rangos que tiene sus características particulares para su control y manejo. Para seleccionar varios rangos desde código, primero debemos crear el “contenedor” de estos rangos, veamos como: Sub Dim Dim Dim Dim Acceso_A_Rangos1() oHojaActiva As Object oRangos As Object oRango As Object oDirRango As Object oHojaActiva = ThisComponent.getCurrentController.getActiveSheet() 'Creamos el contender para los rangos Aprendiendo OOo Basic 171 oRangos = ThisComponent.createInstance("com.sun.star.sheet.SheetCellRanges") 'Creamos la estructura CellRangeAddress necesaria oDirRango = oHojaActiva.getCellRangeByName( "A1:B2" ).getRangeAddress() 'Y lo agregamos al contenedor de rangos oRangos.addRangeAddress( oDirRango ,False ) 'Aquí solo hacemos referencia al rango oRango = oHojaActiva.getCellRangeByName( "E1:G2" ) 'Y lo agregamos al contenedor de rangos, nota como tenemos que usar 'el método getRangeAddress para pasarle el argumento correcto oRangos.addRangeAddress( oRango.getRangeAddress() ,False ) 'Aquí agregamos un rango directamente al contenedor 'toma en cuenta que se van acumulando oRangos.addRangeAddress( oHojaActiva.getCellRangeByName( "D4:E5" ).getRangeAddress() ,False ) 'Comprobamos que están correctos seleccionándolos ThisComponent.getCurrentController.select(oRangos) End Sub No te confundas, los tres líneas donde se agrega el rango con el método addRangeAddress() son iguales, lo que cambia es la forma en que hacemos referencia a la dirección del rango, si vas empezando a programar, te recomiendo ir desglosando cada línea, con el tiempo y la experiencia, podrás concentrar código de forma más natural, por ahora, usa todas las líneas que consideres pertinentes para que tu código lo entiendas con solo verlo. Por supuesto, también de estos rangos podemos obtener información, por ejemplo, los nombres de los rangos que contiene: Sub Acceso_A_Rangos2() Dim oHojaActiva As Object Dim oRangos As Object oHojaActiva = ThisComponent.getCurrentController.getActiveSheet() 'Creamos el contender para los rangos oRangos = ThisComponent.createInstance("com.sun.star.sheet.SheetCellRanges") 'Agregamos los rangos que queramos oRangos.addRangeAddress( oHojaActiva.getCellRangeByName( oRangos.addRangeAddress( oHojaActiva.getCellRangeByName( oRangos.addRangeAddress( oHojaActiva.getCellRangeByName( oRangos.addRangeAddress( oHojaActiva.getCellRangeByName( oRangos.addRangeAddress( oHojaActiva.getCellRangeByName( 'Mostramos las direcciones de los rangos MsgBox oRangos.getRangeAddressesAsString() End Sub "A1:A2" ).getRangeAddress() ,False ) "B4:B5" ).getRangeAddress() ,False ) "C7:C8" ).getRangeAddress() ,False ) "D10:D11" ).getRangeAddress() ,False ) "E13:E14" ).getRangeAddress() ,False ) Nota como los rangos es una cadena larga de las direcciones de los rangos separados por un “ ; ”, si lo quieres mejor presentable, reemplaza los puntos y comas por un salto de línea con el siguiente código. 'Lo unico que hacemos es reemplazar los ; por saltos de linea sTmp = Join( Split(oRangos.getRangeAddressesAsString(),";"),Chr(13)) 'Mostramos el resultado MsgBox sTmp Los rangos también se pueden remover de la colección... Sub Acceso_A_Rangos4() Dim oHojaActiva As Object getCurrentController. cuando consultamos con hasByName si el rango existe.SheetCellRanges") 'Agregamos los rangos que queramos oRangos.getRangeAddressesAsString() 'Removemos el rango deseado oRangos.4 Referencia a filas y columnas Las filas y columnas de una hoja de calculo siguen siendo rangos de celdas.addRangeAddress( oHojaActiva.False ) "B4:B5" ).getRangeAddress() .172 Dim oRangos As Object 6.getCellRangeByName( oRangos.removeRangeAddress(oHojaActiva.getCurrentController.getRangeAddressesAsString() End Sub "A1:A2" ).sun. 6. de tarea te queda garantizar que se corresponde uno con el otro. efectivamente corresponda en nombre con el rango pasado. que el objeto que apunta a la hoja.getCellRangeByName( oRangos.2.getCellRangeByName( "A1:A65536" ) 'Y lo seleccionamos ThisComponent. te dará un error en tiempo de ejecución. como en.select(oRango) .getCellRangeByName( "D10:D11" ). en función de hacer referencia a ellas.getRangeAddress() .getRangeAddress() ) 'Volvemos a verificar que se haya removido MsgBox oRangos.False ) "C7:C8" ).D10:D11") Then 'Removemos el rango deseado oRangos. lo mejor es validar antes que existe.getActiveSheet() 'Referencia a la columna A oRango = oHojaActiva. lo único que las caracteriza. observa que le pasamos el nombre del rango como texto ("Hoja1. Sub AccesoColumna1() Dim oHojaActiva As Object Dim oRango As Object oHojaActiva = ThisComponent.getCellRangeByName( 'Comprobamos que estén los rangos MsgBox oRangos. es decir. si el rango que quieres remover no existe en la colección.hasByName("Hoja1.getActiveSheet() 'Creamos el contender para los rangos oRangos = ThisComponent.star.addRangeAddress( oHojaActiva. 'Validamos que el rango a remover exista en la colección If oRangos..createInstance("com. le pasamos un objeto (oHojaActiva) que no necesariamente tiene que corresponder con el nombre de hoja (Hoja1).getRangeAddress()) End If El código anterior tiene un problema que tal vez te pueda causar un pequeño inconveniente.False ) "D10:D11" ). es que abarcan la totalidad de celdas que contienen.getRangeAddress() .addRangeAddress( oHojaActiva.2 Referencia a rangos oHojaActiva = ThisComponent.getCellRangeByName( "D10:D11" ).sheet.D10:D11") y que incluye el nombre de la hoja donde esta el rango.removeRangeAddress( oHojaActiva.False ) Cuidado.getCurrentController.getRangeAddress() . pero observa como al método removeRangeAddress.getCellRangeByName( oRangos..addRangeAddress( oHojaActiva. getActiveSheet() 'Referencia a la columna A que se nombro previamente oRango = oHojaActiva.getActiveSheet() 'Referencia a la fila 15 que se nombro previamente oRango = oHojaActiva.select(oRango) End Sub Podemos hacer lo mismo con las filas: Sub AccesoFilas1() Dim oHojaActiva As Object Dim oRango As Object oHojaActiva = ThisComponent. si la columna completa tienen un nombre.Aprendiendo OOo Basic End Sub 173 Nota como tomamos de la fila 1 y hasta la 65536 que es el número total de filas con que por ahora cuentan las hojas de calculo de Calc.getActiveSheet() 'Referencia a la fila 10 oRango = oHojaActiva.getCellRangeByName( "A10:IV10" ) 'Y lo seleccionamos ThisComponent.getCellRangeByName( "Claves" ) 'Y lo seleccionamos ThisComponent. también es posible acceder por medio de este nombre: Sub AccesoColumna2() Dim oHojaActiva As Object Dim oRango As Object oHojaActiva = ThisComponent.getCurrentController.select(oRango) End Sub Sub AccesoFilas2() Dim oHojaActiva As Object Dim oRango As Object oHojaActiva = ThisComponent.getCurrentController.getCurrentController. al acceder por medio de estos métodos.getCurrentController.getCellRangeByName( "Registros" ) 'Y lo seleccionamos ThisComponent.select(oRango) End Sub OOo Basic cuenta con métodos específicos para manipular filas y columnas. pero propiamente hablando. dejan de ser rangos de celdas y pasan a ser objetos ScTableRowsObj y ScTableColumnsObj respectivamente como lo demostramos a continuación: Sub AccesoColumna3() Dim oHojaActiva As Object Dim oRango As Object oHojaActiva = ThisComponent.getCurrentController.getCurrentController.getActiveSheet() 'Referencia al rango A1:E1 oRango = oHojaActiva.getCurrentController.getCellRangeByName( "A1:E1" ) 'Mostramos el tipo de objeto . getImplementationName() & " .getRows() 'Verificamos el tipo de objeto MsgBox oRango.getImplementationName() End Sub Por lo anterior.getCurrentController.getImplementationName() End Sub Los métodos getColumns y getRows. Es el mismo caso para las filas: Sub AccesoFilas3() Dim oHojaActiva As Object Dim oRango As Object oHojaActiva = ThisComponent. trata de acceder a la información de depuración como se vio en capítulos anteriores y nota como implementan métodos y propiedades diferentes.getCellRangeByName( "A1:A10" ) 'Mostramos el tipo de objeto MsgBox oRango.getColumns() 'Verificamos el tipo de objeto MsgBox oRango. para poder tener acceso a los métodos y propiedades disponibles en los rangos.getActiveSheet() 'Referencia al rango A1:A10 oRango = oHojaActiva. tenemos que acceder a cada fila o columna de forma individual o construir un contenedor de rangos para acceder a varias filas o columnas.getImplementationName() 'Renombramos el objeto oRango accediendo a sus filas oRango = oRango. así como para poder hacer selecciones. la recomendación es que mantengas tu referencia original al rango y uses una segunda variable si necesitas acceder a las filas o columnas completas como te muestro en el siguiente ejemplo: Sub Dim Dim Dim Dim AccesoFilasColumnas1() oHojaActiva As Object oRango As Object oFil As Object oCol As Object oHojaActiva = ThisComponent. también.getImplementationName() 'Renombramos el objeto oRango accediendo a sus columnas oRango = oRango." & oFil.getRows() 'Verificamos el tipo de objeto MsgBox oCol.getImplementationName() End Sub 6.getActiveSheet() 'Referencia al rango C5:E10 oRango = oHojaActiva. veamos los dos casos: Para seleccionar la primer columna del rango .174 MsgBox oRango.getCurrentController.getImplementationName() 'Creamos una nueva referencia a las filas y columnas oCol = oRango.2 Referencia a rangos Trata de seleccionar el rango tal y como queda al final del código y veras que te da un error. siempre (aunque en el rango exista solo una fila o columna) te devolverá un conjunto de Columnas y Filas.getColumns() oFil = oRango.getCellRangeByName( "C5:E10" ) 'Mostramos el tipo de objeto MsgBox oRango. getRangeAddress().getCurrentController.addRangeAddress( oHojaActiva.Aprendiendo OOo Basic Sub Dim Dim Dim AccesoFilasColumnas2() oHojaActiva As Object oRango As Object oCol As Object 175 oHojaActiva = ThisComponent. podemos acceder directamente a la fila o columna que queramos de cualquier hoja por medio de la colección de estas (getColumns y getRows) y por medio del índice (getByIndex) a la fila o columna deseada: oHojaActiva.star.getRows().getCellRangeByName( "C5:E10" ) 'Creamos una nueva referencia a la primer columna del rango la C oCol = oRango.getRows().sheet.getCurrentController.createInstance("com.getByIndex(1) 'Y lo seleccionamos ThisComponent.getActiveSheet() 'Referencia al rango C5:E10 oRango = oHojaActiva.SheetCellRanges") 'Agregamos la columna E y la fila 10 al contenedor oRangos. podemos seleccionar una fila y una columna al mismo tiempo Sub AccesoFilasColumnas4() Dim oHojaActiva As Object Dim oRangos As Object oHojaActiva = ThisComponent.getColumns().getByIndex(9) 'Columna E 'Fila 10 .getByIndex(4) oHojaActiva.getActiveSheet() 'Referencia al rango C5:E10 oRango = oHojaActiva.getCellRangeByName( "C5:E10" ) 'Creamos una nueva referencia a la segunda fila del rango la 6 oFil = oRango.select(oFil) End Sub Por supuesto.getActiveSheet() 'Creamos el contender para los rangos oRangos = ThisComponent.select(oCol) End Sub Para seleccionar la primer fila del rango Sub Dim Dim Dim AccesoFilasColumnas3() oHojaActiva As Object oRango As Object oFil As Object oHojaActiva = ThisComponent.addRangeAddress( oHojaActiva.sun.getByIndex(4).False ) 'Comprobamos que estan correctos seleccionandolos ThisComponent.getCurrentController.select(oRangos) End Sub Como ya notaste.getRows().getCurrentController.getRangeAddress().False ) oRangos.getColumns().getByIndex(9).getByIndex(0) 'Y lo seleccionamos ThisComponent.getCurrentController.getCurrentController.getColumns(). getImplementationName() End Sub Pero cuidado. seleccionado los siguientes elementos: 1. nuestra selección pueden ser muchas cosas. en las dos siguientes selecciones.getCurrentSelection() MsgBox oSel. por ejemplo.5 Referencia a la selección actual Trabajar con la selección actual. en capítulos posteriores. vuelve a ejecutar la macro anterior. veamos uno muy importante. si lo hiciste en el mismo orden que yo. te tuvo que haber dado el error “Propiedad o método no encontrado”. la selección actual. ScCellRangesObj 4. la siguiente lista de mensajes: 1. vamos a tratar de ver el contenido de una celda. y también. siempre que sea posible. de un rango y varios rangos. es decir. la macro anterior te tiene que mostrar ese contenido. Para acceder a la selección actual dentro de nuestra hoja de calculo usamos el método getCurrentSelection() de la siguiente manera: Sub SeleccionActual1() Dim oSel As Object oSel = ThisComponent.sun. mover.drawing. veremos como manipular estos rangos. Una celda 2.getString() End Sub Si seleccionaste una sola celda y esta contenía algo.176 6.star. 6. para terminar este tema de hacer referencia a rangos. etc.SvxShapeCollection Observa la diferencia entre una sola celda (1) y un rango (2 y 3).2. copiar. ejecuta la macro siguiente. ScCellObj 2. teniendo cada vez. insertar. y nota también la diferencia en un rango (2) y varios (3). com. Varios rangos de celdas 4. esto es muy importante para actuar en consecuencia por que son objetos diferentes y por lo tanto implementan métodos y propiedades diferentes. el método . muy propensa a errores (ya sabes como son los usuarios).. por que efectivamente. con lo que el usuario tenga seleccionado al momento de llamar a una macro. teniendo seleccionado cada uno de los tres primeros rangos mencionados.getCurrentSelection() MsgBox oSel.2 Referencia a rangos Por ahora hemos visto como hacer referencia a diferentes tipos de rangos. es una actividad muy común. ScCellRangeObj 3. Un objeto de dibujo Debes de obtener. Un rango de celdas 3. Sub SeleccionActual2() Dim oSel As Object oSel = ThisComponent. trataremos de mantener el control de la selección. 0 ) Case Else MsgBox "Se requiere seleccionar una celda" End Select .getImplementationName() Case "ScCellObj" oCelda = oSel MsgBox oCelda. accedemos a la primer celda oCelda = oSel.getCellByPosition( 0.getCurrentSelection() Select Case oSel. primero accedemos al primer rango 'con getByIndex(0) y despues a la primer celda oCelda = oSel.getCurrentSelection() Select Case oSel.getImplementationName() Case "ScCellObj" MsgBox "Muy bien seleccionaste solo una celda" Case "ScCellRangeObj" MsgBox "Te pasaste un poco" Case "ScCellRangesObj" MsgBox "No tienes remedio" Case Else MsgBox "No se ni que seleccionaste" End Select End Sub Ahora ya sabemos que es lo que el usuario selecciono. supongamos que nuestra macro requiere que el usuario seleccione una y solo una celda.getString() Case Else MsgBox "Se requiere seleccionar solo UNA celda" End Select End Sub O podemos tomar solo la primer celda del rango o de los rangos que haya seleccionado como en: Sub SeleccionActual5() Dim oSel As Object Dim oCelda As Object oSel = ThisComponent. pero dependerá de que queramos hacer con la selección para actuar en consecuencia. podemos solo informarle como en el siguiente ejemplo: Sub SeleccionActual4() Dim oSel As Object Dim oCelda As Object oSel = ThisComponent.getCurrentSelection() Select Case oSel. por ejemplo. primer intento: Sub SeleccionActual3() Dim oSel As Object oSel = ThisComponent.0 ) Case "ScCellRangesObj" 'Si son varios rangos.getCellByPosition( 0.getByIndex(0). por ello es muy importante discriminar la selección que haya hecho el usuario.Aprendiendo OOo Basic 177 getString() solo esta implementado en celdas individuales.getImplementationName() Case "ScCellObj" oCelda = oSel Case "ScCellRangeObj" 'Si es un solo rango. pero en relación al rango seleccionado.2. en que hoja. recuerda que la posición 0.2 Referencia a rangos Nota que aun tenemos que evaluar que oCelda. veamos cuales son: Sub Dim Dim Dim Dim InfoRangos1() oSel As Object oDir As Object sTmp As String co1 As Integer oSel = ThisComponent. "ScCellRangeObj". por ejemplo: Sub SeleccionActual6() Dim oSel As Object Dim oRango As Object oSel = ThisComponent. puede ser cualquier otra.178 If Not IsNull(oCelda) Then MsgBox oCelda. es decir.0 en relación con la hoja siempre se refiere a la celda A1. siempre válida los datos. Lo que he querido ilustrarte. requieren se les pasen las estructuras correctas de la dirección de los rangos. es necesario saber donde estamos ubicados. siempre válida sus datos. más adelante veremos a detalle este método. por ello podemos llamarlo sin problemas. recuerda que en la interfaz del usuario. tienes que discriminar una u otra cosa. esta implementado en los tres tipos de rangos. y en un grupo de rangos.clearContents(31) End If End Sub El método clearContents. por ello es importante saber cuales son y como están estructuradas.6 Obteniendo información de rangos En diversas ocasiones.getString() End If End Sub 6. puede haber más elementos seleccionables. la primer celda siempre será la superior izquierda.getCurrentSelection() . como recomendación malévola. y disculpa la necedad. En algunos casos. es decir. el rango 0 también siempre será el que este más arriba y a la izquierda. también. apunte a un rango válido. 6. dependiendo de tus necesidades. los rangos cuentas con métodos y estructuras con esta información.getCurrentSelection() Select Case oSel. pero siempre. tal vez sea valido cualquiera de los tres tipos de rangos. algunas de ellas ya las hemos usado. es que. muchos métodos de manipulación de rangos. También. no importa si fue el ultimo rango en ser seleccionado. nunca confíes en el usuario. que el método a usar esta implementado en los tres.getImplementationName() Case "ScCellObj". fila y columna. "ScCellRangesObj" oRango = oSel Case Else MsgBox "Se requiere seleccionar un rango" End Select If Not IsNull(oRango) Then 'Borramos el contenido de las celdas oRango. Es importante que recuerdes que en el caso de un rango. Column & Chr(13) & "Fila: " & oDir.StartRow & Chr(13) & _ "Columna Fin: " & oDir. no se te olvide que todo empieza en 0. que contiene.StartColumn & Chr(13) & _ "Fila Inicio: " & oDir.Sheet).Sheet & Chr(13) & _ "Columna Inicio: " & oDir.Chr(13)) 'Mostramos el resultado MsgBox sTmp Case Else MsgBox "Se requiere seleccionar un rango de celdas" End Select End Sub Observa que si es una sola celda se tiene que usar getCellAddress que obtiene. desconozco su existe."). cuando es un rango de celdas se usa getRangeAddress. obtenemos sus datos oDir = oSel.EndColumn & Chr(13) & _ "Fila Fin: " & oDir. por ejemplo “Datos. la hoja donde esta la celda.getSheets(). la columna y fila donde empieza y la columna y fila donde termina. pero podemos crearnos nuestra propia función que lo haga por nosotros: Sub InfoRangos2() Dim oSel As Object oSel = ThisComponent. podemos acceder a cada uno. No he encontrado. observa como hacemos uso del índice de la hoja 'oDir.getCellAddress() 'Mostramos sus datos.getRangeAddress() 'Construimos el texto informativo sTmp = "El rango esta en la hoja: " & oDir.getByIndex(oDir.StartColumn & Chr(13) & _ "Fila Inicio: " & oDir.Sheet & Chr(13) & _ "Columna Inicio: " & oDir. la columna y fila.getRangeAddressesAsString().getName() & Chr(13) & "Columna: " & oDir.EndColumn & Chr(13) & _ "Fila Fin: " & oDir.Sheet para obtener el nombre de la hoja MsgBox "Hoja: " & ThisComponent. una propiedad o método similar para los casos de una celda y un rango.StartRow & Chr(13) & _ "Columna Fin: " & oDir.getByIndex(co1).A2:E5”.EndRow MsgBox sTmp Next 'O podemos acceder a las direcciones de todos los rangos sTmp = Join( Split(oSel. la hoja por índice donde esta el rango. todo desde 0.EndRow MsgBox sTmp Case "ScCellRangesObj" 'Si son varios rangos.Aprendiendo OOo Basic 179 Select Case oSel. podemos obtener los datos de cada rango For co1 = 0 To oSel. pero estos si cuentan con una propiedad de texto (getRangeAddressesAsString) que directamente nos devuelve las direcciones de los rangos en un formato entendible “casi” por cualquier usuario.getRangeAddress() sTmp = "El rango " & co1 & " esta en la hoja: " & oDir.getCurrentSelection() 'Usamos nuestra función personalizada MsgBox DireccionRango(oSel) End Sub 'Que linda quedo esta funcion Function DireccionRango(Rango As Object) As String .getImplementationName() Case "ScCellObj" 'Obtenemos la direccion de la celda oDir = oSel.Row Case "ScCellRangeObj" 'Si es un solo rango.".getCount()-1 oDir = oSel. reitero. Observa como en el caso de varios rangos. getName() & ".EndRow+1.mDatos()) Case "ScCellRangeObj" 'Si es un rango de celdas usamos getRangeAddress oDir = Rango.callFunction("ADDRESS".getCellAddress 'Construimos la matriz de datos para la función mDatos = Array( oDir.". los argumentos requeridos y estos.Rango. columna.Rango. sino que obtenemos los datos solo con propiedades del rango.getByIndex(0).getRangeAddress() 'Obtenemos la celda superior izquierda del rango mDatos =Array(oDir.getColumns(). la referencia a la celda.getName() & _ Rango. oDir.getName() ) DireccionRango = oSFA.EndRow + 1 Case "ScCellRangesObj" sTmp = Join( Split(Rango.getRangeAddress.oDir.getName() & "." & _ Rango. si queremos la referencia absoluta o relativa y la hoja.getSpreadsheet.getColumns().mDatos()) Case "ScCellRangesObj" 'Esta ya la vimos DireccionRango = Join( Split(Rango.FunctionAccess" ) 'Validamos el tipo de rango pasado Select Case Rango.Chr(13)) End Select End Function La función DIRECCION de Calc.".getCellAddress. integer.EndColumn+1.sun." & _ Rango. deben estar en el formato (string. nos devuelve en formato de texto. etc.getSpreadsheet.getByIndex(Rango.Chr(13) ) End Select DireccionRango2 = sTmp End Function .4. Una segunda versión de esta función. oDir. si usamos las funciones de Calc desde OOo Basic. indicándole la fila.Row+1.getByIndex(0).callFunction("ADDRESS".getRangeAddressesAsString(). el nombre de estas tenemos que indicarlas en ingles y pasarle los argumentos de la función en forma de matriz de datos.getSpreadsheet.getImplementationName() Case "ScCellObj" 'Si es una sola celda usamos getCellAddress oDir = Rango. es muy importante pasarle.getName() & _ Rango.Column+1. sino.2 Referencia a rangos 'Nos apoyamos en la funcion de Calc DIRECCION (ADDRESS) oSFA = createUnoService( "com. tal y como sucede en la hoja de calculo.Row + 1 Case "ScCellRangeObj" sTmp = Rango.getRangeAddressesAsString().getImplementationName() Case "ScCellObj" sTmp = Rango.getRangeAddress.getCount()1).getName()) DireccionRango = oSFA.180 Dim oSFA As Object Dim oDir As Object Dim mDatos 6.callFunction("ADDRESS".sheet.getName() & _ Rango. nota que no hacemos uso de ninguna función de hoja de calculo.StartRow + 1 & ":" & _ Rango.getColumns().StartColumn+1.getColumns(). puede ser la siguiente. 4 ) DireccionRango = DireccionRango & oSFA. puedes usar indistintamente cualquiera de las dos: Function DireccionRango2(Rango As Object) As String Dim sTmp As String Select Case Rango.StartRow+1.mDatos()) & ":" 'Ahora la celda celda inferior derecha del rango mDatos = Array( oDir. mínimo.").star. la función te retornara un error.").4.) que “espera” la función.getSpreadsheet. 7 Trabajando con Cursores Un cursor. la región actual es un concepto sumamente. útil y poderoso cuando se programa. es el rango de celdas “con datos” delimitado por filas y columnas en blanco.Aprendiendo OOo Basic 181 Por ultimo.2. que como sabes.getCount() End Select End Sub Los rangos. por ello le daremos un poco de énfasis. supongamos la siguiente tabla de datos: . cuentan con una propiedad que nos devuelve la dirección del rango seleccionado. Lo más usual es crearlo a partir de un rango para desplazarse dentro de el.getCount() & Chr(13) & _ "Columnas = " & oSel. pero además tiene métodos muy útiles para expandir por ejemplo a la región actual. podemos saber el número de filas y columnas que tiene un rango usando los métodos getRows y getColumns respectivamente.getColumns(). Sub InfoRangos3() Dim oSel As Object oSel = ThisComponent.AbsoluteName End Sub 6. también. estos métodos solo están disponibles cuando el rango es una sola celda y un rango. se llama AbsoluteName y el resultado como su nombre lo indica es con las referencias absolutas. Sub InfoRangos4() Dim oSel As Object oSel = ThisComponent.getCurrentSelection() Select Case oSel. es un objeto que nos permite movernos por la hoja entera o dentro de un rango especificado sin afectar o modificar al rango a partir del cual se crea.getCurrentSelection() MsgBox oSel. cuando son varios rangos tienes que ingeniarteles que no es complicado.getImplementationName() Case "ScCellObj"."ScCellRangeObj" MsgBox "Filas = " & oSel.getRows(). cuando le pasemos como argumento una celda. tenemos que agregar el tipo de objeto "ScCellCursorObj". nota que usaremos una función creada en tema anterior que se llama DireccionRango. ahora. no necesariamente es así y solo es para fines didácticos. Case "ScCellRangeObj". esta trabajara bien.gotoEnd() MsgBox DireccionRango( oCursor ) 'Expandismo el cursor a toda la region actual oCursor. para solucionar esto. ejecuta la siguiente macro: Sub Cursores1() Dim oSel As Object Dim oCursor As Object 'Partimos de la seleccion oSel = ThisComponent.182 6. pero cuando intentemos pasarle un cursor. pero muy importante.getImplementationName() = "ScCellObj" Then 'Mostramos la direccion de la celda seleccionada MsgBox DireccionRango( oSel ) 'Creamos un cursor a partir de esta celda oCursor = oSel. ahora si.createCursorByRange( oSel ) 'Verificamos que apunten a la misma celda MsgBox DireccionRango( oCursor ) 'Nos movemos al inicio de la region actual oCursor.2 Referencia a rangos Observa que el cursor esta en la celda D8 y que la región actual de este rango de datos es B2:F11. al ser un objeto diferente. te devolverá una cadena vacía. lo cual sabes. "ScCellCursorObj" Observa que ahora evaluara si es un rango de celdas o un cursor. busca y corrige la siguiente línea en dicha función personalizada.gotoStart() MsgBox DireccionRango( oCursor ) 'Nos movemos al final oCursor.getCurrentSelection() 'Solo si es una sola celda If oSel. ejecuta la siguiente macro donde obligamos al usuario a seleccionar solo una celda.getSpreadSheet().collapseToCurrentRegion() MsgBox DireccionRango( oCursor ) 'Mostramos de nuevo la direccion de la celda seleccionada 'observa que esta no se a movido MsgBox DireccionRango( oSel ) Else . Aprendiendo OOo Basic 183 MsgBox "Selecciona solo una celda" End If End Sub Los cursores.EndRow + 1 Else MsgBox "Selecciona solo una celda" End If End Sub Por supuesto. esto es muy sencillo: Sub Cursores2() Dim oSel As Object Dim oCursor As Object 'Partimos de la seleccion oSel = ThisComponent. "ScCellRangeObj" MsgBox "La siguiente fila libre es la: " & FilaLibre( oSel ) End Select End Sub Otros métodos con que cuentan los cursores son: Sub Cursores4() Dim oSel As Object Dim oCursor As Object .getSpreadSheet().getImplementationName() = "ScCellObj" Then 'Creamos un cursor a partir de esta celda oCursor = oSel. Una pregunta recurrente en las listas de correo. algo como: Function FilaLibre( Rango As Object) As Long Dim oCursor As Object oCursor = Rango. heredan la mayoría de sus métodos y propiedades. pero sus métodos particulares son lo que los hacen especiales e interesantes.getCurrentSelection() 'Solo si es una sola celda If oSel. con un cursor. sera esta fila mas 1 MsgBox oCursor.gotoEnd() FilaLibre = oCursor. algo muy practico es tener una función personalizada que nos encuentre la siguiente fila libre.getRangeAddress().gotoEnd() 'La siguiente fila libre.getCurrentSelection() 'Solo funciona con celdas individuales o rangos de celdas Select Case oSel.getRangeAddress().getImplementationName() Case "ScCellObj". al compartir la mayoría de los servicios de las celdas y los rangos.createCursorByRange( oSel ) 'Nos movemos al final oCursor.createCursorByRange( Rango ) oCursor.getSpreadSheet(). es ¿como encuentro la siguiente fila libre?.EndRow + 1 End Function Y que usamos de una forma muy sencilla: Sub Cursores3() Dim oSel As Object Dim oCursor As Object 'Partimos de la seleccion oSel = ThisComponent. gotoOffset(2. usa estos métodos con precaución.gotoEnd() MsgBox DireccionRango( oCursor ) 'Nos movemos tres columnas a la derecha y tres filas abajo oCursor.createCursorByRange( oSel ) 'Nos movemos a la siguiente celda oCursor. pero como sabes. te saldrás del rango y ya no podrás regresar al inicio (gotoStart).gotoPrevious() MsgBox DireccionRango( oCursor ) 'Nos movemos dos columnas a la derecha y tres filas abajo oCursor. estas llaves nos indican que dicha formula forma parte de una formula matricial.gotoStart() 'Toma nota de esta direccion MsgBox DireccionRango( oCursor ) oCursor.gotoOffset(3. estas se introducen con la .getSpreadSheet().3) MsgBox DireccionRango( oCursor ) Else MsgBox "Selecciona solo una celda" End If End Sub 6. nota en la barra de formulas que la formula mostrada esta encerrada en unas llaves.gotoNext() MsgBox DireccionRango( oCursor ) 'Nos movemos a la celda anterior oCursor. nota como NO es la 'misma de la primer linea oCursor.3) MsgBox DireccionRango( oCursor ) 'Intentamos regresar al inicio.3).createCursorByRange( oSel ) oCursor. o sea tres columnas a la derecha y tres filas abajo. por ejemplo.getImplementationName() = "ScCellObj" Then oCursor = oSel.getCurrentSelection() If oSel.2 Referencia a rangos Estos métodos hay que usarlos con cuidado.getCurrentSelection() If oSel.getSpreadSheet().184 oSel = ThisComponent. Sub Cursores5() Dim oSel As Object Dim oCursor As Object oSel = ThisComponent. como sabes.getImplementationName() = "ScCellObj" Then oCursor = oSel. pues puedes “salirte” del rango donde estas trabajando y ya no podrás moverte con otros métodos como gotoStart o gotoEnd.gotoStart() MsgBox DireccionRango( oCursor ) Else MsgBox "Selecciona solo una celda" End If End Sub Observa atentamente la siguiente imagen. como no es el tema de este libro las formulas matriciales no entraremos en detalle alguno. si te mueves al final de un rango (gotoEnd) y después te desplazas con gotoOffset(3. Con un cursor. probado en los datos mostrados en la imagen anterior: Sub Cursores6() Dim oSel As Object Dim oCursor As Object oSel = ThisComponent.getImplementationName() = "ScCellObj" Then oCursor = oSel. solo te devolverá la celda superior izquierda de dicho rango.getSpreadSheet().createCursorByRange( oSel ) oCursor.getCurrentSelection() If oSel.createCursorByRange( oSel ) 'Comprobamos que solo devuelve una celda MsgBox DireccionRango( oSel ) 'Expandimos el cursor a todas las celdas combinadas oCursor.getSpreadSheet(). cuando establecemos el cursor en celdas combinadas y tratamos de obtener dicha dirección.getImplementationName() = "ScCellObj" Then oCursor = oSel. sino tienes que hacerlo con toda la matriz. pero con un cursor podemos saber el rango completo de estas celdas combinadas: Sub Cursores7() Dim oSel As Object Dim oCursor As Object oSel = ThisComponent.collapseToMergedArea() MsgBox DireccionRango( oCursor ) .getCurrentSelection() If oSel. no puedes modificar solo una celda de dichas matrices.collapseToCurrentArray() MsgBox DireccionRango( oCursor ) Else MsgBox "Selecciona solo una celda" End If End Sub En la siguiente imagen. podemos saber cual es el rango de una formula matricial. como lo demostramos en el siguiente ejemplo.Aprendiendo OOo Basic 185 combinación de teclas CTRL+SHIFT+ENTER y que ya creada. observa las celdas combinadas. lo importante es saber que estas haciendo siempre: Sub Cursores10() Dim oSel As Object Dim oCursor As Object oSel = ThisComponent.getCurrentSelection() If oSel.collapseToCurrentRegion() MsgBox DireccionRango( oCursor ) 'Y luego a todas las filas oCursor.createCursorByRange( oSel ) 'Expandimos el cursor a la region actual oCursor.expandToEntireRows() MsgBox DireccionRango( oCursor ) 'Nota como devuelve la hoja entera oCursor.expandToEntireColumns() MsgBox DireccionRango( oCursor ) Else MsgBox "Selecciona solo una celda" End If End Sub Intuirás que también es posible hacerlo en las filas: 'Expandimos el cursor a la region actual oCursor.expandToEntireRows() MsgBox DireccionRango( oCursor ) Ten cuidado cuando uses los dos métodos anteriores.createCursorByRange( oSel ) 'Expandimos el cursor a la region actual oCursor. tendrás un cursor con tu hoja completa.expandToEntireColumns() .collapseToCurrentRegion() MsgBox DireccionRango( oCursor ) 'Y luego a todas las columnas oCursor.getImplementationName() = "ScCellObj" Then oCursor = oSel.getCurrentSelection() If oSel.getSpreadSheet().collapseToCurrentRegion() MsgBox DireccionRango( oCursor ) 'Y luego a todas las columnas oCursor.2 Referencia a rangos Else MsgBox "Selecciona solo una celda" End If End Sub Podemos expandir nuestro cursor para que abarque todas las columnas de nuestra región actual: Sub Cursores8() Dim oSel As Object Dim oCursor As Object oSel = ThisComponent. si los ejecutas uno detrás de otro.getSpreadSheet().getImplementationName() = "ScCellObj" Then oCursor = oSel.186 6. que no descartes usar un día. veamos dos métodos más de los cursores. toma en cuenta que la celda superior izquierda no cambia: Sub Cursores11() Dim oSel As Object Dim oCursor As Object oSel = ThisComponent.getCount() + 1.5 ) MsgBox DireccionRango( oCursor ) Else MsgBox "Selecciona solo una celda" End If End Sub Nota que estamos “cambiando” el tamaño del cursor.createCursorByRange( oSel ) 'Expandimos el cursor a la region actual oCursor.getSpreadSheet().collapseToSize( oCursor.getCurrentSelection() If oSel.collapseToCurrentRegion() MsgBox DireccionRango( oCursor ) 'Y luego cambiamos el cursor a 2 columnas y 5 filas oCursor.getRows().getCurrentSelection() If oSel.getCount() + 5 ) MsgBox DireccionRango( oCursor ) Else MsgBox "Selecciona solo una celda" End If End Sub Nota como hemos usado algunos métodos vistos en el tema anterior ( getColumns().getImplementationName() = "ScCellObj" Then oCursor = oSel. como en el siguiente ejemplo: Sub Cursores12() Dim oSel As Object Dim oCursor As Object oSel = ThisComponent. tienes que sumarle el ancho y alto de la región actual. esto es posible por que los cursores comparten la mayoría de los servicios con los rangos.getCount ). oCursor.getImplementationName() = "ScCellObj" Then oCursor = oSel. como ya lo mencionamos.Aprendiendo OOo Basic 187 MsgBox DireccionRango( oCursor ) Else MsgBox "Selecciona solo una celda" End If End Sub También puedes ampliar tu cursor el número de columnas y filas que necesites.getColumns().getSpreadSheet().collapseToSize( 2. si lo que quieres realmente es expandirlo. Casi para finalizar.collapseToCurrentRegion() MsgBox DireccionRango( oCursor ) 'Y luego ampliamos el cursor 1 columna y 5 filas oCursor.createCursorByRange( oSel ) 'Expandimos el cursor a la region actual oCursor. Sub Cursores13() . .2 Referencia a rangos 'Vamos al inicio del area usada.. la cosa cambia en cuanto tienes dos o más celdas usadas. por ejemplo. para terminar.createCursorByRange( oSel ) oCursor.getCurrentSelection() If oSel.getImplementationName() = "ScCellObj" Then oCursor = oSel. es aquel rango “efectivamente” usado.getImplementationName() = "ScCellObj" Then oCursor = oSel. si tienes “una” sola celda usada. esta. será el inicio y el fin de tu área de usuario.getSpreadSheet(). y digo que es dinámica.collapseToCurrentRegion() ThisComponent.select( oCursor ) Else MsgBox "Selecciona solo una celda" End If End Sub Con lo cual observamos que estos cursores con bastante versátiles. es muy dinámico pues varia de acuerdo a su uso y eliminación.2. 6. el “área de usuario”. como en el ejemplo siguiente donde seleccionamos la región actual del rango: Sub Cursores14() Dim oSel As Object Dim oCursor As Object oSel = ThisComponent. por que si eliminas datos o celdas. el argumento False.gotoEndOfUsedArea( False ) MsgBox DireccionRango( oCursor ) Else MsgBox "Selecciona solo una celda" End If End Sub En una hoja de calculo.getCurrentSelection() If oSel. cuentan con unos métodos bastante interesantes (y útiles) para hacer algunas selecciones especiales.188 Dim oSel As Object Dim oCursor As Object oSel = ThisComponent. esta área se ira ajustando conforme a estos cambios. evita que se 'expanda la selección del rango oCursor.createCursorByRange( oSel ) 6. en una hoja nueva el inicio y el final de esta área siempre será el mismo. también lo puedes usar para establecer una selección.getCurrentController. podemos seleccionar las celdas vacías de un rango como en: . un cursor. Ahora si.8 Selecciones especiales Los rangos. la regla es: el inicio de tu área de usuario será la celda (“con datos”) que este más cercana al extremo superior izquierdo de la hoja y el final será la celda (“con datos”) que este más cercana al extremo inferior derecho de dicha hoja.gotoStartOfUsedArea( False ) MsgBox DireccionRango( oCursor ) 'Ahora vamos al final oCursor. la celda A1.getSpreadSheet(). getCurrentController.getCurrentSelection() 'Recuperamos las celdas con formulas oSelEsp = oSel.Aprendiendo OOo Basic 189 Sub SeleccionesEspeciales1() Dim oSel As Object Dim oSelEsp As Object 'Accedemos a la selección actual oSel = ThisComponent.CellFlags.sheet.sheet.queryEmptyCells() 'Y las seleccionamos ThisComponent. si una celda tiene aunque sea solo un espacio o algún carácter especial no visible (tabuladores. esta.sheet.star.STRING com.CellFlags.DATETIME com.FORMULA Valor 1 2 4 8 16 .3. saltos de página).sun.star.FORMULA ) ThisComponent.sheet.CellFlags.getCurrentSelection() 'Recuperamos las celdas con texto oSelEsp = oSel. Un punto importante.sun. También podemos seleccionar celdas de acuerdo a su contenido.select( oSelEsp ) End Sub Como hemos visto a lo largo de estas notas.star. ya no será vacía y no la obtendrás por este método.select( oSelEsp ) End Sub Los valores posibles para el argumento de este método son los siguientes. no es siempre necesario que selecciones.getCurrentSelection() 'Recuperamos las celdas vacías oSelEsp = oSel.VALUE com.sun. puedes manipular el rango obtenido sin que esto sea necesario.sun. valores que también se usan para borrar datos como se ve en el tema 6.queryContentCells( com.ANNOTATION com.4.sun.queryContentCells( 4 ) 'Y las seleccionamos ThisComponent.star. las celdas con formulas: Sub SeleccionesEspeciales3() Dim oSel As Object Dim oSelEsp As Object oSel = ThisComponent.CellFlags.getCurrentController.star. los cuales tienes que manipular como ya lo hemos aprendido.getCurrentController.sheet.CellFlags.sheet.Borrando datos Constante com. en el siguiente ejemplo seleccionamos las celdas con texto: Sub SeleccionesEspeciales2() Dim oSel As Object Dim oSelEsp As Object 'Accedemos a la seleccion actual oSel = ThisComponent.CellFlags.select( oSelEsp ) End Sub Ahora.sun. es que este método siempre retorna un conjunto de rangos (ScCellRangesObj).star. sheet.star.CellFlags.queryFormulaCells( 4 ) If oSelEsp.CellFlags. pero informamos si hubo o no celdas con el criterio especificado.star.OBJECT com.CellFlags.sheet. estos métodos siempre devuelven un conjunto de rangos (ScCellRangesObj). seleccionemos las celdas que contengan error: Sub SeleccionesEspeciales6() Dim oSel As Object Dim oSelEsp As Object oSel = ThisComponent.EDITATTR com.sheet.getCount = 0 Then MsgBox "No hay celdas con errores" Else MsgBox DireccionRango2( oSelEsp ) . por ejemplo.getCurrentSelection() 'Recuperamos las celdas con notas oSelEsp = oSel.sun.getCurrentSelection() 'Recuperamos las celdas con texto y valores oSelEsp = oSel.select( oSelEsp ) End Sub Como ya se menciono.190 Constante com. las celdas que tengan notas. pero también podemos seleccionar formulas.star. en el siguiente ejemplo.sun.star. para este ejemplo.CellFlags. de acuerdo su resultado.FORMATTED 6.2 Referencia a rangos Valor 32 64 128 256 512 Puedes usar de forma indistinta el valor numérico o su constante como se ve en los dos ejemplos anteriores y también sumar los valores para tener múltiples combinaciones.sun.sheet.getCount = 0 Then MsgBox "No hay celdas con notas" Else 'Mostramos la dirección de los rangos encontrados MsgBox DireccionRango2( oSelEsp ) End If End Sub Ya vimos como seleccionar formulas.getCurrentController.sheet.HARDATTR com.sun.CellFlags.queryContentCells( 8 ) If oSelEsp. que ya hemos usado anteriormente: Sub SeleccionesEspeciales5() Dim oSel As Object Dim oSelEsp As Object oSel = ThisComponent.getCurrentSelection() 'Recuperamos las celdas con formulas cuyo resultado sea error oSelEsp = oSel. observa que usamos una función personalizada (DireccionRango2). ya no seleccionamos.STYLES com.sun.queryContentCells( 5 ) ThisComponent. por lo que es muy sencillo saber si hay o no resultados. como en el ejemplo siguiente donde seleccionamos las celdas con texto y valores: Sub SeleccionesEspeciales4() Dim oSel As Object Dim oSelEsp As Object oSel = ThisComponent.star. FormulaResult. solo acepta los tres valores siguiente: Constante com.FormulaResult.sun.FormulaResult.getCurrentController().queryFormulaCells( 3 ) If oSelEsp.ERROR Valor 1 2 4 Los cuales.sheet.star.sheet.VALUE com.getActiveSheet() 'El rango a evaluar oRango = oHojaActiva.getCurrentSelection() 'Recuperamos las celdas con formulas cuyo resultado sea texto o valor oSelEsp = oSel.sun. supongamos la siguiente lista de datos: A 1 2 3 4 5 6 7 8 9 10 3 5 3 1 1 4 1 5 5 3 B 3 2 1 1 5 1 3 1 3 2 C 5 1 2 3 5 4 1 1 3 4 D 3 2 5 4 5 1 1 5 2 5 E 4 4 5 5 4 3 5 3 3 1 Selecciona el rango A1:A10 y ejecuta la siguiente macro: Sub Dim Dim Dim Dim SeleccionesEspeciales8() oHojaActiva As Object oRango As Object oSelEsp As Object oCelda As Object oHojaActiva = ThisComponent.star. podemos combinar: Sub SeleccionesEspeciales7() Dim oSel As Object Dim oSelEsp As Object oSel = ThisComponent.getCount = 0 Then MsgBox "No hay celdas con texto o valor" Else MsgBox DireccionRango2( oSelEsp ) End If End Sub Los siguiente métodos requieren una atención especial.getCellRangeByName("A1:A10") 'La celda de comparación .sun.sheet.Aprendiendo OOo Basic End If End Sub 191 El argumento de este método.star.STRING com. 2 Referencia a rangos Que te tiene que seleccionar: Observa como seleccionó las celdas con un valor diferente al de la celda de comparación.select( oSelEsp ) End If End Sub Que nos devuelve: .getActiveSheet() oRango = oHojaActiva. después pasale la celda C2 y observa el resultado. Con el siguiente ejemplo.select( oSelEsp ) End If End Sub 6. es muy importante entender que.192 oCelda = oHojaActiva. de la celda de comparación. “únicamente toma la fila” de la dirección para la comparación. queda bastante claro como trabaja este método.getCellAddress ) If oSelEsp.queryColumnDifferences( oCelda.getCurrentController().getCount = 0 Then MsgBox "No se encontraron celdas" Else 'Las seleccionamos ThisComponent. el valor comparado.getCellRangeByName("A1:C10") oCelda = oHojaActiva.getCellRangeByName("B10") oSelEsp = oRango. intenta pasarle a esta misma macro la celda C1.getCount = 0 Then MsgBox "No se encontraron celdas" Else ThisComponent.getCellRangeByName("A1") 'Buscamos las celdas diferentes por columna oSelEsp = oRango. observa el resultado.getCurrentController. es el valor de la fila respectiva para cada columna: Sub Dim Dim Dim Dim SeleccionesEspeciales9() oHojaActiva As Object oRango As Object oSelEsp As Object oCelda As Object oHojaActiva = ThisComponent.queryColumnDifferences( oCelda.getCellAddress ) If oSelEsp. observa el rango pasado y la celda de comparación. creo.getCurrentController. getCurrentController().Aprendiendo OOo Basic 193 Por ultimo.getCount = 0 Then MsgBox "No se encontraron celdas" Else ThisComponent.getCellAddress ) If oSelEsp.select( oSelEsp ) End If End Sub Y comprueba que es correcto el resultado. como en: Sub Dim Dim Dim Dim SeleccionesEspeciales10() oHojaActiva As Object oRango As Object oSelEsp As Object oCelda As Object oHojaActiva = ThisComponent. con la celda de comparación que quieras. llamando al rango completo de pruebas.getCount = 0 Then MsgBox "No se encontraron celdas" Else ThisComponent.getCellRangeByName("A3") oSelEsp = oRango. como en el siguiente ejemplo.getCurrentController().getActiveSheet() oRango = oHojaActiva.queryColumnDifferences( oCelda.getCellRangeByName("A1:E10") oCelda = oHojaActiva.queryRowDifferences( oCelda.getActiveSheet() oRango = oHojaActiva.getCellAddress ) If oSelEsp. ejecuta la macro.select( oSelEsp ) End If End Sub Y el resultado: . usando la misma tabla de datos: Sub Dim Dim Dim Dim SeleccionesEspeciales11() oHojaActiva As Object oRango As Object oSelEsp As Object oCelda As Object oHojaActiva = ThisComponent.getCurrentController.getCellRangeByName("A10:E10") oCelda = oHojaActiva.getCellRangeByName("C10") 'Buscamos las celdas diferentes por filas oSelEsp = oRango.getCurrentController. El mismo tipo de comparación lo podemos hacer pero por filas. .getCount = 0 Then MsgBox "No se encontraron celdas" Else ThisComponent.queryRowDifferences( oCelda. así que solo hagamos un ejemplo más con el rango completo de datos: Sub Dim Dim Dim Dim SeleccionesEspeciales12() oHojaActiva As Object oRango As Object oSelEsp As Object oCelda As Object oHojaActiva = ThisComponent.getCellAddress ) If oSelEsp.194 6.getCurrentController. puede ser cualquier tipo de dato. “solo toma la columna” de la celda de comparación.getCellRangeByName("A1:E10") oCelda = oHojaActiva.getActiveSheet() oRango = oHojaActiva. en cuyo caso. incluyendo formulas.select( oSelEsp ) End If End Sub Que nos selecciona: Lo interesante de estos métodos.2 Referencia a rangos La lógica es exactamente la misma de hacerlo por columnas. no tienen que ser necesariamente texto.getCellRangeByName("D1") 'Buscamos las celdas diferentes por filas oSelEsp = oRango.getCurrentController(). se tomará el tipo de resultado de esta. solo que ahora. es que los valores de las celdas. Aprendiendo OOo Basic 195 El siguiente método nos sirve para saber el rango de celdas comunes a dos rangos, observa la siguiente imagen, la macro de ejemplo, nos tiene que seleccionar el rango en verde: Sub Dim Dim Dim Dim SeleccionesEspeciales13() oHojaActiva As Object oRango1 As Object oRango2 As Object oSelEsp As Object oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() oRango1 = oHojaActiva.getCellRangeByName("B2:I11") oRango2 = oHojaActiva.getCellRangeByName("G8:N17") 'Buscamos las celdas comunes oSelEsp = oRango1.queryIntersection( oRango2.getRangeAddress ) If oSelEsp.getCount = 0 Then MsgBox "No hay nada en común" Else ThisComponent.getCurrentController.select( oSelEsp ) End If End Sub Para terminar este tema, veamos un método muy interesante, nos permite seleccionar, del rango invocado, solo las celdas visibles. Observa la siguiente imagen: 196 6.2 Referencia a rangos Nota, en los encabezados de fila, que tenemos muchas filas ocultas, con la siguiente macro, mostramos la dirección de los rangos visibles: Sub Dim Dim Dim SeleccionesEspeciales14() oHojaActiva As Object oRango As Object oVisibles As Object oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() oRango = oHojaActiva.getCellRangeByName("A1:G243") 'Buscamos las celdas visibles oVisibles = oRango.queryVisibleCells() If oVisibles.getCount = 0 Then MsgBox "No hay celdas ocultas" Else 'Mostramos la dirección de los rangos visibles MsgBox DireccionRango2( oVisibles ) End If End Sub Cuando haces un filtro automático o especial y cuando calculas subtotales e intentas hacer operaciones de copiado, la copia resultante, solo contendrá las celdas visibles, cuando agrupas u ocultas filas o columnas manualmente, la copia incluirá aun las celdas ocultas, pero con este método siempre obtendrás las celdas visibles, que, en conjunto con los conocimientos del siguiente capitulo, puedes hacer tu propia versión de copiado. Aprendiendo OOo Basic 197 6.3 Manipulando rangos En el capitulo anterior aprendimos a referenciar cualquier rango que nos interese, ahora, aprenderemos a manipular estos rangos, principalmente, a moverlos, insertarlos, eliminarlos y copiarlos. 6.3.1 Moviendo rangos Para mover un rango, usamos el método moveRange de las hojas de calculo, este método requiere de dos argumentos, la celda superior izquierda (CellAddress) destino donde se moverá el rango origen (CellRangeAddress) Hoja.moveRange( Destino As CellAddress, Origen As CellRangeAddress ) El siguiente ejemplo mueve el rango A1:B5 de la hoja activa, a la celda D10 de la misma hoja: Sub Dim Dim Dim MoverRangos1() oHojaActiva As Object oOrigen As Object oDestino As Object oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() 'Rango a mover oOrigen = oHojaActiva.getCellRangeByName( "A1:B5" ) 'Celda destino oDestino = oHojaActiva.getCellRangeByName( "D10" ) 'Movemos el rango oHojaActiva.moveRange( oDestino.getCellAddress(), oOrigen.getRangeAddress() ) End Sub Toma en cuenta que el rango origen “tiene” que ser un rango de celdas, que la celda destino “tiene” que ser una celda individual, que los datos del rango origen se borran y los datos del rango destino son “reemplazados sin preguntarte” por los datos origen y muy importante, si el rango contiene formulas, estas, “no se actualizan a la nueva posición” aun y cuando las referencias sean relativas, también, el rango origen cambia para adaptarse al rango destino, es decir, la referencia a dicho rango se actualizara automáticamente como lo puedes comprobar si muestras la dirección del rango origen, antes y después de moverse: MsgBox DireccionRango( oOrigen ) 'Movemos el rango oHojaActiva.moveRange( oDestino.getCellAddress(), oOrigen.getRangeAddress() ) MsgBox DireccionRango( oOrigen ) Recuerda que la función DireccionRango, es personalizada y la hemos usado en los últimos temas vistos. Si quieres mover solo una celda, prueba la siguiente macro: 198 Sub Dim Dim Dim MoverRangos2() oHojaActiva As Object oOrigen As Object oDestino As Object oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() 'Nota como hacemos la referencia para que sea un rango oOrigen = oHojaActiva.getCellRangeByName( "B2:B2" ) 'Esta tiene que seguir siendo una sola celda oDestino = oHojaActiva.getCellRangeByName( "E5" ) 6.3 Manipulando rangos 'Movemos el rango oHojaActiva.moveRange( oDestino.getCellAddress(), oOrigen.getRangeAddress() ) End Sub Por supuesto podemos validar que por lo menos el origen y el destino sean efectivamente los argumentos que necesita este método: Sub Dim Dim Dim MoverRangos3() oHojaActiva As Object oOrigen As Object oDestino As Object oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() oOrigen = oHojaActiva.getCellRangeByName( "C5" ) oDestino = oHojaActiva.getCellRangeByName( "F15" ) 'Validamos que los rangos sean correctos If oOrigen.getImplementationName() = "ScCellRangeObj" And oDestino.getImplementationName() = "ScCellObj" Then oHojaActiva.moveRange( oDestino.getCellAddress(), oOrigen.getRangeAddress() ) Else MsgBox "Los rangos no son correctos" End If End Sub Esta validación es más útil cuando tomamos el rango a mover a partir de la selección actual del usuario, para que funcione el siguiente código, tienes que seleccionar más de una celda es decir, un rango de celdas, por supuesto, te queda de tarea hacer que funcione, aun y con solo seleccionar una celda. Sub Dim Dim Dim MoverRangos4() oHojaActiva As Object oOrigen As Object oDestino As Object oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() oOrigen = ThisComponent.getCurrentSelection() 'Validamos que los rangos sean correctos If oOrigen.getImplementationName() = "ScCellRangeObj" Then 'Dejamos una columna y una fila en blanco oDestino = oHojaActiva.getCellByPosition( oOrigen.getRangeAddress().EndColumn + 2, oOrigen.getRangeAddress().EndRow + 2 ) oHojaActiva.moveRange( oDestino.getCellAddress(), oOrigen.getRangeAddress() ) Else MsgBox "El rango Origen no es correcto" End If End Sub Nota como solo validamos el origen, por que el destino lo construimos a partir del este, observa que cuando mueves un rango, la selección actual no cambia, se queda en el rango Aprendiendo OOo Basic 199 origen, si seleccionamos el rango cuando se ha movido, podremos ir moviendo el rango, tantas veces como llames a la macro, modifica la macro anterior para que quede así: Sub Dim Dim Dim MoverRangos5() oHojaActiva As Object oOrigen As Object oDestino As Object oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() oOrigen = ThisComponent.getCurrentSelection() If oOrigen.getImplementationName() = "ScCellRangeObj" Then oDestino = oHojaActiva.getCellByPosition( oOrigen.getRangeAddress().EndColumn + 2, oOrigen.getRangeAddress().EndRow + 2 ) oHojaActiva.moveRange( oDestino.getCellAddress(), oOrigen.getRangeAddress() ) 'Seleccionamos el nuevo origen ThisComponent.getCurrentController().select( oOrigen ) Else MsgBox "El rango Origen no es correcto" End If End Sub Y llamala (ejecutala) varias veces, notaras como se va moviendo el rango, pero cuidado, puede pasar que en algún momento te un error, ¿cuando?, muy bien, cuando el rango destino quede fuera de la hoja de calculo, por lo que tenemos que evaluar también que esto no suceda: Sub Dim Dim Dim Dim MoverRangos6() oHojaActiva As Object oOrigen As Object oDestino As Object lLimiteCol As Long oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() oOrigen = ThisComponent.getCurrentSelection() If oOrigen.getImplementationName() = "ScCellRangeObj" Then 'Garantizamos que no sobre pase el maximo de columnas en la hoja de calculo lLimiteCol = oOrigen.getRangeAddress().EndColumn + 2 + oOrigen.getColumns().getCount() If lLimiteCol <= oHojaActiva.getColumns().getCount() Then oDestino = oHojaActiva.getCellByPosition( oOrigen.getRangeAddress().EndColumn + 2, oOrigen.getRangeAddress().EndRow + 2 ) oHojaActiva.moveRange( oDestino.getCellAddress(), oOrigen.getRangeAddress() ) ThisComponent.getCurrentController().select( oOrigen ) Else MsgBox "Se llego al limite de la hoja" End If Else MsgBox "Los rangos no son correctos" End If End Sub Nota que con oHojaActiva.getColumns().getCount(), obtenemos el total de columnas de la hoja activa, no importa si esta tiene 256 como en Openoffice.org 2.x o 1024 como en Openoffice.org 3.x, con lo que este código funcionara en las dos versiones, de hecho, en cualquier versión que implemente estas propiedades, y si, claro que tienes que evaluar también que no pases el limite de filas, pero esa, es tu tarea. Hasta ahora hemos movido rangos dentro de la misma hoja, pero de forma muy sencilla podemos mover rangos entre hojas, solo hay que establecer el destino correctamente y el método se encargará del resto: Sub MoverRangos7() 200 Dim Dim Dim Dim oHojaActiva As Object oOrigen As Object oDestino As Object lLimiteCol As Long 6.3 Manipulando rangos oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() oOrigen = ThisComponent.getCurrentSelection() If oOrigen.getImplementationName() = "ScCellRangeObj" Then oDestino = ThisComponent.getSheets().getByIndex(0).getCellByPosition( 0, 0 ) oHojaActiva.moveRange( oDestino.getCellAddress(), oOrigen.getRangeAddress() ) ThisComponent.getCurrentController().select( oOrigen ) Else MsgBox "El rango Origen no es correcto" End If End Sub Observa como el origen lo establecemos en la hoja activa, pero el destino lo referenciamos a la primer hoja del documento, claro que puedes hacerlo a cualquier otra, por índice o por nombre como ya lo hemos aprendido. Nota que el método moveRange, lo llamamos desde la hoja activa, pero también lo puedes llamar desde cualquier hoja, lo importante es que los argumentos, es decir, el origen y destino estén correctos, observa en el siguiente ejemplo, como llamamos al método moveRange desde la hoja del rango destino: Sub Dim Dim Dim Dim MoverRangos8() oHojaActiva As Object oOrigen As Object oDestino As Object lLimiteCol As Long oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() oOrigen = ThisComponent.getCurrentSelection() If oOrigen.getImplementationName() = "ScCellRangeObj" Then oDestino = ThisComponent.getSheets().getByIndex(0).getCellByPosition( 0, 0 ) oDestino.getSpreadSheet().moveRange( oDestino.getCellAddress(), oOrigen.getRangeAddress() ) ThisComponent.getCurrentController().select( oOrigen ) Else MsgBox "El rango Origen no es correcto" End If End Sub También podemos mover una columna completa, recuerda que una columna no es más que un rango de celdas: Sub Dim Dim Dim MoverRangos9() oHojaActiva As Object oOrigen As Object oDestino As Object oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() 'Referenciamos como origen la columna E oOrigen = oHojaActiva.getColumns().getByIndex(4) 'Como destino una columna a la derecha oDestino = oHojaActiva.getCellByPosition( oOrigen.getRangeAddress().EndColumn + 1, 0 ) oHojaActiva.moveRange( oDestino.getCellAddress(), oOrigen.getRangeAddress() ) ThisComponent.getCurrentController().select( oOrigen ) End Sub Y ya encarrerados, movemos filas también: Aprendiendo OOo Basic Sub Dim Dim Dim MoverRangos10() oHojaActiva As Object oOrigen As Object oDestino As Object 201 oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() 'Referenciamos como origen la fila 5 oOrigen = oHojaActiva.getRows().getByIndex(4) 'Como destino la fila 10 oDestino = oHojaActiva.getCellByPosition( 0, 9 ) oHojaActiva.moveRange( oDestino.getCellAddress(), oOrigen.getRangeAddress() ) ThisComponent.getCurrentController().select( oOrigen ) End Sub Cuando muevas columnas y filas completas, ten en cuenta las mismas consideraciones vistas en los demás ejemplos, de las cuales las principales son que los datos se mueven del origen al destino sin preguntar, es decir, no hay ninguna confirmación de sobreescritura en caso de que el destino no este vacío, por lo que tu tienes que implementar esta validación y tener cuidado de no salirse de los limites de la hoja de calculo. 6.3.2 Insertando rangos En la interfaz del usuario, cuando insertamos un rango, recordaras que Calc, nos muestra un cuadro de dialogo preguntándonos como desplazar las demás celdas, esta misma consideración hay que tener cuando lo hacemos por código, veamos como: Hoja.insertCells( Celdas As CellRangeAddress, Modo As CellInsertMode) Sub InsertarRangos1() Dim oHojaActiva As Object Dim oSel As Object oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() oSel = ThisComponent.getCurrentSelection() 'Insertamos un rango de celdas igual a la selección actual 'y movemos las celdas hacia abajo oHojaActiva.insertCells(oSel.getRangeAddress(), com.sun.star.sheet.CellInsertMode.DOWN) End Sub 202 6.3 Manipulando rangos El rango a insertar no tiene por que ser a partir de la selección actual, puedes crear una estructura CellRangeAddress vacía del tamaño que quieras como en el siguiente ejemplo: Sub InsertarRangos2() Dim oHojaActiva As Object Dim oRango As Object oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() 'Creamos una estructura vacía de dirección de un rango oRango = CreateUnoStruct( "com.sun.star.table.CellRangeAddress" ) 'Establecemos los valores del rango, tres filas por tres columnas With oRango .Sheet = oHojaActiva.getRangeAddress().Sheet .StartColumn = 1 .StartRow = 1 .EndColumn = 3 .EndRow = 3 End With 'Insertamos y desplazamos hacia la derecha oHojaActiva.insertCells(oRango, com.sun.star.sheet.CellInsertMode.RIGHT) End Sub Es muy importante que establezcas la propiedad Sheet (hoja) de esta estructura, si no lo haces, el valor predeterminado es 0, con lo que el rango insertado “siempre” lo hará en la primer hoja del documento. En este segundo ejemplo hemos desplazado las celdas a la derecha, las demás opciones de este método son insertar filas completas o columnas completas, en la siguiente tabla resumimos los cuatro valores posibles para este método: Constante com.sun.star.sheet.CellInsertMode.DOWN com.sun.star.sheet.CellInsertMode.RIGHT com.sun.star.sheet.CellInsertMode.ROWS com.sun.star.sheet.CellInsertMode.COLUMNS 1 2 3 4 Valor Puedes usar indistintamente la constante o el valor de esta como en el siguiente ejemplo donde insertamos filas completas: Sub InsertarRangos3() Dim oHojaActiva As Object Dim oRango As Object oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() oRango = CreateUnoStruct( "com.sun.star.table.CellRangeAddress" ) With oRango .Sheet = oHojaActiva.getRangeAddress().Sheet .StartColumn = 1 .StartRow = 1 .EndColumn = 3 .EndRow = 3 End With 'Insertamos filas completas oHojaActiva.insertCells( oRango, 3 ) Aprendiendo OOo Basic End Sub 203 Cuando quieras insertar filas o columnas completas, puedes usar los métodos vistos hasta ahora o, puedes usar los métodos específicos del conjunto de filas y columnas como en el siguiente ejemplo donde insertamos 2 columnas a partir de la columna E: Sub InsertarRangos4() Dim oHojaActiva As Object oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() 'Insertamos 2 columnas a partir de la columna E oHojaActiva.getColumns().insertByIndex( 4, 2 ) End Sub Nota que ahora usamos el método insertByIndex, que es especifico del conjunto de columnas, por ello primero llamados a getColumns(), el primer argumento de este método es el índice de la columna donde comenzara la inserción y el segundo es el número de columnas que deseamos insertar. El método para insertar filas es exactamente igual, excepto por que lo llamamos desde el conjunto de filas (getRows) como en: Sub InsertarRangos5() Dim oHojaActiva As Object oHojaActiva = ThisComponent.getCurrentController().getActiveSheet() 'Insertamos 5 filas a partir de la fila 3 oHojaActiva.getRows().insertByIndex( 2, 5 ) End Sub Para terminar este tema, recuerda que no puedes desplazar celdas fuera del rango de la hoja de calculo, por lo que tienes que evaluar que tengas suficiente espacio para la inserción, de lo contrario, te dará un error en tiempo de ejecución. 6.3.3 Eliminando rangos Eliminar rangos, es la operación inversa a insertarlos, en este caso, tenemos que decidir que hacer con las celdas adyacentes al rango, es decir, como se desplazarán, en nuestro primer ejemplo, movemos las celdas hacia arriba: Hoja.removeRange( Celdas As CellRangeAddress, Modo As CellDeleteMode) CellDeleteMode.table.star.CellDeleteMode. 4 + 32.getCurrentController().3 Manipulando rangos Sub BorrarRangos1() Dim oHojaActiva As Object Dim oSel As Object oHojaActiva = ThisComponent.CellRangeAddress" ) 'Establecemos el rango E8:F21 oRango = oHojaActiva.getActiveSheet() oSel = ThisComponent.getRangeAddress.CellDeleteMode.star.COLUMNS 1 2 3 4 Valor Podemos borrar columnas completas.CellDeleteMode. en el siguiente ejemplo usamos el valor de la constante en vez de esta.star. es casi una regla que lo hagas.sun.sheet.removeRange( oSel.sun.star.LEFT com.star.sun. después de confirmar la eliminación: Sub Dim Dim Dim BorrarRangos2() oHojaActiva As Object oRango As Object iRes As Integer oHojaActiva = ThisComponent. es una buena practica de programación que confirmes esta acción con el usuario.getActiveSheet() oRango = CreateUnoStruct( "com.getActiveSheet() .sun.sun.sheet.CellDeleteMode.sun. com.getCurrentController().CellDeleteMode. En el siguiente ejemplo.sheet. ya no pedimos confirmación. Constante com. com. "Borrar rango" ) 'Solo borramos si el usuario respondio SI If iRes = 6 Then 'Borramos el rango y movemos las celdas hacia la izquierda oHojaActiva. con aquellas acciones que no es posible deshacer.sheet.getRangeAddress().removeRange( oRango. así como sus valores que puedes usar en vez de ellas.sun.204 6.star.star.sheet. pero te recomiendo siempre hacerla.getCurrentSelection() 'Borramos la selección actual y movemos las celdas hacia arriba oHojaActiva.sheet. desplazamos hacia la izquierda.UP ) End Sub Cuando se hace cualquier operación de borrado o eliminación.LEFT ) End If End Sub En la siguiente tabla puedes ver las posibilidades de este método. Sub Dim Dim Dim BorrarRangos3() oHojaActiva As Object oRango As Object iRes As Integer oHojaActiva = ThisComponent.UP com. sobre todo.getCellRangeByName( "E8:F21" ) 'Confirmamos la eliminacion iRes = MsgBox( "Estas seguro de borrar el rango".ROWS com.getCurrentController(). getCurrentController(). veamos como: Sub BorrarRangos4() Dim oHojaActiva As Object oHojaActiva = ThisComponent.copyRange( oDestino. 4 ) End Sub Al igual que con la inserción. ¿verdad? Hoja. para la eliminación de filas y columnas completas.getRangeAddress.removeByIndex( 9.removeByIndex( 0.getActiveSheet() 'Borramos 3 filas a partir de la fila 10 oHojaActiva. claro.removeRange( oRango.getActiveSheet() 'Rango a copiar oOrigen = oHojaActiva.copyRange( Destino As CellAddress. pero como ya sabes implementarla. 3 ) 'Borramos 2 columnas a partir de la A oHojaActiva. al igual que cuando movemos. se cuenta con métodos alternativos accesibles desde el conjunto de filas (getRows) y columnas (getColumns).getRangeAddress() ) End Sub .table.CellRangeAddress" ) 'Establecemos el rango B2:D2 oRango = oHojaActiva.Aprendiendo OOo Basic 205 oRango = CreateUnoStruct( "com.getCellRangeByName( "A1:B3" ) 'Celda destino oDestino = oHojaActiva. Origen As CellRangeAddress) Sub Dim Dim Dim CopiarRangos1() oHojaActiva As Object oOrigen As Object oDestino As Object oHojaActiva = ThisComponent.3.getCellRangeByName( "D10" ) 'Copiamos el rango oHojaActiva.4 Copiando rangos Copiar rangos es muy similar a moverlos. un rango origen y una celda destino. cambia el método usado.getCurrentController().getCellRangeByName( "B2:D2" ) 'Borramos las columnas completas oHojaActiva. oOrigen.getColumns().getRows(). 2 ) End Sub No se te olvide siempre confirmar las eliminaciones.star. 6. no tienes problemas con ello. se usan los mismos argumentos.getCellAddress().sun. el destino será reemplazado con el origen sin ningún tipo de confirmación. las referencias relativas se ajustarán automáticamente a la nueva posición.EndRow + 1 ) oHojaActiva. oOrigen.getCurrentSelection() oDestino = oHojaActiva.getByIndex( 0 ) 'Rango a copiar oOrigen = oHojaOrigen.getCellAddress().getSheets().getCellRangeByName( "B2:D5" ) 'Celda destino oDestino = oHojaDestino.getRangeAddress() ) ThisComponent.getSheets(). copiamos el rango B2:D5 de la ultima hoja del documento a la celda A1 de la primera: Sub Dim Dim Dim Dim ) oHojaDestino = ThisComponent.copyRange( oDestino.getSheets().EndColumn + 1.getCurrentController().getByIndex( 1 ) oDestino = oHojaDestino.getRangeAddress() ) ThisComponent.getCellByPosition( oOrigen.getCellRangeByName( "A1" ) 'Copiamos el rango oHojaDestino. oOrigen.getRangeAddress(). oOrigen.getCount() .3 Manipulando rangos A diferencia de cuando movemos.getCurrentController().select( oOrigen ) End Sub Para copiar en una hoja diferente.getSheets(). además de que el rango origen permanece con la referencia original: Sub Dim Dim Dim CopiarRangos2() oHojaActiva As Object oOrigen As Object oDestino As Object oHojaActiva = ThisComponent.getColumns().getByIndex( 1 ) 'Segunda Hoja oHojaDestino = ThisComponent.getActiveSheet() oOrigen = ThisComponent.copyRange( oDestino. el siguiente ejemplo.getCellAddress().206 6. solo tienes que establecer el destino correctamente en dicha hoja. si el rango contiene formulas.getRangeAddress().1 Puedes copiar columnas o filas completas: Sub Dim Dim Dim Dim CopiarRangos4() oHojaOrigen As Object oHojaDestino As Object oOrigen As Object oDestino As Object 'Primer hoja oHojaOrigen = ThisComponent.getCellRangeByName( "E1" ) .select( oDestino ) End Sub CopiarRangos3() oHojaOrigen As Object oHojaDestino As Object oOrigen As Object oDestino As Object oHojaOrigen = ThisComponent.getSheets().getByIndex( 0 ) 'Rango a copiar columna B oOrigen = oHojaOrigen. el origen permanece tal cual y aquí si.getByIndex( ThisComponent.getCurrentController(). oRangoOrigen ) Next co1 'Seleccionamos la nueva hoja con los datos copiados ThisComponent.getCurrentController.getSpreadSheet. contendrá aun. claro.select( oDestino ) End Sub Hagamos algo muy interesante. solo con fines didácticos puesto que estamos aprendiendo: Sub Dim Dim Dim Dim Dim Dim Dim Dim Dim CopiarSoloVisibles1() oSel As Object oCursor As Object oVisibles As Object oHojaOrigen As Object oHojaDestino As Object oRangoOrigen As Object oCeldaDestino As New com.StartColumn oCeldaDestino.queryVisibleCells() ElseIf oSel. oHojaOrigen ) 'Obtenemos una matriz con las direcciones de todos los rangos mDir = oVisibles. Antes de que sigas leyendo.getImplementationName() = "ScCellRangesObj" Then oVisibles = oSel End If 'si no hay celdas visibles If IsNull( oVisibles ) Then MsgBox "No hay celdas ocultas" Else 'Agregamos una nueva hoja oHojaDestino = getNuevaHoja( ThisComponent.getRangeAddress.sun.Row = oRangoOrigen.Sheet = oHojaDestino. ¿te parece?.createCursorByRange( oSel ) oCursor.getActiveSheet() 'Referencia a la selección actual oSel = ThisComponent.table.copyRange( oCeldaDestino.Aprendiendo OOo Basic 207 oHojaDestino.getCurrentController.getRangeAddresses() 'Iteramos en cada dirección For co1 = LBound(mDir) To UBound(mDir) oRangoOrigen = mDir( co1 ) 'La celda destino tendra la misma dirección del rango pero en la hoja destino oCeldaDestino.getRangeAddress() ) ThisComponent.setActiveSheet( oHojaDestino ) MsgBox "Rangos copiados" End If End Sub .Column = oRangoOrigen.getCellAddress().copyRange( oDestino.CellAddress co1 As Long mDir oHojaOrigen = ThisComponent.Sheet oCeldaDestino. después checa mi versión y compáralas.star.collapseToCurrentRegion() 'Y las celdas visibles oVisibles = oCursor. cuando copiamos un rango de celdas y este rango tiene filas o columnas ocultas manualmente o por estar agrupadas.getImplementationName() = "ScCellObj" Then oCursor = oSel. te invito a que intentes resolverlo por ti mismo primero. la copia resultante. podemos intentar hacer nuestra versión de una herramienta que llamaremos “Copiar solo visibles”.getCurrentController().StartRow 'Copiamos el rango oHojaDestino. con el método para seleccionar solo las celdas visibles (queryVisibleCells) aprendido en el capitulo anterior y el método para copiar rangos.getcurrentSelection() 'Si es una sola celda regresamos la región actual If oSel. oOrigen. las filas y columnas ocultas. como sabemos. copyRange( oCeldaDestino.StartColumn = oRangoOrigen.getRangeAddresses() 'Copiamos el primer rango oRangoOrigen = mDir( 0 ) oCeldaDestino. Vamos a mejorarla.Sheet 'En la celda A1 oCeldaDestino. Hoja.Row = 0 oHojaDestino.createCursorByRange( oSel ) oCursor. Col As Long mDir oHojaOrigen = ThisComponent.getActiveSheet() oSel = ThisComponent. "ScCellRangesObj" oVisibles = oSel.3 Manipulando rangos 'Devuelve una nueva hoja en Documento.StartColumn Then .getSheets() sNombre = "Rangos Copiados" Do While oHojas.queryVisibleCells() Case "ScCellRangeObj".getSpreadSheet. oRangoOrigen ) 'Si tenemos más rangos If oVisibles. claro. a la derecha del argumento Hoja Function getNuevaHoja( Documento As Object. intenta corregirla tu y después continuas: Sub Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim CopiarSoloVisibles2() oSel As Object oCursor As Object oVisibles As Object oHojaOrigen As Object oHojaDestino As Object oRangoOrigen As Object oRangoAnterior As Object oCeldaDestino As New com.208 6. solo cuando cambien If oRangoAnterior.getImplementationName Case "ScCellObj" oCursor = oSel.getRangeAddress. Hoja As Object ) As Object Dim oHojas As Object Dim co1 As Integer Dim sNombre As String oHojas = Documento. de nuevo.getCount() > 1 then For co1 = 1 To UBound(mDir) oRangoOrigen = mDir( co1 ) oRangoAnterior = mDir( co1-1 ) 'Vamos sumando cada ancho y alto de cada rango. Fil As Long.star.CellAddress co1 As Long. oHojaOrigen ) mDir = oVisibles.getcurrentSelection() Select Case oSel.Sheet = oHojaDestino. no es nada practico que use la misma dirección del origen en el destino pues los datos quedan todos dispersos.Sheet+1 ) getNuevaHoja = Documento.queryVisibleCells() End Select If IsNull( oVisibles ) Then MsgBox "No hay celdas ocultas o no es un rango de celdas" Else Fil = 0 Col = 0 oHojaDestino = getNuevaHoja( ThisComponent.sun.getByName( sNombre ) End Function Seguro que ya viste que no trabaja muy bien que digamos.table.insertNewByName( sNombre.getRangeAddress.hasByName( sNombre ) co1 = co1 + 1 sNombre = sNombre & " " & Format(co1) Loop oHojas.getCurrentController.collapseToCurrentRegion() oVisibles = oCursor.getSheets.Column = 0 oCeldaDestino. todavía tiene un “pequeño” detalle. oRangoOrigen ) Next co1 End If ThisComponent. tal y como se ve en la interfaz del usuario. pero.4. 6.Column = Col + oRangoAnterior. puedes considerar evaluarlo o dejarla así. te mostrara el resultado de dicha formula y si es fecha y tiene formato.Column End If oHojaDestino. es decir.setActiveSheet( oHojaDestino ) End If End Sub Ahora si.EndRow oRangoAnterior.Row + oRangoAnterior. donde veremos con empezar a interactuar con las celdas de nuestra hoja de calculo.EndColumn oRangoAnterior. trabaja mucho mejor.getCurrentController.1 Obteniendo datos La forma más simple y directa de obtener el contenido de una celda. y digo que es un detalle por que no te dará ningún error y seguirá funcionando.copyRange( oCeldaDestino.4 Manipulando datos Ya vamos llegando a temas más interesantes y divertidos. También. podrías mejorar esta macro para que copie solo datos o resultados de formulas. que te devuelve el contenido de la celda. si el contenido de la celda es texto. tienes que tener presente los diferentes tipos de datos que soporta Calc.Aprendiendo OOo Basic 209 oCeldaDestino.getImplementationName() = "ScCellObj" Then 'Mostramos el contenido de la celda MsgBox oSel.StartColumn + 1 oCeldaDestino. Para el mejor aprovechamiento de este capitulo.Row = Fil Col = oCeldaDestino. esto lo podrás hacer cuando adquieras los conocimientos del próximo capitulo. te la devolverá como se ve en pantalla: Sub Datos1() Dim oSel As Object oSel = ThisComponent.getString() Else MsgBox "Selecciona solo una celda" End If . hay un caso particular donde el rango no contenga celdas ocultas y nuestra macro no lo informe. tu tarea es encontrar este caso particular. es usando el método getString.getCurrentSelection() If oSel. te lo muestra tal cual. pero eso si. si contiene una formula. 6.Row = oCeldaDestino.StartRow + 1 Else oCeldaDestino. entonces usa la propiedad FormulaLocal. este método te devolverá el nombre de esta función en ingles. dicho valor. si la celda contiene una fecha.4 Manipulando datos Si lo que deseas es devolver el valor de la celda.getCurrentSelection() If oSel. VLOOKUP. si la celda contiene una formula. si tiene un valor. este método te devolverá 0. BUSCARV. como SUMA. si es un valor. dependerá del tipo de resultado de esta formula. donde te las devuelve como aparecen en la barra de formulas. como en: Sub Datos4() Dim oSel As Object oSel = ThisComponent. se usa el método getValue. excepto en las formulas. te devuelve dicha formula. si la celda contiene texto. también. si es un valor. que se comporta de forma muy similar a getString.getImplementationName() = "ScCellObj" Then 'Mostramos el valor de la celda MsgBox oSel. si la celda contiene texto. si tiene un error de nuevo será 0.getImplementationName() = "ScCellObj" Then 'Mostramos la formula local de la celda MsgBox oSel. Sub Datos3() Dim oSel As Object oSel = ThisComponent.getCurrentSelection() If oSel. toma en cuenta que si la formula devuelta contiene alguna función incorporada de Calc.getImplementationName() = "ScCellObj" Then 'Mostramos la formula de la celda MsgBox oSel. ese valor. te devolverá este texto. incluyendo el signo de igual (=) con que empieza toda formula aun y cuando la formula tenga como resultado un erro. si es texto de nuevo te devolverá 0.getCurrentSelection() If oSel.FormulaLocal Else MsgBox "Selecciona solo una celda" End If . SUM.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. te devolverá el número de serie de esta fecha: Sub Datos2() Dim oSel As Object oSel = ThisComponent.210 End Sub 6. etc.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. este valor. de una fecha te devuelve el número de serie y si es formula. etc. si la celda no contiene una formula. texto (2) o formula (3).getImplementationName() = "ScCellObj" Then 'Mostramos las diferencias entre los metodos sTmp = "getString : " & oSel. Sub Datos5() Dim oSel As Object Dim sTmp As String oSel = ThisComponent.getError() End Sub El error división entre cero.getCurrentSelection() MsgBox oSel. texto.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. captura valores en varias celdas.Aprendiendo OOo Basic End Sub 211 Si quieres ver las diferencias. que te devolverá un entero dependiendo del contenido de la celda. números. Sub Datos7() Dim oSel As Object oSel = ThisComponent. en una de las formulas usa la función =ALEATORIO().getCurrentSelection() If oSel.getType() End Sub Si la celda contiene una formula y esta devuelve un error. Podríamos aventurar una primera forma de usar el método correcto. veras claramente las diferencias entres estos métodos. este método solo esta disponible es una sola celda: Sub Datos6() Dim oSel As Object oSel = ThisComponent. también puedes probar con el error de cuando a una formula le faltan argumentos. de nuevo. valor (1).getCurrentSelection() MsgBox oSel. toma en cuenta que estos métodos solo los puedes usar en celdas individuales. de acuerdo al contenido de la celda: Sub Datos8() Dim oSel As Object oSel = ThisComponent. y prueba la siguiente macro.getValue & Chr(13) sTmp = sTmp & "getFormula : " & oSel. devuelve el error 532.getFormula & Chr(13) sTmp = sTmp & "FormulaLocal : " & oSel. fechas y formulas.getString & Chr(13) sTmp = sTmp & "getValue : " & oSel. puedes saber que error es con el método getError. establece este error en una formula cualquiera para que lo compruebes. normalmente da el error 511. este método siempre te devolverá 0. vacía (0). por ello hacemos la validación.getCurrentSelection() . col As Long oSel = ThisComponent.212 Select Case oSel.getValue() Case 2 MsgBox oSel.getString() Case 3 If Celda.getError() End If End Select ContenidoCelda = tmp End Function Toma en cuenta que una celda te puede devolver 532 y estar correcto.getError() = 0 Then tmp = Celda. seguir siendo correcto.getError() End If End Select End Sub 6. así que no tomes la función anterior como definitiva.getError() = 0 Then MsgBox oSel. 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.4 Manipulando datos Y si se convierte en función: Function ContenidoCelda(Celda As Object) Dim tmp Select Case Celda. sino tan solo como una guía para lo que realmente necesites.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.getString() Case 3 If oSel.getCurrentSelection() Select Case oSel.FormulaLocal Else tmp = Celda.getValue() Case 2 : tmp = Celda. Ahora solo nos resta poder llamarla desde la celda: Sub Datos9() Dim oSel As Object oSel = ThisComponent.getImplementationName() Case "ScCellObj" MsgBox ContenidoCelda ( oSel ) Case "ScCellRangeObj" .FormulaLocal Else MsgBox oSel.getType() Case 0 MsgBox "La celda esta vacia" Case 1 MsgBox oSel.getType() Case 0 : tmp = "La celda esta vacia" Case 1 : tmp = Celda. procura seleccionar un rango pequeño por que te mostrará el valor de cada celda: Sub Dim Dim Dim Dim Datos11() oSel As Object mDatos mTmp co1 As Long.1 For col = 0 To oSel.getCount() . obtiene una referencia a una sola celda. te queda de tarea. usaremos el método getData. en las celdas vacías devuelve un valor un tanto “extraño”.1 MsgBox ContenidoCelda ( oSel.getImplementationName() = "ScCellRangeObj" Then 'Obtenemos todo los datos mDatos = oSel. pero cuidado.Aprendiendo OOo Basic 213 For fil = 0 To oSel. co2 As Long oSel = ThisComponent.getCellByPosition(col. te doy dos pistas. además. los métodos usados solo funcionan cuando hacemos referencia a una sola celda.getCurrentSelection() If oSel. es en “referencia” a la selección original. co2 As Long oSel = ThisComponent.getCount() .getRows().getDataArray() For co1 = LBound(mDatos) to UBound(mDatos) mTmp = mDatos(co1) For co2 = LBound(mTmp) to UBound(mTmp) MsgBox mTmp(co2) .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 Si quieres obtener el contenido sea cual sea. usa getDataArray como en: Sub Dim Dim Dim Dim Datos12() oSel As Object mDatos mTmp co1 As Long. usa el mismo método (getCellByPosition). pero en vez de usar getData. que te devuelve una matriz de matrices con el contenido de las celdas. si quieres obtener el contenido de un rango de celdas. En todos lo casos anteriores. getData solo te devuelve las celdas con valores.getImplementationName() = "ScCellRangeObj" Then 'Obtenemos SOLO VALORES mDatos = oSel. puedes verificarlo con el siguiente ejemplo. pero toma como base de información para los ciclos.getColumns().fil) ) Next col Next fil End Select End Sub Toma en cuenta que getCellByPosition. la que te devuelve el método getRangeAddress. usa la misma estructura. obtener lo mismo pero con relación a la hoja completa. y esta.getCurrentSelection() If oSel. 214 Next Next End If End Sub 6. Sub Introducir1() Dim oSel As Object oSel = ThisComponent.4. 6.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.4 Manipulando datos Y si lo que quieres es el contenido de las celdas. co2 As Long oSel = ThisComponent. Para el caso de cadenas de texto.getImplementationName() = "ScCellObj" Then 'Insertamos una cadena en la celda oSel. toma en cuenta que este método reemplazará el contenido de la celda sin preguntarte nada. del mismo modo que setString. son más o menos los mismos que para obtenerlos.getImplementationName() = "ScCellRangeObj" Then 'Obtenemos todo los datos como si se usara getFormula pero en todo el rango mDatos = oSel.getCurrentSelection() If oSel. pero en vez de obtenerlos (get) los establecemos (set). usamos setString. veamos ahora como introducir información. puedes acceder a cualquier información de una celda o un rango de celdas. simplemente reemplazará el contenido de la celda sin consultarte. usas getFormulaArray: Sub Dim Dim Dim Dim Datos13() oSel As Object mDatos mTmp co1 As Long. como si hubieses usado en cada una el método getFormula.getCurrentSelection() If oSel.getFormulaArray() For co1 = LBound(mDatos) to UBound(mDatos) mTmp = mDatos(co1) For co2 = LBound(mTmp) to UBound(mTmp) MsgBox mTmp(co2) Next Next End If End Sub De la combinación de los métodos vistos en este tema. .2 Introduciendo datos Los métodos para introducir datos en celdas. getCurrentSelection() If oSel.Aprendiendo OOo Basic Sub Introducir2() Dim oSel As Object 215 oSel = ThisComponent.setFormula( "=A1+A5" ) Else MsgBox "Selecciona solo una celda" End If End Sub Si introduces una formula no válida. los argumentos deben estar correctamente establecidos.getImplementationName() = "ScCellObj" Then 'Insertamos una formula oSel. como en el siguiente ejemplo: Sub Introducir4() Dim oSel As Object oSel = ThisComponent.getCurrentSelection() If oSel. así como los tipos de estos para que no te devuelva ningún error. Sub Introducir5() Dim oSel As Object oSel = ThisComponent. este método no te dará ningún error.setFormula( "=SUM(A1:A10)" ) End If End Sub . tienes que usar el nombre en ingles de la función a usar. para las formulas podemos usar setFormula. la formula debe estar como una cadena de texto y debe ser una formula válida. pero si lo obtendrás en la interfaz del usuario.org.getImplementationName() = "ScCellObj" Then 'Insertamos una formula con funcion oSel.getImplementationName() = "ScCellObj" Then 'Insertamos una formula no valida oSel. también.setValue( 34 ) Else MsgBox "Selecciona solo una celda" End If End Sub Ya lo habrás intuido.getImplementationName() = "ScCellObj" Then 'Insertamos un valor en la celda oSel.getCurrentSelection() If oSel.getCurrentSelection() If oSel.setFormula( "=C2-C3+" ) End If End Sub Si hace uso de funciones incorporadas de OpenOffice. Sub Introducir3() Dim oSel As Object oSel = ThisComponent. de lo contrario te dará un error en tiempo de ejecución.14. Cuando queramos introducir valores en rangos de celdas.FormulaLocal = "=SUMA(A1:A10)" End If End Sub En el Apendice C.getActiveSheet() 'El rango donde se insertaran los valores.getCurrentController().getCurrentSelection() If oSel. si la matriz lleva alguna cadena de texto.3) Array(4. "debe" 'ser del mismo tamaño en ancho y alto de la matriz oRango = oHojaActiva. Sub Dim Dim Dim Introducir7() oHojaActiva As Object oRango As Object mDatos(4) mDatos(0) mDatos(1) mDatos(2) mDatos(3) mDatos(4) = = = = = Array(1.11. el siguiente ejemplo hace lo mismo que el anterior: Sub Introducir6() Dim oSel As Object oSel = ThisComponent.setDataArray( mDatos ) . así. hay que tener la precaución de establecer el rango destino.4 Manipulando datos Si prefieres usar los nombres de las funciones en español.216 6. “exactamente” del mismo ancho y alto de la matriz origen.8.getCellRangeByName("A1:C5") 'Insertamos la matriz completa oRango.getActiveSheet() 'El rango donde se insertaran los valores.getCurrentController()."Gloria".34567891) Array(4."Nombre". te muestro una lista de equivalencias de las 375 formulas que incorpora Calc.9) Array(10.6) Array(7. para valores y cadenas.23456789) Array(3.getCellRangeByName("A1:C5") 'Insertamos la matriz completa oRango.12) Array(13. "debe" 'ser del mismo tamaño en ancho y alto de la matriz oRango = oHojaActiva."Tel") Array(1."Lizette". usa la propiedad FormulaLocal."Paola".setData( mDatos ) End Sub También.5. puedes usar el método que quieras.getImplementationName() = "ScCellObj" Then 'Insertamos una formula con función oSel.87654321) oHojaActiva = ThisComponent. toma nota de que con el método setData."Lidia". este método la reemplazara por 0. entre español e ingles. debes usar setDataArray: Sub Dim Dim Dim Introducir8() oHojaActiva As Object oRango As Object mDatos(4) mDatos(0) mDatos(1) mDatos(2) mDatos(3) mDatos(4) = = = = = Array("No". en vez de este método.15) oHojaActiva = ThisComponent.12345678) Array(1. solo puedes introducir valores.2. getActiveSheet() oRango = oHojaActiva. por ejemplo valores (1). En el siguiente ejemplo."=SUM(A2:A4)") Array(4. de tres rangos diferentes.getCellRangeByName("G1:K100") 'Borramos solo las formulas oRango.getCellRangeByName("A1:C5") 'Borramos solo los valores oRango. textos y formulas."Nombre". se borran solo las celdas con valores.3 Borrando datos Para borrar datos de celdas usamos el método clearContents."Lizette"."=A3") Array(3.getActiveSheet() oRango = oHojaActiva.Aprendiendo OOo Basic 217 End Sub Si tus datos a introducir incluyen formulas.clearContents( 4 ) oRango = oHojaActiva."Tel") Array(1. este método requiere un entero indicándole el tipo de contenido que deseamos borrar.setFormulaArray( mDatos ) End Sub 6."=RAND()") oHojaActiva = ThisComponent.getCurrentController(). este método esta presente en los tres tipos de rangos vistos.getCellRangeByName("D2:E10") 'Borramos solo los texto oRango."Lidia". por lo que solo tienes que asegurarte que efectivamente sea un rango de celdas.clearContents( 16 ) End Sub Puedes sumar los valores de los tipos a borrar."Paola"."Gloria". textos (4) o formulas (16)."=RAND()") Array(1.getCurrentController(). en el siguiente ejemplo. es mejor que uses setFormulaArray: Sub Dim Dim Dim Introducir9() oHojaActiva As Object oRango As Object mDatos(4) mDatos(0) mDatos(1) mDatos(2) mDatos(3) mDatos(4) = = = = = Array("No". se borra los textos y las formulas del rango seleccionado: Sub Borrando2() Dim oSel As Object oSel = ThisComponent.clearContents( 1 ) oRango = oHojaActiva.getCurrentSelection() .4. Sub Borrando1() Dim oHojaActiva As Object Dim oRango As Object oHojaActiva = ThisComponent.getCellRangeByName("A1:C5") 'Insertamos la matriz completa oRango. CellFlags.star. en general la forma automática funcionara.CellFlags.HARDATTR com.star.4 Manipulando datos 'Borramos los textos (4) + formulas (16) oSel.FORMULA com.sheet.star.sun.218 6.4 Llenando series de datos Llenar series es un método muy divertido de introducir datos en nuestra hoja de calculo.sheet. en la celda A1 tenemos solo un valor y en la columna C como queremos que quede nuestra serie.getCurrentSelection() 'Borramos todo oSel. Sub Borrando3() Dim oSel As Object oSel = ThisComponent.sheet.sheet.CellFlags.star.star.sheet.CellFlags.sun.DATETIME com.clearContents( 1023 ) End Sub 6.4.star.star.star.sun.sun. te deja la selección como nueva. cuyos valores se listan en la siguiente tabla: Constante com.OBJECT com.sun.CellFlags.sheet.sun. observa la siguiente imagen.CellFlags.CellFlags.sun.star.star. El siguiente ejemplo borra “todo”. .STRING com.sun.clearContents( 20 ) End Sub Los valores permitidos para este método. existen dos formas de hacerlo.CellFlags.sheet. si se establecen correctamente los valores iniciales.sun.CellFlags.sheet.star.sheet.EDITATTR com.STYLES com.FORMATTED Valor 1 2 4 8 16 32 64 128 256 512 Puedes usar de forma indistinta las constantes o los valores de estas.sheet.CellFlags.sun.sheet.CellFlags.ANNOTATION com. están condicionados por las constantes del grupo com.VALUE com.sun. así como cualquier combinación de estas. TO_LEFT Si quisiéramos llenar el rango con números pares.sun.getActiveSheet() oRango = oHojaActiva.sheet. lo haríamos así: Sub LlenandoSeries2() Dim oHojaActiva As Object Dim oRango As Object oHojaActiva = ThisComponent.getCellRangeByName("A1:A15") 'Establecemos los valores guias oHojaActiva. Constante com.star. el primero es para indicarle la dirección del llenado en nuestro ejemplo.getCellRangeByName("A2").TO_TOP com.getActiveSheet() oRango = oHojaActiva. cuantas celdas del rango tomara como “guías” para determinar el algoritmo de llenado.getCurrentController().sun.Aprendiendo OOo Basic 219 El código para lograr esto es el siguiente. 1 ) End Sub El método fillAuto. En la siguiente tabla están las cuatro posibilidades del argumento “dirección” de este método.fillAuto( 0.setValue( 4 ) 'Llenamos hacia abajo.FillDirection.star. abajo (TO_BOTTOM = 0) y un entero que le indica.getCellRangeByName("A1:A15") 'Llenamos hacia abajo oRango.getCellRangeByName("A1").FillDirection. solo requiere dos argumentos. observa que sencillo: Sub LlenandoSeries1() Dim oHojaActiva As Object Dim oRango As Object oHojaActiva = ThisComponent.setValue( 2 ) oHojaActiva.TO_BOTTOM com.star.sheet.getCurrentController().FillDirection.FillDirection. nota que ahora tomamos dos celdas como guias Valor 0 1 2 3 .sun.sheet.star.sheet.sun.TO_RIGHT com. setString( "enero" ) 'Llenamos a la derecha oRango.getCellRangeByName("A1").org Calc.getActiveSheet() oRango = oHojaActiva.getActiveSheet() oRango = oHojaActiva. dentro de la rama OpenOffice. subrama Ordenar listas. 2 ) End Sub 6. el siguiente código establece el rango A1:L1 con los meses del año. las puedes personalizar en el menú Herramientas | Opciones. esta y otras listas. observa que los datos terminan en la fila 1001 pero eso no importa.fillAuto( 1.getCellRangeByName("A1:L1") 'Establecemos el valor guia oHojaActiva.getCurrentController().getCurrentController().220 oRango. 1 ) End Sub Esto es posible por que esta lista viene de forma predeterminada en OpenOffice.fillAuto( 0. pueden terminar en la 1000 o la que sea pues esto lo determinaremos por código.. de la siguiente forma: Sub Dim Dim Dim LlenandoSeries4() oHojaActiva As Object oRango As Object oCursor As Object oHojaActiva = ThisComponent. solo restando el año actual de la de nacimiento..4 Manipulando datos Por supuesto no solo con números es posible. Sub LlenandoSeries3() Dim oHojaActiva As Object Dim oRango As Object oHojaActiva = ThisComponent. para fines didácticos daremos por buena la edad. es en la forma transparente de copiar o llenar un rango con una formula deseada. observa la siguiente imagen El fin es establecer la formula para calcular la edad de cada persona..org.getCellRangeByName("A1") . Donde más me gusta el llenado de series. por ejemplo. fillAuto( 0.getCellRangeByName("D2"). no es restrictiva. nos limitaremos a las opciones más comunes y generales.Aprendiendo OOo Basic 221 'Establecemos la primer formula oHojaActiva. después. si bien tiene tantas variantes como las que puedes ver en..getCellRangeByName( "D2:D" & CStr(oCursor. Editar | Buscar y reemplazar. nuestra formula de ejemplo quedaría así: oHojaActiva. puedes usar la que gustes.getCount()) ) 'Llenamos hacia abajo oRango.org es una herramienta muy poderosa.getRows().collapseToCurrentRegion() 'Construimos el rango a llenar oRango = oHojaActiva. pero esta pequeña nos permite comprobar rápidamente los resultados para comprobar que funciona correctamente. 6. entre español e ingles. así puedes usar el método que quieras.setFormula( "=YEAR(NOW())-C2" ) 'Creamos un cursor a partir de la primer celda oCursor = oHojaActiva. quedándote de tarea la investigación del resto. llenamos todo el rango.getCount(). puedes usar también la propiedades FormulaLocal. te muestro una lista de equivalencias de las 375 formulas que incorpora Calc..FormulaLocal = "=AÑO(AHORA())-C2" Observa como obtenemos la ultima fila del rango usado con la ayuda del cursor y el método oCursor. 1 ) End Sub Para establecer la formula.5 Buscar y reemplazar La búsqueda y reemplazo en OpenOffice. En el Apendice C. que. puedes usar listados del tamaño que quieras y los recursos de tu equipo te lo permitan: Nº 1 2 3 4 5 6 7 8 9 10 11 12 Nombre edgar gloria antonio lidia paola vanessa lizette edgar gloria antonio lidia paola Año 1975 1976 1965 1966 1974 1976 1975 1969 1971 1969 1973 1975 Edad 33 32 43 42 34 32 33 39 37 39 35 33 . y con una sola línea más.4.createCursorByRange( oRango ) 'Expandimos a la region actual oCursor.getRows().. Usaremos para nuestras pruebas la siguiente tabla de datos. como ya lo vimos.getCellRangeByName("D2"). setSearchString( "33" ) 'Realizamos la busqueda de TODAS las coincidencias oEncontrado = oBuscarEn.setSearchString( "a" ).getActiveSheet() 'Establecemos el rango donde buscaremos oBuscarEn = oHojaActiva.4 Manipulando datos En las búsquedas. que es el rango donde queremos hacer la búsqueda. por supuesto puedes buscar en toda la hoja.getCurrentController. . la respuesta es que la búsqueda predeterminada se hace buscando dentro de las formulas.createSearchDescriptor 'Establecemos lo que estamos buscando oSD.getCurrentController().222 13 14 15 16 17 18 vanessa lizette edgar gloria antonio lidia 1975 1967 1975 1965 1967 1980 33 41 33 43 41 28 6.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”. establece el valor buscado en “a” y realiza la búsqueda: oSD. ¿porque. 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. y todos los 33 que ves en la lista son el “resultado” de una formula. dicha formula es: =AÑO(AHORA())-C2. si aparentemente si tenemos valores 33 en nuestros datos?.findAll( oSD ) 'Si no hay coincidencias oEncontrado = Null If Not IsNull( oEncontrado ) Then 'Si encuentra algo lo seleccionamos ThisComponent. la forma más sencilla de una búsqueda es la siguiente: Sub Dim Dim Dim Dim Buscar1() oHojaActiva As Object oBuscarEn As Object oEncontrado As Object oSD As Object oHojaActiva = ThisComponent. incluso en todas las hojas.getCellRangeByName( "A1:D19" ) 'Creamos el descriptor de busqueda oSD = oHojaActiva. ahora. searchType = 1 'Establecemos lo que estamos buscando oSD. la búsqueda predeterminada se hace por formulas. regresemos a nuestro primer ejemplo y agreguemos una propiedad a la búsqueda.1980).ENTRE(1965. ¿verdad?.getCurrentController. la razón es la misma. la búsqueda te devuelve todo. Sub Dim Dim Dim Dim Buscar3() oHojaActiva As Object oBuscarEn As Object oEncontrado As Object oSD As Object oHojaActiva = ThisComponent.select( oEncontrado ) Else MsgBox "No se encontraron coincidencias" End If End Sub . no “dentro” de las formulas. lo que tenemos que hacer es discriminar un poco más con los criterios de búsqueda.getCellRangeByName( "A1:D19" ) 'Creamos el descriptor de busqueda oSD = oHojaActiva. y claro.Aprendiendo OOo Basic 223 Ahora nos pasa al revés.getActiveSheet() oBuscarEn = oHojaActiva. lo cual es correcto. le diremos que busque por valores.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. esto lo logramos con la propiedad: searchType. 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. también tienen la letra “a” entre su texto. para que busque en el “resultado” de las formulas. ahora. por ello. como vez. sino acorde a lo que “estas buscando”.createSearchDescriptor 'Buscamos por valores oSD. devolvemos demasiados resultados.getCurrentController(). no necesariamente tiene que ser más restrictiva. la formula de la columna D ya la vimos y contiene la letra buscada. la búsqueda esta bien. la formula de la columna C es: =ALEATORIO. lo que esperas devolver. createSearchDescriptor oSD.setSearchString( "li" ) y observa el resultado: Nota que las búsquedas las puede hacer en partes del texto.searchWords = True oSD. por que no hay palabras completas que sean “li”. aun.setSearchString( "li" ) oEncontrado = oBuscarEn. prueba a reemplazar la cadena buscada por el nombre que más de guste de los existentes en nuestra lista.select( oEncontrado ) Else MsgBox "No se encontraron coincidencias" End If End Sub La búsqueda anterior te tiene que devolver "No se encontraron coincidencias". Como siguiente prueba.getCurrentController. en el tema Referencia a varios rangos.4 Manipulando datos Mucho mejor ¿verdad?. prueba a establecer la búsqueda con la letra “a” o cualquiera que tu quieras y observa los resultados.224 6. este. ahora si.getCurrentController(). tratamos como manejar este tipo de rangos. formará parte de dicha colección. como en: Sub Dim Dim Dim Dim Buscar3() oHojaActiva As Object oBuscarEn As Object oEncontrado As Object oSD As Object oHojaActiva = ThisComponent. por ejemplo “lizette” y obtendremos: .searchType = 1 'Buscamos por palabras completas oSD.getActiveSheet() oBuscarEn = oHojaActiva.getCellRangeByName( "A1:D19" ) oSD = oHojaActiva. es muy importante que sepas que el resultado es una colección de rangos. pero podemos restringirla a palabras completas con la propiedad searchWords. cuando y solo te devuelva un solo rango.findAll( oSD ) If Not IsNull( oEncontrado ) Then ThisComponent. establece la búsqueda en oSD. solo las celdas con el valor 33 son seleccionadas. setSearchString( "A" ) oEncontrado = oBuscarEn. veamos un ejemplo sencillo y después la explicación. es decir. Sub Dim Dim Dim Reemplazar1() oHojaActiva As Object oBuscarEn As Object lReemplazados As Long . para para reemplazar algo. únicamente te tiene que regresar la celda C1 que contiene la palabra “Año”.getActiveSheet() oBuscarEn = oHojaActiva.Aprendiendo OOo Basic 225 Por que estamos haciendo la búsqueda por palabras completas.getCellRangeByName( "A1:D19" ) oSD = oHojaActiva. puedes realizar búsquedas dentro de las notas de las celdas si estableces la propiedad searchType = 2.createSearchDescriptor oSD. Podemos hacerla aun más restrictiva.searchType = 1 oSD.SearchCaseSensitive = True oSD. si establecemos que distinga entre mayúsculas y minúsculas con la propiedad SearchCaseSensitive de la siguiente manera: Sub Dim Dim Dim Dim Buscar4() oHojaActiva As Object oBuscarEn As Object oEncontrado As Object oSD As Object oHojaActiva = ThisComponent.getCurrentController(). continuamos haciendo uso de nuestra tabla usada en la búsqueda. Incluso.findAll( oSD ) If Not IsNull( oEncontrado ) Then ThisComponent.searchWords = False 'Distinguimos mayusculas de minusculas oSD.getCurrentController. El reemplazo es la continuación de la búsqueda.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. primero se tiene que buscar. En la búsqueda anterior. 4 Manipulando datos Observa que ahora.getActiveSheet() oBuscarEn = oHojaActiva.searchWords = True lReemplazados = oBuscarEn. creamos un descriptor de reemplazo (createReplaceDescriptor). este método (replaceAll) devuelve un entero largo (long) con el número total de reemplazos que tuvieron éxito. en ves de un descriptor de búsqueda (createSearchDescriptor).getCellRangeByName( "A1:D19" ) oRD = oHojaActiva. reemplazaremos palabras completas. con el siguiente código. mi amigo Edgar no me reclamará nada si lo cambio por Nikole.226 Dim oRD As Object oHojaActiva = ThisComponent.setSearchString( "=año" ) 'Reemplazado por oRD.createReplaceDescriptor 'Texto a buscar oRD. establecemos el valor buscado (setSearchString) y el valor por el que se reemplazara (setReplaceString).getCellRangeByName( "A1:D19" ) 'Creamos el descriptor de reemplazo oRD = oHojaActiva.createReplaceDescriptor oRD. como lo podemos comprobar en la siguiente imagen: Ahora.getActiveSheet() oBuscarEn = oHojaActiva. de hecho me felicitará: Sub Dim Dim Dim Dim Reemplazar2() oHojaActiva As Object oBuscarEn As Object lReemplazados As Long oRD As Object oHojaActiva = ThisComponent. teníamos la formula =AÑO(AHORA())-C2.replaceAll( oRD ) If lReemplazados = 0 Then MsgBox "No se encontraron coincidencias" Else MsgBox "Se realizaron " & lReemplazados & " reemplazos" End If End Sub 6. si es cero no encontró coincidencias.setSearchString( "edgar" ) oRD.getCurrentController(). En la columna D de nuestros datos de ejemplo. después de ejecutar la macro anterior. deberíamos tener en esta columna la formula =MES(AHORA())-C2.replaceAll( oRD ) If lReemplazados = 0 Then MsgBox "No se encontraron coincidencias" .getCurrentController().setReplaceString( "nikole" ) 'Le indicamos que busque palabras completas oRD.setReplaceString( "=mes" ) 'El metodo devuelve el numero de reemplazos que tuvieron exito lReemplazados = oBuscarEn. insertNew( oDirCelda.getCount .star. insertamos una nueva nota en la celda E7: Sub Dim Dim Dim Notas1() oHojaActiva As Object oNotas As Object oDirCelda As New com.getCount() End Sub Para mostrar la dirección de cada una de las celdas con notas y su contenido: Sub Dim Dim Dim Dim Notas3() oHojaActiva As Object oNotas As Object oNota As Object co1 As Long oHojaActiva = ThisComponent. 6.1 .4. “casi” puedes estar seguro de que el reemplazo lo estará.6 Trabajando con notas Las notas.getAnnotations() 'Mostramos el total de notas en la hoja MsgBox oNotas.getAnnotations() 'La celda donde insertaremos la nota oDirCelda. es conveniente hacer primero una búsqueda y comprobar que esta correcta para después hacer el reemplazo.getCurrentController.getActiveSheet() 'Obtenemos la colección de notas de la hoja activa oNotas = oHojaActiva.getActiveSheet() oNotas = oHojaActiva.getCurrentController.getActiveSheet() 'Obtenemos la colección de notas de la hoja activa oNotas = oHojaActiva.getAnnotations() If oNotas.sun.getCount() > 0 Then For co1 = 0 To oNotas.Aprendiendo OOo Basic Else 227 MsgBox "Se realizaron " & lReemplazados & " reemplazos" End If End Sub A veces.getCurrentController.CellAddress oHojaActiva = ThisComponent.table. "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. si tus búsquedas están bien establecidas.Row = 6 'Insertamos la nota oNotas. en el siguiente ejemplo. son muy fáciles de manejar.Column = 4 oDirCelda. en las celdas de una hoja de calculo. 4 Manipulando datos 'Obtenemos una nota oNota = oNotas.getCellRangeByName("A1") 'Accedemos a la nota de la celda oNota = oCelda.getActiveSheet() oCelda = oHojaActiva. 4 ) DireccionCelda = oSFA.228 6.getAnnotation If Len( oNota.FunctionAccess" ) 'Construimos la matriz de datos para la función mDatos = Array( DirCelda. DirCelda.getCurrentController.mDatos()) End Function Puedes acceder a una celda primero y después a su nota para modificarla: Sub Dim Dim Dim Notas4() oHojaActiva As Object oCelda As Object oNota As Object oHojaActiva = ThisComponent.getAnnotation 'Le cambiamos su contenido 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: . el cambio no se verá reflejado en la interfaz del usuario.getCellRangeByName("A1") 'Accedemos a la nota de la celda oNota = oCelda.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.Column+1. por lo que tienes que asegurarte que la celda contienen una nota.getActiveSheet() oCelda = oHojaActiva.sheet.getCurrentController.getPosition ) & ": " & oNota.callFunction("ADDRESS".star.getByIndex( co1 ) 'Mostramos su posición y su contenido MsgBox DireccionCelda( oNota.Row+1. puedes usar la longitud del contenido de la nota para saberlo: Sub Dim Dim Dim Notas5() oHojaActiva As Object oCelda As Object oNota As Object oHojaActiva = ThisComponent.sun.setString( "Cambio de texto en nota" ) End Sub Si la celda referenciada no tiene una nota. getAnnotations() If oNotas.Column = oCelda.getPosition.getCurrentController.getCellRangeByName("E7") oNotas = oHojaActiva. tampoco te dará ningún error.setIsVisible( Not oNota.getActiveSheet() oCelda = oHojaActiva.getAnnotation 'La hacemos visible oNota.getByIndex( co1 ) 'Intercambiamos su visibilidad oNota. si esta oculta la muestra y si esta visible la oculta: Sub Dim Dim Dim Dim Notas8() oHojaActiva As Object oNotas As Object oNota As Object co1 As Long oHojaActiva = ThisComponent.getCount . si la celda no tiene nota.setIsVisible( False ) End Sub De nuevo.getActiveSheet() oNotas = oHojaActiva.Row = oCelda.getCount() > 0 Then For co1 = 0 To oNotas. el siguiente ejemplo te intercambia la visibilidad de las notas de la hoja.getActiveSheet() oCelda = oHojaActiva.getCount() > 0 Then For co1 = 0 To oNotas.1 oNota = oNotas. el código anterior no hará nada.getCellAddress.getByIndex( co1 ) 'Comparamos las direcciones If oNota.getPosition.getCurrentController.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 Dim Dim Dim Notas7() oHojaActiva As Object oCelda As Object oNota As Object oHojaActiva = ThisComponent.getCellAddress.getIsVisible ) Next co1 Else MsgBox "No hay notas en esta hoja" End If . es decir.1 oNota = oNotas.getCellRangeByName("E7") oNota = oCelda.getCurrentController.getAnnotations() If oNotas.Aprendiendo OOo Basic Sub Dim Dim Dim Dim Dim Notas6() oHojaActiva As Object oCelda As Object oNotas As Object oNota As Object co1 As Long 229 oHojaActiva = ThisComponent.Column And oNota.getCount . getActiveSheet() oCelda = oHojaActiva.Width = oTam.230 End Sub 6.getSize 'Lo duplicamos oTam.getActiveSheet() oCelda = oHojaActiva.getAnnotations() If oNotas. podemos saber si la nota de la celda es visible (getIsVisible).getCellAddress.setIsVisible( True ) 'Accedemos a la forma oForma = oNota.getCellRangeByName("A1") oNotas = oHojaActiva.getPosition.getCellAddress.Height = oTam.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 Dim Dim Dim Dim Dim Notas10() oHojaActiva As Object oCelda As Object oNota As Object oForma As Object oTam As Object oHojaActiva = ThisComponent.getCellRangeByName("E7") 'Accedemos a la nota oNota = oCelda. con el operador de negación (Not) invertimos este valor y por consiguiente la visibilidad.Column And oNota.getCount() > 0 Then For co1 = 0 To oNotas.getCount .getCurrentController.setSize( oTam ) . esta propiedad nos devuelve falso (False) o verdadero (True) según este o no visible la nota.getPosition.getCurrentController.Row Then 'Borramos la nota por su índice oNotas.1 oNota = oNotas.Height * 2 'Establecemos el nuevo tamaño oForma.4 Manipulando datos Nota como hacemos el intercambio. es preciso saber el índice de esta. por lo que hay que iterar entre el conjunto de notas: Sub Dim Dim Dim Dim Dim Notas9() oHojaActiva As Object oCelda As Object oNotas As Object oNota As Object co1 As Long oHojaActiva = ThisComponent.getAnnotationShape 'Obtenemos el tamaño actual oTam = oForma.getByIndex( co1 ) 'Comparamos las direcciones If oNota.Column = oCelda.getAnnotation 'La hacemos visible oNota.Row = oCelda.Width * 2 oTam. Para borrar una nota. CharFontName = "Liberation Sans" 'Tamaño de letra . pero a veces. en una hoja nueva.5. tipo de fuente. veamos las opciones más comunes de formato por código. es decir.CharUnderline = 1 End With End Sub Para saber la lista completa de fuentes (CharFontName) que tienes disponibles en OpenOffice.CharPosture = 2 'Subrayado .getCurrentSelection() With oSel 'Tipo de letra . En la mayoría de los ejemplos trataremos de trabajar sobre la selección.org.Rnd()*255) End Sub Esta autoforma. pero no se te olvide que siempre es bueno comprobar que estas trabajando en una hoja de calculo. cursiva y oSel = ThisComponent. crea una macro que nos haga un informe. así como en un rango de celdas cuando sea necesario. negritas. de todas las notas existentes en la hoja activa.Aprendiendo OOo Basic 231 'Cambiamos el color de fondo de forma aleatoria oForma. tiene decenas de propiedades para manipularse. usa las macros disponibles en: Listar fuentes en un archivo de Calc . dando formato a los datos se consume una gran cantidad de tiempo y ya sabes. 6. por lo que volveremos a ellas en el capítulo correspondiente a autoformas.FillColor = RGB(Rnd()*255.5 Dando formato No se si estarás de acuerdo conmigo.CharHeight = 20 'Negritas . tienes todos los elementos para manipular las notas de celdas a tu antojo. Por ahora. 6. tamaño. De tarea.Rnd()*255.1 subrayado: Sub FormatoCeldas1() Dim oSel As Object Formato de celdas Primero las características más usuales. ¿vale?. casi siempre.CharWeight = 150 'Cursiva o italica . uno que es bastante flojo esta encantado que se haga de forma automática. nos tiene que devolver la dirección completa y su contenido. sun.DONTKNOW com.star.FontWeight.sun.star.FontWeight.FontSlant.sun.sun.awt.sun.star.star.BLACK Valor 0 50 60 75 90 100 110 150 175 200 Al estilo cursiva o itálica le corresponden las siguiente constantes: Constante com.sun.star.FontSlant.BOLD com.awt.SINGLE com.star.REVERSE_ITALIC El tipo de subrayado esta determinado por las constantes: Constante com.sun.NONE com.FontWeight.star.star.awt.REVERSE_OBLIQUE com. de las cuales.sun.DASH com.FontSlant.awt.star.awt.FontWeight.ITALIC com.star.awt.sun.sun.sun.awt.NONE com.FontWeight.sun.star.FontUnderline.awt.star.5 Dando formato El tamaño de la fuente (CharHeight) se establece en puntos.DONTKNOW com.awt.DOTTED com.FontWeight.sun.FontWeight.FontUnderline.sun.awt. no hay muchas variantes entre ellas: Constante com. excepto los extremos.awt.FontUnderline.awt.DASHDOT Valor 0 1 2 3 4 5 6 7 Valor 0 1 2 3 4 5 .awt.ULTRALIGHT com.awt.FontSlant.sun.DOUBLE com.FontUnderline.awt.OBLIQUE com.awt.star.NORMAL com.awt.LONGDASH com.star.FontSlant.DONTKNOW com.star.FontWeight.sun.sun.LIGHT com.sun.awt.awt.star. El estilo negritas se establece por cualquiera de las siguiente constantes.3528 mm.sun.FontSlant.awt.star.SEMILIGHT com.sun.sun.FontUnderline.FontUnderline.FontUnderline.star.SEMIBOLD com.awt.FontWeight.awt.star. aproximadamente 0.star.FontUnderline.star.sun.sun.232 6.ULTRABOLD com.star.awt.star. recordando que un punto es igual a 1/72 de pulgada.sun.star.FontWeight.THIN com.awt. sun.awt.sun.BOLDDOTTED com.FontUnderline.FontUnderline.star.sun.awt.star.BOLDDASHDOT com.FontUnderline.CharWordMode = True 'Tachado de fuente .CharUnderline = 1 'Color de subrayado rojo .star.FontUnderline.DOUBLEWAVE com.0.awt.WAVE com. el color. Ahora.BOLDWAVE Valor 8 9 10 11 12 13 14 15 16 17 18 Recuerda que puedes usar tanto las constantes como el valor de estas.awt. te deja los espacios entre palabras sin subrayar.sun.CharCrossedOut = True 'Contorno de fuente .star.BOLDLONGDASH com.FontUnderline.getCurrentSelection() With oSel 'Color de la fuente azul .FontUnderline.CharUnderlineColor = RGB(255.BOLDDASH com. establezcamos el color de la fuente y del subrayado de esta: Sub FormatoCeldas3() Dim oSel As Object oSel = ThisComponent.star.awt.BOLDDASHDOTDOT com.awt.Aprendiendo OOo Basic 233 Constante com.awt.star.DASHDOTDOT com.FontUnderline.star.awt.awt.awt.awt.sun.star.0.sun.FontUnderline. Las otras dos propiedades creo que son bastante autoexplicativas.BOLD com.star.CharColor = RGB( 0.sun. Algunos de los valores de estas constantes.star.FontUnderline. los puedes establecer pero no veras ningún efecto aparente.255 ) 'Estilo de subrayado .sun.sun.SMALLWAVE com.FontUnderline. veamos algo muy divertido.star.0. Algunas otras opciones de formato de fuente son: Sub FormatoCeldas2() Dim oSel As Object oSel = ThisComponent.) . según tu gusto y criterio.sun.getCurrentSelection() With oSel 'Espacios sin subrayar .sun.CharContoured = True End With End Sub Cuando se subraya la fuente y la propiedad CharWordMode se establece en verdadera (True).FontUnderline. table.getCellByPosition( col. el color del subrayado será del mismo color que el de la fuente. si esta propiedad se establece en falso (false).getImplementationName = "ScCellRangeObj" Then With oSel For col = 0 To oSel.Rnd()*255. Sub Dim Dim Dim FormatoCeldas4() oSel As Object col As Long fil As Long oSel = ThisComponent.HoriJustify = 2 End Sub Los valores posibles para cada propiedad son: Propiedad VertJustify com.getRows.CellVertJustify.sun. Con la siguiente macro.Rnd()*255) . después el color de este (CharUnderlineColor) y por ultimo establecemos si queremos que se muestre el color (CharUnderlineHasColor). fil ) . establecemos el color de la fuente.getCount . para el subrayado.sun.1 With .STANDARD com.CellVertJustify.Rnd()*255 ) .1 For fil = 0 To oSel.VertJustify = 2 'Alineamos centrado horizontalmente oSel.CharUnderlineHasColor = True End With Next Next End With End If End Sub La alineación del contenido de la celda.CharUnderlineHasColor = True End With End Sub 6.getCurrentSelection() 'Alineamos en medio verticalmente oSel.star.getCurrentSelection() If oSel.star.234 'Si se muestra el color .table.CellVertJustify. primero establecemos el estilo (CharUnderline).CharUnderline = 1 .CENTER Valor 0 1 2 . se establece con las propiedades VertJustify para el sentido vertical y HoriJustify para el sentido horizontal de la siguiente forma: Sub FormatoCeldas5() Dim oSel As Object oSel = ThisComponent.CharUnderlineColor = RGB( Rnd()*255.Rnd()*255. a cada celda del rango seleccionado se le establecerá un color de fuente y de subrayado aleatorio.TOP com.star.getCount .CharColor = RGB( Rnd()*255.5 Dando formato Con la propiedad CharColor y la ayuda de la función RGB.getColumns.table.sun. Orientation = 3 End Sub Los valores para esta propiedad son: . usamos: Sub FormatoCeldas6() Dim oSel As Object oSel = ThisComponent.CellHoriJustify.table.ShrinkToFit =True End Sub Si queremos cambiar la orientación del texto: Sub FormatoCeldas8() Dim oSel As Object oSel = ThisComponent.CellHoriJustify.star.sun.table.CellHoriJustify.BLOCK com.CellHoriJustify.table.CENTER com.CellHoriJustify.REPEAT.LEFT com.sun.table.Aprendiendo OOo Basic 235 Propiedad VertJustify com.STANDARD com.star.sun. prueba a establecer esta propiedad en una celda cuyo contenido sea un punto para que notes su comportamiento.BOTTOM Valor 3 Propiedad HoriJustify com.getCurrentSelection() 'Orientacion vertical del texto oSel.getCurrentSelection() 'Ajuste de texto oSel.sun. Si queremos ajustar el texto automáticamente en la celda.CellHoriJustify.sun. La constante com.CellHoriJustify.star.CellVertJustify.star.sun.sun. usamos: Sub FormatoCeldas7() Dim oSel As Object oSel = ThisComponent.sun.star. tenemos muchas posibilidades de alineación de una celda.getCurrentSelection() 'Reduccion de texto oSel.table.table. es muy interesante por que te repite el valor de la celda hasta llenar el ancho de ella.star.IsTextWrapped = True End Sub Si queremos reducir el texto hasta que quepa en la celda.table.table.REPEAT Valor 0 1 2 3 4 5 Con la combinación de estos valores.RIGHT com.star.star. table.ParaIndent = 1000 End Sub También podemos establecer el color de fondo de las celdas: Sub FormatoCeldas12() Dim oSel As Object oSel = ThisComponent.RotateAngle = 9000 End Sub Valor 0 1 2 3 El valor del ángulo esta dado en centésimas de ángulo. en el ejemplo anterior establecemos el ángulo en 90º (9000) para 180º podemos 18000 y así sucesivamente.table.ParaIndent = 1000 End Sub Sub FormatoCeldas11() Dim oSel As Object oSel = ThisComponent.TOPBOTTOM com.CellBackColor = RGB(200. es decir.table.sun.getCurrentSelection() 'Color del fondo de la celda (gris) oSel.IsTextWrapped = True 'Tamaño de sangria oSel.getCurrentSelection() oSel.5 Dando formato Propiedad Orientation com. de los dos ejemplos siguiente.star.CellOrientation.200.STANDARD com.star. Toma en cuenta que algunas de las propiedades vistas hasta ahora. solo el segundo es correcto: Sub FormatoCeldas10() Dim oSel As Object oSel = ThisComponent.getCurrentSelection() oSel.200) End Sub La siguiente macro te colorea cada celda de la selección.sun.star.CellOrientation.HoriJustify = 1 oSel.BOTTOMTOP com. se autoexcluyen mutuamente.table.star.CellOrientation.IsTextWrapped = True 'Tamaño de sangria oSel.STACKED O podemos establecer el ángulo de rotación: Sub FormatoCeldas9() Dim oSel As Object oSel = ThisComponent.236 6.getCurrentSelection() oSel.sun.sun.CellOrientation.HoriJustify = 2 oSel. tanto la fuente como el fondo de la celda de un color aleatorio: . por lo que tienes que asegurarte que no se contraponen. getCount .RightBorder = oBordeLinea End With End Sub 'Superior 'Inferior 'Izquierdo 'Derecho El ancho de las lineas y la distancia entre ellas esta dada en centésimas de milímetros. tiene que usar la estructura TableBorder: Sub FormatoCeldas15() Dim oSel As Object .getCellByPosition( col. Si deseas establecer también las líneas diagonales. veras una linea simple. fil ) .0.InnerLineWidth = 50 'El ancho de la linea interior . usa la propiedad DiagonalTLBR para la línea que va desde la esquina superior izquierda a la inferior derecha y DiagonalBLTR para la que va de la esquina inferior izquierda a la superior derecha. si quieres establecer el borde de solo los extremos del rango.table.Color = RGB(255.getRows.TopBorder = oBordeLinea .star.CellBackColor = RGB( Rnd()*255.BorderLine) vista en los ejemplos.0) 'El ancho de la linea exterior .getCount .star.1 With .getColumns.Rnd()*255 ) .getCurrentSelection() 'Establecemos las caracteristicas de la linea With oBordeLinea 'El color (rojo) . El código anterior te establecerá el borde de cada celda del rango seleccionado.LeftBorder = oBordeLinea .getImplementationName = "ScCellRangeObj" Then With oSel For col = 0 To oSel.CharColor = RGB( Rnd()*255. si establecemos solo una de las dos líneas.sun.1 For fil = 0 To oSel.table. tienes que establecerles la misma estructura de línea (com.Rnd()*255 ) End With Next Next End With End If End Sub Los bordes de las celdas tienen muchas posibilidades.BottomBorder = oBordeLinea .Rnd()*255.BorderLine oSel = ThisComponent.Aprendiendo OOo Basic Sub Dim Dim Dim FormatoCeldas13() oSel As Object col As Long fil As Long 237 oSel = ThisComponent.LineDistance = 20 End With 'Establecemos los bordes With oSel .Rnd()*255.sun. veamos algunas: Sub FormatoCeldas14() Dim oSel As Object Dim oBordeLinea As New com.getCurrentSelection() If oSel.OuterLineWidth = 50 'La distancia entre las lineas . ParaBottomMargin = 500 'Abajo .getCurrentSelection() 'Establecemos la seleccion en el formato Estandar oSel.TableBorder = oBordeTabla End Sub 6.NumberFormat = 0 End Sub .ParaTopMargin = 500 'Arriba .IsRightLineValid = True End With 'Establecemos los bordes oSel.Color = RGB(0.OuterLineWidth = 75 End With 'Establecemos las características de la tabla With oBordeTabla .5 Dando formato 'Superior 'Inferior 'Izquierdo 'Derecho Las propiedades IsTopLineValid. usamos: Sub FormatoCeldas16() Dim oSel As Object oSel = ThisComponent.getCurrentSelection() 'Para establecer los margenes de la celda With oSel . por ejemplo: Sub FormatoCeldas17() Dim oSel As Object oSel = ThisComponent.TopLine = oBordeLinea .IsTopLineValid = True . Para establecer los margenes de la celda.BorderLine Dim oBordeTabla As New com.getCurrentSelection() 'Establecemos las características de la linea With oBordeLinea 'El color (azul) .sun.star.table.0.BottomLine = oBordeLinea .238 Dim oBordeLinea As New com.star.IsLeftLineValid = True . tienes que establecerlas en verdadero (true) si quieres que se vea la línea. IsLeftLineValid y IsRightLineValid. IsBottomLineValid.IsBottomLineValid = True .ParaLeftMargin = 800 'Izquierda .RightLine = oBordeLinea .TableBorder oSel = ThisComponent.sun.LeftLine = oBordeLinea .255) 'El ancho de la linea interior . usamos la propiedad NumerFormat. la cual es necesario establecer como un entero largo (long) correspondiente a la clave del formato que nos interese.ParaRightMargin = 800 'Derecha End With End Sub Para dar un formato predeterminado a la celda.table. getIsMerged ) End Sub Ahora. el valor que nos devuelve el consultar su propiedad getIsMerged y observa hasta cuando nos funciona el método para separar las celdas.Aprendiendo OOo Basic 239 El numero de clave no es secuencial. ahora. las celdas en las cuales verificamos si están combinadas. Si estableces el argumento en falso (false).merge( Not oRango. Listar formatos en un archivo de Calc.merge( True ) End Sub Si se puede.getCellRangeByName( "B2:D10" ) 'Invertimos la combinacion oRango.getActiveSheet() oRango = oHojaActiva. no en una colección de rangos así que validalo cuando lo uses. Ahora. para ello. La siguiente consideración que debes tomar en cuenta. Para ello. para ello. nota como consultamos la propiedad getIsMerged para saber si el rango esta combinado. primero las separamos y después las combinamos. es decir. claro. Este método es sencillo pero debes de tomar en cuenta algunas consideraciones.getCurrentSelection() 'Combinamos las celdas seleccionadas oSel. pero has la prueba en la interfaz del usuario. veamos como combinar y separar celdas. es saber que pasa cuando las celdas se combinan.merge( True ) End Sub Este método solo esta presente en un rango de celdas. haremos unas pruebas ya no con la selección sino con rangos con nombre. con el argumento verdadero (true). por código estoy hablando. tratemos de emularlo con código. la macro siguiente te alternara entre combinar y separar la el rango seleccionado. Sub FormatoCeldas20() Dim oRango As Object Dim oHojaActiva As Object oHojaActiva = ThisComponent. por lo que tenemos que saber de antemano la clave del formato que nos interesa. este método no hará nada. Sub FormatoCeldas21() Dim oRango As Object . manualmente y observa que pasa. ¿verdad?.getCurrentController.merge( False ) 'Las combinamos oSel. nota el rango que estamos combinando. usamos el método merge.. usa la macro que te muestro en.. Sub FormatoCeldas19() Dim oSel As Object oSel = ThisComponent. separara las celdas de la selección.getCurrentSelection() 'Separamos las celdas seleccionadas oSel. Si seleccionas un rango ya combinado. como en el siguiente ejemplo: Sub FormatoCeldas18() Dim oSel As Object oSel = ThisComponent. tienes que poner mucha atención. en la siguiente macro. junto con un área que no. createCursorByRange( oHojaActiva. para hacer esto.getCurrentController.getIsMerged() oHojaActiva.getCellRangeByName( "G19" ).getCellRangeByName( "E15:H20" ) oRango. veamos como proteger y desproteger celdas.merge( False ) 'Ahora si. eso nos obliga a buscar y encontrar esta celda a partir de otra cuando intentemos separar celdas. entonces.merge( True ) 'Verificamos que este combinada MsgBox oHojaActiva. Como ultimo tema de este capitulo. a partir de otra celda.getCurrentController.merge( False ) Msgbox oHojaActiva.getCellRangeByName( "G19" ). verificalo en la interfaz del usuario y trata de anticipar este caso.getActiveSheet() oRango = oHojaActiva. nos dice que esta combinada y 'finalmente logramos separarlas Msgbox oHojaActiva. nos auxiliaremos de un cursor cuyo uso ya lo hemos visto.merge( True ) 'Nota que la celda G19 forma parte del rango combiando 'consultamos la propiedad y tratamos de separar Msgbox oHojaActiva.240 Dim oHojaActiva As Object oHojaActiva = ThisComponent.getCellRangeByName( "G19" ) ) 'Expandimos el cursor al area combinada oCursor. todas. recuerda que esta protección solo es efectiva si la hoja de calculo esta protegida Sub ProtegerCeldas1() Dim oRango As Object Dim oHojaActiva As Object .getCellRangeByName( "E15" ).getIsMerged() oHojaActiva. Sub Dim Dim Dim FormatoCeldas22() oRango As Object oHojaActiva As Object oCursor As Object oHojaActiva = ThisComponent.getCellRangeByName( "E15" ).getActiveSheet() oRango = oHojaActiva. Toma en cuenta que pasa con las celdas que tienen contenido cuando se combinan.getIsMerged() 'Creamos un cursor a partir de una celda que no sea la de 'la esquina superio izquierda oCursor = oHojaActiva.getCellRangeByName( "E15:H20" ) oRango.getCellRangeByName( "E15" ).getIsMerged() 'Tratamos de separar las celdas oHojaActiva.merge( False ) End Sub Esta vez.merge( False ) End Sub 6. cuando se combinan celdas. expandimos el cursor a la región combinada y pudimos separar fácilmente. se marcan como “no” combinadas.merge( False ) Msgbox oHojaActiva.getCellRangeByName( "G19" ).getCellRangeByName( "E16" ).getCellRangeByName( "G19" ).getIsMerged() oHojaActiva. excepto la de la esquina superior izquierda del rango.5 Dando formato ¿Lo notaste?.collapseToMergedArea() 'Separamos las celdas oCursor.getCellRangeByName( "F17" ). getCurrentController.getActiveSheet() oRango = oHojaActiva. solo veras el resultado . usamos la propiedad Height.sun.CellProtection = oPC oHojaActiva.IsFormulaHidden = True 'Determina si se oculta el contenido de las celdas .2 Formato de filas y columnas Para establecer la altura de las filas.Aprendiendo OOo Basic 241 Dim oPC As New "com.star.Protect("") End Sub Para desproteger las celdas. de todos modos puedes deshabilitar las opciones de protección con solo establecer las opciones de protección en falso (False).getCurrentController.IsHidden = True 'Para ocultar solo para la impresión .50 cm le asignamos un valor de 500 como en el siguiente ejemplo: Sub FormatoFilas1() Dim oSel As Object oSel = ThisComponent. el valor se establece en centésimas de milímetros.CellProtection = oPC End Sub 6. por supuesto. es suficiente con desproteger la hoja.util.CellProtection" oHojaActiva = ThisComponent. no siempre tienen que estar todas seleccionadas.util. por ejemplo: Sub Dim Dim Dim ProtegerCeldas2() oRango As Object oHojaActiva As Object oPC As New "com.IsLocked = True 'Determina si se ocultan las formulas.getActiveSheet() oRango = oHojaActiva.IsPrintHidden = True End With oRango.unProtect("") With oPC 'Determina si la celda esta bloqueada para modificarse .IsFormulaHidden = True 'Determina si se oculta el contenido de las celdas . tu determinaras el nivel de acceso en cada uno de tus proyecto.5.getCellRangeByName( "J27:L30" ) With oPC 'Determina si la celda esta bloqueada para modificarse .IsLocked = True 'Determina si se ocultan las formulas.IsPrintHidden = True End With oRango.IsHidden = True 'Para ocultar solo para la impresión .star.CellProtection" oHojaActiva = ThisComponent.sun.getCellRangeByName( "J27:L30" ) 'Desprotegemos la hoja oHojaActiva. solo veras el resultado .getCurrentSelection() 'Establecemos el alto de las filas seleccionadas . por lo que para tener una fila de 0. getCurrentController. cuando la fila consultada este oculta como consecuencia de un filtro.getActiveSheet() 'Consultamos si la fila 3 esta filtrada MsgBox oHojaActiva.getRows.getCurrentSelection() 'Alternamos entre visible y oculta oSel. prueba a hacer un filtro en tu hoja activa y procura que la fila consultada (getByIndex(Indice)) este filtrada. aun.IsVisible = Not oSel. como en: Sub FormatoFilas2() Dim oSel As Object oSel = ThisComponent. tampoco veras ningún cambio.IsFiltered End Sub También podemos establecer el alto optimo de las filas con la propiedad OptimalHeight. Sub FormatoFilas4() Dim oHojaActiva As Object oHojaActiva = ThisComponent.getRows. si tu la ocultas con IsVisible.getRows.IsVisible = False End Sub Esta propiedad se establece en falso (false) para ocultar la fila y en verdadero (true) para mostrarla. si bien no te dará ningún error.242 oSel.IsVisible End Sub Las filas. toma nota de que “solo” cuando este oculta por un filtro. y te devolverá verdadero (true).getCurrentSelection() 'Establecemos el alto optimo de las filas seleccionadas oSel. IsVisible. Sub FormatoFilas5() Dim oSel As Object oSel = ThisComponent. esta propiedad se llama IsFiltered. adquieren una propiedad particular cuando se les aplica un filtro. estableciendo el valor en la unidad veras que la fila sigue siendo notable.getRows.getRows. Si lo que deseas es ocultarla.getByindex(2). debe estar en verdadero (true) para que tenga efecto.5 Dando formato Cuando tratas de establecer la altura de las filas en cero (0). es mejor usar la propiedad correspondiente. para este caso.OptimalHeight = True End Sub . el siguiente ejemplo te alternara en ocultar y mostrar conforme la ejecutes: Sub FormatoFilas3() Dim oSel As Object oSel = ThisComponent.Height = 500 End Sub 6.getCurrentSelection() 'Ocultamos las filas seleccionadas oSel.getRows. esta propiedad (IsFiltered) seguirá siendo falsa (false). getColumns.CellBackColor = RGB( Rnd()*255.Width = 1000 End Sub Y ocultarlas.200.IsVisible = False End Sub Ajustar al contenido. puedes crearte tu .Aprendiendo OOo Basic 243 A las filas también es posible cambiarles el color de fondo.getCurrentSelection() 'Establecemos el color de fondo de las celdas de la fila completa oSel.getByIndex( co1 ).getRows. Sub FormatoColumnas3() Dim oSel As Object oSel = ThisComponent.1 Step 2 'Establecemos un color aleatorio para las filas impares de la seleccion oSel.getRows. no hay filtros horizontales.getRows.200) End Sub La siguiente macro te cambiara el color de las filas impares de la selección.getColumns.getColumns.OptimalWidth = True End Sub Las columnas no tienen una propiedad IsFiltered. Sub FormatoFilas6() Dim oSel As Object oSel = ThisComponent.Rnd()*255 ) Next End Sub A las columnas también les podemos establecer el ancho.getCurrentSelection() 'Ocultamos las columnas seleccionadas oSel. por que como sabes.getCount() . Sub FormatoColumnas2() Dim oSel As Object oSel = ThisComponent. esto nos permite establecer el color de toda la fila.CellBackColor = RGB(200.getCurrentSelection() 'Establecemos el ancho de las columnas seleccionadas oSel.getCurrentSelection() For co1 = 0 To oSel.Rnd()*255. Sub FormatoColumnas1() Dim oSel As Object oSel = ThisComponent.getCurrentSelection() 'Ajustamos al contenido oSel. Sub FormatoFilas7() Dim oSel As Object Dim co1 As Long oSel = ThisComponent. pero con un poco de ingenio y usando la propiedad IsVisible. en la posibilidad de agrupar bajo un nombre.getSpreadSheet. Dentro de las hojas de cálculo.getSpreadSheet. después el alto de las filas también en 1 y coloreará alternadamente filas y columnas para hacer un lindo mosaico.3 Estilos y autoformato Como buen usuario de OpenOffice.210) End Sub La siguiente macro.CellBackColor = RGB(210.getCurrentSelection() oSel. una serie de características de formato y que podemos aplicar con un solo clic. Tampoco puedes usar la propiedad CellBackColor para establecer el color de fondo. por lo que se verán en el capitulo correspondiente a impresión.getCount() . los estilos de celda que veremos en este capitulo y los estilos de página que se verán en el siguiente.getCurrentSelection() 'Nos apoyamos en un cursor oCursor = oSel.expandToEntireColumns() oCursor.createCursorByRange( oSel ) oCursor.230 ) Next For co1 = 0 To oSel.1 Step 2 oCursor = oSel. 6.1 Step 2 oSel. es decir.230. aquí una primera aproximación.createCursorByRange( oSel.CellBackColor = RGB( 230.Width = 1000 For co1 = 0 To oSel.5 Dando formato versión de filtros horizontales.getRows.230) Next End Sub Las filas y columnas cuentan con algunas propiedades involucradas en la impresión de los documentos.getRows.CellBackColor = RGB(230.getCount() . Para ver los estilos de celda actuales. tenemos dos estilos perfectamente definidos. pero también podemos implementar nuestras versión. usamos la siguiente macro: Sub Dim Dim Dim Dim Estilos1() oDoc As Object oEstilos As Object oEstilosCelda As Object oSel As Object .Height = 1000 oSel.230.org que somos.expandToEntireColumns() oCursor.getColumns.getCellByPosition(co1.210.244 6. establecerá el ancho de las columnas en 1 cm. Sub FormatoColumnas4() Dim oSel As Object Dim oCursor As Object oSel = ThisComponent.0) ) oCursor.getRows.getColumns.5. Sub Dim Dim Dim FormatoFilasColumnas1() oSel As Object oCursor As Object co1 As Long oSel = ThisComponent.getByIndex( co1 ). sabemos que una de sus características más ricas esta en sus “estilos”. getStyleFamilies() 'Accedemos a los estilos de celda oEstilosCelda = oEstilos. vuelve a correr la macro y tienes que ver listado el nuevo estilo. un rango de celdas.getCurrentSelection() With oSel . los podemos establecer a una celda.Aprendiendo OOo Basic 245 'Accedemos al documento actual oDoc = ThisComponent 'Accedemos a todos los estilos oEstilos = oDoc. En nuestro ejemplo. veamos como: Sub Estilos2() Dim oSel As Object oSel = ThisComponent.getByName("CellStyles") 'Mostramos sus nombres MsgBox Join( oEstilosCelda. Chr(13) ) End Sub Si no tienes ningún estilo de celda personalizado.CellStyle = "Domingos" End Sub Veamos la diferencia entre aplicar formato directo a las celdas y usar un estilo. los estilos de celda. hemos agregado un nuevo estilo de celda que se llama “Domingos”. formateamos la selección con las características indicada en cada línea: Sub Estilos3() Dim oSel As Object oSel = ThisComponent.getElementNames(). crea uno con el formato que quieras (tecla F11). un grupo de rangos de una forma sumamente sencilla. en la siguiente macro.getCurrentSelection() 'Aplicamos el estilo de celda Domingos a la selección actual oSel. CellStyle" ) 'Lo agregamos a la colección de estilos oEstilosCelda.createInstance( "com. simplemente no hará nada. Veamos un ejemplo: Sub Dim Dim Dim Dim Dim Estilos5() oDoc As Object oSel As Object oEstilos As Object oEstilosCelda As Object oEstiloNuevo As Object 'Accedemos al documento actual oDoc = ThisComponent 'Accedemos a la selección oSel = ThisComponent.getCurrentSelection() oSel. es recomendable verificar que no exista ya el nombre propuesto. te dará un error en tiempo de ejecución.hasByName( "Resaltado1" ) Then oSel.CharFontName = "Nimbus Sans L" 'Tamaño de letra . mayúsculas y minúsculas. por ello. también.5 Dando formato Ahora. las celdas que tengan este estilo.getCurrentSelection() 'Accedemos a todos los estilos oEstilos = oDoc.246 'Tipo de letra .getStyleFamilies() 'Accedemos a los estilos de celda oEstilosCelda = oEstilos.getByName("CellStyles") 'Verificamos que el estilo exista If oEstilosCelda. crearlo. cuando se borra un estilo de celda personalizado.CharPosture = 2 'Alineamos en medio verticalmente .sun.0. verificar que el estilo exista y en caso de que no exista.VertJustify = 2 'Alineamos centrado horizontalmente . es recomendable. pues si intentas agregar un nombre ya existente.CharColor = RGB(0. oEstiloNuevo ) . el código no te dará ningún error.CharWeight = 150 'Cursiva o italica .CellStyle = "Resaltado1" End Sub No puede ser más fácil.255) End With End Sub 6.CellStyle = "Resaltado1" Else 'Si no existe lo creamos oEstiloNuevo = oDoc. pasarán a tener el estilo de celda predeterminado. pero (siempre hay un pero).style.CharHeight = 15 'Negritas .HoriJustify = 2 'Color de fondo de la celda . crea un estilo con estas mismas características. como sucede en la interfaz del usuario. para nuestro ejemplo le llamaremos “Resaltado1” y procedamos a aplicar a la selección: Sub Estilos4() Dim oSel As Object oSel = ThisComponent.star. que son los únicos que puedes eliminar.204) 'Color de la fuente .insertByName( "Resaltado1". debe estar escrito tal cual se dio de alta incluyendo. al crearlo. si el estilo de celda no existe. el nombre del estilo.CellBackColor = RGB(204.204. getStyleFamilies() 'Accedemos a los estilos de celda oEstilosCelda = oEstilos.CellStyle = "Resaltado1" End If End Sub 247 Para borrar un estilo. las celdas que tengan dicho estilo.TableAutoFormats") 'Mostramos sus nombres MsgBox Join( oAutoFormatos.CharPosture = 2 .hasByName( "Domingos" ) Then If MsgBox("¿Estas seguro de borrar el estilo?".CharFontName = "Nimbus Sans L" .36.HoriJustify = 2 .getElementNames().0.sun.CharWeight = 150 .sheet.CharHeight = 15 .getByName("CellStyles") 'Verificamos que el estilo exista If oEstilosCelda.CellBackColor = RGB(204. Sub Dim Dim Dim Dim Estilos6() oDoc As Object oEstilos As Object oEstilosCelda As Object oEstiloNuevo As Object 'Accedemos al documento actual oDoc = ThisComponent 'Accedemos a todos los estilos oEstilos = oDoc. “todas”.204) . mínimo.204. para ver los autoformatos disponibles usamos: Sub Autoformato1() Dim oAutoFormatos As Object oAutoFormatos = createUnoService("com.Aprendiendo OOo Basic 'Establecemos su formato With oEstiloNuevo . la diferencia. este servicio esta disponible tanto en hojas de calculo como en tablas de Writer.removeByName( "Domingos" ) MsgBox "Estilo de celda borrado" Else MsgBox "NO se borro ningún estilo" End If Else MsgBox "El estilo no existe" End If End Sub El manejo de autoformato. de tres columnas por tres filas.255) End With 'Y lo aplicamos oSel.star. regresaran al estilo predeterminado. es que el autoformato siempre se aplica a un rango de celdas.CharColor = RGB(0.VertJustify = 2 ."Borra estilo") = 6 then 'Quitamos el estilo oEstilosCelda. perdiéndose todo el formato. Chr(13) ) End Sub Para aplicar un autoformato se usa el método autoFormat de la siguiente manera: . usamos el método removeByName de la siguiente manera. recordando que al borrar el estilo. es muy similar al de estilos. "Borra autoformato") = 6 Then 'Quitamos el autoformato oAutoFormatos. es validar que la selección es correcta. debe ser exactamente como se llamo al crearlo.sheet.getImplementationName = "ScCellRangeObj" Then 'de minimo tres filas por tres columnas If oSel.removeByName( "VerdeRojo" ) MsgBox "Autoformato borrado" Else MsgBox "NO se borro nada" End If Else MsgBox "El autoformato no existe" End If .TableAutoFormats") 'Verificamos que exista If oAutoFormatos. te dará un error en tiempo de ejecución.5 Dando formato Toma en cuenta que el rango seleccionado. antes de usarlo. si usas esta técnica.star. El nombre del autoformato.hasByName( sNombreAF ) Then oSel = ThisComponent. como siempre.sun. 3 columnas por 3 filas" End If Else MsgBox "No es un rango de celdas" End If Else MsgBox "El autoformato no existe" End If End Sub Para eliminar un autoformato. pero a diferencia de los estilos. si seleccionas varios rangos de celdas. es decir.autoFormat("Verde") End Sub 6.TableAutoFormats") 'verificamos que exista el autoformato If oAutoFormatos.36.hasByName( "VerdeRojo" ) Then If MsgBox("¿Estas seguro de borrar el autoformato?".getCurrentSelection() oSel. si bien.getColumns. como en el siguiente ejemplo: Sub Dim Dim Dim Autoformato3() oAutoFormatos As Object oSel As Object sNombreAF As String sNombreAF = "VerdeRojo" oAutoFormatos = createUnoService("com.getCount > 2 And oSel. te dará un error pues ese objeto no implementa el método autoFormat. por código.248 Sub Autoformato2() Dim oSel As Object oSel = ThisComponent. si escribes mal el nombre.sheet.getCount > 2 Then oSel. por ello.getRows.sun. un rango de celdas.star. usamos el método removeByName como en: Sub Autoformato4() Dim oAutoFormatos As Object oAutoFormatos = createUnoService("com. lo mejor.autoFormat( sNombreAF ) Else MsgBox "El rango debe ser de minimo. “debe” ser un objeto ScCellRangeObj. es mejor validar que exista.getCurrentSelection() 'Nos aseguramos que la seleccion sea un rango de celdas If oSel. como en los estilos. podrás aplicarlo a una sola celda pero te formateará un mínimo de tres fila por tres columnas. cuando borras un autoformato. cada cruce de columna y fila representa un estilo de celda. el formato de las columnas de datos se ira duplicando y alternando. tenemos 16 estilos diferentes que podemos establecer. ya no estará disponible para usarse. como podrás notar. tiene las mismas características de formato de las celdas vistas anteriormente (aunque no es posible aplicar todos los formatos presentes normalmente en celdas). lo mismo pasará con las filas en el sentido vertical. Para crear un autoformato. es de 3 x 3 celdas. el área mínima para usar un autoformato. que. como podrás notar. usamos la siguiente macro.Aprendiendo OOo Basic End Sub 249 A diferencia de los estilos de celda. primero hay que saber (y entender) como esta estructurado. vamos a formatear 16 celdas. Observa la siguiente imagen. como es que queremos que quede. y en la parte inferior. Para crear el autoformato anterior. soy una nulidad para el diseño. observa la siguiente tabla: 1a Columna Encabezado 1a Fila 1a Fila de datos 2a Fila de datos Pie de Tabla Ultima Fila 1a Columna de datos 2a Columna de datos Ultima Columna 0 4 8 12 1 5 9 13 2 6 10 14 3 7 11 15 Un autoformato. en la parte superior. las celdas establecidas con este. por lo que tenemos que crearlo de nuevo. lo único es que el autoformato borrado. así que no te pongas muy estricto. permanecen con dicho formato. no es más que una colección de formatos de celdas individuales. están nuestros datos sin formato (“pelones” dicen en mi pueblo). si tu rango tiene más área. Como ya lo mencionamos. te recuerdo que el formato de cada celda (campo) del autoformato. así que . por lo que no comentaré esa parte. 150. 16711680.sun. . 13. 150.star.TableAutoFormat") oAutoFormatos = createUnoService("com. 2. 100.IsRightLineValid = True End With 'Celda 0 Call FormatearCampoAF( oBordeTabla. "Liberation Sans". 2 ) 'Celda 5 Call FormatearCampoAF( oBordeTabla.getByIndex(3).TableBorder oDoc = ThisComponent oSel = oDoc.insertByName( sNombreAF.getByIndex(1). oNuevoAF ) 'Le damos formato a cada celda With oBordeLinea .getByIndex(4). 150. oNuevoAF. oNuevoAF.getByIndex(0).getByIndex(2). 150. 13421772. veamos: Sub Dim Dim Dim Dim Dim Dim Dim CrearAutoFormato() oAutoFormatos As Object oNuevoAF As Object sNombreAF As String oDoc As Object oSel As Object oBordeLinea As New com. oNuevoAF.getByIndex(5). 2. 16777215. 2 ) 'Celda 3 Call FormatearCampoAF( oBordeTabla. 13. 3. "Liberation Sans". oNuevoAF. 2 ) 'Celda 4 Call FormatearCampoAF( oBordeTabla.getCurrentSelection() oNuevoAF = oDoc.table. 0.LeftLine = oBordeLinea . 0.hasByName( sNombreAF ) Then 'Lo agregamos a la colección de AutoFormatos oAutoFormatos. 16711680.BottomLine = oBordeLinea . 2.IsLeftLineValid = True .sun.star.5 Dando formato será una macro un poco más larga de las que hemos venido probando.getByIndex(7).RightLine = oBordeLinea . 150.createInstance("com.TableAutoFormats") sNombreAF = "MiFormatoNuevo" 'Verificamos que no exista If Not oAutoFormatos.getByIndex(6). 13. 13. "Liberation Sans". oNuevoAF. oNuevoAF. 150.getByIndex(8).sheet.table.TopLine = oBordeLinea . 10. 0.sun. "Liberation Sans".sheet. 16711680.OuterLineWidth = 60 End With With oBordeTabla . 2 ) 'Celda 9 oNuevoAF. oNuevoAF. 10. "Liberation Sans". 2 ) 'Celda 2 Call FormatearCampoAF( oBordeTabla. 16777215. "Liberation Sans". 13421772. "Liberation Sans". 12. 16777215. 2621593. 12. 150.star.250 6. 100.IsBottomLineValid = True . 2 ) 'Celda 1 Call FormatearCampoAF( oBordeTabla. 2621593. 0. 16777215.BorderLine oBordeTabla As New com.sun. 16711680. 12. 2. pero muy sencilla por que se repite bastante el código. 3. 2 ) 'Celda 6 Call FormatearCampoAF( oBordeTabla. 16777215. 2 ) 'Celda 7 Call FormatearCampoAF( oBordeTabla.star. "Liberation Sans". "Liberation Sans".IsTopLineValid = True . 2 ) 'Celda 8 Call FormatearCampoAF( oBordeTabla. 13421772. oNuevoAF.Color = 255 . 2621593. 13421772. 0. tu tarea es notar las diferencias. 150.CharWeight = Negritas . ColorFondo As Long. 16764057. "Liberation Sans". tiene una pequeña deficiencia que también . 10.getByIndex(11). 10.CellBackColor = ColorFondo . 2621593.CharHeight = TamFuente .getByIndex(13).IncludeNumberFormat = True . "Liberation Sans". oNuevoAF. 'De forma predeterminada incluimos todos las opciones With oNuevoAF . 2 ) 'Celda 15 Call FormatearCampoAF( oBordeTabla. 0. 150.CharColor = ColorFuente . 16777215. 0. TamFuente As Integer.getByIndex(14).getImplementationName = "ScCellRangeObj" Then oSel.autoFormat( sNombreAF ) End If End If End Sub 'Puedes agregar todas las propiedades que consideres Sub FormatearCampoAF(Campo As Object.getByIndex(9). 3. 150. 0.getImplementationName = "ScCellRangeObj" Then oSel. 10. Negritas As Integer. 12.CharFontName = Fuente .getByIndex(15).IncludeNumberFormat = True . 0.Aprendiendo OOo Basic Call FormatearCampoAF( oBordeTabla. 2 ) 251 oNuevoAF. 0. 2 ) 'Celda 12 Call FormatearCampoAF( oBordeTabla. 16764057. 150. oNuevoAF.IncludeFont = True . "Liberation Sans".IncludeBorder = True . oNuevoAF.getByIndex(12). 0. 13421772. HJ As Byte. "Liberation Sans". 16777215.IncludeWidthAndHeight = True End With 'Solo lo aplicamos si la selección es un rango de celdas If oSel. 0.IncludeBackground = True . "Liberation Sans".VertJustify = VJ End With End Sub La macro anterior tiene unas pequeñas diferencias con la imagen mostrada al inicio de ella. ColorFuente As Long.IncludeJustify = True .autoFormat( sNombreAF ) End If Else 'Si existe el formato lo aplicanos If oSel. así mismo. 150. VJ As Byte) With Campo . 2621593. "Liberation Sans". 2 ) 'Celda 11 Call FormatearCampoAF( oBordeTabla. Bordes As Object. 12. oNuevoAF. 0. 150. oNuevoAF. 150. 12. 2621593. 16777215. 2 ) 'Celda 14 Call FormatearCampoAF( oBordeTabla. 12. oNuevoAF. 0. 2621593.getByIndex(10).HoriJustify = HJ . 16777215. 2 ) 'Celda 10 Call FormatearCampoAF( oBordeTabla. 2 ) 'Celda 13 Call FormatearCampoAF( oBordeTabla. Fuente As String. "Liberation Sans".TableBorder = Bordes . Chr(13) ) End Sub Verifica que efectivamente sean los estilos que tienes. ve a tu hoja y presiona la tecla F11 para abrir el cuadro de dialogo “Estilo y Formato”. puedes complementarla con todas las que necesites pues estos campos tienen más de cuarenta propiedades. te dará control completo sobre el formato de página. este. solo estoy considerando las propiedades más representativas.4 Formato de página El formato de página.252 6. usamos: Sub Dim Dim Dim Dim FormatoPagina2() oDoc As Object oHojaActiva As Object oEstilos As Object oEstilosPagina As Object . la lista debería ser igual a la que te devuelve la macro anterior.getStyleFamilies() 'Accedemos a los estilos de página oEstilosPagina = oEstilos. la lista de formatos de página existentes en el documento desde el cual se ejecuta: Sub Dim Dim Dim FormatoPagina1() oDoc As Object oEstilos As Object oEstilosPagina As Object 'Accedemos al documento actual oDoc = ThisComponent 'Accedemos a todos los estilos oEstilos = oDoc. no esta difícil. por supuesto. Observa que hacemos uso de una subrutina (macro) de apoyo para darle formato a cada campo del autoformato.getElementNames(). La siguiente macro te muestra en un cuadro de mensaje. 6.getByName("PageStyles") 'Mostramos sus nombres MsgBox Join( oEstilosPagina. Para saber que estilo de página tenemos en nuestra hoja activa. en conjunto con otra serie de propiedades de la hoja donde estés trabajando. selecciona los estilos de página.5 Dando formato tienes que encontrar. siempre tiene que establecerse por medio de un estilo de página.5. solo tienes que ser un poco observador. BottomMargin 'Margen izquierdo y derecho MsgBox oEP." & oEP.getCurrentController.getStyleFamilies() oEstilosPagina = oEstilos.LeftMargin & " .getCurrentController.getActiveSheet() 'Verificamos el nombre del estilo actual MsgBox oHojaActiva.getByName("PageStyles") 'Verificamos que el nombre del estilo exista If oEstilosPagina.Width & " .hasByName( sEstilo ) Then oEP = oEstilosPagina. mostramos algunas propiedades del estilo de página predeterminado.Aprendiendo OOo Basic 253 oDoc = ThisComponent oHojaActiva = oDoc.getStyleFamilies() oEstilosPagina = oEstilos.getActiveSheet() oEstilos = oDoc.getByName("PageStyles") If oEstilosPagina." & oEP.PageStyle End Sub Para aplicar el estilo de página que quieras. usamos el método removeByName de la siguiente manera: Sub FormatoPagina5() Dim oDoc As Object .getCurrentController.PageStyle( sEstilo ) Else MsgBox "No se aplico ningún estilo de página" End If End Sub Con el siguiente ejemplo.RightMargin End If End Sub Para borrar un estilo. Sub Dim Dim Dim Dim Dim Dim FormatoPagina4() oDoc As Object oHojaActiva As Object oEstilos As Object oEstilosPagina As Object sEstilo As String oEP As Object sEstilo = "Default" oDoc = ThisComponent oHojaActiva = oDoc." & oEP.getByName( sEstilo ) 'Ancho y alto de la página MsgBox oEP.Height 'Margen superior e inferior MsgBox oEP.getActiveSheet() oEstilos = oDoc. usamos la siguiente macro: Sub Dim Dim Dim Dim Dim FormatoPagina3() oDoc As Object oHojaActiva As Object oEstilos As Object oEstilosPagina As Object sEstilo As String sEstilo = "Report" oDoc = ThisComponent oHojaActiva = oDoc.TopMargin & " .hasByName( sEstilo ) Then 'Si existe lo aplicamos oHojaActiva. 254 Dim Dim Dim Dim oHojaActiva As Object oEstilos As Object oEstilosPagina As Object sEstilo As String 6. puedes volver a crearlos. borra todos los estilos para verificarlo. si no me crees y te gusta experimentar como a mi.removeByName( sEstilo ) MsgBox "Estilo borrado" Else MsgBox "El estilo no se borro" End If Else MsgBox "No existe el estilo de página" End If End Sub Ten cuidado con la macro anterior.ScaleToPagesY = 0 'Las que salgan de alto .Width = 27940 'Ancho .BottomMargin = 2000 'Margen inferior . los estilos Reporte (Report) y Predeterminado (Default) no se pueden borrar.getByName("PageStyles") If oEstilosPagina. no obstante.hasByName( sEstilo ) Then oHojaActiva. ya no podrás hace uso del menú Formato | Página.Height = 21590 'Alto . claro.IsLandscape = True 'Orientación de la página (horizontal) . pero.star. si los borras de la plantilla. 36) = 6 Then 'Borramos el estilo oEstilosPagina.LeftMargin = 1000 'Margen izquierdo .style. oEP ) 'Le damos formato With oEp .insertByName( sEstilo. pero por código si que se puede.sun.ScaleToPagesX = 1 'Una página de ancho .PageStyle" ) 'Lo agregamos a la colección de estilos oEstilosPagina.getStyleFamilies() oEstilosPagina = oEstilos.getByName("PageStyles") If oEstilosPagina. aunque los borres. al estar basadas en la plantilla predeterminada.PageStyle( sEstilo ) Else 'Creamos un nuevo estilo oEP = oDoc.hasByName( sEstilo ) Then If MsgBox("¿Estas seguro de borrar el estilo de página?".getActiveSheet() oEstilos = oDoc.getCurrentController.TopMargin = 2000 'Margen superior . dentro de la interfaz del usuario.getStyleFamilies() oEstilosPagina = oEstilos.getCurrentController. como en el siguiente ejemplo: Sub Dim Dim Dim Dim Dim Dim FormatoPagina6() oDoc As Object oHojaActiva As Object oEstilos As Object oEstilosPagina As Object sEstilo As String oEP As Object sEstilo = "Videoteca" oDoc = ThisComponent oHojaActiva = oDoc.getActiveSheet() oEstilos = oDoc. tendrán de nuevo los estilos predeterminados.CenterHorizontally = True 'Centrado horizontal del contenido . si llegas a borrar “todos” los estilos.5 Dando formato sEstilo = "Videoteca" oDoc = ThisComponent oHojaActiva = oDoc. las hojas nuevas.createInstance( "com.RightMargin = 1000 'Margen derecho . si que te quedarás sin estilos. tienes que usarlas correctamente en combinación con la propiedad Orientación (IsLandscape).. estas propiedades. es decir. entonces el ancho debe ser mayor que el alto. que.IsLandscape = False End With 'Ancho 'Alto 'Orientación de la página (horizontal) 'Ancho 'Alto 'Orientación de la página (vertical) Los margenes también están en centésimas de milímetros y se ven afectados por el diseño de página (PageStyleLayout). si estableces las páginas derecha e izquierda igual . son bastantes.Width = 27940 . hay que establecerlos en centésimas de milímetro.Height = 21590 . El ancho (Width) y alto (Height) de la página. es decir. la primer forma es correcta. cada 100 unidades es igual a 1 milímetro. ni son todas las que están-.. si la estableces en falso (False) es decir vertical.Height = 21590 .IsLandscape = True End With With oEp . la segunda no: With oEp . Las características establecidas son las mismas del menú Formato | Página.Width = 27940 . es decir. En el siguiente ejemplo.. como dicen en mi pueblo -ni están todas las que son. se refiere al tamaño del papel.Aprendiendo OOo Basic End With End If End Sub 255 Observa las características indicadas dentro de la misma macro. si estableces esta propiedad en verdadero (True) es decir horizontal. como podrás notar. el alto debe ser mayor para que lo veas correctamente. veamos las más comunes. para el sentido horizontal (CenterHorizontally) y vertical (CenterVertically).PageStyleLayout.style.star.star.LEFT com.PageStyleLayout.5 Dando formato o si las reflejas.256 6. cuyos posibles valores son los siguientes: Propiedad PageStyleLayout com.MIRRORED El Formato.sun. sus valores van del 0 al 5 y se corresponden al orden mostrado en la interfaz del usuario: oEP.sun. tenemos: .PageStyleLayout = com.style.NumberingType = 4 En Orientación de la hoja.sun. lo correcta seria.PageStyleLayout = 0 oEP.MIRRORED Valor 0 1 2 3 Valor en Interfaz Derecha e izquierda Solo izquierda Solo derecha Reflejado Puedes establecer el valor o la constante como en el siguiente ejemplo: oEP.PageStyleLayout.RIGHT com.ALL com. centrado del contenido.sun. pues eso es lo que realmente hacen estas propiedades.PageStyleLayout.CenterHorizontally = True oEP.style.star.sun. oEP.style.style.star.CenterVertically = False En la ficha Borde.PageStyleLayout. son valores booleanos. se refiere al estilo de numeración que se usará cuando se establece la numeración de páginas en el encabezado o en el pie de página. este valor esta determinado por la enumeración PageStyleLayout.star. Aprendiendo OOo Basic 257 Para establecer el borde de la página.0. si quieres la mista distancia para los cuatro bordes.RightBorderDistance = 2000 . si quieres un distancia diferente para cada lado.LeftBorderDistance = 1500 oEP. ya vista en otros capítulos. en el siguiente ejemplo. como si estuviera activada la casilla de verificación Sincronizar.Color = RGB(0. usamos al estructura BorderLine.TopBorder = oBordeLinea oBordeLinea.BottomBorderDistance = 1000 oEP.LineDistance = 100 'Distancia entre líneas End With oEP.Color = RGB(200.BorderDistance = 500 'Para establecer cada borde diferente oEP.Color = RGB(200.LeftBorder = oBordeLinea oBordeLinea.Color = RGB(0.table.OuterLineWidth = 50 'Línea exterior .InnerLineWidth = 100 'Línea interior .5 mm oEP.BorderLine With oBordeLinea .200) oEP.RightBorder = oBordeLinea Si quieres ver solo una línea. usa la propiedad BorderDistance.200) oEP. La opción Distancia al texto. usa las siguientes propiedades: 'Para sincronizar todos los bordes a .0) . las unidades son centésimas de milímetros.sun. de nuevo. se refiere a la distancia entre los bordes y el contenido.200.0) oEP. establecemos el borde de cada lado de un color diferente: Dim oBordeLinea As New com.BottomBorder = oBordeLinea oBordeLinea. ya sea la interior (InnerLineWidth) o la exterior (OuterLineWidth) y no establezcas la distancia entre ellas (LineDistance). establece solo una de las líneas.TopBorderDistance = 500 oEP.star.200.0. ShadowLocation.sun.IsTransparent = False .table.sun.Color = RGB(180.table.TOP_LEFT com.TOP_RIGHT com.star.ShadowLocation. veamos su propiedad que es muy sencilla: oEP.ShadowFormat. que es una estructura com.star.ShadowLocation.sun.220.star.star. con las siguiente propiedades: With oSombra .BackColor = RGB(200.table.ShadowFormat = oSombra 'Donde esta la sombra 'Ancho de la sombra 'Si es transparente 'Color La propiedad Location.star.sun.table.BOTTOM_RIGHT Valor 0 1 2 3 4 Valor en Interfaz Ninguna Arriba a la izquierda Arriba a la derecha Abajo a la izquierda Abajo a la derecha Si estableces la propiedad de transparencia (IsTransparent) en verdadero (True).Location = 4 .table. esta determinada por la siguiente enumeración: Propiedad ShadowLocation com.180) End With oEp.258 6. la sombra no se vera.sun.sun.ShadowLocation. La siguiente ficha se llama Fondo.240) También podemos establecer una imagen de fondo. aquí puedes ver a mi novia Marion Cotillard: .star.BOTTOM_LEFT com.NONE com.ShadowWidth = 1000 .180.table.5 Dando formato La sombra se establece con la propiedad ShadowFormat.ShadowLocation. Aprendiendo OOo Basic 259 La ruta de la imagen la establecemos con BackGraphicURL. te cubrirá la hoja completa con la imagen. en la opción Área. Nos saltamos el encabezado y pie de página que por su complejidad veremos al final. de acuerdo a la siguiente imagen. y veamos la ultima ficha. 'Establecemos la ruta de la imagen oEP. que tiene las siguientes propiedades: .jpg" ) 'Y la posición donde la queremos oEP. no te dará un error pero no te mostrará nada. que es lo usual. si se usara solo en pantalla.BackGraphicLocation = 5 La posición (BackGraphicLocation) puede tomar valores de 1 a 11. si no. Hoja. es importante que le pases la ruta en formato URL. no requieres ni un gran tamaño ni una gran resolución. y por supuesto que la imagen exista. cuida mucho el tamaño de las imágenes insertadas en documentos.BackGraphicURL = ConvertToURL( "/home/mau/marion. PrintHeaders = False . en vez del resultado la cuadrícula de las celdas encabezados de filas y columnas Objetos e imágenes los valores cero La escala de impresión nos puede resolver muy fácilmente problemas de impresión. solo es visible en la vista preliminar y a la hora de imprimir. valor booleano que equivale a: • • Verdadero (True) = De arriba hacia abajo.PrintCharts = True . PrintDownFirst. toma en cuenta que este porcentaje de cambio. en cada línea te muestro su equivalencia en la interfaz del usuario: With oEP .260 6. .PrintObjects = True . la primera opción es aumentar o disminuirla según nuestras necesidades con la propiedad PageScale. pues te puede dar resultados algo extraños.PrintDownFirst = True El valor de Primer núm. después hacia la derecha Falso (False) = De izquierda a derecha y hacia abajo oEP. Ten cuidado si lo usas en conjunto con el total de hojas.5 Dando formato El orden de impresión (Orden de página) lo establecemos con la propiedad. un valor tipo entero (integer) entre 10 y 400. en tu interfaz de usuario no veras ningún cambio de tamaño. valor tipo entero (integer) que establece un inicio de numeración de página diferente de uno.PrintAnnotations = False . si lo estableces fuera de estos limites. oEP.PrintZeroValues = True End With 'Imprimir 'Imprimir 'Imprimir 'Imprimir 'Imprimir 'Imprimir 'Imprimir 'Imprimir las notas de celdas los Gráficos los Objetos de dibujo las formulas.FirstPageNumber = 8 Las siguientes propiedades solo determinan que opciones se imprimirán y cuales no. de página. se ajustará al valor mínimo o máximo más cercano.PrintFormulas = False .PrintGrid = False . esta representado por la propiedad FirstPageNumber.PrintDrawing = True . como mostrarte Hoja 5 de 3. PageScale = 80 'Ajustamos al 80% de escala La segunda opción es ajustar a un determinado número de páginas. es activarlos o desactivarlos según nuestras necesidades: .ScaleToPagesY = 2 Pero estas propiedades. estamos forzando a usar exactamente una de ancho por las “necesarias” de alto.ScaleToPagesY = 0 Ahora si.ScaleToPagesX = 1 oEp. ya casi para terminar. por ejemplo: 'Establecemos la impresión en tres de ancho por dos de alto oEp. ya sea vertical u horizontal.Aprendiendo OOo Basic 261 oEP. tienes que considerar un ajuste óptimo entre cantidad de datos y este valor.ScaleToPages = 3 Por ultimo la que más me gusta. 'Ajustamos a tres páginas de impresión oEP. 'Establecemos la impresión en una de ancho por las que salgan de alto oEp. son muy útiles en eso grandes listados de datos. veamos como modificar el encabezado y el pie de página de nuestro estilo de página. muy comunes donde tienes muchas filas y un determinado número de columnas que caben en el ancho de una hoja. puedes establecer un determinado número de páginas de ancho por otro de alto. el factor de escala se reducirá tanto que los datos no serán legibles. Lo primero que hay que hacer. pues si tienes muchos datos y estableces un valor de páginas muy pequeño.ScaleToPagesX = 3 oEp. si estableces el ancho en 1 y el alto en 0. Para activarla o desactivarla. este margen es distinto e independiente del margen de la página.HeaderLeftMargin = 3000 'Establecemos los margenes del pie de página en 2 cm oEP. junto con la de Diseño de página vista anteriormente. pero toma en cuenta que dentro de este valor.HeaderBodyDistance 'Y del pie de página oEP.FooterIsShared = True Después tenemos las opciones para establecer los margenes en centésimas de milímetros. Para activarla o desactivarla usamos: 'Lo desactivamos en el encabezado oEP. es la altura del encabezado o pie de página. el espacio disponible para introducir información. usamos: 'Establecemos la altura dinámica para el encabezado oEP.262 6.FooterRightMargin = 2000 oEP. es decir.FooterHeight = 1000 + oEP. esta opción.FooterLeftMargin = 2000 La propiedad Espacio. por lo que si quieres una distancia absoluta.5 Dando formato Como son muy similares las opciones de encabezado y pie de página.FooterBodyDistance = 1000 La propiedad Altura.HeaderOn = True 'y desactivamos el pie de página oEp. Para activarlos o desactivarlos usamos: 'Activamos el encabezado oEp. si esta activada. como en: 'Ajustamos la altura del encabezado sumando el espacio al cuerpo oEP.HeaderDynamic = True 'La desactivamos para el pie de página . te iré mostrando sus propiedades. nos permite.HeaderIsShared = False 'Lo activamos en el pie de página oEP.HeaderRightMargin = 3000 oEP. esta considerada la distancia entre el encabezado o pie de página y el cuerpo del documento. establecer las opciones de encabezado o pie de página.HeaderBodyDistance = 500 'Ajustamos la distancia del pie de página al cuerpo del documento¡ oEP. se refiere a la distancia entre en el encabezado o pie de página y el contenido del documento: 'Ajustamos la distancia del encabezado al cuerpo del documento¡ oEP.HeaderHeight = 2000 + oEP.FooterBodyDistance La propiedad Ajuste dinámico de la altura. nos permite adaptar la altura al contenido del encabezado o pie de página. de forma diferente para las páginas pares e impares de nuestra impresión. nos permiten configurar nuestra impresión como si de un libro se tratará. si esta desactivada. una junto a otra. 'Establecemos los margenes del encabezado en 3 cm oEP. la medida introducida en la propiedad anterior no será tomada en cuenta. debes de sumarle dicho valor. esta propiedad es muy útil si establecemos por código el contenido de los encabezados o pies de página.FooterOn = False La opción Contenido a la izquierda/derecha igual. Rnd()*255. 'Establecemos el color de fondo del encabezado de forma aleatoria oEP.HeaderBackGraphicURL = ConvertToURL( "/home/mau/arriba. tenemos las opciones de establecer. un borde.Location = 4 .FooterLeftBorder = oBordeLinea oEP.HeaderLeftBorder = oBordeLinea oEP.Color = RGB(0.Rnd()*255 ) 'Igual para el pie de página oEP. en el encabezado como en el pie de página.150.ShadowWidth = 500 .HeaderShadowFormat = oSombra 'Para el pie de página oEP.FooterDynamic = False 263 Igual que en el estilo de la página.Rnd()*255 ) Para agregar una imagen.HeaderTopBorder = oBordeLinea oEP.Color = RGB(150. usamos: 'Establecemos la ruta de la imagen oEP.FooterBottomBorder = oBordeLinea oEP.0) End With 'Establecemos el mismo para todos oEP.FooterTopBorder = oBordeLinea oEP.170) End With 'Para el encabezado oEP.150. es a a las propiedades a que se establecen estas: 'Configuramos el tipo de borde With oBordeLinea .HeaderRightBorder = oBordeLinea 'Cambiamos el color para el borde del pie de página With oBordeLinea .0) .HeaderBottomBorder = oBordeLinea oEP. la forma es la misma.InnerLineWidth = 0 'Línea interior .OuterLineWidth = 80 'Línea exterior End With 'Establecemos el mismo para todos oEP. .FooterBackGraphicLocation = 10 Para quitar una imagen agregada.jpg" ) 'Y la posición donde la queremos oEP.FooterShadowFormat = oSombra 'Donde esta la sombra 'Ancho de la sombra 'Color Y el color de fondo.jpg" ) 'Y la posición donde la queremos oEP. lo que cambia.160. una sombra.FooterBackColor = RGB ( Rnd()*255.Rnd()*255.Color = RGB(150. tienes que establecer esta propiedad en vacía.HeaderBackGraphicLocation = 10 'Ahora en el pie de página oEP. un color de fondo o una imagen.HeaderBackColor = RGB ( Rnd()*255.Aprendiendo OOo Basic oEP.FooterRightBorder = oBordeLinea Para la sombra aplica igual que en estilo de página: 'Configuramos la sombra With oSombra .FooterBackGraphicURL = ConvertToURL( "/home/mau/abajo. de forma independiente. Contenido a la izquierda/derecha igual. dado que son las mismas opciones para uno y otro.RightText. tanto el encabezado o pie de página. puedes establecer.RightPageHeaderContent.RightPageHeaderContent. como se ilustra en la siguiente imagen: Veamos como controlar el contenido de estas secciones. de este modo. tenemos acceso a las tres secciones mostradas en la imagen anterior. el tipo de letra y su estilo de las tres áreas disponibles. pero si esta desactivada. aun manipulando solo las de las páginas derechas.String 'Y de la derecha MsgBox oEP.LeftText.264 oEP. tres para el encabezado y tres para el pie de página. tanto de las páginas pares como de las impares.RightPageHeaderContent.HeaderBackGraphicURL = "" 6. es muy rico. daremos por hecho que las propiedades (HeaderIsShared y FooterIsShared) están seleccionadas. entonces solo tenemos que modificar el contenido de un lado.5 Dando formato El contenido que puede llevar el encabezado o el pie de página.String Vamos a cambiar el texto de mostrado en el ejemplo anterior de las seis secciones accedibles. de la siguiente manera: . Lo primero que tenemos que tener presente. entonces tenemos que establecer. si esta propiedad esta seleccionada.String 'Del centro MsgBox oEP. pero no te confundas. que serán iguales a las de la izquierda. solo modificamos las propiedades de las páginas derechas.CenterText. estas propiedades son: • • • • RightPageHeaderContent LeftPageHeaderContent RightPageFooterContent LeftPageFooterContent Para el encabezado de las páginas derechas Para el encabezado de las páginas izquierdas Para el pie de página de las páginas derechas Para el pie de página de las páginas izquierdas Para nuestro ejemplo. veamos como: 'Mostramos el contenido de la izquierda del encabezado MsgBox oEP. es la opción vista anteriormente. .0.0.RightPageFooterContent = oContenido oTexto = oContenido.HeaderOn = True oEP.RightPageHeaderContent = oContenido 'Ahora modificamos el pie de página oContenido = oEP.Text.0) oEP.RightText() oTexto.Text. veamos como insertarlos. el número de página y el total de páginas.RightPageHeaderContent = oContenido 'Lo mismo para el centro del encabezado oTexto = oContenido.LeftText() 'Cambiamos el texto oTexto.CharColor = RGB(0.CharColor = RGB(255. hay una serie de campos predeterminados que podemos incluir en cualquier área de un encabezado o de un pie de página.CharColor = RGB(255.LeftText() oTexto.RightPageFooterContent = oContenido End If End Sub Como sabes.getByName("PageStyles") If oEstilosPagina.String = "Esta es la derecha" & Chr(13) & "en el pie de página" oTexto.RightPageFooterContent() oTexto = oContenido.0) oEP.String = "Este es el centro" & Chr(13) & "en el encabezado" oTexto.RightText() oTexto. la hora.Text.CenterText() oTexto.Text.0.FooterOn = True 'Accedemos al contenido del encabezado oContenido = oEP.String = "Este es el centro" & Chr(13) & "en el pie de página" oTexto.0.Text.RightPageHeaderContent() 'Accedemos a la parte izquierda oTexto = oContenido.CenterText() oTexto.Text.255.255) oEP.String = "Esta es la izquierda" & Chr(13) & "en el encabezado" 'Y el color oTexto.hasByName( sEstilo ) Then oEP = oEstilosPagina.255) oEP. campos como.getByName( sEstilo ) oEP.0) oEP.CharColor = RGB(0.String = "Esta es la izquierda" & Chr(13) & "en el pie de página" oTexto.0) 'Reasignamos el contenido para ver los cambios oEP.CharColor = RGB(0.CharColor = RGB(0. la fecha.Aprendiendo OOo Basic Sub Dim Dim Dim Dim Dim Dim Dim FormatoPagina8() oDoc As Object oEstilos As Object oEstilosPagina As Object sEstilo As String oEP As Object oContenido As Object oTexto As Object 265 sEstilo = "Videoteca" oDoc = ThisComponent oEstilos = oDoc.String = "Esta es la derecha" & Chr(13) & "en el encabezado" oTexto.RightPageFooterContent = oContenido oTexto = oContenido.getStyleFamilies() oEstilosPagina = oEstilos.RightPageHeaderContent = oContenido 'Y la derecha oTexto = oContenido.255. text.PageCount") 'Lo insertamos oContenido.getStyleFamilies() oEstilosPagina = oEstilos.RightPageFooterContent() 'Creamos una instancia del campo Nombre del archivo oCampo = oDoc.createTextCursor() 'Nos movemos al final oCursor.CenterText.getByName("PageStyles") If oEstilosPagina.String = "" 'Creamos un cursor en esa sección oCursor = oContenido.HeaderOn = True oEP.createInstance ("com.CenterText.5 Dando formato sEstilo = "Videoteca" oDoc = ThisComponent oEstilos = oDoc.createInstance ("com.TextField.star.hasByName( sEstilo ) Then oEP = oEstilosPagina.star. True) 'Actualizamos el contenido del pie de página oEP.text.star. Total de páginas oCampo = oDoc.FooterOn = True 'Accedemos al contenido del pie de página oContenido = oEP.gotoEnd( False ) 'Nos movemos 'Insertamos el campo oContenido.266 Sub Dim Dim Dim Dim Dim Dim Dim Dim Dim FormatoPagina9() oDoc As Object oEstilos As Object oEstilosPagina As Object sEstilo As String oEP As Object oContenido As Object oTexto As Object oCursor As Object oCampo As Object 6.CenterText.PageNumber") 'Creamos un cursor en la sección central oCursor = oContenido. oCampo.star. True) 'Creamos el campo de Fecha oCampo = oDoc.createTextCursor() oCursor. True) 'Creamos el campo Número de página oCampo = oDoc.text.gotoEnd( False ) 'Nos movemos 'Creamos el campo. True) oCursor.LeftText.RightText.TextField.text.DateTime") oCampo.createInstance ("com.gotoEnd( False ) 'Nos movemos oCursor. oCampo.TextField.insertTextContent (oCursor.String = "Página " 'Insertamos un texto oCursor.LeftText.FileName") 'Limpiamos las tres secciones oContenido.gotoEnd( False ) 'Nos movemos 'Insertamos el campo oContenido.TextField.createInstance ("com.CenterText.IsDate = True 'Es una fecha 'Creamos un cursor en la sección derecha oCursor = oContenido.gotoEnd( False ) 'Nos movemos oCursor.String = "" oContenido.sun.RightText.insertTextContent (oCursor.sun. oCampo. oCampo.createTextCursor() oCursor.sun.insertTextContent (oCursor.gotoEnd( False ) 'Insertamos el campo oContenido.getByName( sEstilo ) oEP.sun.String = "" oContenido.insertTextContent (oCursor.LeftText.String = " de " 'Insertamos más texto oCursor.RightText.RightPageFooterContent = oContenido End If End Sub . Value = "Resaltado1" 'Agregamos las condiciones al formato oFC. que se evaluarán una a una. formatear una celda con diferentes estilos.sun. solo puedes aplicar estilos de celdas existentes.EQUAL mCondiciones(1).5 Formato condicional El formato condicional nos permite. aplicamos el estilo Resaltado1. no te dará ningún error.Value = "100" mCondiciones(2). esto es importante.setPropertyValue( "ConditionalFormat". veamos una primer condición sencilla: Sub Dim Dim Dim Dim Dim FormatoCondicional1() oDoc As Object oHojaActiva As Object oRango As Object oFC As Object mCondiciones(3) As New com. por lo que asegurate de tener algunos de prueba.getPropertyValue("ConditionalFormat") 'Limpiamos cualquier formato existente. si el valor de la celda es igual a 100.clear() 'Establecemos las condiciones del formato mCondiciones(0). le establezca el estilo de celda Resaltado1.sheet.getActiveSheet() oRango = oHojaActiva.Name = "Operator" 'El operador = mCondiciones(0). Puedes establecer de una a tres condiciones. si el estilo no existe.Value = com. a la celda A1.Name = "Formula1" 'El valor de la formula 1.ConditionOperator. de acuerdo al resultado de una expresión o formula. las condiciones 'se agregarán como segunda o terce condición según corresponda oFC. 'recuerda que debes de crearlo previamente mCondiciones(2). es decir. verifiquemos que la agrego correctamente: .5. la condición de que. si no lo haces.sun.addNew ( mCondiciones() ) 'Reestablecemos la propiedad para que surtan efecto los cambios oRango.star. oFC ) End Sub Acabamos de agregar.star. si la celda = 100 mCondiciones(1). simplemente no aplicará ningún formato.getCurrentController.Aprendiendo OOo Basic 267 6.getCellRangeByName( "A1" ) 'Accedemos al formato condicional oFC = oRango.beans.PropertyValue oDoc = ThisComponent oHojaActiva = oDoc.Name = "StyleName" 'En caso de que se cumpla la condiciones. FORMULA Valor 0 1 2 3 4 5 6 7 8 9 Valor en Interfaz Ninguna Igual Distinta de Mayor que Mayor o igual Menor que Menor o igual Entre No entre Formula .Name = "Operator" mCondiciones(0).Name = "StyleName" mCondiciones(2).ConditionOperator.star.Value = "50" mCondiciones(2). por ejemplo.sun.PropertyValue oDoc = ThisComponent oHojaActiva = oDoc.Name = "Formula1" mCondiciones(1).getActiveSheet() oRango = oHojaActiva. si es igual a 50 un estilo y si es mayor a 50 otro estilo.sun.star.5 Dando formato Ahora intentemos.star. oFC ) End Sub Observa la matriz de propiedades mCondiciones.Name = "Formula1" mCondiciones(1).EQUAL com.sun. esta forma de establecer pares de propiedades con un nombre (Name) y un valor (Value).sun. es una enumeración que puede tener los siguiente valores: com.sheet.LESS com.NOT_BETWEEN com. ya la hemos usado anteriormente por lo que no te debe ser desconocida.ConditionOperator.star.sheet.addNew ( mCondiciones() ) mCondiciones(0). la propiedad operador (Operator).GREATER com.ConditionOperator.star.star.sun.sun.sun.beans.ConditionOperator.star.star.sheet.addNew ( mCondiciones() ) 'Reestablecemos la propiedad para que surtan efecto los cambios oRango.sheet.ConditionOperator.ConditionOperator.sun.star.GREATER_EQUAL com.ConditionOperator com.sun. a la celda C1.star.ConditionOperator.star.getCurrentController.Value = com.sun.sheet.star.ConditionOperator.setPropertyValue( "ConditionalFormat".getCellRangeByName( "C1" ) 'Accedemos al formato condicional oFC = oRango.GREATER mCondiciones(1).ConditionOperator.NONE com.ConditionOperator.sheet.star.ConditionOperator.sheet.EQUAL mCondiciones(1).Value = com.getPropertyValue("ConditionalFormat") oFC.BETWEEN com.sun.sheet.clear() mCondiciones(0).sheet.LESS_EQUAL com.Name = "Operator" mCondiciones(0). agregar dos condiciones en vez de una.sun.Name = "StyleName" mCondiciones(2).ConditionOperator.Value = "50" mCondiciones(2).star.sun.sheet.Value = "Azul" oFC.sun.sheet.sheet.Value = "Roja" oFC.NOT_EQUAL com.sheet. que quedaría así: Sub Dim Dim Dim Dim Dim FormatoCondicional2() oDoc As Object oHojaActiva As Object oRango As Object oFC As Object mCondiciones(3) As New com.268 6. Name = "Operator" mCondiciones(0).getActiveSheet() oRango = oHojaActiva.Name = "Formula1" mCondiciones(1).addNew ( mCondiciones() ) 'Reestablecemos la propiedad para que surtan efecto oRango.setPropertyValue( "ConditionalFormat".Aprendiendo OOo Basic 269 Veamos como establecer las condiciones para evaluar entre un par de valores: Sub Dim Dim Dim Dim Dim FormatoCondicional3() oDoc As Object oHojaActiva As Object oRango As Object oFC As Object mCondiciones(3) As New com.star.Value = "Suficiente" oFC.Value = "6" mCondiciones(2).clear() mCondiciones(0).ConditionOperator. lo hemos hecho a un rango de celdas. pues nos da un margen amplísimo para establecer las condiciones. también observa que ahora.Name = "Operator" mCondiciones(0). supongamos que tenemos un rango de celdas con fechas y queremos que los sábados y domingos se distingan de los demás días. crea dos estilos de celda nuevos.BETWEEN mCondiciones(1).addNew ( mCondiciones() ) mCondiciones(0).Name = "Formula2" mCondiciones(2). “B1:B10.Value = "8" mCondiciones(3).sun.BETWEEN mCondiciones(1). Donde realmente me parece. se ve la nobleza del formato condicional.Value = "Excelente" oFC.Value = com.Value = "Reprobado" oFC.sheet.sun.ConditionOperator.Name = "Formula2" mCondiciones(2).Name = "Formula1" mCondiciones(1).ConditionOperator. uno para los sábados y otro para los domingos.star.sheet.Value = com.Name = "Operator" mCondiciones(0).PropertyValue oDoc = ThisComponent oHojaActiva = oDoc.Value = com. en este caso. oFC ) End Sub Observa que ahora hemos usado la propiedad Formula1 y Formula2 para dar el intervalo de valores que nos interesa evaluar. entre 0 y 5.star. entre 6 y 8 y por ultimo entre 9 y 10.Name = "StyleName" mCondiciones(3).Value = "9" mCondiciones(2).getPropertyValue("ConditionalFormat") oFC. en vez de aplicar el formato condicional a una sola celda. por ejemplo.getCellRangeByName( "B1:B10" ) 'Accedemos al formato condicional oFC = oRango.BETWEEN mCondiciones(1).sun.star.Name = "Formula2" mCondiciones(2).Value = "10" mCondiciones(3).Value = "0" mCondiciones(2).sun. creamos su formato condicional con el siguiente ejemplo: .getCurrentController.addNew ( mCondiciones() ) mCondiciones(0).beans.Name = "StyleName" mCondiciones(3).Name = "Formula1" mCondiciones(1).Value = "5" mCondiciones(3).Name = "StyleName" mCondiciones(3). es con el uso de formulas.sheet. observa que nuestro rango empieza en I2 y a la función le estamos pasando la celda A1. el valor que queremos evaluar.PropertyValue 6.clear() mCondiciones(0). Lunes=2.sun.addNew ( mCondiciones() ) 'Reestablecemos la propiedad para que surtan efecto oRango.star. forzosamente hay que proporcionárselos.sun. que nos devuelve el día de la semana que corresponda a la fecha pasada como argumento.Value = "WEEKDAY(A1)=7" mCondiciones(2). le decimos que es la celda A1 por que la referencia es “relativa”. oFC ) End Sub Observa como hemos establecido el valor (Value) de la propiedad Formula1. I3. por supuesto. ajustará correctamente las referencias a cada celda.beans.sheet.getCellRangeByName( "I2:J32" ) 'Accedemos al formato condicional oFC = oRango. estamos haciendo uso de una función incorporada DIASEM (WEEKDAY) de Calc.sheet. pero más divertido. no te confundas. es el de la misma celda I2.Value = com. el formato condicional.Name = "Operator" mCondiciones(0).Value = "WEEKDAY(A1)=1" mCondiciones(2).ConditionOperator.star. Domingo=1.setPropertyValue( "ConditionalFormat".Name = "StyleName" mCondiciones(2).getPropertyValue("ConditionalFormat") oFC.Name = "Formula1" mCondiciones(1). etc.FORMULA mCondiciones(1).getCurrentController. si esta lleva argumentos.Value = com.ConditionOperator. nota como.Value = "Domingos" oFC.Value = "Sabados" oFC.Name = "StyleName" mCondiciones(2). etc.Name = "Operator" mCondiciones(0). Observa el par de listas en la imagen siguiente: .addNew ( mCondiciones() ) mCondiciones(0).star.FORMULA mCondiciones(1).270 Sub Dim Dim Dim Dim Dim FormatoCondicional4() oDoc As Object oHojaActiva As Object oRango As Object oFC As Object mCondiciones(3) As New com. Vamos a crear un formato condicional un poco más elaborado. al ser una función de Calc.getActiveSheet() oRango = oHojaActiva.sun. compruebalo.Name = "Formula1" mCondiciones(1).5 Dando formato oDoc = ThisComponent oHojaActiva = oDoc. A1)=0" mCondiciones(2).getPropertyValue("ConditionalFormat") oFC.getPropertyValue("ConditionalFormat") oFC. Por supuesto. oFC ) 'Para la segunda lista oRango = oHojaActiva. por supuesto.setPropertyValue( "ConditionalFormat". primero te muestro la imagen con el resultado.star.Name = "Operator" mCondiciones(0). para que veas que es posible.star.beans.getCurrentController. confío en ti. antes de ver la solución.Name = "Operator" mCondiciones(0).ConditionOperator.clear() 'Condiciones para la primer lista mCondiciones(0).Value = com.addNew ( mCondiciones() ) 'Reestablecemos la propiedad para que surtan efecto . Ahora la solución: Sub Dim Dim Dim Dim Dim FormatoCondicional5() oDoc As Object oHojaActiva As Object oRango As Object oFC As Object mCondiciones(3) As New com.getActiveSheet() oRango = oHojaActiva.FORMULA mCondiciones(1).sheet. fuente azul y negritas.clear() mCondiciones(0).Value = "Faltante" oFC.Name = "Formula1" 'Observa como ahora usamos referencia absolutas mCondiciones(1). los meses que “no” están en cada lista.PropertyValue oDoc = ThisComponent oHojaActiva = oDoc.sun.Value = "Faltante" oFC.addNew ( mCondiciones() ) 'Reestablecemos la propiedad para que surtan efecto oRango.Name = "Formula1" 'Observa como ahora usamos referencia absolutas mCondiciones(1).sun. es hacer un formato condicional que nos resalte los meses que faltan en una y otra lista. trata de resolverlo por ti mismo.Value = com.getCellRangeByName( "D2:D9" ) oFC = oRango.Value = "COUNTIF($B$2:$B$9.Aprendiendo OOo Basic 271 La tarea.A1)=0" mCondiciones(2).sheet.FORMULA mCondiciones(1). están resaltados con fondo gris.ConditionOperator.sun. después viene la macro con la solución que no tienes que ver hasta que intentes resolverlo.getCellRangeByName( "B2:B9" ) oFC = oRango.Name = "StyleName" mCondiciones(2). esto funciona con cualquier par de listas.Value = "COUNTIF($D$2:$D$9. Observa como hemos satisfecho la condición.Name = "StyleName" mCondiciones(2).star. Para mostrar el nombre de la impresora activa. El método usado para imprimir es print y se usa de la siguiente manera: Sub Imprimiendo1() Dim mOpc() ThisComponent. para cambiar la impresora a usar. muchas veces consume mucho más código que otras necesidades.setPropertyValue( "ConditionalFormat".star. pero debes de recordar los elementos que están implicados en ella.PropertyValue Dim mOpc() .O..5 Dando formato Y con esto terminamos el tema de los formatos.Print( mOpc() ) End Sub Observa que simple.sun. usamos: Sub Imprimiendo3() 'Matriz para el descriptor de impresión Dim mDI(2) As New com.beans.6 Imprimiendo La impresión en OpenOffice. entre otros elementos que veremos en este capítulo.Value End Sub El nombre mostrado dependerá del nombre registrado de tu impresora en tu S.getPrinter() MsgBox mDI(0). ¡¡Feliz programación!! 6. la línea anterior podría enviarte a imprimir una gran cantidad de hojas. oFC ) End Sub 6. usamos: Sub Imprimiendo2() Dim mDI() 'Mostramos el nombre de la impresora activa mDI = ThisComponent. por ejemplo.org es sumamente sencilla. usala con cuidado pero mejor aun.272 oRango. controla todas las opciones de impresión que aprenderemos aquí. la impresora disponible. dependiendo de la configuración actual que tengas. pero !cuidado¡. el área de impresión. el estilo de página establecido. te habrás dado cuenta. que. LETTER ThisComponent.star.PropertyValue Dim mDI(2) As New com.Print( mOpc() ) End Sub Si la impresora no esta registrada con dicho nombre.setPrinter( mDI ) 'Enviamos a imprimir ThisComponent. En las opciones de impresión tienes algunas características para controlar la cantidad de copias.PaperFormat.star.sun.Value = "HP_LaserJet" mDI(1).Aprendiendo OOo Basic 273 'Cambiamos la impresora para imprimir mDI(0).view.10-15 .Value = 1 'Establecemos las opciones de la impresora ThisComponent.view.7.Value = True 'Las páginas a imprimir mOpc(2).12 5-10 4. el orden y las páginas que deseamos imprimir: Sub Imprimiendo4() 'Matriz para las opciones de impresión Dim mOpc(2) As New com.Value = "1" 'Enviamos a imprimir ThisComponent. la propiedad Pages.Name = "PaperFormat" mDI(2).PORTRAIT mDI(2).star. mi recomendación es que solo uses el descriptor de impresión para cambiar de impresora.Value = com. y todas las demás opciones las establezcas en un estilo de página donde tenemos más riqueza de opciones y parámetros.Name = "PaperOrientation" mDI(1). así que asegurate de usar el nombre correcto.PaperOrientation.Name = "Pages" mOpc(2).Name = "CopyCount" mOpc(0).setPrinter( mDI ) 'El número de copias mOpc(0). 1 = Horizontal mDI(1).Name = "Name" mDI(0).sun.sun.Value = "HP_PSC_2200" 'Cambiamos la orientación 0 = Vertical. Si bien podemos cambiar la orientación del papel para imprimir desde este descriptor.Value = com.Name = "Collate" mOpc(1). el lenguaje no te dará ni mostrará un error.beans.Name = "Name" mDI(0).Value = 1 'Si se imprimen en juegos mOpc(1).star.sun.Name = "PaperOrientation" mDI(1).Print( mOpc() ) End Sub De estas opciones.8.PropertyValue mDI(0).beans. se puede establecer de las siguientes maneras: • • • • Una sola página Varias páginas Un rango de páginas Combinación de las anteriores 1 3. getPrintAreas() sMensaje = "La hoja activa tiene " & Format( UBound( mAI() ) + 1 ) & " áreas de impresión" MsgBox sMensaje End Sub Observa que estamos obteniendo (getPrintAreas) las áreas de impresión desde la hoja activa pues este método esta implementado en las hojas del archivo.LETTER com.star. que no son más que rangos de celdas con un nombre. Observa que en descriptor de impresión.sun.PaperFormat.star.sun.sun. son las mismas presentes en el menú Formato | Imprimir Rangos ->. Los valores que puede tomar esta propiedad son: com. hemos establecido el formato del papel.table. la posibilidad de repetir una o varias fila o columnas en cada hoja de la impresión. entre comillas y el valor de la propiedad CopyCount. mostramos la dirección de cada área de impresión si las hay: . solo establece el tamaño en el estilo de página.view.view.6 Imprimiendo Asegurate de pasarle el valor a esta propiedad como una cadena de texto. por ejemplo. en mi experiencia.PaperFormat.star.PaperFormat com. definido por com. te dará un error al querer establecer las opciones de impresión. para nuestro ejemplo en tamaño carta (LETTER). En las hojas de calculo. En el siguiente ejemplo.sun.view.sun.view. es decir.star. si no tienes problemas con tu impresión.getActiveSheet. tendrá la estructura de la dirección de un rango de celdas.view.USER Valor 0 1 2 3 4 5 6 7 Valor en Interfaz A3 A4 A5 B5 Carta Oficio Doble carta Usuario Nota que hasta ahora.view.LEGAL com.PaperFormat.B5 com.PaperFormat. visto múltiples veces a lo largo de este libro.star.view.sun. pero con algunas características que los hacen especiales.PaperFormat.CellRangeAddress. este método te devolverá una matriz con todos las áreas de impresión establecidas en la hoja desde donde se invoque.view. algunas impresoras “rebeldes”. por lo que puedes invocarlo desde cualquiera.star.A5 com. de nuevo.star. por ello.PaperFormat. hemos usado el objeto ThisComponent. se niegan a tomar el formato de papel establecido en el formato de página. el método Print esta presente desde cualquier archivo de Calc. tenemos la posibilidad de definir áreas de impresión. si no.star. se tiene que establecer en el descriptor de impresión. el tamaño del papel es mejor establecerlo en el estilo de página. como un valor entero. el objeto desde donde se llama a la macro.view.274 6.sun.star. cada elemento de esta matriz.A4 com.A3 com.sun.PaperFormat.star.PaperFormat.sun. Para obtener las áreas de impresión actuales usamos: Sub Imprimiendo5() Dim mAI() Dim sMensaje As String mAI = ThisComponent. es decir.sun. te sugiero hacer tus pruebas respectivas y si no es necesario.getCurrentController. Las opciones de las áreas de impresión que aprenderemos a usar y manipular.TABLOID com. Calc tomará todas las hojas con datos como disponibles para impresión.sun.star. si la hoja no tiene ningún área actual. Como supongo lo habrás deducido.setPrintAreas( mAI() ) End Sub Observa como simplemente pasándole una matriz vacía. DirRango.StartColumn = 0 mAI(0).getColumns().CellRangeAddress 'Rango A1:E5 mAI(0).getCurrentController.StartRow + 1 & ":" & _ oRango.getActiveSheet.getColumns().getCurrentController.getRangeAddress.Aprendiendo OOo Basic Sub Dim Dim Dim Imprimiendo6() mAI() sMensaje As String co1 As Integer 275 mAI = ThisComponent.table.StartColumn. Para borrar las áreas de impresión de una hoja.getActiveSheet. todas las áreas de impresión serán borrados.StartRow = 0 mAI(0).getCellRangeByPosition( _ DirRango.EndRow = 4 . DirRango.getName() & _ oRango.getRangeAddress. mi recomendación es que siempre establezcas tus áreas de impresión." & _ oRango.getByIndex(oRango.getByIndex(0).getName() & _ oRango. este método no te dará error.EndColumn = 4 mAI(0).getActiveSheet. además de poder combinar áreas de diferentes hojas que al ser impresas quedan como si de un solo estilo se tratara. DirRango. solo tenemos que llenar dicha matriz con direcciones de rango validos como en el siguiente ejemplo: Sub Imprimiendo8() Dim mAI(1) As New com. para agregar áreas de impresión.getSpreadsheet.Sheet = 0 mAI(0).getName() & ".getPrintAreas() If UBound( mAI() ) > -1 Then For co1 = LBound(mAI) To UBound(mAI) sMensaje = DireccionRango( mAI(co1) ) MsgBox sMensaje Next Else MsgBox "No hay área de impresión definidas en la hoja activa" End If End Sub Function DireccionRango( DirRango As Object) As String Dim sTmp As String Dim oRango As Object oRango = ThisComponent.EndRow) sTmp = oRango.getCount()-1).EndColumn. usamos: Sub Imprimiendo7() Dim mAI() 'Borramos todas las áreas de impresión de la hoja activa ThisComponent.getCurrentController.EndRow + 1 DireccionRango = sTmp End Function Si no tienes ningún área de impresión definida.StartRow. nota que ahora estamos usando el método setPrintAreas.getColumns(). esto te permite tener siempre el control de lo que se imprimirá. automáticamente.setPrintAreas( mAI() ) End Sub 6. tanto de columna como de fila.setTitleRows( oFilR ) End Sub Nota que solo hacemos uso de la fila de inicio y fin. no esta de más recordarte que los valores de inicio y fin.276 'Rango K11:P16 mAI(1).CellRangeAddress . no serán tomadas en cuenta. si estableces setPrintTitleRows.table. te sustituye las existentes. pero no esta de más que lo establezcas primero. que. es la hoja activa. vamos a establecer las filas que queremos repetir en cada hoja de impresión: Sub Dim Dim Dim Imprimiendo9() oHojaActiva As Object mAI(0) As New com. la propiedad setPrintTitleRows.EndRow = 15 'Agregamos las áreas de impresión ThisComponent. ya lo notaste. también.star.EndRow = 18 oHojaActiva.StartColumn = 0 mAI(0).sun. en esta misma propiedad puse 1.StartRow = 0 mAI(0).getCurrentController. nota que en el primer rango.EndColumn = 3 mAI(0). Ahora.getActiveSheet() mAI(0). Esta forma de agregar áreas de impresión.StartColumn = 10 mAI(1). pero no estableces un rango con setTitleRows.6 Imprimiendo Si.star.Sheet = 0 mAI(0).EndRow = 3 'Las establecemos oHojaActiva.setPrintAreas( mAI() ) 'Le decimos que queremos títulos de fila a repetir oHojaActiva.setPrintTitleRows(True) 'Establecemos el rango de filas oFilR. en la propiedad Sheet. una estructura vacía.CellRangeAddress oFilR As New com. del mismo modo. hice un poco de “trampita”.star. para nuestro ejemplo.EndColumn = 15 mAI(1).sun.sun.getCurrentController. pues estas se agregarán a la hoja desde donde es invocado el método setPrintAreas. pero como ya sabes manejar matrices. asegurate de establecer un rango de filas valido. puse 0 y en el segundo rango.Sheet = 1 mAI(1).CellRangeAddress oHojaActiva = ThisComponent. si estableces en setTitleRows. Para repetir las columnas es similar: Sub Imprimiendo10() Dim oHojaActiva As Object Dim oColR As New com. se establecerá la fila 1 como titulo a repetir. en verdadero (True). tu tarea es modificar la macro para agregar nuevas sin borrar las existentes. de forma predeterminada. Cuando haces uso del método setTitleRows. se establece en verdadero (True).StartRow = 2 OFilR.StartRow = 10 mAI(1). la fila 1 será establecida.table. deben estar dentro de rangos válidos y en el orden correcto.getActiveSheet. esto no afecta el “destino” de las áreas de impresión. las demás propiedades de la estructura CellRangeAddress. en teoría.table. setTitleColumns( oTitulosR ) oHojaActiva. veamos como hacerlo. Sub Imprimiendo12() Dim oHojaActiva As Object oHojaActiva = ThisComponent. como en: Sub Imprimiendo11() Dim oHojaActiva As Object Dim oTitulosR As New com. IsManualPageBreak. los métodos respectivos omitirán las propiedades no necesarias para ellos.getCurrentController.getByIndex(4).getActiveSheet() 'Quitamos el salto de página oHojaActiva.getCurrentController.setTitleColumns( oColR ) End Sub Estos métodos tienen las mismas consideraciones vistas para las filas. IsStartOfNewPage.getActiveSheet() oTitulosR.getActiveSheet() 'Le decimos que queremos titulos de columna a repetir oHojaActiva. para quitarlo. al establecer esta propiedad en verdadero (True).EndColumn = 1 oTitulosR.CellRangeAddress oHojaActiva = ThisComponent.Aprendiendo OOo Basic 277 oHojaActiva = ThisComponent.EndColumn = 1 'Las establecemos oHojaActiva.getRows.getRows.getRows. estas forzando un salto de página. veras que tienes dos opciones. estamos insertando un salto de página manualmente.EndRow = 2 'Los establecemos oHojaActiva. es decir. si vas a repetir filas y columnas. Salto de fila y Salto de columna.getCurrentController. lo cual verificamos con la propiedad.IsManualPageBreak Then MsgBox "La fila es un salto de página" End If End Sub Nota como estamos accediendo a una fila (la 5) y la establecemos como inicio de una nueva página con la propiedad.setTitleRows( oTitulosR ) End Sub Si vas al menú Insertar | Salto Manual ->.StartRow = 2 oTitulosR.getByIndex(4).StartColumn = 0 OColR.IsManualPageBreak Then MsgBox "La fila NO es un salto de página" .table.IsStartOfNewPage = True 'Verificamos que se haya establecido If oHojaActiva.getCurrentController. puedes hacer uso de una sola estructura CellRangeAddress.getByIndex(4). solo tienes que establecerla en falso (False): Sub Imprimiendo13() Dim oHojaActiva As Object oHojaActiva = ThisComponent.star.setPrintTitleColumns(True) 'Establecemos el rango de Columnas A:B oColR. por supuesto.getByIndex(4).IsStartOfNewPage = False 'Lo verificamos If Not oHojaActiva. tu puedes establecer la fila o columna que desees como un salto de página manual.StartColumn = 1 oTitulosR.getRows.sun.getActiveSheet() 'Establecemos la fila 5 como salto de página oHojaActiva. getByIndex(2).Position + 1 & Chr(13) & _ "Es salto manual: " & mSP(co1).getColumns.IsManualPageBreak Then MsgBox "La columna es un salto de página" End If End Sub Sub Imprimiendo15() Dim oHojaActiva As Object oHojaActiva = ThisComponent. al formato de la página y su contenido.getByIndex(2).getActiveSheet() 'Establecemos un salto de página de columna oHojaActiva.getCurrentController.getRowPageBreaks() 'Mostramos los salto de fila For co1 = LBound( mSP ) To UBound( mSP ) MsgBox "El salto de página esta en la línea: " & mSP(co1). los saltos de páginas. tanto de fila como de columna.getColumns.getCurrentController. de la hoja activa mSP = oHojaActiva.6 Imprimiendo Lo mismo para las columnas: Sub Imprimiendo14() Dim oHojaActiva As Object oHojaActiva = ThisComponent.278 End If End Sub 6. los primeros se insertan automáticamente. los segundos los establecemos nosotros. con el siguiente método: Sub Imprimiendo17() .getColumns. tenemos dos tipos de saltos de página. con el siguiente ejemplo.Position + 1 & Chr(13) & _ "Es salto manual: " & mSP(co1). por filas. tanto de fila como de columna que tenga la hoja activa e informamos si es manual o no: Sub Dim Dim Dim Imprimiendo16() oHojaActiva As Object mSP() co1 As Integer oHojaActiva = ThisComponent.IsManualPageBreak Then MsgBox "La columna NO es un salto de página" End If End Sub En las hojas de Calc.getActiveSheet() 'Obtenemos todos los saltos de página.getColumnPageBreaks() For co1 = LBound( mSP ) To UBound( mSP ) MsgBox "El salto de página esta en la columna: " & mSP(co1).ManualBreak Next co1 'Ahora los de columna mSP = oHojaActiva.getCurrentController.getByIndex(2).getByIndex(2). de acuerdo.IsStartOfNewPage = True 'Lo verificamos If oHojaActiva. mostramos todos los saltos de página.getColumns.ManualBreak Next co1 End Sub Puedes quitar “todos”.getActiveSheet() 'Quitamos un salto de página de columna oHojaActiva.IsStartOfNewPage = False 'Lo verificamos If Not oHojaActiva. los automáticos y los manuales. getByIndex(7). después.addRangeAddress( oHojas. se enviaba todas las hojas del documento.sun.getCellRangeByName("A1").star.sheet. de forma predeterminada.createInstance("com. Para seleccionar varias hojas a imprimir. te inserta un salto de página cada 2 filas en la selección actual.. al seleccionar rangos de diferentes hojas.IsStartOfNewPage = True Next End Sub Por ultimo.addRangeAddress( oHojas. para ver tu vista previa.removeAllManualPageBreaks() End Sub El siguiente ejemplo. como creo.getRows..getByIndex(co1). "".frame. y seleccionarlos. procura no tener una selección muy grande y sobre todo no mandar a imprimir que te podrían salir muchas hojas. puede ser solo una celda. ". solo se envían las hojas seleccionadas. que no me gusta pero por ahora es la única forma que conozco: Sub Imprimiendo19() Dim oDocF As Object Dim oDH As Object oDocF = ThisComponent.getSheets() 'Creamos el contender para los rangos oRangos = oDoc. y agregarlos a un contenedor de rangos que ya aprendimos a usar. usa el siguiente método.getCurrentController.getByIndex(6).getRangeAddress() . claro.getCellRangeByName("A1"). ahora.1 Step 2 oSel. 0. ve el resultado en tu vista preliminar: Sub Imprimiendo18() Dim oSel As Object Dim co1 As Integer oSel = ThisComponent.star.getActiveSheet() 'Quitamos TODOS los saltos de páginas manuales oHojaActiva.. Array()) End Sub En versiones anteriores de OOo. se seleccionaran las hojas que los contienen.Frame oDH = createUnoService("com.SheetCellRanges") 'Agregamos la primer celda de cada hoja.getCurrentController. cuando enviabas a imprimir. como consecuencia.getCount() .False ) .getRows.False ) oRangos.uno:PrintPreview".Aprendiendo OOo Basic Dim oHojaActiva As Object 279 oHojaActiva = ThisComponent. debe ser.getCurrentSelection() 'Insertamos un salto de página cada dos filas For co1 = 2 To oSel. solo tienes que seleccionar un rango de cada una de ellas. esto siempre lo puedes cambiar desde el cuadro de dialogo imprimir en el menú Archivo | Imprimir. puede ser cualquier celda oRangos.sun.DispatchHelper") 'Mostramos la vista previa oDH.getRangeAddress() . podemos enviar a imprimir como en el siguiente ejemplo: Sub Dim Dim Dim Dim Imprimiendo20() oDoc As Object oHojas As Object mOpc() oRangos As Object oDoc = ThisComponent oHojas = oDoc.executeDispatch(oDocF. es bastante amplio. registros. te ayudará mucho recordar que cada columna de tu rango de datos. esto no es indispensable.getRangeAddress() . es mucho mejor tenerla. efectivamente se capturen números. . así como el estilo de página con la configuración deseada. las herramientas disponibles para trabajar con datos estructurados de esta manera. es decir. sin hacer uso de macros.print( mOpc() ) End Sub La recomendación general.getCurrentController. campo. los registros. esto quiere decir que si una columna (campo) lo llamas Edad.7 Rangos de datos Los rangos de datos. estamos seleccionando dichas hojas oDoc. una fila y una columna en blanco.select( oRangos ) 'Enviamos a imprimir oDoc. También. con lo cual. en la primer fila de estos. aunque esta primer fila no es indispensable. imagínate lo que se puede hacer.getByIndex(8). es que siempre establezcas tus áreas de impresión correctamente. El uso de hojas de calculo con datos tratados como bases de datos. normalmente en un formato diferente del resto de los datos. las filas. son las presentes en el menú Datos. 6. pero una base de datos se hace para llenarse de datos. veras que tema tan interesante es. En la actualidad hay una amplia fuente de información para una buena construcción de tus bases de datos. se establecen los “títulos de campo”.getCellRangeByName("A1"). el uso más cotidiano dado a esta herramienta. es recomendable. de nuevo.False ) 'Al seleccionar las celdas de diferentes hojas. poderoso y versátil. que todos sus campos contienen datos. al menos.addRangeAddress( oHojas. Las mayor parte de las opciones que estudiaremos en este capitulo. y cada fila de estos. No confundas estos nombres. ya que son distintos. Si bien este libro no es de bases de datos explícitamente. con los que puedes definir en el cuadro de nombres de la barra de formulas. de tarea. la impresión se facilitará enormemente. Así mismo. Tampoco es recomendable dejar filas completas en blanco. automatizando estos procesos. es decir. no dejar ninguna fila en blanco. presentes en Calc.280 6. lo podemos llamar. según mi experiencia. son áreas rectangulares de rangos de celdas delimitados por. busca algo acerca del siguiente tema: “normalización de bases de datos”. Trata de que tus datos sean “consistentes”. o fechas si la calculas.6 Imprimiendo oRangos. entre esta y los datos. y no es gratuito. a las cuales se les establece un nombre y tienen características especiales que facilitan su uso como si de una base de datos se tratara. de la interfaz del usuario. es. es mejor si están completos. ahora. en el rango A1:D24.MoveCells = True .star.StartColumn = 0 'La columna de inicio .CellRangeAddress oDoc = ThisComponent oSel = oDoc.CellRangeAddress oDoc = ThisComponent 'Accedemos al conjunto de los rangos de bases de datos oRangosBD = oDoc.table.StartRow = 0 'La fila de inicio .star.EndColumn = 3 'La columna final .KeepFormats = True 'Para que mantenga los formatos End With End Sub El nombre del nuevo rango no debe de existir o te dará un error. oDir ) 'Regresamos el rango recién agregado oRBD = oRangosBD.EndRow = 23 'La fila final End With 'Lo agregamos a la colección oRangosBD.Sheet = 0 'La hoja .DataBaseRanges() 'Verificamos que no exista el nombre If Not oRangosBD.DataBaseRanges() 'El nombre del nuevo rango sNombre = "Direcciones" 'La dirección del nuevo rango With oDir . oSel.getByName( sNombre ) With oRBD . Sub Dim Dim Dim Dim Dim RangoDeDatos1() oDoc As Object oRangosBD As Object sNombre As String oRBD As Object oDir As New com.addNewByName( sNombre.sun.Aprendiendo OOo Basic 281 6. Observa como tomamos la dirección de la selección oRangosBD.hasByName( sNombre ) Then 'Y lo agregamos.getImplementationNAme = "ScCellRangeObj" Then 'Solicitamos el nuevo nombre sNombre = Trim( InputBox("Escribe el nombre del nuevo rango") ) 'Si no esta vacío If sNombre <> "" Then oRangosBD = oDoc. en el siguiente ejemplo.sun. también. solicitamos al usuario el nombre del rango de datos y tomamos la selección actual como dirección para el nuevo rango de datos. en la primer hoja del documento.MoveCells = True 'Para que se actualice al insertar o eliminar celdas . definimos un rango de bases de datos.1 Definiendo rangos En el siguiente ejemplo.getByName( sNombre ) With oRBD .table.getRangeAddress() ) oRBD = oRangosBD.addNewByName( sNombre. verificamos que no exista el nuevo nombre: Sub Dim Dim Dim Dim Dim Dim RangoDeDatos2() oDoc As Object oSel As Object oRangosBD As Object sNombre As String oRBD As Object oDir As New com.7.getCurrentSelection() 'Nos aseguramos de que sea un rango de celdas If oSel. 7 Rangos de datos Para borrar un rango de datos usamos el método removeByName.KeepFormats = True End With Else MsgBox "Ya existe el nombre del rango" End If Else MsgBox "El nombre no puede estar vacío" End If Else MsgBox "No es un rango de celdas" End If End Sub 6. las celdas y sus valores se mantienen: Sub Dim Dim Dim RangoDeDatos3() oDoc As Object oRangosBD As Object sNombre As String oDoc = ThisComponent oRangosBD = oDoc.hasByName( sNombre ) Then oRBD = oRangosBD.star.282 .getByName( sNombre ) 'Le cambiamos el nombre oRBD.hasByName( sNombre ) Then 'Lo removemos de la colección oRangosBD.setName ("Nuevo nombre") Else MsgBox "El rango de datos no existe" End If End Sub Sub Dim Dim Dim Dim Dim RangoDeDatos5() oDoc As Object oRangosBD As Object sNombre As String oRBD As Object oDir As New com.removeByName( sNombre ) MsgBox "Rango de datos borrado" Else MsgBox "El rango de datos no existe" End If End Sub Podemos cambiar las propiedades de un rango de datos existente: Sub Dim Dim Dim Dim RangoDeDatos4() oDoc As Object oRangosBD As Object sNombre As String oRBD As Object oDoc = ThisComponent oRangosBD = oDoc. toma en cuenta que lo único que se borra es el nombre del rango de datos y sus propiedades.DataBaseRanges() 'El nombre del rango a borrar sNombre = "Pruebas" 'Si el nombre no existe obtendrás un error If oRangosBD.table.CellRangeAddress .DataBaseRanges() 'El nombre del rango a modificar sNombre = "Pruebas" If oRangosBD.sun. Sheet = 0 'Cambiamos la hoja . Tomaremos como datos de ejemplo.EndRow = 19 'La fila final End With oRBD. puede suceder que acabe apuntando a un rango vacío de celdas sin querer. 6. los siguientes: Nº 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Nombre nikole gloria antonio lidia paola vanessa paola paola paola lizette lizette lizette nikole gloria antonio lidia paola vanessa Año 1976 1976 1977 1967 1979 1974 1972 1968 1968 1978 1978 1978 1977 1975 1979 1977 1968 1978 Edad 33 33 32 42 30 35 37 41 41 31 31 31 32 34 30 32 41 31 .setDataArea( oDir ) Else MsgBox "El rango de datos no existe" End If End Sub En el primer caso le cambiamos el nombre y en el segundo.Aprendiendo OOo Basic 283 oDoc = ThisComponent oRangosBD = oDoc.7.StartRow = 5 'La fila de inicio .2 Ordenar datos Para ordenar datos.StartColumn = 2 'La columna de inicio .hasByName( sNombre ) Then oRBD = oRangosBD. no necesitas forzosamente un rango de datos con nombre.getByName( sNombre ) 'Cambiamos la dirección With oDir . veamos como ordenar un rango de celdas con y sin nombre de rango de datos. cambia la dirección de un rango con cuidado.EndColumn = 5 'La columna final . por supuesto. la dirección del rango.DataBaseRanges() 'El nombre del rango a modificar sNombre = "Direcciones" If oRangosBD. getSheets. mi recomendación es que siempre . o sea.TableSortFieldType. en falso (False). y tu rango de datos efectivamente tiene títulos de campo.TableSortField mDescriptorOrden() 'La hoja donde esta el rango a ordenar oHoja = ThisComponent. ContainsHeader.TableSortFieldType com.table.star.table.table. el "que" 'Los campos empiezan en 0 mCamposOrden(0).star. puede tomar los siguientes valores: com.Name = "ContainsHeader" mDescriptorOrden(1).284 19 20 21 22 23 lizette nikole gloria antonio lidia 1969 1970 1971 1973 1968 40 39 38 36 41 6.sun.7 Rangos de datos Vamos a ordenar los datos por nombre: Sub Dim Dim Dim Dim OrdenarDatos1() oHoja As Object oRango As Object mCamposOrden(0) As New com.Name = "SortFields" mDescriptorOrden(3).star.sun.TableSortFieldType.FieldType = com. esto es.star.getByName("agosto") 'El rango a ordenar oRango = oHoja.Field = 1 'Orden ascendente mCamposOrden(0).getCellRangeByName("A1:D24") 'Descriptor de ordenamiento.ALPHANUMERIC Valor 0 1 2 Valor en Interfaz Automático Numérico Alfanumérico En mis pruebas. el tipo de campo FieldType. no me ha dado muchas variantes en velocidad. el "como" mDescriptorOrden = oRango.table. por que he hecho pruebas con pocos datos.star.NUMERIC com.sun.AUTOMATIC com.createSortDescriptor() 'Los campos a orden.table. supongo. establecer en uno y en otro.Value = True 'La matriz de campos a ordenar mDescriptorOrden(3). habría que hacer pruebas de rendimiento con grandes datos para ver su desempeño pues no creo que esta propiedad este de adorno. o sea. En el descriptor de orden.sun.IsAscending = True 'Sensible a MAYUSCULAS/minusculas mCamposOrden(0).table. si estableces la propiedad.TableSortFieldType.AUTOMATIC 'Indicamos si el rango contiene títulos de campos mDescriptorOrden(1).Value = mCamposOrden 'Ordenamos con los parámetros establecidos oRango.sun.star.sort( mDescriptorOrden ) End Sub Los puntos a los que debes poner atención son.sun. estos no serán tomados en cuenta y se ordenaran en relación con el resto de tus datos.TableSortFieldType.IsCaseSensitive = False 'Tipo de campo AUTOMATICO mCamposOrden(0). IsAscending = True mCamposOrden(0).FieldType = com.Name = "CopyOutputData" .Name = "SortFields" mDescriptorOrden(3).FieldType = com. como en el ejemplo siguiente que ordenamos por nombre ascendente y después por edad descendente: Sub Dim Dim Dim Dim OrdenarDatos2() oHoja As Object oRango As Object mCamposOrden(1) As New com.getCellRangeByName("G1") mDescriptorOrden = oRango. claro.Field = 1 mCamposOrden(0).TableSortFieldType.Aprendiendo OOo Basic 285 establezcas esta propiedad en verdadero (True) y efectivamente te asegures de tenerlos. no hay más que agregar el segundo criterio a la matriz de campos.table.star.Field = 1 mCamposOrden(0).table.createSortDescriptor() mCamposOrden(0).getSheets.sun.AUTOMATIC mDescriptorOrden(1).getCellRangeByName("A1:D24") oDestino = oHoja.Field = 3 'Este es descendente mCamposOrden(1).sun.getByName("agosto") oRango = oHoja.Value = True mDescriptorOrden(3).star.Name = "SortFields" mDescriptorOrden(3).star.Value = mCamposOrden 'Establecemos que queremos copiar el resultado a otro lado mDescriptorOrden(5).AUTOMATIC 'Agregamos un segundo campo mCamposOrden(1).Value = True mDescriptorOrden(3). a menos de que no te sea indispensable o de plano no los necesites.table.sun.sort( mDescriptorOrden ) End Sub Una opción muy interesante.TableSortField oDestino As Object mDescriptorOrden() oHoja = ThisComponent.IsAscending = False mCamposOrden(1).getSheets.IsCaseSensitive = False mCamposOrden(1). Si quieres ordenar por más de un campo (por ahora el limite es tres).AUTOMATIC mDescriptorOrden(1). es la posibilidad de enviar el resultado a un destino diferente como en el siguiente ejemplo: Sub Dim Dim Dim Dim Dim OrdenarDatos3() oHoja As Object oRango As Object mCamposOrden(0) As New com.createSortDescriptor() mCamposOrden(0).IsAscending = True mCamposOrden(0).Value = mCamposOrden 'Ordenamos con los parámetros establecidos oRango.table.TableSortFieldType.sun.sun.getByName("agosto") oRango = oHoja.star.Name = "ContainsHeader" mDescriptorOrden(1).table.star.IsCaseSensitive = False mCamposOrden(0).IsCaseSensitive = False mCamposOrden(0).Name = "ContainsHeader" mDescriptorOrden(1).TableSortField mDescriptorOrden() oHoja = ThisComponent.getCellRangeByName("A1:D24") mDescriptorOrden = oRango.FieldType = com.TableSortFieldType. 7 Rangos de datos Observa como establecemos el destino con una estructura getCellAddress.Value = mCamposOrden oRango.Value = True mDescriptorOrden(3). que te da acceso al rango origen de los datos.TableSortField mDescriptorOrden() oDoc = ThisComponent oRangosBD = oDoc. Si en el rango destino existen datos. estos serán totalmente reemplazados sin preguntarte nada. pero accediendo desde un rango de datos: Sub Dim Dim Dim Dim Dim Dim Dim OrdenarDatos4() oDoc As Object oRangosBD As Object sNombre As String oRBD As Object oRango As Object mCamposOrden(0) As New com. getReferredCells.Name = "SortFields" mDescriptorOrden(3).AUTOMATIC mDescriptorOrden(1).getCellAddress() 'Ordenamos con los parámetros establecidos oRango.IsAscending = True mCamposOrden(0).Name = "OutputPosition" mDescriptorOrden(6).createSortDescriptor() mCamposOrden(0).Name = "ContainsHeader" mDescriptorOrden(1).FieldType = com.star.286 mDescriptorOrden(5). por lo que puedes tener acceso a todas las propiedades de manipulación y formato vistas de este objeto.table.IsCaseSensitive = False mCamposOrden(0).hasByName( sNombre ) Then 'Referencia al rango oRBD = oRangosBD. . Ahora.sun. puedes aplicarle un autoformato de tabla a los datos.Value = True 'Establecemos el destino de la copia mDescriptorOrden(6).getByName( sNombre ) 'Referencia al origen del rango oRango = oRBD.TableSortFieldType. por ejemplo.star.sort( mDescriptorOrden ) Else MsgBox "El rango de datos no existe" End If End Sub La propiedad importante es. esta propiedad te devuelve un objeto ScCellRangeObj.Value = oDestino.getReferredCells() mDescriptorOrden = oRango. esta solo incluye la hoja destino.table. la columna y la fila de inicio. ordenamos.sun.sort( mDescriptorOrden ) End Sub 6.DataBaseRanges() sNombre = "Direcciones" 'Verificamos que exista el nombre del rango de datos If oRangosBD.Field = 1 mCamposOrden(0). muy bien. te agrega un control de lista desplegable en el encabezado de campo de tus datos. solo la establecemos en falso (False) Sub Dim Dim Dim Dim FiltrarDatos2() oDoc As Object oRangosBD As Object sNombre As String oRBD As Object oDoc = ThisComponent oRangosBD = oDoc.Aprendiendo OOo Basic 287 6. son las presentes en el menú Datos | Filtro ->. con cada una de estas opciones.AutoFilter = True Else MsgBox "El rango de datos no existe" End If End Sub ¿Y para quitarlos?. adivinaste. el filtro automático. y seguiremos usando los datos del tema anterior. Doy por hecho que no tienes problemas.hasByName( sNombre ) Then 'Referencia al rango oRBD = oRangosBD. usamos: Sub Dim Dim Dim Dim FiltrarDatos1() oDoc As Object oRangosBD As Object sNombre As String oRBD As Object oDoc = ThisComponent oRangosBD = oDoc. Primero.DataBaseRanges() sNombre = "Direcciones" If oRangosBD.getByName( sNombre ) 'Mostramos el autofiltro oRBD. la más sencilla. como usuario.hasByName( sNombre ) Then 'Referencia al rango .3 Filtrar datos Las opciones que estudiaremos en este capitulo.7. como en: Para hacer lo mismo por código. veamos como establecerlas por código.DataBaseRanges() sNombre = "Direcciones" If oRangosBD. 7 Rangos de datos Pero cuidado.getByName( sNombre ) 'Mostramos el autofiltro oRBD.AutoFilter = False Else MsgBox "El rango de datos no existe" End If End Sub 6. este permanecerá.FilterFields = mCamposFiltro 'Quitamos las flechas oRBD. para eliminar completamente un filtro.sheet.star.Operator = com.288 oRBD = oRangosBD. no es indispensable mostrar las flechas de los campos del filtro.Field = 1 'El tipo de comparación mCamposFiltro(0).sheet.IsNumeric = False 'El valor de comparación mCamposFiltro(0).TableFilterField oDoc = ThisComponent oRangosBD = oDoc.DataBaseRanges() sNombre = "Direcciones" If oRangosBD. podemos filtrar directamente como en el siguiente ejemplo: Sub Dim Dim Dim Dim Dim Dim FiltrarDatos4() oDoc As Object oRangosBD As Object sNombre As String oRBD As Object oDesFiltro As Object mCamposFiltro(0) As New com.FilterOperator.sun.getReferredCells().getFilterDescriptor() 'Le pasamos una matriz vacía con una estructura de campo de filtro oDesFiltro.AutoFilter = False 'Mostramos las filas ocultas oRBD. si tienes establecido un filtro automático.sun. solo te quitará las flechas para desplegar el filtro del campo.getFilterDescriptor() 'El campo por el que queremos filtrar mCamposFiltro(0).StringValue = "lizette" .getRows.getByName( sNombre ) 'Obtenemos la descripción del filtro oDesFiltro = oRBD. tienes que hacer dos cosas. eliminar el filtro y después mostrar las filas ocultas como te muestro en el siguiente ejemplo: Sub Dim Dim Dim Dim Dim Dim FiltrarDatos3() oDoc As Object oRangosBD As Object sNombre As String oRBD As Object oDesFiltro As Object mCamposFiltro() As New com. cuando filtramos por código. la macro anterior.TableFilterField oDoc = ThisComponent oRangosBD = oDoc.DataBaseRanges() sNombre = "Direcciones" If oRangosBD.hasByName( sNombre ) Then oRBD = oRangosBD. primero.EQUAL 'Si es un número mCamposFiltro(0).star.IsVisible = True Else MsgBox "El rango de datos no existe" End If End Sub Entonces.hasByName( sNombre ) Then oRBD = oRangosBD.getByName( sNombre ) oDesFiltro = oRBD.sheet.sun.star. Aprendiendo OOo Basic 289 'Le pasamos los campos oDesFiltro.star.getFilterDescriptor() mCamposFiltro(0). para obtener el resultado deseado. solo tiene dos posibilidades.star.Operator = com. muchos errores de filtros incorrectos.star.refresh() Else MsgBox "El rango de datos no existe" End If End Sub Que comprobamos que lo hace correctamente: Ahora.FilterConnection.sheet.Field = 1 'Establecemos la relación con la condición anterior mCamposFiltro(1).OR mCamposFiltro(1).FilterOperator.getByName( sNombre ) oDesFiltro = oRBD.sheet. son por la incorrecta aplicación de este sencillo parámetro.FilterFields = mCamposFiltro oRBD. una “O” (OR) o una “Y” (AND).DataBaseRanges() sNombre = "Direcciones" If oRangosBD.hasByName( sNombre ) Then oRBD = oRangosBD.StringValue = "paola" oDesFiltro.Field = 1 mCamposFiltro(0).FilterOperator. veamos como filtrar un campo con dos condiciones: Sub Dim Dim Dim Dim Dim Dim FiltrarDatos5() oDoc As Object oRangosBD As Object sNombre As String oRBD As Object oDesFiltro As Object mCamposFiltro(1) As New com.EQUAL mCamposFiltro(1). comprobamos que nuestro filtro esta correcto.sheet.sun.EQUAL mCamposFiltro(0).sun.sheet.FilterFields = mCamposFiltro 'Refrescamos el rango para ver el resultado del filtro oRBD.StringValue = "lizette" 'Agregamos la segunda condición al mismo campo mCamposFiltro(1).star.TableFilterField oDoc = ThisComponent oRangosBD = oDoc.IsNumeric = False mCamposFiltro(1).refresh() Else MsgBox "El rango de datos no existe" End If End Sub Observa muy bien la propiedad Connection. es muy importante establecer correctamente esta.Connection = com.Operator = com. y veamos más ejemplos: .sun.IsNumeric = False mCamposFiltro(0).sun. getByName( sNombre ) oDesFiltro = oRBD.sheet.sun.sun.sun. filtramos a todos los que tengan entre 30 y 35 años: Sub Dim Dim Dim Dim Dim Dim FiltrarDatos7() oDoc As Object oRangosBD As Object sNombre As String oRBD As Object oDesFiltro As Object mCamposFiltro(1) As New com. como yo.TableFilterField .IsNumeric = False mCamposFiltro(0).sun.refresh() Else MsgBox "El rango de datos no existe" End If End Sub Y una vez más lo comprobamos En los siguientes ejemplos.EQUAL mCamposFiltro(0).290 6.FilterOperator.FilterFields = mCamposFiltro oRBD.Field = 1 mCamposFiltro(0).star.star.NumericValue = 32 oDesFiltro.TableFilterField oDoc = ThisComponent oRangosBD = oDoc.star. En el siguiente ejemplo.FilterOperator.StringValue = "lidia" 'Agregamos la segunda condición a otro campo mCamposFiltro(1).EQUAL 'Ahora si buscamos por número mCamposFiltro(1).AND mCamposFiltro(1).sheet. que el resultado esperado es el correcto.sun.IsNumeric = True mCamposFiltro(1).sheet.sheet. que estas comprobando.Connection = com.7 Rangos de datos Ahora filtraremos con condiciones en dos campos diferentes: Sub Dim Dim Dim Dim Dim Dim FiltrarDatos6() oDoc As Object oRangosBD As Object sNombre As String oRBD As Object oDesFiltro As Object mCamposFiltro(1) As New com.Operator = com.hasByName( sNombre ) Then oRBD = oRangosBD.Field = 3 'Establecemos la relación con la condición anterior (Y) mCamposFiltro(1).getFilterDescriptor() mCamposFiltro(0).star.Operator = com.sheet.DataBaseRanges() sNombre = "Direcciones" If oRangosBD.FilterConnection. dando por entendido.star. ya no te mostraré el resultado. FilterOperator.star.NOT_EQUAL com.sheet.FilterOperator.FilterOperator.sun.DataBaseRanges() sNombre = "Direcciones" If oRangosBD.sun.LESS_EQUAL com.star.sun.LESS com.TOP_VALUES com.AND mCamposFiltro(1).refresh() Else MsgBox "El rango de datos no existe" End If End Sub Observa como hemos cambiado la propiedad operador (Operator) para satisfacer la condición.sun.GREATER com.Connection = com.sheet.sun.star.sun.star.FilterOperator.sheet.FilterOperator.NOT_EMPTY com.sun.getFilterDescriptor() mCamposFiltro(0).FilterOperator.Aprendiendo OOo Basic 291 oDoc = ThisComponent oRangosBD = oDoc.FilterOperator.star.sun.sun.sheet.sheet.sun.NumericValue = 35 oDesFiltro.BOTTOM_VALUES com.Operator = com.star.sheet.sheet.getByName( sNombre ) oDesFiltro = oRBD.star.LESS_EQUAL mCamposFiltro(1).sheet.sun.star.FilterOperator com.star.star.sun.sun.BOTTOM_PERCENT Valor 0 1 2 3 4 5 6 7 8 9 10 11 Valor en Interfaz Vacío No vacío Igual No igual Mayor que Mayor o igual que Menor que Menor o igual que El mayor valor El mayor porcentaje El menor valor El menor porcentaje En el siguiente ejemplo.star.IsNumeric = True mCamposFiltro(0).sheet.sun.FilterOperator.sheet.sheet.star.TableFilterField oDoc = ThisComponent oRangosBD = oDoc.EQUAL com.NumericValue = 30 'Agregamos la segunda condición a otro campo mCamposFiltro(1). los posibles valores para esta propiedad.FilterOperator. viene condicionados por la enumeración com.GREATER_EQUAL com.star.Field = 3 mCamposFiltro(0).FilterOperator.sheet.FilterFields = mCamposFiltro oRBD.star.star.GREATER_EQUAL mCamposFiltro(0).sheet.sun.sun.hasByName( sNombre ) Then oRBD = oRangosBD.star.sun.FilterOperator.star.IsNumeric = True mCamposFiltro(1).TOP_PERCENT com.star.sheet.sheet.sheet.sun. cuyos valores son: com. seleccionamos los cinco registros con más edad: Sub Dim Dim Dim Dim Dim Dim FiltrarDatos8() oDoc As Object oRangosBD As Object sNombre As String oRBD As Object oDesFiltro As Object mCamposFiltro(0) As New com.FilterConnection.DataBaseRanges() sNombre = "Direcciones" .Field = 3 mCamposFiltro(1).FilterOperator.FilterOperator.FilterOperator.FilterOperator.sheet.Operator = com.EMPTY com.sheet. star.getFilterDescriptor() mCamposFiltro(0).sun.getFilterDescriptor() mCamposFiltro(0).FilterFields = mCamposFiltro oRBD.sun.StringValue = "l.*" 'Establecemos que use expresiones regulares oDesFiltro.sun. veamos como: Sub Dim Dim Dim Dim Dim Dim Dim FiltrarDatos10() oDoc As Object oRangosBD As Object sNombre As String oRBD As Object oDesFiltro As Object mCamposFiltro(0) As New com.sun.refresh() Else MsgBox "El rango de datos no existe" End If End Sub 6.Field = 3 mCamposFiltro(0).DataBaseRanges() .star.292 If oRangosBD.TableFilterField oDestino As Object oDoc = ThisComponent oRangosBD = oDoc. es poder copiar el resultado en otra posición y dejar el origen intacto.star.hasByName( sNombre ) Then oRBD = oRangosBD.TOP_VALUES mCamposFiltro(0). Otra posibilidad bastante interesante de los filtros.7 Rangos de datos Ahora.FilterFields = mCamposFiltro oRBD. del descriptor del filtro para que tenga efecto nuestra condición.UseRegularExpressions = True oDesFiltro.FilterOperator.getByName( sNombre ) oDesFiltro = oRBD.star.getByName( sNombre ) oDesFiltro = oRBD.Field = 1 mCamposFiltro(0).TableFilterField oDoc = ThisComponent oRangosBD = oDoc.sheet.IsNumeric = False 'Observa el parametro de la condición mCamposFiltro(0).sheet.FilterOperator.refresh() Else MsgBox "El rango de datos no existe" End If End Sub Observa como hemos establecido la propiedad para usar expresiones regulares (UseRegularExpressions).sheet.Operator = com.hasByName( sNombre ) Then oRBD = oRangosBD.IsNumeric = True 'Los cinco de más edad mCamposFiltro(0).EQUAL mCamposFiltro(0). filtremos todos los nombres que comiencen por la letra “L”: Sub Dim Dim Dim Dim Dim Dim FiltrarDatos9() oDoc As Object oRangosBD As Object sNombre As String oRBD As Object oDesFiltro As Object mCamposFiltro(0) As New com.sheet.Operator = com.NumericValue = 5 oDesFiltro.DataBaseRanges() sNombre = "Direcciones" If oRangosBD. star.IsNumeric = False mCamposFiltro(0). observa como obtenemos la dirección de la primer celda del rango oDestino = oRBD.Column + oRBD.Column = oDestino.Field = 0 'Seleccionamos los registros NO vacíos mCamposFiltro(0).OutputPosition = oDestino oDesFiltro.sun.sun. se hace de la siguiente manera: Sub Dim Dim Dim Dim Dim Dim Dim FiltrarDatos11() oDoc As Object oRangosBD As Object sNombre As String oRBD As Object oDesFiltro As Object mCamposFiltro(0) As New com.SaveOutputPosition = True 'Y le indicamos donde.0).Column = oDestino.getCount + 1 oDesFiltro. serán reemplazadas sin preguntarte nada. puedes .ReferredCells().ReferredCells(). hemos aplicados filtros.getCellAddress() 'Despues sumamos el ancho del rango y uno para dejar una columan en blanco oDestino.Aprendiendo OOo Basic 293 sNombre = "Direcciones" If oRangosBD.sheet.getColumns().ReferredCells().NOT_EMPTY 'Le indicamos que solo queremos registros únicos oDesFiltro. copia varios registros iguales para que notes la diferencia. estas.getFilterDescriptor() mCamposFiltro(0). es la posibilidad de filtrar los registros.hasByName( sNombre ) Then oRBD = oRangosBD.Field = 1 mCamposFiltro(0). omitiendo los duplicados.0).Operator = com.FilterFields = mCamposFiltro oRBD.EQUAL mCamposFiltro(0).getCellAddress() oDestino.SkipDuplicates = True oDesFiltro.Column + oRBD.DataBaseRanges() sNombre = "Direcciones" If oRangosBD.getCount + 1 'Establecemos el destino oDesFiltro.SaveOutputPosition = True oDestino = oRBD.FilterFields = mCamposFiltro oRBD.ReferredCells().getByName( sNombre ) oDesFiltro = oRBD.FilterOperator. Otra característica muy poderosa de los filtros.refresh() Else MsgBox "El rango de datos no existe" End If End Sub Hasta ahora. al ser un método de rango de celdas (ScCellRangeObj).sun.getFilterDescriptor() mCamposFiltro(0).refresh() Else MsgBox "El rango de datos no existe" End If End Sub Si las celdas destino no están vacías.star.getCellByPosition(0.getCellByPosition(0.star.getByName( sNombre ) oDesFiltro = oRBD.hasByName( sNombre ) Then oRBD = oRangosBD.sheet.sheet.getColumns().OutputPosition = oDestino oDesFiltro.FilterOperator. pero los filtros no están limitados a estas áreas. desde un rango de datos.StringValue = "gloria" 'Le indicamos que queremos el resultado en otro lugar oDesFiltro.TableFilterField oDestino As Object oDoc = ThisComponent oRangosBD = oDoc.Operator = com. modifica la macro. para evaluar esto y se lo notifiques al usuario. pasándole como parámetro el descriptor de filtro creado. la primera es la forma de crear el descriptor de filtro. con al menos cinco campos y varias decenas de registros. la siguiente macro.FilterOperator. establecemos un nombre a este rango.FilterFields = mCamposFiltro 'Y lo aplicamos oSel. serán reemplazados sin consultarte. Veamos como usar las opciones del filtro especial.sun.SkipDuplicates = True oDesFiltro. también cambia la propiedad para decirle que queremos copiar el resultado (CopyOutputData) en otra posición. selecciona el rango . Para demostrar el poder y versatilidad de esta opción. si lo prefieres. preparate una buena tabla de datos. este tipo de filtro. toma el rango de celdas seleccionado y filtra los datos únicos dos columnas a la derecha.createFilterDescriptor(True) 'Establecemos los campos mCamposFiltro(0).ContainsHeader = False oDesFiltro.filter( oDesFiltro ) Else MsgBox "No es un rango de celdas" End If End Sub Hay diferencias importantes en comparación con los filtros en rango de datos. y por ultimo. no refrescamos el rango. presente en los ejemplos que acompañan a estos apuntes y que será la que yo use. al cual se le pasa el parámetro verdadero (True) si queremos que el nuevo descriptor este vacío y falso (False) si toma el existente en dicho rango de celdas.Operator = com.getCellByPosition(0.getRangeAddress().Field = 0 mCamposFiltro(0).NOT_EMPTY 'Establecemos el destino oDestino = oSel.star.sheet. para un rango de celdas se usa el método createFilterDescriptor.getCurrentSelection() 'Nos aseguramos de que sea un rango de celdas If oSel. si el destino contiene datos. nos permite establecer un rango como origen de los criterios para el filtro. dándonos absoluto control sobre los registros filtrados.getCellAddress() oDestino.getImplementationName = "ScCellRangeObj" Then 'Creamos un nuevo descriptor de filtro vacio (True) oDesFiltro = oSel. El rango de nuestros datos es: “A1:G243”. “Videoteca” si te parece. observa que también hemos establecido que este rango no tiene encabezados de campos (ContainsHeader).sheet. puedes usar la hoja llamada “Peliculas”. verificalo: Sub Dim Dim Dim Dim Dim FiltrarDatos12() oDoc As Object oSel As Object oDesFiltro As Object mCamposFiltro(0) As New com.294 6.CopyOutputData = True oDesFiltro. copia los títulos de los campos a la fila 250. esta macro es muy útil para dejar listados únicos de lo que sea. después.EndColumn + 2 'Establecemos las propiedades del filtro oDesFiltro. Al igual que con los rango de datos.sun.OutputPosition = oDestino oDesFiltro.0).7 Rangos de datos aplicar un filtro a cualquier rango de celdas.Column = oSel. lo que nos da la posibilidad de poder llegar a usar como criterios “todos” los campos de nuestra base de datos.TableFilterField oDestino As Object oDoc = ThisComponent oSel = oDoc.star. si no que aplicamos el filtro (filter). si es de tu agrado. Aquí la macro: Sub Dim Dim Dim Dim Dim Dim FiltrarEspecial1() oDoc As Object oRangosBD As Object oVideoteca As Object oDestino As Object oCriterios As Object oDesFiltro As Object oDoc = ThisComponent oRangosBD = oDoc.DataBaseRanges() 'Nos aseguramos de que existen nuestros tres rangos If oRangosBD. con esta macro en especifico.UseRegularExpressions = True 'Queremos el resultado en otra posición oDesFiltro. Te sugiero.getByName( "Destino" ).createFilterDescriptorByObject( oVideoteca ) 'Sin duplicados oDesFiltro. por ultimo.getCellAddress() 'Obtenemos el descriptor del filtro del rango de criterios a partir del rango de datos oDesFiltro = oCriterios. asignarle una combinación de teclas o un botón en alguna barra de herramientas con la finalidad de que podamos ejecutarla varias veces desde la interfaz del usuario e ir viendo en vivo y en directo los resultados que nos arrogue.0 ).CopyOutputData= True 'Le indicamos donde oDesFiltro. concentrándonos en estudiar la forma de establecer estos criterios desde un rango de datos con nombre..OutputPosition = oDestino 'El rango contiene encabezados de campos oDesFiltro.ReferredCells() oCriterios = oRangosBD.getByName( "Videoteca" ). todo lo anterior puedes hacerlo por código que ya sabes hacerlo.Aprendiendo OOo Basic 295 “A250:G255” y nombrala como “Criterios”. Nuestra tabla debe verse más o menos así. por lo que no lo repetiremos aquí.SkipDuplicates = True 'Que pueda usar expresiones regulares oDesFiltro..ReferredCells() oDestino = oRangosBD. ¿verdad?. se puede hacer como lo hemos venido aprendiendo. La definición de criterios para el filtro especial.hasByName( "Videoteca" ) And oRangosBD.getCellByPosition( 0.hasByName( "Criterios" ) And oRangosBD.ReferredCells. selecciona la celda “A260” y la bautizamos como “Destino”. Recuerda que esta definición de nombres es en el menú Datos | Definir rango.hasByName( "Destino" ) Then 'Obtenemos una referencia a los rangos origen oVideoteca = oRangosBD.getByName( "Criterios" ).ContainsHeader = True . que se invoca desde el rango de criterios (oCriterios). por ejemplo. estas usando el operador “O” (Or). para responder la pregunta. como la respuesta a la pregunta. realizadas en Japón realizadas en 1980? Nº Titulo Director Genero Año País 1980 Japón Duración Si usas diferentes filas. el rango de datos (oVideoteca). por ejemplo. los criterios tienes que establecerlos en las celdas correspondientes. establece la condición y ejecuta la macro para responderla. las restantes propiedades usadas en el ejemplo ya las hemos tratado.filter( oDesFiltro ) Else MsgBox "El rango de datos no existe" End If End Sub Es importante notar que para el filtro especial usamos en nuevo método llamado createFilterDescriptorByObject. usamos: Ejecuta la macro y vemos el resultado: Recuerda que la finalidad de establecer criterios y realizar filtros. ¿cuantas películas tenemos. Ahora.296 6. Nº Titulo Director Genero Año 1974 País Duración Si quieres establecer más de un criterio y lo haces en una misma fila. estas usando el operador “Y” (And). ¿cuantas películas tenemos de la India o del director Peter Greenaway? Nº Titulo Director Genero Año País India Duración . pasándole como argumento. es la de responder preguntas como por ejemplo. ¿cuantas películas tenemos del año 1974?.7 Rangos de datos 'Filtramos con las opciones seleccionadas oVideoteca. para saber que películas tenemos de mi director favorito. por lo tanto.DataBaseRanges() 'Nos aseguramos de que existe el rango If oRangosBD. establecer las condiciones para responder la siguiente pregunta. ¿cuales películas duran entre 60 y 90 minutos?. recuerda que el rango de criterios es solo eso un rango y no estamos limitados a cambiar lo que queramos en este rango.2 ) .GeneralFunction.Column = 1 mCamposSubTotal(0).EnableSort = True oDesSubTotal. a trabajar: Nº Titulo Director Genero Año País Duración ?? 6.hasByName( "Peliculas" ) Then 'Obtenemos una referencia a los rangos origen oPeliculas = oRangosBD.ReferredCells() 'Creamos un nuevo subtotal oDesSubTotal = oRango.* Director Genero Año País Duración Como habrás notado.star.addNew( mCamposSubTotal.sun. en el siguiente ejemplo y continuando trabajando con nuestra base de datos de películas. puedes responder preguntas como. tienes que usar el operador “Y” (AND) para resolverlo.sheet.createSubTotalDescriptor( True ) 'Que ordene de forma ascendente el grupo seleccionado oDesSubTotal.Aprendiendo OOo Basic Peter Greenaway 297 Como declaramos en el descriptor de filtro.SortAscending = True 'La columna en la que se usara la función especificada mCamposSubTotal(0). obtenemos la cantidad de títulos por director: Sub Dim Dim Dim Dim Dim Dim Subtotales1() oDoc As Object oRangosBD As Object oPeliculas As Object oRango As Object oDesSubTotal As Object mCamposSubTotal(0) As New com.7. la primer pista es. con lo que ya te resolví la tarea.sheet.SubTotalColumn oDoc = ThisComponent oRangosBD = oDoc.Function = com. nota que estamos solicitando un rango especifico.getByName( "Peliculas" ) 'Referencia al rango de celdas origen oRango = oPeliculas. y ya casi te dije todo.star. al grupo deseado oDesSubTotal.sun. agrupar y realizar una operación determinada en un grupo de datos. las posibilidades son enormes.4 Subtotales Los subtotales nos permiten obtener información de las áreas de datos. ¿cuantas películas empiezan con la letra “D”? Nº Titulo d.COUNT 'Agregamos la operación. que se usarán expresiones regulares. Te queda de tarea. sun.GeneralFunction.DataBaseRanges() . el descriptor de subtotal y un valor booleano indicándole si deseamos reemplazar el subtotal actual (True).PRODUCT com. True ) End If End Sub 6.sun.GeneralFunction. En la matriz de columnas del subtotal (com.sheet.star. solo la utilizamos para acceder (ReferredCells) al rango de celdas origen. La siguiente macro.sheet.star.sun. Es importante que establezcas que ordene el grupo.GeneralFunction.VAR com.sheet. cuyos parámetros son.GeneralFunction.GeneralFunction.AVERAGE com. a su vez.SubTotalColumn). borra cualquier subtotal existente en el rango del área de datos: Sub Dim Dim Dim Dim Subtotales2() oDoc As Object oRangosBD As Object oPeliculas As Object oRango As Object oDoc = ThisComponent oRangosBD = oDoc.sheet.sun.VARP Valor 0 1 2 3 4 5 6 7 8 9 10 11 12 Valor en Interfaz Ninguna Automático Suma Cuenta Promedio Máximo Mínimo Producto Cuenta solo números Desviación estándar (Muestra) Desviación estándar (Población) Varianza (Muestra) Varianza (Población) Al añadir los campos (addNew) al descriptor de subtotal. si es falso (False).GeneralFunction.sheet.sun.star.sheet.star.GeneralFunction. usa con cuidado este parámetro.NONE com. si es ascendente o descendente.GeneralFunction. le indicamos por que campo queremos agrupar.SUM com.sheet. queda a tu criterio y necesidades.STDEVP com. pero si no ordenas el grupo.sheet.GeneralFunction. determinada por la propiedad función (Function). se le pasa como argumento un valor verdadero (True).sheet.sun.sun.sun.MIN com. que puede tomar los siguientes valores: com. establecemos el campo (Column) en el cual queremos hacer una operación.sheet. la matriz de campos de columna del subtotal donde hemos establecido que campos y que operación haremos con ellos.star.sun.star.COUNT com. con el segundo parámetro.GeneralFunction.sheet.star.sun. le pasamos como parámetros.sheet.AUTO com.sun.GeneralFunction.sun.star. por último.GeneralFunction.COUNTNUMS com.298 'Aplicamos el subtotal oRango. y dependiendo de como estén tus datos origen.sun. aplicamos (applySubTotals) los subtotales. te creara un nuevo descriptor vacío.GeneralFunction.applySubTotals( oDesSubTotal.star. pues si agregas criterios “inconsistentes”.STDEV com.star. del rango seleccionado. o agregamos al existente (False).sun.sheet.sheet. si al método del rango de celdas para crear el descriptor del subtotal (createSubTotalDescriptor). ahí mismo.sun.star.star.GeneralFunction. basada en la enumeración com. el resultado puede ser impreciso y desastroso visualmente hablando.star. si lo hay. te puede dar resultados incorrectos.star.sheet.star.sheet.MAX com.sun.7 Rangos de datos El área de datos (DataBaseRanges). si lo hay.star. tomará el existente.GeneralFunction com. Aprendiendo OOo Basic 299 If oRangosBD.hasByName( "Peliculas" ) Then oPeliculas = oRangosBD.getByName( "Peliculas" ) oRango = oPeliculas.ReferredCells() 'Quitamos el subtotal oRango.removeSubTotals() End If End Sub Como se muestra en el siguiente ejemplo, no es indispensable usar un área de datos para hacer uso de los subtotales, al ser métodos implementados en rangos de celda, podemos invocarlos desde cualquiera de estos. La siguiente macro, nos da el total de títulos por genero y suma la cantidad de minutos del mismo. Sub Dim Dim Dim Dim Subtotales3() oDoc As Object oSel As Object oDesSubTotal As Object mCamposSubTotal(1) As New com.sun.star.sheet.SubTotalColumn oDoc = ThisComponent oSel = oDoc.getCurrentSelection() 'Si es una sola celda o un rango de celdas If oSel.getImplementationName = "ScCellRangeObj" Or oSel.getImplementationName = "ScCellObj" Then oSel = oSel.getSpreadSheet.createCursorByRange(oSel) 'Expandimos a la región actual oSel.collapseToCurrentRegion() 'Creamos el descriptor a partir de la selección oDesSubTotal = oSel.createSubTotalDescriptor( True ) oDesSubTotal.EnableSort = True oDesSubTotal.SortAscending = True 'Columna de titulos mCamposSubTotal(0).Column = 1 mCamposSubTotal(0).Function = com.sun.star.sheet.GeneralFunction.COUNT 'Columna de minutos mCamposSubTotal(1).Column = 6 mCamposSubTotal(1).Function = com.sun.star.sheet.GeneralFunction.SUM 'Aplicamos al genero oDesSubTotal.addNew( mCamposSubTotal,3 ) oSel.applySubTotals( oDesSubTotal, True ) Else MsgBox "No es un rango de celdas" End If End Sub El siguiente ejemplo, nos muestra cuantos títulos tenemos por país, y después otro subtotal nos indica cuantos títulos por genero, “dentro” de cada país tenemos: Sub Dim Dim Dim Dim Subtotales4() oDoc As Object oSel As Object oDesSubTotal As Object mCamposSubTotal(0) As New com.sun.star.sheet.SubTotalColumn oDoc = ThisComponent oSel = oDoc.getCurrentSelection() 'Si es una sola celda o un rango de celdas If oSel.getImplementationName = "ScCellRangeObj" Or oSel.getImplementationName = "ScCellObj" Then oSel = oSel.getSpreadSheet.createCursorByRange(oSel) oSel.collapseToCurrentRegion() oDesSubTotal = oSel.createSubTotalDescriptor( True ) oDesSubTotal.EnableSort = True 300 oDesSubTotal.SortAscending = True 'Columna de títulos mCamposSubTotal(0).Column = 1 mCamposSubTotal(0).Function = com.sun.star.sheet.GeneralFunction.COUNT 'Aplicamos al país oDesSubTotal.addNew( mCamposSubTotal,5 ) 'Columna de títulos mCamposSubTotal(0).Column = 1 mCamposSubTotal(0).Function = com.sun.star.sheet.GeneralFunction.COUNT 'Aplicamos al genero oDesSubTotal.addNew( mCamposSubTotal,3 ) oSel.applySubTotals( oDesSubTotal, True ) Else MsgBox "No es un rango de celdas" End If End Sub 6.7 Rangos de datos Observa, que hemos establecido la matriz de campos dos veces y usado el método addNew también dos veces para lograr el resultado deseado. Solo puedes sacar subtotales por hasta un máximo de tres grupos. El orden en que establezcas y agregues los campos, será el orden de precedencia de los subtotales. La obtención de subtotales, tiene un valor agregado bastante útil, al realizar la operación establecida en algún campo, la herramienta hace una comparación “exacta” de cada valor, por lo que te podrás dar cuenta si tienes campos con, por ejemplo, espacios vacíos de más, al principio o al final de el, o en el caso de tener valores de campo muy similares, si un registro tiene solo un error de “dedo”, con los subtotales te podrás dar cuenta de forma visual muy fácilmente, sobre todo cuando haces uso de la función cuenta, revisa los registros que solo tengan un solo registro, por supuesto, tu debes determinar si es correcto o no. Para ejemplificar esto, si estas usando la misma base de datos que yo, saca un subtotal por genero, busca y observa los géneros “Comedia” y “Drama”, y cuéntame cual es el error. Esa es tu tarea que no es mucha. 6.7.5 Validando datos A estas alturas del libro, te habrás dado cuenta de la importancia de validar la información que el usuario le proporciona a un programa, una gran cantidad de programas, fallan en este tema de, creo yo, alta prioridad. Calc cuenta con una herramienta llamada Validez, presente en el menú Datos, que nos permite establecer criterios en celdas para la captura de información por parte del usuario y limitarlo en la medida de lo posible, a capturar dados válidos en el programa, informando, si lo deseas, con cuadros de mensaje para ayudarle a introducir la información correctamente. Aprendiendo OOo Basic 301 Veamos como establecer estas opciones por código. En el siguiente ejemplo, establecemos que las celdas seleccionadas, solo puedan aceptar números enteros del 1 al 12, es decir, un entero correspondiente a un mes del año: Sub Dim Dim Dim ValidarDatos1() oDoc As Object oSel As Object oValidacion As Object oDoc = ThisComponent oSel = oDoc.getCurrentSelection() 'Validamos que sea una celda o un rango de celdas If oSel.getImplementationName = "ScCellObj" Or oSel.getImplementationName = "ScCellRangeObj" Then 'Obtenemos la estructura validación oValidacion = oSel.getPropertyValue("Validation") 'Establecemos sus propiedades With oValidacion 'El tipo de validación .Type = com.sun.star.sheet.ValidationType.WHOLE 'El operador de la validación .setOperator ( com.sun.star.sheet.ConditionOperator.BETWEEN ) 'Establecemos la primer condición .setFormula1 ( "1" ) 'Establecemos la segunda .setFormula2 ( "12" ) 'Que ignore las celdas en blanco .IgnoreBlankCells = True 'Que muestre un mensaje al seleccionar la celda .ShowInputMessage = True 'El titulo del mensaje .InputTitle = "Introduce el mes del año" 'El mensaje .InputMessage = "Captura un número entre 1 y 12" 'Que muestre un mensaje si la condición no se cumple .ShowErrorMessage = True 'El estilo del mensaje de alerta .ErrorAlertStyle = com.sun.star.sheet.ValidationAlertStyle.STOP 'El titulo del mensaje de error .ErrorTitle = "Dato erroneo" 'El mensaje de error .ErrorMessage = "El valor introducido no es un número entre 1 y 12" End With 'Reinsertamos la propiedad para que surtan efecto los cambios oSel.setPropertyValue("Validation", oValidacion) End If End Sub 302 6.7 Rangos de datos Observa como estamos obteniendo la estructura de validación (getPropertyValue), pasándole como argumento, el nombre de la propiedad que nos interesa. Las restantes propiedades son: el tipo (Type), se refiere al tipo de validación que haremos y esta condicionado por la enumeración com.sun.star.sheet.ValidationType, cuyos posibles valores son: com.sun.star.sheet.ValidationType com.sun.star.sheet.ValidationType.ANY com.sun.star.sheet.ValidationType.WHOLE com.sun.star.sheet.ValidationType.DECIMAL com.sun.star.sheet.ValidationType.DATE com.sun.star.sheet.ValidationType.TIME com.sun.star.sheet.ValidationType.TEXT_LEN com.sun.star.sheet.ValidationType.LIST com.sun.star.sheet.ValidationType.CUSTOM Valor 0 1 2 3 4 5 6 7 Valor en Interfaz Cualquier valor Entero Decimal Fecha Hora Longitud de texto Lista Formula Después, establecemos el operador (setOperator), para evaluar la condición, esta propiedad puede tomar los siguientes valores: com.sun.star.sheet.ConditionOperator com.sun.star.sheet.ConditionOperator.NONE com.sun.star.sheet.ConditionOperator.EQUAL com.sun.star.sheet.ConditionOperator.NOT_EQUAL com.sun.star.sheet.ConditionOperator.GREATER com.sun.star.sheet.ConditionOperator.GREATER_EQUAL com.sun.star.sheet.ConditionOperator.LESS com.sun.star.sheet.ConditionOperator.LESS_EQUAL com.sun.star.sheet.ConditionOperator.BETWEEN com.sun.star.sheet.ConditionOperator.NOT_BETWEEN com.sun.star.sheet.ConditionOperator.FORMULA Valor 0 1 2 3 4 5 6 7 8 9 Valor en Interfaz Ninguna Igual Distinta de Mayor que Mayor o igual Menor que Menor o igual Entre No entre Formula Dependiendo de que operador selecciones, puede que necesites establecer el primer valor de comparación (setFormula1), y también el segundo (setFormula2), comúnmente los operadores “entre” (BETWEEN), y “no entre” (NOT_BETWEEN), son los que requieren los dos valores. Podemos determinar si la validación ignora o no, las celdas en blanco (IgnoreBlankCells), pero debes de saber que esta propiedad no determina el validar celdas vacía o no, si no que trabaja en conjunto la utilidad Detective del menú Herramientas, para determinar si una celda vacía se considera error o no. Podemos mostrar un mensaje (ShowInputMessage), cuando el usuario seleccione una celda, establecer su titulo (InputTitle), y el mensaje que verá (InputMessage), este texto orienta al usuario sobre los valores a introducir. En caso de que el valor capturado por el usuario, no satisfaga las condiciones de la validación, podemos mostrar un mensaje de error (ShowErrorMessage), de determinado estilo (ErrorAlertStyle), este estilo, determinará la acción a tomar con el valor capturado, este estilo esta determinado por los siguientes valores: com.sun.star.sheet.ValidationAlertStyle com.sun.star.sheet.ValidationAlertStyle.STOP Valor 0 Valor en Interfaz Stop Aprendiendo OOo Basic 303 com.sun.star.sheet.ValidationAlertStyle com.sun.star.sheet.ValidationAlertStyle.WARNING com.sun.star.sheet.ValidationAlertStyle.INFO com.sun.star.sheet.ValidationAlertStyle.MACRO Valor 1 2 3 Valor en Interfaz Advertencia Información Macro Si estableces el valor en “stop” (STOP), se mostrara al usuario un mensaje (ErrorMessage) con un titulo (ErrorTitle) para informarle del error, al aceptar, la celda regresará al valor inmediato anterior, en los casos de “advertencia” (WARNING) e “información” (INFO), quedará a criterio del usuario si acepta o no el nuevo valor aun y cuando no cumpla la condición y en el caso de la opción “macro” (MACRO), puedes escoger una macro a ejecutar, para, por ejemplo, mostrar un mensaje más elaborado o realizar una operación más compleja. Por ultimo, es importante, “reinsertar” (setPropertyValue) la propiedad al objeto para que los cambios surtan efecto. Para quitar una validación, solo establece el tipo (Type) en cualquier valor (ANY) y deshabilita el mensaje de entrada (ShowInputMessage). Sub Dim Dim Dim ValidarDatos2() oDoc As Object oSel As Object oValidacion As Object oDoc = ThisComponent oSel = oDoc.getCurrentSelection() 'Validamos que sea una celda o un rango de celdas If oSel.getImplementationName = "ScCellObj" Or oSel.getImplementationName = "ScCellRangeObj" Then 'Obtenemos la estructura validación oValidacion = oSel.getPropertyValue("Validation") 'El tipo de validación oValidacion.Type = com.sun.star.sheet.ValidationType.ANY 'Que muestre un mensaje al seleccionar la celda oValidacion.ShowInputMessage = False 'Reinsertamos la propiedad para que surtan efecto los cambios oSel.setPropertyValue("Validation", oValidacion) End If End Sub El tipo decimal, te permite capturar números con decimales: Sub Dim Dim Dim ValidarDatos3() oDoc As Object oSel As Object oValidacion As Object oDoc = ThisComponent oSel = oDoc.getCurrentSelection() If oSel.getImplementationName = "ScCellObj" Or oSel.getImplementationName = "ScCellRangeObj" Then oValidacion = oSel.getPropertyValue("Validation") With oValidacion .Type = com.sun.star.sheet.ValidationType.DECIMAL .setOperator ( com.sun.star.sheet.ConditionOperator.BETWEEN ) .setFormula1 ( "0" ) .setFormula2 ( "10" ) .IgnoreBlankCells = True .ShowInputMessage = True .InputTitle = "Introduce la calificacion" .InputMessage = "Puedes usar decimales" .ShowErrorMessage = True .ErrorAlertStyle = com.sun.star.sheet.ValidationAlertStyle.INFO .ErrorTitle = "Dato erroneo" .ErrorMessage = "El valor introducido no es válido" 304 End With 'Reinsertamos la propiedad para que surtan efecto los cambios oSel.setPropertyValue("Validation", oValidacion) End If End Sub 6.7 Rangos de datos En el siguiente ejemplo, validamos que no sea una fecha futura, nota el uso de la función incorporada de Calc. Sub Dim Dim Dim ValidarDatos4() oDoc As Object oSel As Object oValidacion As Object oDoc = ThisComponent oSel = oDoc.getCurrentSelection() If oSel.getImplementationName = "ScCellObj" Or oSel.getImplementationName = "ScCellRangeObj" Then oValidacion = oSel.getPropertyValue("Validation") With oValidacion .Type = com.sun.star.sheet.ValidationType.DATE .setOperator ( com.sun.star.sheet.ConditionOperator.LESS_EQUAL ) 'Usamos una formula como condición .setFormula1 ( "TODAY()" ) .IgnoreBlankCells = True .ShowInputMessage = True .InputTitle = "Fecha de Nacimiento" .InputMessage = "La fecha no puede ser futura" .ShowErrorMessage = True .ErrorAlertStyle = com.sun.star.sheet.ValidationAlertStyle.WARNING .ErrorTitle = "Dato erroneo" .ErrorMessage = "El valor introducido no es válido" End With oSel.setPropertyValue("Validation", oValidacion) End If End Sub Ahora, solo puede capturar una hora que no sea entre 1 p.m. 3 p.m.: Sub Dim Dim Dim ValidarDatos5() oDoc As Object oSel As Object oValidacion As Object oDoc = ThisComponent oSel = oDoc.getCurrentSelection() If oSel.getImplementationName = "ScCellObj" Or oSel.getImplementationName = "ScCellRangeObj" Then oValidacion = oSel.getPropertyValue("Validation") With oValidacion .Type = com.sun.star.sheet.ValidationType.TIME .setOperator ( com.sun.star.sheet.ConditionOperator.NOT_BETWEEN ) 'Introducir una hora que no sea entre 1 y 3 p.m. .setFormula1 ( "TIME(13;0;0" ) .setFormula2 ( "TIME(15;0;0" ) .IgnoreBlankCells = True .ShowInputMessage = True .InputTitle = "Hora de salida" .InputMessage = "La hora de salir" .ShowErrorMessage = True .ErrorAlertStyle = com.sun.star.sheet.ValidationAlertStyle.STOP .ErrorTitle = "Dato erroneo" .ErrorMessage = "El valor introducido no es válido" End With oSel.setPropertyValue("Validation", oValidacion) Aprendiendo OOo Basic End If End Sub 305 Observa que estamos haciendo uso de la función de Calc, NSHORA (TIME), que te devuelve el número de serie de la hora pasada, esto es necesario para establecer los limites correctamente. En el siguiente ejemplo, establecemos que los valores los tome desde un rango de celdas, observa que las referencias al rango son absolutas: Sub Dim Dim Dim ValidarDatos6() oDoc As Object oSel As Object oValidacion As Object oDoc = ThisComponent oSel = oDoc.getCurrentSelection() If oSel.getImplementationName = "ScCellObj" Or oSel.getImplementationName = "ScCellRangeObj" Then oValidacion = oSel.getPropertyValue("Validation") With oValidacion .Type = com.sun.star.sheet.ValidationType.LIST 'Introducir valores desde un rango de celdas .setFormula1 ( "$I$2:$I$8" ) .ShowErrorMessage = True .ErrorAlertStyle = com.sun.star.sheet.ValidationAlertStyle.STOP .ErrorTitle = "Dato erroneo" .ErrorMessage = "El valor introducido no es válido" End With oSel.setPropertyValue("Validation", oValidacion) End If End Sub Pero también podemos establece el rango desde un rango de celda con nombre, por ejemplo: Sub Dim Dim Dim ValidarDatos7() oDoc As Object oSel As Object oValidacion As Object oDoc = ThisComponent oSel = oDoc.getCurrentSelection() If oSel.getImplementationName = "ScCellObj" Or oSel.getImplementationName = "ScCellRangeObj" Then oValidacion = oSel.getPropertyValue("Validation") With oValidacion .Type = com.sun.star.sheet.ValidationType.LIST 'Introducir valores desde un rango de celdas .setFormula1 ( "valores" ) .ShowList = 2 .ShowErrorMessage = True .ErrorAlertStyle = com.sun.star.sheet.ValidationAlertStyle.STOP .ErrorTitle = "Dato erroneo" .ErrorMessage = "El valor introducido no es válido" End With oSel.setPropertyValue("Validation", oValidacion) End If End Sub Recuerda que los rangos con nombre los establecemos, en la interfaz del usuario, desde el cuadro de nombres de la barra de formulas, o por código, como hemos aprendido en este libro, aunque también puedes usar un nombre de área de datos definida en el menú Datos | 306 6.7 Rangos de datos Definir..., de hecho, puedes usar cualquier texto o formula que te devuelva un rango de celdas válido, si el rango de celdas tiene más de una columna, solo se usara la primer columna. Observa que hemos usado una nueva propiedad (ShowList), cuando el tipo de la validación esta establecida en “lista” (LIST), podemos determinar si mostramos la flecha de lista de selección, el valor 2 determina que se muestre con los valores ordenados de forma ascendente, el valor 1 que se muestre pero que no ordene los valores, que los muestre tal y como están en el origen, y el valor 0 que no se muestre la lista de selección, algo no muy recomendable cuando se usa una lista. Estos valores corresponden a: com.sun.star.sheet.TableValidationVisibility com.sun.star.sheet.TableValidationVisibility.INVISIBLE com.sun.star.sheet.TableValidationVisibility.UNSORTED com.sun.star.sheet.TableValidationVisibility.SORTEDASCENDING Valor 0 1 2 Valor en Interfaz No mostrar lista Mostrar desordenada Mostrar ordenada ascendente En el siguiente ejemplo, establecemos el origen de celdas con formulas de Calc, esta formula debe estar bien construida, si no, no te dará el rango correcto: Sub Dim Dim Dim ValidarDatos8() oDoc As Object oSel As Object oValidacion As Object oDoc = ThisComponent oSel = oDoc.getCurrentSelection() If oSel.getImplementationName = "ScCellObj" Or oSel.getImplementationName = "ScCellRangeObj" Then oValidacion = oSel.getPropertyValue("Validation") With oValidacion .Type = com.sun.star.sheet.ValidationType.LIST 'Introducir valores desde un rango de celdas .setFormula1 ( "INDIRECT(ADDRESS(1;1)&"":""&ADDRESS(10;1))" ) .ShowList = 2 .ShowErrorMessage = True .ErrorAlertStyle = com.sun.star.sheet.ValidationAlertStyle.STOP .ErrorTitle = "Dato erroneo" .ErrorMessage = "El valor introducido no es válido" End With oSel.setPropertyValue("Validation", oValidacion) End If End Sub Recuerda que la función DIRECCION (ADDRESS), nos devuelve una referencia en forma de texto, de acuerdo a los parámetros pasados, después, la función INDIRECTO (INDIRECT), nos devuelve, de una cadena de texto que tenga un rango de celda válido, la referencia a dicha celda. Como a la función DIRECCION se le pueda establecer entre sus parámetros el nombre de una hoja, te queda de tarea modificar la macro anterior para que el rango de celdas de la validación, este en una hoja diferente. El poder de hacerlo con funciones o desde código, es que la lista de validación la puedes actualizar dinámicamente, por ejemplo, una lista de clientes que va creciendo confirme vamos agregando registros o cualquier otro listado que vaya creciendo en sentido vertical. Otra posibilidad, es introducir una lista fija de valores, o semifija, pues desde código la podemos actualizar siempre que queramos, veamos como: Sub ValidarDatos9() Dim oDoc As Object Aprendiendo OOo Basic Dim oSel As Object Dim oValidacion As Object 307 oDoc = ThisComponent oSel = oDoc.getCurrentSelection() If oSel.getImplementationName = "ScCellObj" Or oSel.getImplementationName = "ScCellRangeObj" Then oValidacion = oSel.getPropertyValue("Validation") With oValidacion .Type = com.sun.star.sheet.ValidationType.LIST 'Introducir valores fijos .setFormula1 ( "VALOR1;VALOR2;VALOR3" ) .ShowList = 2 .ShowErrorMessage = True .ErrorAlertStyle = com.sun.star.sheet.ValidationAlertStyle.STOP .ErrorTitle = "Dato erroneo" .ErrorMessage = "El valor introducido no es válido" End With oSel.setPropertyValue("Validation", oValidacion) End If End Sub Ve a la interfaz del usuario y observa como “aparentemente”, si agrego los valores, pero observa que están en minúsculas, cuando nosotros los agregamos en mayúsculas, verifica desde la interfaz de usuario, desde Datos | Validez..., que esta forma de introducir los datos fijos, la detecta como si fuera un intervalo de celdas, lo cual es incorrecto, para que realmente la detecte como una lista “fija” de valores, tienes que pasarle cada valor como una cadena, como en el siguiente ejemplo: Sub Dim Dim Dim ValidarDatos10() oDoc As Object oSel As Object oValidacion As Object oDoc = ThisComponent oSel = oDoc.getCurrentSelection() If oSel.getImplementationName = "ScCellObj" Or oSel.getImplementationName = "ScCellRangeObj" Then oValidacion = oSel.getPropertyValue("Validation") With oValidacion .Type = com.sun.star.sheet.ValidationType.LIST 'Introducir valores fijos .setFormula1 ( """VALOR1"""&";"&"""VALOR2"""&";"&"""VALOR3""" ) .ShowList = 2 .ShowErrorMessage = True .ErrorAlertStyle = com.sun.star.sheet.ValidationAlertStyle.STOP .ErrorTitle = "Dato erroneo" .ErrorMessage = "El valor introducido no es válido" End With oSel.setPropertyValue("Validation", oValidacion) End If End Sub Pero ve que cantidad de comillas, ¿y son muchos valores?, podemos hacer una función que agregue las comillas por nosotros, como en el siguiente ejemplo: Sub Dim Dim Dim Dim Dim ValidarDatos11 sTmp As String m oDoc As Object oSel As Object oValidacion As Object ".setFormula2 ( "10" ) . El siguiente ejemplo te limita la entrada a una palabra de entre 5 y 10 letras. es preferible agregar unas cuantas líneas más de código a correr el riesgo de que un dato inconsistente nos devuelva información inconsistente.sun.ValidationType.sheet.getImplementationName = "ScCellObj" Or oSel.setPropertyValue("Validation".ErrorAlertStyle = com. pero sobre todo.getImplementationName = "ScCellRangeObj" Then oValidacion = oSel.setOperator ( com.STOP .ConditionOperator." ) End Function Ahora si.BETWEEN ) .star.setPropertyValue("Validation".Type = com. no te acepta solo números. sentido común.sheet.sheet. no lo tomes como un tema menor.TEXT_LEN .star. oValidacion) End If End Sub 'Toma una matriz y le agrega comillas a cada elemento 'Devuelve una cadena con los elementos.sun.ValidationType. . imaginación.sun.308 6."Cuatro".getCurrentSelection() If oSel.LIST .getCurrentSelection() If oSel.star.sheet.IgnoreBlankCells = True ." Function JuntarEnLista( ByVal m ) As String Dim co1 As Long For co1 = LBound(m) To UBound(m) m(co1) = """" & m(co1) & """" Next JuntarEnLista = Join( m.ShowErrorMessage = True . inteligencia. explotalos."Cinco") 'Los juntamos sTmp = JuntarEnLista(m) . y aun más desde código.setFormula1 ( "5" ) .star. la validación de datos es un tema central en la programación."Tres".ErrorMessage = "La palabra debe ser de entre 5 y 10 caracteres" End With 'Reinsertamos la propiedad para que surtan efecto los cambios oSel.7 Rangos de datos oDoc = ThisComponent oSel = oDoc. Tienes instrucciones limitadas pero suficientes para evitarlo y tienes algo ilimitado. es un poco más fácil agregar valores a una lista."Dos".getPropertyValue("Validation") With oValidacion . solo letras o alfanuméricas: Sub Dim Dim Dim ValidarDatos12() oDoc As Object oSel As Object oValidacion As Object oDoc = ThisComponent oSel = oDoc.ErrorTitle = "Longitud erronea" .sun.ValidationAlertStyle.getPropertyValue("Validation") With oValidacion 'Valores a agregar m = Array("Uno".setFormula1( sTmp ) End With oSel.getImplementationName = "ScCellRangeObj" Then oValidacion = oSel.Type = com. separados por ". oValidacion) End If End Sub Tanto en la interfaz del usuario.ShowList = 2 .getImplementationName = "ScCellObj" Or oSel. Aprendiendo OOo Basic 309 6.Sheet 'La columna de inicio . que el índice de hoja exista.EndColumn = 4 End With 'Creamos el grupo. puedes provocar una caída de la aplicación. agrupamos las primeras diez filas de la hoja activa: Sub Dim Dim Dim Agrupar2() oDoc As Object oHojaActiva As Object oRango As New com.EndRow = 9 End With 'Y agrupamos. estén dentro de rangos válidos.6 Agrupando datos Cuando se maneja una gran cantidad de información.star. 0 = por columnas oHojaActiva.CellRangeAddress oDoc = ThisComponent oHojaActiva = oDoc.getCurrentController. 0 ) End Sub La macro anterior nos agrupará las columnas 1 a 5 en la interfaz del usuario. es muy importante que validez que la hoja y el rango de columnas establecidas. podemos probar lo siguiente: Sub Dim Dim Dim Agrupar1() oDoc As Object oHojaActiva As Object oRango As New com.getRangeAddress.sun.getActiveSheet() With oRango . 1 = por filas oHojaActiva. Ahora. le pasamos una estructura de dirección de un rango (CellRangeAddress).7. encontrar una manera simple y rápida de agrupar datos.star.getCurrentController.StartColumn = 0 'La columan de fin .StartRow = 0 . que no es más que ocultarlas.group( oRango.getActiveSheet() 'Establecemos las propiedades del grupo With oRango 'La hoja donde se creará .CellRangeAddress oDoc = ThisComponent oHojaActiva = oDoc. el ordenar y los subtotales.table.Sheet = oHojaActiva. Observa como al agrupar (group).sun. puede ser la diferencia entre eficiencia e ineficiencia.getRangeAddress.Sheet = oHojaActiva. los filtros. estamos verificando el ¿porque? de esto.Sheet 'Ahora establecemos el rango de filas . son herramientas que pueden apoyarnos. vista muchas veces en este libro y como segundo argumento.table. cuando simplemente necesitemos agrupar por un rango de columnas o filas. por ejemplo. si queremos que se agrupe por columnas (0) o por filas (1). si no. 1 ) End Sub .group( oRango. group( oRango.EndRow = 19 End With 'Agrupamos por columnas 10 a la 20 oHojaActiva.ungroup( oRango. 0 ) oHojaActiva. es suficiente. usa los mismos argumentos que para agrupar.Sheet = oHojaActiva.StartColumn = 0 . no tiene que coincidir exactamente.sun.sun.StartRow = 9 .getActiveSheet() With oRango .star.7 Rangos de datos Por supuesto.Sheet . antes de comprobarlo.table.Sheet = oHojaActiva.ungroup( oRango. lo que borrara cualquier grupo creado.table. con que este “dentro” del rango con que se agrupo.star.getCurrentController.StartRow = 0 .EndColumn = 4 . la segunda: Sub Dim Dim Dim Agrupar5() oDoc As Object oHojaActiva As Object oRango As New com. 1 ) End Sub Desagrupar (ungroup) es trivial.CellRangeAddress oDoc = ThisComponent oHojaActiva = oDoc.group( oRango.EndColumn = 19 . al rango original de agrupamiento.getCurrentController.getRangeAddress.CellRangeAddress .StartColumn = 9 .getActiveSheet() With oRango .sun. en tamaño. desde la hoja donde estés haciendo estas pruebas. ejecuta la primer macro siguiente e inmediatamente después. como en el siguiente ejemplo: Sub Dim Dim Dim Agrupar3() oDoc As Object oHojaActiva As Object oRango As New com. 0 ) 'Agrupamos por filas 10 a 20 oHojaActiva.getRangeAddress.Sheet . puedes establecer.table. Sub Dim Dim Dim Agrupar4() oDoc As Object oHojaActiva As Object oRango As New com. con la misma estructura.EndRow = 9 End With 'Deagrupamos filas y columnas oHojaActiva. después.CellRangeAddress oDoc = ThisComponent oHojaActiva = oDoc. tanto las columnas como las filas.310 6. 1 ) End Sub El rango usado para desagrupar (ungroup).star. ve al menú Datos | Agrupar y Esquema | Eliminar. 1 ) End Sub Sub Dim Dim Dim Agrupar6() oDoc As Object oHojaActiva As Object oRango As New com.Sheet 'Solo indicamos la primer columna y fila . pero asegurate.table.Aprendiendo OOo Basic 311 oDoc = ThisComponent oHojaActiva = oDoc. para evitar esto.getActiveSheet() With oRango .Sheet = oHojaActiva.EndRow = 0 End With 'Desagrupamos filas y columnas oHojaActiva.sun. el rango a desagrupar.StartColumn = 0 .ungroup( oRango. ahora sí.getRangeAddress.EndColumn = 0 .EndRow = 19 End With 'Agrupamos filas (1-20) y columnas (1-10) oHojaActiva.ungroup( oRango.getCurrentController.sun. 0 ) oHojaActiva. antes de desagrupar.getActiveSheet() With oRango .EndColumn = 9 .EndRow = 19 .getCurrentController. antes de desagrupar.StartColumn = 0 . vuelve a realizar la prueba anterior.EndColumn = 9 . ejecuta la macro para desagrupar.CellRangeAddress oDoc = ThisComponent oHojaActiva = oDoc.group( oRango. este “dentro” del rango agrupado.Sheet 'Solo indicamos la primer columna y fila . notaras que el rango usado seguirá oculto.StartRow = 0 . se mostrarán inmediatamente. 1 ) End Sub Observa como agrupamos por un rango y desagrupamos por otro. contrae el grupo para ocultar su contenido.Sheet = oHojaActiva.getCurrentController. no sucede lo mismo cuando lo haces por código.group( oRango.Sheet .getRangeAddress. 0 ) oHojaActiva.star.table.StartRow = 0 .StartRow = 0 . si el grupo esta contraído.Sheet = oHojaActiva.StartColumn = 0 .getActiveSheet() With oRango . Cuando eliminas los grupos desde la interfaz del usuario. asegurate de mostrar el detalle del rango como en el siguiente ejemplo: Sub Dim Dim Dim Agrupar7() oDoc As Object oHojaActiva As Object oRango As New com. de que.getRangeAddress. las columnas o filas ocultas.star. donde solo nos tenemos que asegurar que.CellRangeAddress oDoc = ThisComponent oHojaActiva = oDoc. el rango agrupado (group).EndColumn = 5 End With .sun.group( oRango. 1 ) End Sub 6.sun.getActiveSheet() oHojaActiva. 0 ) oHojaActiva.Sheet = oHojaActiva.table. es mucho más sencillo.getCurrentController.clearOutline() With oRango .star. sucederá cualquiera de las siguientes acciones.ungroup( oRango.ungroup( oRango.clearOutline() End Sub Con lo cual.EndColumn = 3 End With 'Agrupamos las columnas 1-4 oHojaActiva. en el primero comprobamos que se agregan los grupos en niveles: Sub Dim Dim Dim Agrupar9() oDoc As Object oHojaActiva As Object oRango As New com.CellRangeAddress oDoc = ThisComponent oHojaActiva = oDoc. eliminar cualquier grupo y volver a crear el necesario. lo cual. se creará un nuevo nivel de agrupamiento. puedes crear hasta ocho niveles de ellos. dependiendo de si exista o no previamente uno en el rango pasado.star. Cuando agregas grupos.showDetail( oRango ) 'Desagrupamos filas y columnas oHojaActiva. se agregará al mismo nivel.table.Sheet .group( oRango. en ocasiones.StartColumn = 0 .getActiveSheet() 'Eliminamos cualquier grupo de la hoja oHojaActiva.getCurrentController. si el rango no contiene un grupo. 0 ) With oRango .7 Rangos de datos El ejemplo anterior funcionará.CellRangeAddress oDoc = ThisComponent oHojaActiva = oDoc. veamoslo con ejemplos. Si lo que quieres es eliminar cualquier grupo existente en una hoja.getRangeAddress.StartColumn = 0 . podría no ser tan fácil de conocer. si el rango ya contiene un grupo. este.StartColumn = 0 . siempre y cuando.312 End With 'Expandimos el grupo contenido en el rango oHojaActiva. 0 ) With oRango . usamos: Sub Dim Dim Dim Agrupar8() oDoc As Object oHojaActiva As Object oRango As New com.EndColumn = 1 End With 'Agrupamos las columnas 1-2 oHojaActiva. corresponda “exactamente” con el rango mostrado (showDetail) y con el rango desagrupado (ungroup). 0 ) End Sub 313 Ahora.getCurrentController. 1 ) End Sub Y lo comprobamos: Puedes crear un grupo y ocultarlo inmediatamente.getRangeAddress.group( oRango.star. 1 ) With oRango . veamos como agregar al mismo nivel: Sub Dim Dim Dim Agrupar10() oDoc As Object oHojaActiva As Object oRango As New com.group( oRango.EndRow = 8 End With 'Agrupamos la fila 4 a 7 oHojaActiva.StartRow = 5 .StartRow = 0 .EndRow = 3 End With 'Agrupamos la fila 1 a 4 oHojaActiva.CellRangeAddress oDoc = ThisComponent oHojaActiva = oDoc. 1 ) With oRango .group( oRango.StartRow = 10 .EndRow = 13 End With 'Agrupamos la fila 9 a 12 oHojaActiva.getActiveSheet() oHojaActiva.Sheet . como en: .sun.clearOutline() With oRango .group( oRango.Aprendiendo OOo Basic 'Agrupamos las columnas 1-6 oHojaActiva.Sheet = oHojaActiva.table. table.CellRangeAddress oDoc = ThisComponent oHojaActiva = oDoc.getCurrentController.Sheet .getRangeAddress.group( oRango. También tienes la posibilidad de mostrar cualquier nivel de agrupamiento.group( oRango. los demás niveles hacia arriba. el nivel a mostrar como primero y como segundo parámetro.StartColumn = 0 . se cerraran: Sub Dim Dim Dim Agrupar12() oDoc As Object oHojaActiva As Object oRango As New com.sun.group( oRango.EndRow = 4 End With oHojaActiva.Sheet . solo usa dos parámetros. 1 ) 'Mostramos el nivel 2 oHojaActiva.StartRow = 0 .Sheet = oHojaActiva. con que apunte a cualquier celda dentro del rango a ocultar.star.Sheet = oHojaActiva.StartRow = 0 . 1 ) With oRango .EndRow = 14 End With oHojaActiva.StartRow = 0 .EndRow = 19 End With oHojaActiva.getRangeAddress. el rango no necesariamente debe ser del mismo tamaño.star.sun.314 6. cuando lo ocultas (hideDetail). 1 ) End Sub El método para mostrar un nivel especifico (showLevel).EndRow = 9 End With oHojaActiva. funcionará.group( oRango.group( oRango. si los hay. 1 ) With oRango . 0 ) 'Ocultamos el grupo contenido en el rango oHojaActiva.table.showLevel( 2.getActiveSheet() With oRango .CellRangeAddress oDoc = ThisComponent oHojaActiva = oDoc.EndColumn = 9 End With oHojaActiva.getActiveSheet() With oRango .hideDetail( oRango ) End Sub A diferencia de mostrar un grupo (showDetail).7 Rangos de datos Sub Dim Dim Dim Agrupar11() oDoc As Object oHojaActiva As Object oRango As New com.StartRow = 0 . 1 ) With oRango . si el nivel a mostrar esta en columnas .getCurrentController. Aprendiendo OOo Basic 315 (0) o en filas (1).getCurrentSelection() 'Obligamos a seleccionar solo una celda If oSel.EndRow End With oHojaActiva. veamos un ejemplo practico bastante útil.StartRow = co1 + 1 oRango.EndRow oHojaActiva. página por página For co1 = 0 To oCursor.getVisibleRange. 1 ) End If oHojaActiva.getCurrentController.getVisibleRange.StartRow = 0 .CellRangeAddress co1 As Long oDoc = ThisComponent oHojaActiva = oDoc.collapseToCurrentRegion() 'Obtenemos el número de filas visibles por página iNumFilPag = oDoc.getRangeAddress.StartRow .Sheet = oHojaActiva. es decir.group( oRango.group( oRango. Para terminar este tema. si tienes más filas.getImplementationName = "ScCellObj" Then 'Creamos un cursor a partir de la celda seleccionada oCursor = oHojaActiva. 1 ) Next 'Para el ultimo rango si no es exacto If co1 > oCursor.table.EndRow Then oRango.sun.EndRow = oCursor. de filas. 1 ) 'Agregamos un segundo nivel de agrupamiento.ShowLevel( 1.getActiveSheet() oSel = oDoc. teniendo el cursor dentro de un rango de celdas que tenga al menos dos pantallas de datos en sentido vertical.getRangeAddress.EndRow = co1 + iNumFilPag .getRangeAddress.getCurrentController.getCurrentController. 1 ) Else MsgBox "Selecciona solo una celda" End If End Sub Y mira que bien queda: . procura llamarla.iNumFilPag + 1 oRango.getRangeAddress. es mucho mejor pues se paginara más: Sub Dim Dim Dim Dim Dim Dim Dim Agrupar13() oDoc As Object oHojaActiva As Object oSel As Object oCursor As Object iNumFilPag As Integer oRango As New com.group( oRango.createCursorByRange( oSel ) 'Expandimos a la región actual oCursor. para que veas su uso.EndRow oDoc.EndRow = oCursor.EndRow Step iNumFilPag oRango.Sheet .StartRow = co1 .getRangeAddress.1 'Establecemos el primer nivel de agrupamiento en el total de filas With oRango .star.1 oHojaActiva. También. para ve el siguiente cuadro de dialogo: . campo. estén registradas en OOo. consulta. 6. SQL.. Dada la amplia documentación existente en castellano de estos temas.8 Bases de datos La manipulación y administración de datos. pues las herramientas presentes en ellas.. es una de las necesidades más recurrentes en usuarios de hoja de cálculo. clave primaria. facilitan enormemente esta tarea. es indispensable que las bases de datos que usemos.7 Rangos de datos Claro que el área no esta limitada a que tenga datos. selecciona la rama OpenOffice. no duplicaremos esfuerzos y te queda de tarea investigar un poco acerca de ello.org Base y después la subrama Bases de datos. puedes establecer tus criterios pero sobre todo tus necesidades particulares para agrupar. esto no es gratuito.316 6. registro. seguimos los siguientes pasos. tabla.. si no los dominas.. Para el mejor aprovechamiento de este capitulo. ve al menú Herramientas | Opciones. sería deseable que conocieras los siguientes conceptos: base de datos. índice. al menos en este capitulo. relaciones e integridad referencial.. para registrar una base de datos.. donde tienes que ver las siguientes opciones: Da clic en el botón de comando Nuevo. ahora. navega hasta la ruta donde hayas guardado la base de datos o este localizada la base de datos que quieras registrar y selecciónala. le darás clic al botón de comando Examinar. pero mi recomendación es que no uses ni espacios ni caracteres “extraños”. tienes que regresar al cuadro de dialogo anterior.. por ultimo da un clic en el botón de comando Abrir.. este nombre puedes personalizarlo a tu gusto pues acepta espacios incluso. para nuestro ejemplo. tienes que ver la ruta completa del archivo que acabas de seleccionar. dejaremos el propuesto: . Al dar clic en el botón de comando Abrir. así como el nombre propuesto con el que se registrará la base de datos.Aprendiendo OOo Basic 317 En el cual.. que te mostrará el conocido cuadro de dialogo para seleccionar archivos. pero. Solo te resta cerrar este cuadro de dialogo con el botón de comando Aceptar. solo te resta seleccionar todo con el botón de seleccionar todo. junto con todos sus objetos. expandir para mostrar su contenido.1 Importando datos Importa datos desde bases de datos registradas en OpenOffice. es trivial. 6. tendrás que ver la nueva base de datos registrada. que te mostrará estas bases en la ventana “Fuente de datos”. Agrega de una vez la otra base de datos que acompaña a estos apuntes. donde. ahora. tienes que tener los datos seleccionados. tablas y consultas. como en la siguiente imagen: . seleccionar la base de datos de nuestro interés. te lo mostrará en el panel derecho del examinador de fuentes de datos. se llama “Videoteca” y también la usaremos para nuestros ejemplos.8 Bases de datos Da un clic en el botón de comando Aceptar para regresar al primero cuadro de dialogo. el contenido de dicho objeto.8.org. arrastrar a tu documento y listo.318 6. solo tienes que presionar la tecla F4. seleccionar la tabla o consulta que quieras. por código. presente en rangos de datos. con el cual.TABLE 'El nombre del objeto fuente mOpcBD(2). primero el nombre de la base de datos mOpcBD(0).PropertyValue" 'El nombre de nuestra base de datos sBaseDatos = "Directorio" 'La tabla que nos interesa traer sTabla = "tblContactos" 'La hoja activa oHojaActiva = ThisComponent.Value = sBaseDatos 'El tipo de objeto fuente mOpcBD(1).getCurrentController. usamos el método doImport. podrás comprobarlo más adelante.sun. tenemos posibilidades “casi” ilimitadas para importar datos.org.Name = "SourceType" mOpcBD(1). por ejemplo: Sub Dim Dim Dim Dim BasesDeDatos1() oHojaActiva As Object sBaseDatos As String sTabla As String mOpcBD(2) As New "com.sheet.DataImportMode.Aprendiendo OOo Basic 319 En este capitulo.getActiveSheet() 'Las propiedades de la importación. pero claro. Para importar datos.beans.sun.Name = "SourceObject" . se le pasa una matriz de propiedades.Name = "DatabaseName" mOpcBD(0).star. aprenderemos a hacer esto mismo. con las indicaciones de que queremos importar.star. de bases de datos previamente registradas en OpenOffice. a este método.Value = com. beans. luego. consultas. por lo que tienes que ser muy cuidadoso de como nombrarlos y usar exactamente este nombre al importar.star.getCellRangeByName("A1").sheet.sun. el nombre del objeto (SourceObject) que queremos importar.NONE com.DataImportMode.DataImportMode.getActiveSheet() .getCurrentController.TABLE com.320 mOpcBD(2). a partir de la celda A1 oHojaActiva.star.sun. de lo contrario te puede alguno de los siguientes errores: Cuando el nombre de la base de datos no corresponde: Cuando la tabla este incorrecta: En el siguiente ejemplo. entonces tienes que pasarle una instrucción SQL.sheet.doImport( mOpcBD() ) End Sub 6. importamos una tabla diferente en una celda diferente: Sub Dim Dim Dim Dim BasesDeDatos2() oHojaActiva As Object sBaseDatos As String sTabla As String mOpcBD(2) As New "com. por ultimo aplicamos la importación (doImport).sun.sheet.DataImportMode com. de lo contrario te dará error al importar. El tipo de objeto esta determinado por la enumeración: com. Todos los nombres de objetos (bases de datos.star.sun.sheet.DataImportMode.PropertyValue" 'El nombre de nuestra base de datos sBaseDatos = "Directorio" 'La tabla que nos interesa traer sTabla = "tblPaises" 'La hoja activa oHojaActiva = ThisComponent.Value = sTabla 'Importamos la tabla. después. le estamos indicando el tipo de objeto (SourceType) que queremos importar.DataImportMode. campos) distingue mayúsculas de minúsculas.QUERY Valor 0 1 2 3 Valor en Interfaz Vacio Instrucción SQL Tabla Consulta Si estableces el tipo de objeto fuente en 0 (NONE).star. tablas.sheet.8 Bases de datos Nota como estamos usando el nombre con que registramos la base de datos (DatabaseName).sun.star.star.sun.SQL com. el método te devolverá un error: Importamos una consulta diferente: Sub Dim Dim Dim Dim BasesDeDatos4() oHojaActiva As Object sBaseDatos As String sConsulta As String mOpcBD(2) As New "com.sun.doImport( mOpcBD() ) End Sub Tienes que tener la precaución de que el nombre del objeto corresponda a su tipo.getCellRangeByName("A1").Value = com.Value = sConsulta 'Importamos la tabla.sheet.star.getActiveSheet() mOpcBD(0). a partir de la celda A10 oHojaActiva.doImport( mOpcBD() ) End Sub Ahora.Name = "SourceObject" mOpcBD(2).DataImportMode.Name = "SourceType" mOpcBD(1).Value = sBaseDatos 'El tipo de objeto fuente mOpcBD(1).sun.sheet. si no. primero el nombre de la base de datos mOpcBD(0). una consulta mOpcBD(1).DataImportMode.getCellRangeByName("A10").getCurrentController.TABLE 'El nombre del objeto fuente mOpcBD(2).sun. importamos una consulta (QUERY) en vez de una tabla (TABLE).star. Sub Dim Dim Dim Dim BasesDeDatos3() oHojaActiva As Object sBaseDatos As String sConsulta As String mOpcBD(2) As New "com.star.Value = com.Name = "DatabaseName" mOpcBD(0).Name = "SourceObject" mOpcBD(2).PropertyValue" sBaseDatos = "Directorio" 'Una consulta .star.Name = "DatabaseName" mOpcBD(0).Value = sBaseDatos 'El tipo de objeto fuente.Name = "SourceType" mOpcBD(1).PropertyValue" sBaseDatos = "Directorio" 'Ahora una consulta sConsulta = "qryCiudades" 'La hoja activa oHojaActiva = ThisComponent.QUERY 'El nombre del objeto fuente mOpcBD(2).Value = sTabla 'Importamos la tabla.beans.Aprendiendo OOo Basic 321 'Las propiedades de la importación. a partir de la celda A1 oHojaActiva.beans.sun. Cuando importamos tablas o consultas.Value = sBaseDatos mOpcBD(1). es decir. cualquier documentación de el “debería” servirte.star.sheet.DataImportMode. la respuesta sencilla. en “teoría”.star.beans.Name = "SourceType" 'Observa como hemos cambiado el tipo de fuente a SQL mOpcBD(1). se importan con todo su contenido. es que estamos usando una instrucción SQL para importar los datos.Value = sSQL oHojaActiva. Materno FROM tblContactos" oHojaActiva = ThisComponent. En los siguiente ejemplos.PropertyValue" sBaseDatos = "Directorio" 'Establecemos la consulta SQL sSQL = "SELECT Nombre.Name = "SourceObject" mOpcBD(2). el siguiente ejemplo. pero. Paterno y Materno) campos de la tabla (tblContactos): Sub Dim Dim Dim Dim BasesDeDatos6() oHojaActiva As Object sBaseDatos As String sSQL As String mOpcBD(2) As New "com.8 Bases de datos Cambiemos de tipo de objeto fuente. con SQL.Value = com.Value = sBaseDatos mOpcBD(1).getCellRangeByName("A1")..SQL mOpcBD(2).getCurrentController.sheet. hace exactamente lo mismo que el primer ejemplo. nos permite recuperar “casi” cualquier dato de cualquier base de datos con soporte para SQL. nos importa la tabla “tblContactos”: Sub Dim Dim Dim Dim BasesDeDatos5() oHojaActiva As Object sBaseDatos As String sSQL As String mOpcBD(2) As New "com. así que.Name = "SourceType" mOpcBD(1).star. me limitaré a darte muestras de instrucciones SQL que sean lo suficientemente ilustrativas del poder y versatilidad de este lenguaje.getActiveSheet() mOpcBD(0).getCurrentController. estas.sun.getActiveSheet() mOpcBD(0).doImport( mOpcBD() ) End Sub 6.Value = com.sun.sun.doImport( mOpcBD() ) End Sub Entonces.getCellRangeByName("A1").Name = "DatabaseName" mOpcBD(0).PropertyValue" sBaseDatos = "Directorio" 'Establecemos la consulta SQL sSQL = "SELECT * FROM tblContactos" oHojaActiva = ThisComponent. SQL es un estándar. ¿cual es la diferencia?.DataImportMode. la respuesta compleja nos podría llevar una libro completo.star.Name = "DatabaseName" mOpcBD(0). en el siguiente ejemplo. solo importamos tres (Nombre.QUERY mOpcBD(2). ¿que es SQL?. SQL es un lenguaje estructurado de consultas.322 sConsulta = "qryContactos" oHojaActiva = ThisComponent.beans.. Paterno.sun. la primera. podemos limitarnos exclusivamente a los datos que necesitamos.Value = sConsulta oHojaActiva.getActiveSheet() .getCurrentController. es obvio.Name = "SourceObject" mOpcBD(2). sheet. Materno FROM tblContactos ORDER BY Paterno" oHojaActiva = ThisComponent. filtrar y ordenar entre otras acciones a los datos importados. ordenamos (ORDER BY) los datos importados: Sub Dim Dim Dim Dim BasesDeDatos7() oHojaActiva As Object sBaseDatos As String sSQL As String mOpcBD(2) As New "com. por uno de más fácil lectura para el usuario. si el campo no existe.star. limitar.getActiveSheet() mOpcBD(0). en este segundo ejemplo.Value = sSQL oHojaActiva.sun. le indicamos explícitamente que campos queremos importar.Name = "DatabaseName" mOpcBD(0).star.DataImportMode.Name = "SourceType" mOpcBD(1).Value = sBaseDatos mOpcBD(1).Value = com.Name = "DatabaseName" mOpcBD(0).Name = "SourceType" mOpcBD(1). veamos como: Sub Dim Dim Dim BasesDeDatos8() oHojaActiva As Object sBaseDatos As String sSQL As String .star.SQL mOpcBD(2).Value = com. tenemos una clausula para cambiar el nombre original del campo. pero muchas veces este nombre no le dice mucho al usuario. tiene unos modificadores que se llaman “clausulas”. el método te devolverá un error: Nota como claramente nos esta diciendo que el campo no existe. ten mucho cuidado con los nombres de tus campos.SQL mOpcBD(2). de nuevo.sun.PropertyValue" sBaseDatos = "Directorio" 'Establecemos la consulta SQL sSQL = "SELECT Nombre.Value = sBaseDatos mOpcBD(1).Aprendiendo OOo Basic 323 mOpcBD(0).getCellRangeByName("A1"). le indicamos que queremos todo (*) con el asterisco.beans. recuerda que en los nombres se distingue entre mayúsculas y minúsculas. casi siempre se establece de forma que sea fácil de recordar y de manipular por el programador. para estos casos.sun.doImport( mOpcBD() ) End Sub Observa como en el primer ejemplo de instrucción SQL.doImport( mOpcBD() ) End Sub El nombre de los campos.Name = "SourceObject" mOpcBD(2).DataImportMode. Paterno. Las instrucciones SQL. estas no permiten complementar.Value = sSQL oHojaActiva. En el siguiente ejemplo.getCellRangeByName("A1").getCurrentController.Name = "SourceObject" mOpcBD(2).sheet. Value = sSQL oHojaActiva. Paterno As ""Apellido Paterno"".SQL mOpcBD(2). Materno As ""Apellido Materno"". para consultar una fecha especifica.star. y mostramos como podemos ordenar de forma ascendente (ASC) por un campo y de forma descendente (DESC) por otro: Sub Dim Dim Dim Dim BasesDeDatos9() oHojaActiva As Object sBaseDatos As String sSQL As String mOpcBD(2) As New "com. Cumple As Cumpleaños FROM tblContactos ORDER BY Paterno" oHojaActiva = ThisComponent.getActiveSheet() mOpcBD(0).Name = "SourceObject" mOpcBD(2).DataImportMode. no tendrás problemas con el manejo de fechas.Name = "SourceType" mOpcBD(1). para hacer consultas sobre campos de fechas.Name = "SourceType" mOpcBD(1).SQL mOpcBD(2).Name = "DatabaseName" mOpcBD(0). Director DESC" oHojaActiva = ThisComponent. nota el uso de la letra D (de Date) y las comillas en la fecha.Name = "SourceObject" mOpcBD(2). ni una más ni una menos. si estableces correctamente este criterio.sun. seguiremos usando la base de datos “Videoteca”. en el siguiente ejemplo.DataImportMode.getActiveSheet() mOpcBD(0).beans.8 Bases de datos sBaseDatos = "Directorio" 'Establecemos la consulta SQL sSQL = "SELECT Nombre.sun. el orden tiene que ser precisamente así añomes-día.sheet. Cambiemos de base de datos.getCurrentController.Value = sBaseDatos mOpcBD(1).getCellRangeByName("A1").getCurrentController. solo te mostraré esta. usamos la base de datos “Videoteca”.sun.Value = sBaseDatos mOpcBD(1). por ejemplo.star.Value = com. deben ser exactamente las necesarias.324 Dim mOpcBD(2) As New "com.getCellRangeByName("A1"). tienes que usar una sintaxis muy singular.doImport( mOpcBD() ) End Sub Como en los ejemplos siguiente solo cambia la instrucción SQL.doImport( mOpcBD() ) End Sub Nota el uso de las dobles comillas.Name = "DatabaseName" mOpcBD(0). además. En el siguiente ejemplo. ten cuidado con su uso.Value = com. Si revisas la estructura de la tabla “tblContactos” notaras que el campo “Cumple” es de tipo fecha (Date). mientras no se indique lo contrario. y estas. .sheet.PropertyValue" 6. filtramos los datos importados por el campo Pais.sun. usamos: sSQL = "SELECT * FROM tblContactos WHERE Cumple={ D '1974-01-15' }" Observa como todo el criterio de la fecha va encerrado entre llaves.PropertyValue" sBaseDatos = "Videoteca" 'Establecemos la consulta SQL sSQL = "SELECT * FROM tblVideo ORDER BY Genero ASC.Value = sSQL oHojaActiva. esto es indispensable cuando el nombre usado (AS) contenga espacios como en nuestro ejemplo.beans.star.star. La siguiente instrucción.Aprendiendo OOo Basic 325 sSQL = "SELECT * FROM tblVideo WHERE Pais='México'" Siempre que quieras establecer un criterio de filtrado usa WHERE en donde estableces el CAMPO=CRITERIO deseado y nota también. importamos todas las películas que “contengan” la palabra “anillos”: sSQL = "SELECT * FROM tblVideo WHERE Titulo LIKE '%anillos%'" Con la siguiente instrucción. tenemos una nueva clausula para importar datos entre dos valores (BETWEEN) junto con el operador “y” (AND): sSQL = "SELECT * FROM tblVideo WHERE Duracion BETWEEN 60 AND 90 ORDER BY Duracion" Ahora. por ejemplo. hace exactamente lo mismo que el anterior. y después los contamos (COUNT). en vez de regresar los distintos países que tenemos. solo que ahora hacemos uso de la clausula IN para establecer los años deseados: sSQL = "SELECT * FROM tblVideo WHERE Año IN(1974. es importante. como hacemos uso de comillas simples para el parámetro del criterio. le establecemos un nombre a este resultado (AS ""Total Países""): . lo que nos da la posibilidad de importar. observa que volvemos a hace uso de la forma CAMPO=CRITERIO: sSQL = "SELECT * FROM tblVideo WHERE Año=1974 OR Año=1986 OR Año=2000" Nuestro siguiente ejemplo. importamos todas las películas que duren entre 60 y 90 minutos ordenados por duración. importamos las películas que sean de cualquiera (OR) de los siguientes años.2000)" El siguiente ejemplo es muy interesante.1986. observa el uso de una nueva clausula LIKE sin signo igual y con el símbolo de porcentaje después de la letra deseada sin olvidar el uso de las comillas simples: sSQL = "SELECT * FROM tblVideo WHERE Titulo LIKE 'V%'" Ahora. por ejemplo. además. es una buena alternativa para encontrar campos mal capturados. además. si algún campo tiene un solo espacio de más. ya que los considerará como dos registros diferentes: sSQL = "SELECT DISTINCT Director FROM tblVideo" El lenguaje SQL. nota que primero obtenemos los países (DISTINCT Pais). solo los contamos (COUNT). 1974 o 1986 o 2000. todos los directores que tenemos en nuestra videoteca. nos importa todos los títulos que comiencen por la letra “V”. esto. por ejemplo. nos permite obtener un listado con registros únicos (DISTINCT). con esta clausula te darás cuenta cuales de ellos pueden tener este caso. también nos permite hacer algunas operaciones sobre los campos. el resultado de la consulta interior. SUM(Duracion) AS ""Duración por Genero"" FROM tblVideo GROUP BY Genero" Observa como en los ejemplos para obtener la película de máxima (MAX) y mínima (MIN) duración. donde si devolvemos todos los campos. lo establecemos como criterio (WHERE) de la consulta exterior. suficientes para tengas mucho para practicar y probar. usamos una nueva clausula que nos sirve para agrupar (GROUP BY) el resultado por algún campo. Los ejemplos de instrucciones SQL vistas en todos los ejemplos anteriores. pero creo. después. no es el único método para consultar datos en bases de datos pero si el más sencillo. este valor. en donde. sumando (SUM) los minutos de duración de todas las películas: sSQL = "SELECT SUM(Duracion) AS ""Total Minutos"" FROM tblVideo" U obtener el promedio (AVG) de duración por película: sSQL = "SELECT AVG(Duracion) AS ""Promedio en Minutos"" FROM tblVideo" O la duración máxima: sSQL = "SELECT MAX(Duracion) AS ""Duración Máxima"" FROM tblVideo" O la mínima: sSQL = "SELECT MIN(Duracion) AS ""Duración Mínima"" FROM tblVideo" En el siguiente ejemplo. efectivamente obtenemos el valor. con en el siguiente ejemplo. es el criterio de filtro para la exterior. usamos la siguiente instrucción SQL: sSQL = "SELECT Genero. el total de minutos de nuestra videoteca. primero. solo el valor. son solo una muestra ínfima de su poder y versatilidad. . vamos a realizar una “subconsulta”.326 sSQL = "SELECT COUNT(DISTINCT Pais) AS ""Total Países"" FROM tblVideo" 6. para saberlo. El método doImport. obtenemos todos los datos de la película de máxima duración en nuestra videoteca: sSQL = "SELECT * FROM tblVideo WHERE Duracion=(SELECT MAX(Duracion) FROM tblVideo)" No te confundas.8 Bases de datos Podemos obtener. ahora si. pero no sabes que título es este. para obtener al suma de minutos por genero. es muy importante el uso de los paréntesis para la consulta interior. que no es otra cosa que consultas anidadas. obtenemos la máxima duración (SELECT MAX(Duracion) FROM tblVideo). de no cumplir con algún requerimiento especifico o no coincidir el tipo de dato que se desea insertar con el tipo del campo de la tabla.Value = sBaseDatos mOpcBD(1). importar. por lo que para insertar nuevos datos usaremos una técnica diferente.Name = "SourceType" mOpcBD(1).sdb. lo más probable es que la instrucción no tenga éxito y te devuelva un error.getCurrentController.sun. es la clave primaria y su inserción es automática. la estructura de la tabla.star. En el siguiente ejemplo. y el tercero.Value = sTabla oHojaActiva.sun. te mostrará todas las bases de datos “registradas” en OpenOffice.Aprendiendo OOo Basic 327 6. “Pais” y “LDPais”. no puede faltar.Name = "DatabaseName" mOpcBD(0). Si revisas la estructura de la tabla “tblPaises”. es un entero que puede o no puede estar. observaras que esta formada por tres campos.beans.2 Insertando nuevos datos Las instrucciones SQL.8. tiene que haberte devuelto algo muy similar a: Pero el método para importar (doImport).sun. el siguiente código.DatabaseContext") .getActiveSheet() mOpcBD(0). “Id”. el tipo de campo y si es requerido o no. Antes de empezar con los ejemplos propios de inserción de datos.doImport( mOpcBD() ) End Sub La importación anterior.DataImportMode. el primero es un campo tipo entero.sheet. importamos los países dados de alta en nuestra tabla “tblPaises” de nuestra base de datos “Directorio”: Sub Dim Dim Dim Dim BasesDeDatos10() oHojaActiva As Object sBaseDatos As String sTabla As String mOpcBD(2) As New "com. es decir.getCellRangeByName("A1"). veamos la nueva forma de acceder a nuestra base de datos.Name = "SourceObject" mOpcBD(2).org: Sub Dim Dim Dim BasesDeDatos11() oDBC As Object mNombresBD() As String co1 As Integer 'Creamos el servicio para acceder y manipular las bases de datos oDBC = createUnoService("com.Value = com. hace exactamente solo eso.star. también nos sirven para insertar nuevos datos en las tablas de nuestra base de datos. ya que. el segundo es un campo tipo texto y es requerido. no solo sirven para importar datos. esto. son datos indispensables para insertar nuevos datos. el nombre de los campos.PropertyValue" sBaseDatos = "Directorio" sTabla = "tblPaises" oHojaActiva = ThisComponent.star.TABLE mOpcBD(2). 8 Bases de datos Para acceder a la base de datos de nuestro interés.sdb.DatabaseContext") 'Nos aseguramos de que exista la base de datos If oDBC.getElementNames() 'Mostramos el nombre de cada una For co1 = LBound( mNombresBD ) To UBound ( mNombresBD ) MsgBox mNombresBD(co1) Next End Sub 6. Sub Dim Dim Dim Dim Dim Dim Dim BasesDeDatos13() oDBC As Object oBD As Object oConexion As Object oDeclaracion As Object oResultado As Object sBaseDatos As String sSQL As String 'El nombre de la base de datos sBaseDatos = "Directorio" sSQL = "SELECT * FROM tblPaises" 'Creamos el servicio para acceder y manipular las bases de datos oDBC = createUnoService("com.next 'Mostramos el contenido del campo .sun. accedemos por el nombre oBD = oDBC.createStatement() 'Ejecutamos la consulta oResultado = oDeclaracion. usamos: Sub Dim Dim Dim BasesDeDatos12() oDBC As Object oBD As Object sBaseDatos As String 'El nombre de la base de datos sBaseDatos = "Directorio" 'Creamos el servicio para acceder y manipular las bases de datos oDBC = createUnoService("com.star. este nuevo método.DatabaseContext") 'Nos aseguramos de que exista la base de datos If oDBC.Name ) End If End Sub El siguiente ejemplo. tienen muchas variantes y posibilidades. accedemos por el nombre oBD = oDBC.getByName( sBaseDatos ) 'Creamos una conexion a la base de datos oConexion = oBD.sdb.sun. pues nos da acceso al resultado de la consulta para manipular cada registro y cada campo según nuestras necesidades."") 'Creamos un objeto para las instrucciones SQL oDeclaracion = oConexion.star. diferente al método doImport.328 'Obtenemos los nombres de las bases de datos registradas mNombresBD = oDBC.hasByName( sBaseDatos ) Then 'Si existe.getByName( sBaseDatos ) 'Mostramos la ruta de la base de datos MsgBox ConvertFromURL( oBD. nos ilustra una nueva forma de hacer una consulta (executeQuery).getConnection("".hasByName( sBaseDatos ) Then 'Si existe.executeQuery( sSQL) 'Si hay resultados If Not IsNull( oResultado ) Then Do While oResultado. accedemos por el nombre oBD = oDBC. intentando insertar valores duplicados para la columna (campo) Id.createStatement() 'Ejecutamos la insercion de datos oDeclaracion. es posible insertarlo si lo deseas. donde claramente nos indica que estamos violando la unicidad del índice. Nota que en la tabla y los campos.sdb. por ello omitimos. estas “no admiten duplicados”.Aprendiendo OOo Basic 329 MsgBox oResultado.DatabaseContext") 'Nos aseguramos de que exista la base de datos If oDBC. usamos comillas simples.star. ""Pais"") VALUES (11. veamos como insertar un nuevo registro en nuestra base de datos: Sub Dim Dim Dim Dim Dim Dim BasesDeDatos14() oDBC As Object oBD As Object oConexion As Object oDeclaracion As Object sBaseDatos As String sSQL As String 'El nombre de la base de datos sBaseDatos = "Directorio" sSQL = "INSERT INTO ""tblPaises"" (""Pais"") VALUES ('Honduras')" 'Creamos el servicio para acceder y manipular las bases de datos oDBC = createUnoService("com. usamos una nueva instrucción SQL (INSERT INTO). seguida de la tabla donde insertaremos los nuevos datos. será automáticamente insertado. si estos son texto. el primero se llama “Id” y es un entero.getString( 2 ) Loop End If End If End Sub Ahora si. por que este. te dará un error como el siguiente. al ser este campo una clave primaria.'Honduras')" Observa como indicamos el nombre del campo (Id) y su valor (11). usamos doble comilla y en los valores a insertar. tanto el campo como el valor."") 'Creamos un objeto para las instrucciones SQL oDeclaracion = oConexion.hasByName( sBaseDatos ) Then 'Si existe. Para insertar registros. por lo que si el valor indicado ya existe. pero. entre paréntesis. Recordemos que la tabla “tblPaises” esta conformada por tres campos. los valores a insertar entre paréntesis.getConnection("". que además es clave primaria y de inserción automática. no obstante. como en: sSQL = "INSERT INTO ""tblPaises"" (""Id"".executeUpdate( sSQL) End If End Sub Es importante que notes que estamos usando un nuevo método (executeUpdate) para ejecutar la instrucción SQL.getByName( sBaseDatos ) 'Creamos una conexion a la base de datos oConexion = oBD. después la clausula para indicar los valores (VALUES) y por ultimo. los nombres de los campos. .sun. ¿es esto correcto?. notaras que ahora.close() MsgBox "El país: " & sPais & " ya existe en la base de datos" End If 'Cerramos las conexiones oDeclaracion.createStatement() 'Verificamos que el país no exista oResultado = oDeclaracion. Después tenemos el campo “Pais”. si tienes un campo que es clave primaria y de inserción automática como el campo “Id” de nuestra tabla.getRow = 0 Then 'Si no existe lo insertamos sSQL = "INSERT INTO ""tblPaises"" (""Pais"") VALUES ('" & sPais & "')" oDeclaracion. una primera aproximación a este solución seria: Sub Dim Dim Dim Dim Dim Dim Dim Dim BasesDeDatos15() oDBC As Object oBD As Object oConexion As Object oDeclaracion As Object oResultado As Object sBaseDatos As String sSQL As String sPais As String sPais = Trim( InputBox( "Introduce el nombre del nuevo país" ) ) If sPais <> "" Then sBaseDatos = "Directorio" sSQL = "SELECT Pais FROM ""tblPaises"" WHERE Pais='" & sPais & "'" oDBC = createUnoService("com. obtendrás un error interceptable en tiempo de ejecución. tienes que modificar la tabla desde Base y agregar el índice manualmente (o por código) lo cual aprenderemos más adelante. si ejecutaste la macro varias veces y haces la consulta de la tabla o la abres desde Base.sdb. usaremos el segundo método. para ello. tenemos varias veces el país recién insertado.DatabaseContext") If oDBC. se encargue de insertar el valor siguiente como en nuestro ejemplo. por ahora.executeUpdate( sSQL) MsgBox "El país: " & sPais & " se inserto correctamente en la base de datos" Else oResultado. Para evitar la duplicidad de datos en otro campo que no sea la clave primaria. en el cual se le indica que solo contenga datos únicos con lo cual. y actuar en consecuencia.330 6.8 Bases de datos Aunque este error en tiempo de ejecución es interceptable y manipulable.close() .getByName( sBaseDatos ) oConexion = oBD."") oDeclaracion = oConexion.sun. “no debería” haber información repetida en una base de datos. si se intentan agregar datos duplicados. claro que no.executeQuery( sSQL) oResultado. la idea de una base de datos es tener la menor cantidad de información repetida. que.star.next() If oResultado.getConnection("". inserta el valor automáticamente. tienes dos posibles soluciones. la recomendación es que permitas al motor de bases de datos. puedes crear un índice en este campo. de hecho. una. ejecuta varias veces para que notes que efectivamente. Control de errores.10. como lo vimos en el capitulo 4. que consiste en consultar si el país ya existe o no.hasByName( sBaseDatos ) Then oBD = oDBC. Para terminar este tema. es modificar la estructura de la tabla para que ignore esta distinción.'Perez'.sdb. no lleva comillas. el valor devuelto con el valor nuevo todo en mayúsculas o minúsculas según prefieras. “MÉxico”. tienes la ultima palabra.close() 'Liberamos la memoria oResultado = Nothing oDeclaracion = Nothing oConexion = Nothing End If Else MsgBox "El campo no puede estar vacío" End If End Sub 331 Aun con esta validación. por lo que.2)" oDBC = createUnoService("com. te evitaras algunos dolores de cabeza. una base de datos ideal.Aprendiendo OOo Basic oConexion.getByName( sBaseDatos ) oConexion = oBD. si no. la otra. debe ir entre comillas simples y muy importante. es mucho mejor y más eficiente. aunque no sea obligatorio. veamos un ejemplo donde se inserta una fecha. esta segunda opción es más rápida. Modifica la macro anterior para que no distinga mayúsculas de minúsculas y permite al usuario seguir introduciendo países hasta que quiera presionando el botón Cancelar del cuadro de dialogo. no así el campo. es posible que haya todavía datos duplicados cuando intentemos introducir variantes como “México”. te dará un error en tiempo de ejecución. tienes dos alternativas. o puedes insertarlo. esto es por que el campo distingue mayúsculas de minúsculas. en algunas ocasiones. “MÉXico” o “MÉXICO”."") oDeclaracion = oConexion.""Paterno"". por lo que puedes omitirlo como lo hemos hecho hasta ahora.""IdCiudad"") VALUES ('Juan'. salvo en contadas excepciones. haces la consulta y comparas (si hay resultado).45)" Observa que al ser un número. si un campo esta casi siempre vacío. ""LDPais"") VALUES ('Venezuela'. la cual. la primero es obvia.DatabaseContext") oBD = oDBC. procura dejar vacíos la menor cantidad de campos posible. pero el campo no es requerido.'Gomez'.executeUpdate( sSQL) . “todos” llevan sus comillas dobles. tal vez podrías plantearte la posibilidad de eliminarlo de la tabla. anticipando lo mejor posible.createStatement() oDeclaracion. como en el siguiente ejemplo: sSQL = "INSERT INTO ""tblPaises"" (""Pais"". aunque no es muy recomendable estar eliminando o insertando campos. “diseñar” tus tablas. que es un entero. de nuevo.star.'1981-01-31'. su contenido y estructura y evitar en lo posible cambios constantes durante la implementación de tu código.getConnection("". no “debería” tener campos vacíos.""Cumple"".""Materno"".sun. Sub Dim Dim Dim Dim Dim Dim BasesDeDatos16() oDBC As Object oBD As Object oConexion As Object oDeclaracion As Object sBaseDatos As String sSQL As String sBaseDatos = "Directorio" sSQL = "INSERT INTO ""tblContactos"" (""Nombre"". en el orden año-mes-día. practica y segura y como siempre. En “teoría”. El ultimo campo de nuestra tabla es: “”LDPais”. usamos una nueva instrucción SQL (UPDATE). actualiza el campo “LDPais” de la tabla “tblPaises” pero solo el registro que cumple la condición: Sub Dim Dim Dim Dim Dim Dim BasesDeDatos17() oDBC As Object oBD As Object oConexion As Object oDeclaracion As Object sBaseDatos As String sSQL As String sBaseDatos = "Directorio" 'Construimos la instrucción de actualización sSQL = "UPDATE ""tblPaises"" SET ""LDPais""=57 WHERE ""Pais""='Colombia'" oDBC = createUnoService("com.8. si no estableces un criterio. En el siguiente ejemplo.executeUpdate( sSQL) oDeclaracion. Si el criterio no devuelve ningún resultado. el campo a actualizar y el nuevo valor.332 6. cuidado.star. el siguiente ejemplo. por último. mostramos el país y la clave lada de cada uno.close() oConexion.getConnection("".close() oDeclaracion = Nothing oConexion = Nothing End Sub Para actualizar. es una acción recurrente en la manipulación de bases de datos. después establecemos (SET).DatabaseContext") oBD = oDBC. Veamos como hacerlo.close() oConexion. simplemente no hará ningún cambio en la tabla.sun.close() oDeclaracion = Nothing oConexion = Nothing End Sub Las recomendaciones generales al insertar datos son: ten cuidado con el tipo de datos del campo destino. cuida de que no falte ningún campo requerido y cuida los campos que tienen alguna “relación” con un campo de otra tabla.createStatement() oDeclaracion. con la posibilidad de cambiarlo: Sub Dim Dim Dim Dim BasesDeDatos18() oDBC As Object oBD As Object oConexion As Object oDeclaracion As Object ."") oDeclaracion = oConexion.3 Actualizando datos La actualización de datos en una tabla. 6.getByName( sBaseDatos ) oConexion = oBD.8 Bases de datos oDeclaracion. te actualizará “todos” los registros de tu tabla. no veras ningún mensaje.sdb. si hay más campo se separan por comas. la condición (WHERE) para actualizar solo los registros deseados. "") oDeclaracion = oConexion."") oDeclaracion = oConexion. no puedes usar la misma.getString(2) & Chr(13) & Chr(13) & "Introduce la nueva clave lada" sClave = Val(Trim(InputBox(sInfo))) If sClave > 0 Then sSQL = "UPDATE ""tblPaises"" SET ""LDPais""=" & sClave & " WHERE ""Pais""='" & oResultado.sun. LDPais FROM tblPaises" oDBC = createUnoService("com.executeUpdate( sSQL) oDeclaracion.sun.Next sInfo = "El pais: " & oResultado.star.close() oDeclaracion1.getConnection("".close() oConexion. una es para la consulta de selección y la otra para la actualización.getByName( sBaseDatos ) oConexion = oBD.DatabaseContext") oBD = oDBC.getConnection("".DatabaseContext") oBD = oDBC.createStatement() oDeclaracion.star. actualizamos la fecha del contacto con Id = 0: Sub Dim Dim Dim Dim Dim Dim BasesDeDatos19() oDBC As Object oBD As Object oConexion As Object oDeclaracion As Object sBaseDatos As String sSQL As String sBaseDatos = "Directorio" 'Construimos la instrucción de actualización sSQL = "UPDATE ""tblContactos"" SET ""Cumple""='1980-02-28' WHERE ""Id""=0" oDBC = createUnoService("com. pues se ven afectadas una por la otra.sdb.executeQuery( sSQL) Do While oResultado.createStatement() oResultado = oDeclaracion.getString(1) & " tiene como clave Lada: " & _ oResultado.close() oConexion.sdb.close() oDeclaracion.createStatement() oDeclaracion1 = oConexion. En nuestro siguiente ejemplo.close() oResultado = Nothing oDeclaracion = Nothing oDeclaracion1 = Nothing oConexion = Nothing End Sub Observa que creamos dos declaraciones (createStatement).getByName( sBaseDatos ) oConexion = oBD.close() oDeclaracion = Nothing oConexion = Nothing End Sub .executeUpdate( sSQL) End If Loop oResultado.Aprendiendo OOo Basic Dim Dim Dim Dim Dim Dim oDeclaracion1 As Object oResultado AS Object sBaseDatos As String sSQL As String sInfo As String sClave As String 333 sBaseDatos = "Directorio" sSQL = "SELECT Pais.getString(1) & "'" oDeclaracion1. comprenderlo y aplicarlo en tus bases de datos.sdb.close() oDeclaracion = Nothing oConexion = Nothing End Sub ¡Cuidado!. estudiarlo. con que tengas el cuidado de no dejar “huérfanos” a tus datos es más que suficiente. un archivo o lo que sea. es recomendable.close() oConexion. una tabla. están ligados con un concepto en bases de datos que se llama “integridad referencial”. ten mucho cuidado cuando uses esta instrucción. por ahora. pueden afectar a tablas que estén “relacionadas”. por ello. “borraras toda el contenido de la tabla”.8.getByName( sBaseDatos ) oConexion = oBD.star.sun.getConnection(""."") .DatabaseContext") oBD = oDBC. borramos todos los contactos que se llamen 'Juan': Sub Dim Dim Dim Dim Dim Dim BasesDeDatos21() oDBC As Object oBD As Object oConexion As Object oDeclaracion As Object sBaseDatos As String sSQL As String sBaseDatos = "Directorio" 'Construimos la instrucción de borrado sSQL = "DELETE FROM ""tblContactos"" WHERE ""Nombre""='Juan'" oDBC = createUnoService("com. 6.4 Borrando datos Borrar datos es sumamente simple.getByName( sBaseDatos ) oConexion = oBD.DatabaseContext") oBD = oDBC. preguntarle al usuario si esta seguro de realizar la acción e informarle que esta no se puede deshacer.sdb. En el siguiente ejemplo.8 Bases de datos Al igual que en la inserción. el siguiente ejemplo borra un país de la tabla: Sub Dim Dim Dim Dim Dim Dim BasesDeDatos20() oDBC As Object oBD As Object oConexion As Object oDeclaracion As Object sBaseDatos As String sSQL As String sBaseDatos = "Directorio" 'Construimos la instrucción de borrado sSQL = "DELETE FROM ""tblPaises"" WHERE ""LDPais""=57" oDBC = createUnoService("com. si no estableces la condición.star. la fecha debe cumplir el orden año-mes-día y estar entre comillas simples. Las instrucciones de borrado.sun."") oDeclaracion = oConexion. tema que sale de los propósitos de este libro.executeUpdate( sSQL) oDeclaracion.334 6.getConnection("". así sea un campo. en cualquier operación de borrado. tienes que conocerlo. Cuida.createStatement() oDeclaracion. respetar el tipo de dato del campo a actualizar. tanto la actualización como el borrado. pero que si quieres profundizar en ello. close() oConexion. El cual creamos con la siguiente macro: Sub Dim Dim Dim Graficando1() oHojaActiva As Object oGraficos As Object mRangos(0) .close() oDeclaracion = Nothing oConexion = Nothing End Sub 335 Los temas vistos en este capitulo. la verdad es que yo prefiero las mil palabras. que de eso se trata cuando hacemos gráficos. herramientas suficientes para obtener mucho provecho de tus datos y tus conocimientos. Vamos a crear el siguiente gráfico de la población de cinco países de América Latina.executeUpdate( sSQL) oDeclaracion. volveremos a ellos en el capitulo referente a Base.createStatement() oDeclaracion.9 Graficando datos Dicen que una imagen vale más que mil palabras. 6. aunque procurando mantener el nivel básico que venimos manejando. son solo una pequeña parte de ese enorme tema que son las bases de datos.Aprendiendo OOo Basic oDeclaracion = oConexion. daré por cierta la aseveración anterior y veremos como darle “imagen” a nuestros datos. no obstante. no obstante. tienes ya. 4. Rangos: es una matriz de rangos.getRangeAddress.CellRangeAddress que guardan la dirección del rango para los datos de origen del gráfico.Sheet = oHojaActiva. establecido en verdadero (True) sirve para indicar si se usará la columna de la izquierda como etiquetas de eje o leyenda.EndRow = 5 End With 'Es una matriz de rangos.awt. uno al lado de otro. 5. todas las medidas 'en centésimas de milímetro With oRec . teniendo como origen de datos.getActiveSheet() 'El nombre de nuestro gráfico sNombre = "Grafico01" 'El tamaño y la posición del nuevo gráfico.CellRangeAddress 'Acceso a la hoja activa oHojaActiva = ThisComponent.sun.StartRow = 0 . mRangos.Height = 10000 'El alto del gráfico End With 'La dirección del rango de datos para el gráfico With oDir .X = 5500 'Distancia desde la izquierda de la hoja . establecido en verdadero (True) sirve para indicar si la fila superior se usara como titulo de etiquetas para eje o leyenda.getCurrentController.getCharts() 'Verificamos que no exista el nombre If oGraficos.sun.star.table. creamos tres nuevos gráficos. consta de cinco argumentos: addNewByName(Nombre. barras y circular. En el siguiente ejemplo.9 Graficando datos El método para agregar un nuevo gráfico (addNewByName).Y = 0 'Distancia desde la parte superior .Sheet . True) End If End Sub 6.sun.StartColumn = 0 .EndColumn = 1 . el mismo del ejemplo anterior: .star. de tres estilos diferentes: columnas. 2.Rectangle Dim oDir As New com. EncabezadoColumna. pues se pueden establecer más de uno mRangos(0) = oDir 'Accedemos al conjunto de todos los gráficos de la hoja oGraficos = oHojaActiva. es indispensable que no exista otro gráfico con este valor. Ya creado el gráfico. Rectángulo: es una estructura com.star.hasByName( sNombre ) Then MsgBox "Ya existe este nombre de gráfico. EncabezadoFila) 1. las unidades están especificadas en centésimas de milímetro.awt.addNewByName(sNombre.Width = 10000 'El ancho del gráfico . Rectangulo. de estructuras com. es decir. 1000 = 1 cm 3. EncabezadoFila: valor booleano. True. oRec. este nombre es diferente del que puede establecer el usuario en la interfaz de la aplicación.Rectangle que permite establecer el tamaño y la posición del gráfico. podemos personalizarlo completamente a nuestro gusto.star. escoge otro" Else 'Si no existe lo agregamos oGraficos.sun.table. EncabezadoColumna: valor booleano.336 Dim sNombre As String Dim oRec As New com. Rangos. Nombre: es el nombre del objeto a nivel código. EndColumn = 1 . oRec.hasByName( sNombre ) Then MsgBox "Ya existe este nombre de gráfico. True) 'Accedemos al nuevo gráfico oGrafico = oGraficos.getBYName( sNombre ). True.getRangeAddress.Width = 10000 'El ancho del gráfico .getEmbeddedObject() 'Establecemos que sean barras en vez de columnas oGrafico.getCharts() 'Verificamos que no exista el nombre If oGraficos.sun.Height = 10000 'El alto del gráfico End With 'La dirección del rango de datos para el gráfico With oDir . mRangos.star.X = 20000 .X = 0 'Distancia desde la izquierda de la hoja . pues se pueden establecer más de uno mRangos(0) = oDir 'Accedemos al conjunto de todos los gráficos de la hoja oGraficos = oHojaActiva.sun.X = 10000 .Y = 4000 'Distancia desde la parte superior .getDiagram.star.Y = 4000 End With If oGraficos.EndRow = 5 End With 'Es una matriz de rangos.CellRangeAddress 'Acceso a la hoja activa oHojaActiva = ThisComponent.StartColumn = 0 .table.Y = 4000 End With If oGraficos. True) End If 'Cambiamos el nombre y la posición para un segundo gráfico sNombre = "GraficoB" With oRec . True. oRec. mRangos.getActiveSheet() 'El nombre de nuestro gráfico sNombre = "GraficoA" 'El tamaño y la posición del nuevo gráfico. todas las medidas 'en centésimas de milímetro With oRec .addNewByName(sNombre.Vertical = True End If 'Volvemos a cambiar el nombre y la posición para un tercer gráfico sNombre = "GraficoC" With oRec .addNewByName(sNombre. escoge otro" Else oGraficos.Aprendiendo OOo Basic 337 Sub Dim Dim Dim Dim Dim Dim Dim Graficando2() oHojaActiva As Object oGraficos As Object oGrafico As Object mRangos(0) sNombre As String oRec As New com. escoge otro" .awt.hasByName( sNombre ) Then MsgBox "Ya existe este nombre de gráfico.Sheet = oHojaActiva.Sheet .StartRow = 0 .Rectangle oDir As New com. de forma predeterminada se crea 'un gráfico de columnas oGraficos.hasByName( sNombre ) Then MsgBox "Ya existe este nombre de gráfico.getCurrentController. escoge otro" Else 'Si no existe lo agregamos. lo establecemos circular.star.star.sun.chart.star.star.sun. solo pasa una cadena vacía en los textos y un 0 en los números Sub FormatoTexto(Obj As Object. negritas.sun.setText( mTexto ) Else oTexto = Obj .LineDiagram com. uno es vertical y otro es horizontal. representaciones en 3D. principalmente. Texto As String.FormattedString") 'Y agregarse a una matriz mTexto(0) = oTexto 'Establecer el texto Obj.getEmbeddedObject() oGrafico.9 Graficando datos oGraficos.BarDiagram com. color.AreaDiagram com. agregar líneas y puntos. el estilo de letra (tipo de fuente. entre otras características que veremos más adelante.chart.XYDiagram com. tamaño. cambiamos completamente su tipo (setDiagram). si no quieres cambiar alguna 'propiedad.addNewByName(sNombre.Title") Then 'Requiere un objeto "Cadena Formateada" (FormattedString) oTexto = createUnoService("com.chart com. Fuente As String. True.PieDiagram")) End If End Sub Los gráficos de columnas y barras son el mismo tipo de gráfico.star.sun. Color As Long) Dim oTexto As Object Dim mTexto(0) 'El titulo del gráfico es algo especial If Obj.star. toma en cuenta.chart. y el estilo de borde (tipo de línea. tiene variantes que multiplican las posibilidades para graficar la información. etc). son en realidad una forma (Shape). mRangos.sun. True) oGrafico = oGraficos.chart.DonutDiagram com.sun.chart.setDiagram( oGrafico. pero todas las propiedades que veremos.getBYName( sNombre ).supportsService("com. entre otras más. Neg As Integer.chart2.sun.338 Else 6. Tam As Integer.star. para el tercer gráfico. La mayor parte de los elementos de un gráfico. excepto por la orientación.chart.NetDiagram com.chart.sun. el estilo de fondo (estilo. por ejemplo.star. a la cual le puedes establecer sus propiedades. las puedes establecer perfectamente al crearlo de modo que tu gráfico este configurado completamente a tu gusto y necesidad a la primera.chart. los siguientes ejemplos manipulan el gráfico seleccionado. etc).comp.sun. Vamos a hacer uso de las siguientes subrutinas para dar formato: 'Subrutina para formatear el texto de una forma.sun. vamos a mostrar como modificar los principales elementos de un gráfico.PieDiagram com.star. color. color.star. que cada gráfico esta pensado para un determinado tipo de datos. oRec.star.chart.StockDiagram Tipo Barras (y columnas) Áreas Líneas Circular Dona Red Dispersión XY Stock Cada uno de estos tipos. ancho.star. etc).sun.sun.createInstance("com.chart. los tipos de gráficos que puedes establecer son: com. sun. Ancho As Integer) With Obj .CharHeight = Tam If Color > 0 Then . Estilo As Integer.CharFontName = Fuente If Neg > 0 Then . Color As Long) With Obj .getCurrentController. observa que si no existe el titulo lo creamos. el subtitulo siempre existe.star.drawing.getActiveSheet() oGraficos = oHojaActiva.getByIndex(0) If oSel. agregamos y damos formato al titulo y al subtitulo del gráfico.Aprendiendo OOo Basic 339 End If 'Cambiamos el formato del texto With oTexto If Texto <> "" Then . Color As Long.SvxShapeCollection" Then oSel = oSel.supportsService("com.String = Texto If Fuente <> "" Then . si no quieres ningún fondo 'establece el estilo en 0 Sub FormatoFondo(Obj As Object.getCurrentSelection() If oSel.LineWidth = Ancho End With End Sub 'Función para devolver el gráfico activo 'devuelve NULL si no es un gráfico Function getGrafico() As Object Dim oHojaActiva As Object Dim oGraficos As Object Dim oGrafico As Object Dim oSel As Object Dim sNombre As String Dim sInfo As String oSel = ThisComponent.getByName( sNombre ). si no quieres línea.LineStyle = Estilo If Color > 0 Then .getImplementationName = "com. 'establece el estilo en 0 Sub FormatoLinea(Obj As Object.FillColor = Color End With End Sub 'Subrutina para cambiar la línea de una forma.LineColor = Color If Ancho > 0 Then . Estilo As Integer.CharColor = Color End With End Sub 'Subrutina para cambiar el fondo de una forma.PersistName oHojaActiva = ThisComponent.FillBackground = True . solo hay que determinar si lo mostramos o no.OLE2Shape") Then sNombre = oSel. como se indica en los comentarios: Sub Graficando3() .star.drawing.sun.hasByName( sNombre ) Then getGrafico = oGraficos.FillStyle = Estilo If Color > 0 Then .getCharts() If oGraficos.CharWeight = Neg If Tam > 0 Then .getEmbeddedObject() End If End If End If End Function En el siguiente ejemplo. no así en el subtítulo. 1.0) ) Call FormatoFondo( oSubTitulo. RGB(255. .25). 1. Si usas normalmente un conjunto de fuentes.chart2. "América Latina".star. RGB(100.50.getTitleObject() If IsNull(oTitulo) Then 'Si no existe el título lo creamos oTitulo = createUnoService("com.sun. fondo y línea Call FormatoTexto( oSubTitulo.340 Dim oGrafico As Object Dim oTitulo As Object Dim oSubTitulo As Object 'Accedemos al gráfico seleccionado oGrafico = getGrafico() If Not IsNull( oGrafico ) Then 6.Title") End If 'Le damos formato al texto del título Call FormatoTexto( oTitulo. "Habitantes Por País". RGB(220. seleccionamos el título oTitulo = oGrafico. 150. por ejemplo: Dim mFuentes(4) As String mFuentes(0) mFuentes(1) mFuentes(2) mFuentes(3) mFuentes(4) = = = = = "Liberation Serif" "Liberation Sans" "Liberation Mono" "FreeMono" "FreeSans" Y mira que bien nos va quedando. así que no te me pongas exigente. RGB(100. ya sabes que soy muy malo para el diseño.HasSubTitle = True 'Accedemos al subtitulo oSubTitulo = oGrafico.SubTitle 'Le damos formato al texto. RGB(255. RGB(240. 50 ) Else MsgBox "Selecciona un gráfico" End If End Sub Los margenes del borde al texto.220) ) 'Le damos formato a la línea Call FormatoLinea( oTitulo.9 Graficando datos 'Si hay un gráfico. 1. tal vez sea buena idea.0) ) 'Le damos formato al fondo del titulo Call FormatoFondo( oTitulo.setTitleObject( oTitulo ) 'Establecemos que se muestre el subtitulo oGrafico. podrías usar una matriz de texto (string) con los nombres de las fuentes que más uses. bueno.ParaLeftMargin = 300 . 100 ) 'Si estableces la línea. 2. "Liberation Serif".ParaBottomMargin = 200 End With 'Y lo establecemos oGrafico.240) ) Call FormatoLinea( oSubTitulo. 15.220.150. 150. solo existen en el título. 12.ParaTopMargin = 200 .50.ParaRightMargin = 300 . "Liberation Serif".25).0. no tan bien. establecer los margenes 'al texto para que no se vea tan pegado With oTitulo .240. le pasamos una cadena vacía. 10.25). esto es muy importante.150.50. fondo y línea Call FormatoTexto( oLeyenda. "". pues la leyenda no implementa la propiedad String. el argumento Texto.Aprendiendo OOo Basic 341 Ahora. que nos sirve para establecer el título y el subtítulo. no tiene mucho sentido mostrar la leyenda.Legend() 'Le damos formato al texto. Nota que en la llamada a la subrutina FormatoTexto. ahora. el circulo (bueno. RGB(240. RGB(100.240) ) Call FormatoLinea( oLeyenda. 150. 50 ) Else MsgBox "Selecciona un gráfico" End If End Sub En algunos casos. intento de circulo) rojo en la imagen anterior. RGB(255. 1. pues es una sola serie de datos. como en este ejemplo.HasLegend = False 'Accedemos al titulo del eje X . puedes interceptar y manipular. Sub Graficando4() Dim oGrafico As Object Dim oLeyenda As Object oGrafico = getGrafico() If Not IsNull( oGrafico ) Then 'Accedemos a la leyenda oLeyenda = oGrafico. "Liberation Sans".100) ) Call FormatoFondo( oLeyenda. Sub Graficando5() Dim oGrafico As Object Dim oTituloEje As Object oGrafico = getGrafico() If Not IsNull( oGrafico ) Then 'Ocultamos la leyenda oGrafico.240. te dará un error en tiempo de ejecución. así que mejor la ocultamos y establecemos el titulo de el eje X y el eje Y. así como su formato. que claro. 3. por lo que si intentas establecerla. cambiaremos el formato de la leyenda. 150. 1. RGB(50.150. RGB(100.HasXAxisTitle = True Call FormatoTexto( oTituloEje.150.getDiagram. están contenidos “dentro” del gráfico. RGB(100. RGB(0. "Liberation Sans". "Liberation Sans".HasYAxisTitle = True Call FormatoTexto( oTituloEje. es la forma en que accedemos a los títulos de los ejes (getDiagram).240) ) Call FormatoLinea( oTituloEje. Sub Graficando6() Dim oGrafico As Object Dim oEje As Object oGrafico = getGrafico() If Not IsNull( oGrafico ) Then 'Accedemos al eje X oEje = oGrafico.XAxisTitle 'Establecemos que se muestre oGrafico. 1. 1.getDiagram.255).200.50. 150.getXAxis Call FormatoTexto( oEje. RGB(200. "Liberation Sans".Max = 200000000 'Establecemos el intervalo superior oEje.342 6.0).100) ) Call FormatoFondo( oTituloEje.getDiagram. "Países".0. 10.50) ) Call FormatoLinea( oEje. estos. RGB(240.0).getDiagram.240) ) Call FormatoLinea( oTituloEje.50) ) Call FormatoLinea( oEje. 150. RGB(0.200). RGB(200.YHelpGrid Call FormatoLinea( oEje.240. pero también “dentro” de un forma que se llama diagrama.StepHelpCount = 5 'Líneas del eje principal oEje = oGrafico. 30 ) 'Establecemos el limite superior del eje oEje. 1.TextRotation = 6000 'Accedemos al eje Y oEje = oGrafico.getDiagram. 25 ) Else MsgBox "Selecciona un gráfico" End If End Sub Modificamos las propiedades de toda el área del gráfico Sub Graficando7() Dim oGrafico As Object . RGB(255. 30 ) 'Rotamos 60º el texto oEje. RGB(150. 50 ) 'Mostramos las líneas secundarias oGrafico. "Liberation Sans".getYAxis Call FormatoTexto( oEje.255). 1. RGB(50.240. 1. 20 ) 'Accedemos al titulo del eje Y oTituloEje = oGrafico.getDiagram. 10. 1.getDiagram. 1. 20 ) Else MsgBox "Selecciona un gráfico" End If End Sub El punto importante.getDiagram. "Habitantes".200.YMainGrid Call FormatoLinea( oEje. 11. "".getDiagram.0.100) ) Call FormatoFondo( oTituloEje.0. 11. 150.HasYAxisHelpGrid = True oEje = oGrafico.9 Graficando datos oTituloEje = oGrafico. "".200).YAxisTitle 'Establecemos que se muestre oGrafico. RGB(240.50.0. que es propiamente el área donde se muestra el gráfico.StepMain = 50000000 'El número de marcas secundarias oEje. solo tenemos una. RGB(0. RGB(50.Aprendiendo OOo Basic Dim oArea As Object 343 oGrafico = getGrafico() If Not IsNull( oGrafico ) Then 'Seleccionamos el área del gráfico oArea = oGrafico. 150. 9 ) Else MsgBox "Selecciona un gráfico" End If End Sub Modificamos la serie de datos. 5 ) 'Establecemos que se muestren los valores de cada punto oDatos. 2. "Liberation Sans".Size oGrafico = getGrafico() If Not IsNull( oGrafico ) Then .50). 11 ) Call FormatoLinea( oArea.250) ) Call FormatoFondo( oDatos. 2.star.sun. "". solo del fondo del gráfico. 4.awt. 20 ) Else MsgBox "Selecciona un gráfico" End If End Sub Ahora.getDiagram. 1.getWall Call FormatoFondo( oFondo. Sub Graficando8() Dim oGrafico As Object Dim oFondo As Object oGrafico = getGrafico() If Not IsNull( oGrafico ) Then 'Seleccionamos el fondo del gráfico oFondo = oGrafico.getArea() Call FormatoFondo( oArea.getDiagram. el área efectiva donde se muestran los datos.255. por ahora. tienes que hacerlo como si fuera una forma (shape) como te muestro en el siguiente ejemplo: Sub Dim Dim Dim Graficando10() oGrafico As Object oSel As Object oTam As New com. 11.getDataRowProperties(0) Call FormatoTexto( oDatos.DataCaption = 1 Else MsgBox "Selecciona un gráfico" End If End Sub Para cambiar de tamaño un gráfico.0. Sub Graficando9() Dim oGrafico As Object Dim oDatos As Object oGrafico = getGrafico() If Not IsNull( oGrafico ) Then 'La primer serie de datos oDatos = oGrafico. 9 Graficando datos Si has probado cada una de las macros de ejemplo sobre el mismo gráfico.getByIndex(0) 'Establecemos el nuevo tamaño oTam.setSize( oTam ) Else MsgBox "Selecciona un gráfico" End If End Sub 6.sun.Width = 15000 oTam. repetimos lo que hace la función que nos regresa el gráfico 'esto es por que ya estamos seguros de que es un gráfico y por que. 'para cambiar de tamaño. algo sumamente necesario para tener realmente un gráfico dinámico y podamos actualizarlo cuando sea necesario.CellRangeAddress oHojaActiva = ThisComponent.getActiveSheet() 'Accedemos al gráfico oGrafico = getGrafico2() If Not IsNull( oGrafico ) Then . hay que hacerlo como si fuera una forma (shape) oSel = ThisComponent. La siguiente macro. al fin que no es curso de diseño.table.getCurrentController.star. cambiara el rango de datos origen.344 'Aquí. Sub Dim Dim Dim Dim Graficando11() oGrafico As Object oHojaActiva As Object mRangos(0) oDir As New com.Height = 15000 oSel. esta horrible. tienes que tener algo así: Si lo se.getCurrentSelection() oSel = oSel. getRangeAddress.drawing. cuando grafiques. El siguiente ejemplo.Sheet . Function getGrafico2() As Object Dim oHojaActiva As Object Dim oGraficos As Object Dim oGrafico As Object Dim oSel As Object Dim sNombre As String Dim sInfo As String oSel = ThisComponent. accede directamente al gráfico (getByName).getCurrentSelection() If oSel.getByName( sNombre ) End If End If End If End Function La diferencia.sun.hasByName( sNombre ) Then getGrafico2 = oGraficos. debes de cuidar la correspondencia de tus datos con el tipo de gráfico.supportsService("com.getCurrentController. como ya lo mencionamos.StartRow = 0 .getActiveSheet() oGraficos = oHojaActiva. así mismo. por ejemplo.PersistName oHojaActiva = ThisComponent. puedes establecerle ejes a un gráfico circular.Sheet = oHojaActiva.OLE2Shape") Then sNombre = oSel.EndColumn = 1 . Veamos algunos ejemplos más de creación de gráficos.sun.drawing.EndRow = 10 End With mRangos(0) = oDir 'Establecemos el nuevo rango oGrafico. es que la primera te devuelve el objeto (no me gusta la palabra pero así es) “embebido” (getEmbeddedObject). modifica nuestro gráfico para que se vea en 3D.getByIndex(0) If oSel.StartColumn = 0 . esta segunda forma.setRanges( mRangos ) Else MsgBox "Selecciona un gráfico" End If End Sub Nota que estamos usando una segunda versión de la función para regresar el gráfico seleccionado.star.getImplementationName = "com. la función es casi idéntica.star. Sub Graficando12() Dim oGrafico As Object oGrafico = getGrafico() If Not IsNull( oGrafico ) Then .Aprendiendo OOo Basic 345 'El nuevo rango de datos With oDir . cuando personalices un gráfico.getCharts() If oGraficos.SvxShapeCollection" Then oSel = oSel. con el cual tenemos acceso a todos los objetos dentro del gráfico. pero dejaría de ser un gráfico circular y te aseguro que no obtendrías el resultado previsto. asegurate de que el tipo de gráfico es correcto. getDiagram.9 Graficando datos Observa el siguiente gráfico.getImplementationName = "ScCellObj" Then oCursor = oHojaActiva.getSelection() If oSel.getCurrentController.collapseToCurrentRegion() mRangos(0) = oCursor.EndRow + 2 ) With oRec .getRangeAddress sNombre = "Grafico10" 'Celda para la posición del gráfico oCelda = oHojaActiva. para obtenerlo.getDiagram.sun.Position.awt. Sub Dim Dim Dim Dim Dim Dim Dim Dim Graficando13() oHojaActiva As Object oSel As Object oCursor As Object oGraficos As Object mRangos(0) sNombre As String oRec As New com.createCursorByRange( oSel ) 'Expandimos el cursor a la región actual oCursor.X .X = oCelda.StartColumn.Y = oCelda.Rectangle oCelda As Object oHojaActiva = ThisComponent.Dim3D = True 'Mostramos cilindros en vez de columnas oGrafico. oCursor. es indispensable que el cursor este en “una sola celda” de los datos.getRangeAddress.star.346 'Establecemos el gráfico en 3D oGrafico.getRangeAddress.SolidType = 1 Else MsgBox "Selecciona un gráfico" End If End Sub 6. lo demás se calcula.Position.Y . tanto el rango de datos como la posición.Width = 11500 'El ancho del gráfico .getActiveSheet() oSel = ThisComponent.getCellByPosition( oCursor.getCurrentController. getCellByPosition( oCursor.getRangeAddress sNombre = "Grafico10" 'Celda para la posición del gráfico oCelda = oHojaActiva.getRangeAddress.StartColumn.Rectangle oCelda As Object oHojaActiva = ThisComponent. True) End If Else MsgBox "Selecciona solo una celda con datos" End If End Sub El mismo gráfico. oRec.hasByName( sNombre ) Then MsgBox "Ya existe este nombre de gráfico. escoge otro" Else oGraficos.createCursorByRange( oSel ) 'Expandimos el cursor a la región actual oCursor.getCharts() If oGraficos.X = oCelda. True.Aprendiendo OOo Basic 347 .getActiveSheet() oSel = ThisComponent.star.getImplementationName = "ScCellObj" Then oCursor = oHojaActiva. Sub Dim Dim Dim Dim Dim Dim Dim Dim Dim Graficando14() oHojaActiva As Object oSel As Object oCursor As Object oGraficos As Object oGrafico As Object mRangos(0) sNombre As String oRec As New com.addNewByName(sNombre.awt.collapseToCurrentRegion() mRangos(0) = oCursor.Position.getCurrentController.X .sun.getRangeAddress.getSelection() If oSel. pero ahora lo hacemos de barras.getCurrentController.Height = 7000 'El alto del gráfico End With oGraficos = oHojaActiva.EndRow + 2 ) With oRec . mRangos. oCursor. getEmbeddedObject.hasByName( sNombre ) Then MsgBox "Ya existe este nombre de gráfico.awt.Width = 11500 'El ancho del gráfico .9 Graficando datos Los gráficos circulares nos dan la imagen de la relación de cada punto respecto al total.getByName( sNombre ) oGrafico.getActiveSheet() oSel = ThisComponent.getSelection() If oSel.Y = oCelda. True) oGrafico = oGraficos.Height = 7000 'El alto del gráfico End With oGraficos = oHojaActiva. mRangos.collapseToCurrentRegion() mRangos(0) = oCursor.getDiagram.getRangeAddress .sun.getImplementationName = "ScCellObj" Then oCursor = oHojaActiva.Position.Vertical = True End If Else MsgBox "Selecciona solo una celda con datos" End If End Sub 6. Sub Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim Graficando15() oHojaActiva As Object oSel As Object oCursor As Object oGraficos As Object oGrafico As Object mRangos(0) sNombre As String oRec As New com.star.createCursorByRange( oSel ) oCursor. oRec.getCurrentController.getCharts() If oGraficos.addNewByName(sNombre. True.348 .getCurrentController.Rectangle oCelda As Object oDatos As Object oHojaActiva = ThisComponent.Y . escoge otro" Else oGraficos. sun.getCellByPosition( oCursor.HasColumnHeaders = True oGrafico.X .getDiagram.getDiagram. "".HasRowHeaders = True 'Hay que reasignar el rango de datos.Dim3D = True oGrafico.getRangeAddress.StartColumn.PieDiagram") ) oDatos = oGrafico.LabelPlacement = 0 Call FormatoTexto( oDatos. lo pierde al cambiar de tipo de gráfico oGrafico. oCursor. "Liberation Sans". 150.Y = oCelda.getEmbeddedObject. True.getByName( sNombre ) 'Cambiamos el tipo de gráfico oGrafico. 15.Aprendiendo OOo Basic 349 sNombre = "Grafico15" oCelda = oHojaActiva.DataCaption = 2 oDatos.chart.55) ) End If Else MsgBox "Selecciona solo una celda con datos" End If End Sub Los gráficos de área.X = oCelda.star.getRangeAddress.EndRow + 2 ) With oRec .Y . mRangos. escoge otro" Else oGraficos. destacan la magnitud de un cambio en el tiempo. oRec.hasByName( sNombre ) Then MsgBox "Ya existe este nombre de gráfico.Position.getCharts() If oGraficos.addNewByName(sNombre.setRanges( mRangos ) oDatos.Width = 10000 . Sub Dim Dim Dim Graficando16() oHojaActiva As Object oSel As Object oCursor As Object .getEmbeddedObject. True) oGrafico = oGraficos.Position.getEmbeddedObject.setDiagram( oGrafico.Height = 7000 End With oGraficos = oHojaActiva. RGB(55.55.createInstance("com.getDataRowProperties(0) oGrafico.getEmbeddedObject. Position. .Y .Height = 7000 End With oGraficos = oHojaActiva.star.Rectangle oCelda As Object oDatos As Object 6.createInstance("com.chart. True) oGrafico = oGraficos.9 Graficando datos oHojaActiva = ThisComponent.collapseToCurrentRegion() mRangos(0) = oCursor.getEmbeddedObject.X = oCelda.getEmbeddedObject.hasByName( sNombre ) Then MsgBox "Ya existe este nombre de gráfico.getRangeAddress.Position.sun. True.350 Dim Dim Dim Dim Dim Dim Dim oGraficos As Object oGrafico As Object mRangos(0) sNombre As String oRec As New com. mRangos.awt.X .Width = 10000 .getCurrentController.getCellByPosition( oCursor. oRec.setDiagram( oGrafico.StartColumn.getSelection() If oSel.getCharts() If oGraficos. escoge otro" Else oGraficos.sun.addNewByName(sNombre.star.getCurrentController.getRangeAddress sNombre = "Grafico16" oCelda = oHojaActiva.EndRow + 2 ) With oRec .createCursorByRange( oSel ) oCursor.getRangeAddress.Y = oCelda.getActiveSheet() oSel = ThisComponent.AreaDiagram") ) End If Else MsgBox "Selecciona solo una celda con datos" End If End Sub Los gráficos de líneas muestran principalmente los cambios de valor en el tiempo y su relación con otros valores. oCursor.getByName( sNombre ) 'Cambiamos el tipo de gráfico oGrafico.getImplementationName = "ScCellObj" Then oCursor = oHojaActiva. aun así.Y .getDiagram.star.EndRow + 2 ) With oRec .getEmbeddedObject.Rectangle oCelda As Object oDatos As Object oHojaActiva = ThisComponent.setDiagram( oGrafico.getRangeAddress sNombre = "Grafico17" oCelda = oHojaActiva.awt.getCharts() If oGraficos. True. pero pueden representar más de una serie de datos.getImplementationName = "ScCellObj" Then oCursor = oHojaActiva.Y = oCelda.getCurrentController.X = oCelda.LineDiagram") ) oGrafico.getCurrentController.collapseToCurrentRegion() mRangos(0) = oCursor. son parecidos a los circulares.hasByName( sNombre ) Then MsgBox "Ya existe este nombre de gráfico.Position.Aprendiendo OOo Basic 351 Sub Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim Graficando17() oHojaActiva As Object oSel As Object oCursor As Object oGraficos As Object oGrafico As Object mRangos(0) sNombre As String oRec As New com.getRangeAddress.chart.getActiveSheet() oSel = ThisComponent. escoge otro" Else oGraficos.getEmbeddedObject. .Width = 12000 .sun.getEmbeddedObject.star.addNewByName(sNombre.sun. no son una buena elección.Position.getByName( sNombre ) 'Cambiamos el tipo de gráfico oGrafico. oRec.getSelection() If oSel.SymbolType = 1 End If Else MsgBox "Selecciona solo una celda con datos" End If End Sub Los gráficos de anillo.getRangeAddress.StartColumn.X . oCursor. creo.createInstance("com.createCursorByRange( oSel ) oCursor. mRangos.Height = 7000 End With oGraficos = oHojaActiva.getCellByPosition( oCursor. True) oGrafico = oGraficos. oCursor.getCharts() If oGraficos.X = oCelda. Sub Graficando19() . True.setDiagram( oGrafico.Rectangle oCelda As Object oDatos As Object oHojaActiva = ThisComponent.getActiveSheet() oSel = ThisComponent.Y .9 Graficando datos Sub Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim Graficando18() oHojaActiva As Object oSel As Object oCursor As Object oGraficos As Object oGrafico As Object mRangos(0) sNombre As String oRec As New com. pero ahí esta el ejemplo.chart. mRangos.star.X .hasByName( sNombre ) Then MsgBox "Ya existe este nombre de gráfico.getEmbeddedObject.sun.getEmbeddedObject.getImplementationName = "ScCellObj" Then oCursor = oHojaActiva.sun.Position.getRangeAddress sNombre = "Grafico18" oCelda = oHojaActiva.Position.Height = 7000 End With oGraficos = oHojaActiva.createInstance("com.collapseToCurrentRegion() mRangos(0) = oCursor.getRangeAddress.addNewByName(sNombre. no le hayo mucho sentido a un gráfico radial.EndRow + 2 ) With oRec .createCursorByRange( oSel ) oCursor.352 6.StartColumn. escoge otro" Else oGraficos.awt.getCurrentController.star.getByName( sNombre ) 'Cambiamos el tipo de gráfico oGrafico.Y = oCelda.getSelection() If oSel.getRangeAddress. oRec.getCellByPosition( oCursor.Width = 12000 .getCurrentController.DonutDiagram") ) End If Else MsgBox "Selecciona solo una celda con datos" End If End Sub Lo confieso. True) oGrafico = oGraficos. Aprendiendo OOo Basic Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim oHojaActiva As Object oSel As Object oCursor As Object oGraficos As Object oGrafico As Object mRangos(0) sNombre As String oRec As New com.Width = 12000 .Rectangle oCelda As Object oDatos As Object 353 oHojaActiva = ThisComponent. el orden de los datos es importante.collapseToCurrentRegion() mRangos(0) = oCursor.getByName( sNombre ) 'Cambiamos el tipo de gráfico oGrafico.getRangeAddress.sun.awt.getImplementationName = "ScCellObj" Then oCursor = oHojaActiva.getCharts() If oGraficos. True) oGrafico = oGraficos.getCurrentController.getCellByPosition( oCursor.createInstance("com.star. True.Height = 7000 End With oGraficos = oHojaActiva.sun.getRangeAddress.getCurrentController.Position.star.Y .getSelection() If oSel.getEmbeddedObject.addNewByName(sNombre.getEmbeddedObject.chart.X = oCelda.getActiveSheet() oSel = ThisComponent.createCursorByRange( oSel ) oCursor. mRangos. escoge otro" Else oGraficos.X .NetDiagram") ) End If Else MsgBox "Selecciona solo una celda con datos" End If End Sub Para un gráfico de stock.Y = oCelda.setDiagram( oGrafico. oRec.getRangeAddress sNombre = "Grafico19" oCelda = oHojaActiva.EndRow + 2 ) With oRec .Position. Sub Graficando20() Dim oHojaActiva As Object .StartColumn. oCursor.hasByName( sNombre ) Then MsgBox "Ya existe este nombre de gráfico. getRangeAddress. True) oGrafico = oGraficos.X = oCelda.Position.getSelection() If oSel.getEmbeddedObject.setDiagram( oGrafico.getCurrentController.chart.getCurrentController.EndRow + 2 ) With oRec .getRangeAddress sNombre = "Grafico20" oCelda = oHojaActiva. True.354 Dim Dim Dim Dim Dim Dim Dim Dim Dim oSel As Object oCursor As Object oGraficos As Object oGrafico As Object mRangos(0) sNombre As String oRec As New com.collapseToCurrentRegion() mRangos(0) = oCursor.sun.getByName( sNombre ) 'Cambiamos el tipo de gráfico oGrafico.Rectangle oCelda As Object oDatos As Object 6.star.createInstance("com. mRangos. Sub Dim Dim Dim Dim Dim Graficando21() oHojaActiva As Object oSel As Object oCursor As Object oGraficos As Object oGrafico As Object .addNewByName(sNombre.sun.star.getCellByPosition( oCursor.hasByName( sNombre ) Then MsgBox "Ya existe este nombre de gráfico.9 Graficando datos oHojaActiva = ThisComponent.StartColumn.getActiveSheet() oSel = ThisComponent.Y = oCelda. escoge otro" Else oGraficos.getEmbeddedObject. oCursor.Width = 12000 .Y .X .createCursorByRange( oSel ) oCursor.Height = 7000 End With oGraficos = oHojaActiva. oRec.getRangeAddress.awt.StockDiagram") ) End If Else MsgBox "Selecciona solo una celda con datos" End If End Sub El gráfico XY (dispersión) muestra la relación de un valor en función de otro.getImplementationName = "ScCellObj" Then oCursor = oHojaActiva.Position.getCharts() If oGraficos. Y = oCelda.getCellByPosition( oCursor. con el gráfico de datos. oRec. True.createCursorByRange( oSel ) oCursor.awt.sun.collapseToCurrentRegion() mRangos(0) = oCursor.getRangeAddress.Width = 12000 .getCurrentController.star. inmediatamente que agregues el gráfico.getRangeAddress sNombre = "Grafico21" oCelda = oHojaActiva.setDiagram( oGrafico.getCurrentController.10 Trabajando con elementos gráficos No se si estarás de acuerdo conmigo.sun.Height = 7000 End With oGraficos = oHojaActiva.chart.HasLegend = False End If Else MsgBox "Selecciona solo una celda con datos" End If End Sub Cada tipo de gráfico tiene sus particularidades que tendrás que considerar a la hora de graficar.getImplementationName = "ScCellObj" Then oCursor = oHojaActiva. pero poco a poco se ha ido diluyendo la frontera entre aplicaciones.StartColumn.createInstance("com. la recomendación general es. no obstante.X . tienes un combinación bastante poderosa y eficiente para representar tus datos en informes. mRangos. estableces todas las propiedades que quieras.hasByName( sNombre ) Then MsgBox "Ya existe este nombre de gráfico. Si sumas la importación de bases de datos. en uno y en otro podemos hacer muchas tareas similares. es decir.getRangeAddress. True) oGrafico = oGraficos.getByName( sNombre ). podemos hacer uso de esas características extras. oCursor. entre un procesador de textos y una hoja de calculo por ejemplo. . cambia su tipo al que necesites y solo al final.getCharts() If oGraficos. escoge otro" Else oGraficos. tan variadas y ricas con que cuentan las aplicaciones actuales. lo cual aprenderemos en este capitulo.Position.Aprendiendo OOo Basic Dim Dim Dim Dim Dim mRangos(0) sNombre As String oRec As New com.Y .getActiveSheet() oSel = ThisComponent.X = oCelda.Position.Rectangle oCelda As Object oDatos As Object 355 oHojaActiva = ThisComponent.getSelection() If oSel.EndRow + 2 ) With oRec .XYDiagram") ) oGrafico. soy de la opinión de seguir usando cada aplicación especifica para la tarea que fue diseñada.getEmbeddedObject 'Cambiamos el tipo de gráfico oGrafico.star.addNewByName(sNombre. 6. GraphicURL = sRuta 'La agregamos a la página de dibujo. en el siguiente ejemplo.appendFilter( "Imagenes PNG".png") oDlgAbrirArchivo.appendFilter( "Imagenes JPG".FilePicker") 'Establecemos los filtros de archivo oDlgAbrirArchivo.setTitle("Selecciona la imagen") 'Con el metodo .getFiles() 'El primer elemento de la matriz es el archivo seleccionado .GraphicObjectShape" ) 'Establecemos la ruta de la imagen oImagen. solo se puede seleccionar un archivo 'pero devuelve una matriz de todos modos con la ruta completa 'del archivo en formato URL mArchivo() = oDlgAbrirArchivo.star.sun.Size 'Creamos el servicio necesario oDlgAbrirArchivo = CreateUnoService ("com. al conjunto de formas oPaginaDibujo. "*.getDrawPage() 'Para crear y manipular imagenes oImagen = oDoc.sun.jpg") 'Establecemos el titulo del cuadro de dialogo oDlgAbrirArchivo.356 6.Width = 10000 oTam.10.star. insertamos una imagen PGN en la hoja activa.png") oDoc = ThisComponent 'Pagina de dibujo de la hoja activa oPaginaDibujo = oDoc.*.Execute() mostramos el cuadro de dialogo 'Si el usuario presiona Abrir el metodo devuelve 1 que podemos evaluar como Verdadero (True) 'Si presiona Cancelar devuelve 0 If oDlgAbrirArchivo. "*.sun.drawing.*.jpg.*.tiff") oDlgAbrirArchivo. si no 'se insertará con un tamaño mínimo casi invisible 'la unidad es centésimas de milímetro oTam.1 Trabajando con imágenes Calc.appendFilter( "Todos los formatos".createInstance( "com.sun.getCurrentController.star. Sub Dim Dim Dim Dim Dim Imagenes1() oDoc As Object oPaginaDibujo As Object oImagen As Object sRuta As String oTam As New com.10 Trabajando con elementos gráficos 6.setSize( oTam ) End Sub Ahora permitimos al usuario seleccionar una imagen. soporta la inclusión de una amplia variedad de formatos de imágenes.Execute() Then 'De forma predeterminada. Sub Dim Dim Dim Dim Dim Dim Imagenes2() oDlgAbrirArchivo As Object mArchivo() sRuta As String oPaginaDibujo As Object oImagen As Object oTam As New com. el método para abrir un archivo lo usamos casi al principio de estos apuntes.ui.png. pero aquí lo recordamos.star.add( oImagen ) 'Establecemos el tamaño de la imagen.bmp.dialogs.Height = 7500 oImagen. por ende.Size 'La ruta de la imagen sRuta = ConvertToURL("/home/mau/globo.jpge. siempre establece un tamaño.*.getActiveSheet.awt.awt. "*. Aprendiendo OOo Basic 357 sRuta = mArchivo(0) 'Insertamos la imagen oPaginaDibujo = ThisComponent.Execute() Then mArchivos() = oDlgAbrirArchivo.GraphicObjectShape" ) oImagen.sun. "*. 'Función para devolver la imagen a insertar Function SelecionarImagen() As String Dim oDlgAbrirArchivo As Object Dim mArchivos() oDlgAbrirArchivo = CreateUnoService ("com.bmp.*. pero tu puedes mejorarla.getActiveSheet.getDrawPage() . "*.sun.*.appendFilter( "Imagenes JPG". "*.star.png. pasándole el título del dialogo y los filtros que soporte. Sub Imagenes3() Dim sRuta As String sRuta = SelecionarImagen() MsgBox sRuta End Sub La siguiente subrutina.tiff") oDlgAbrirArchivo.Width = 10000 oTam.*.appendFilter( "Imagenes PNG".jpg") oDlgAbrirArchivo.drawing.GraphicURL = sRuta oPaginaDibujo.getFiles() SelecionarImagen = mArchivos(0) End If End Function Comprueba que funciona como se espera.jpg. puedes mejorarla pasándole la hoja donde se insertará.FilePicker") oDlgAbrirArchivo.awt.getActiveSheet.createInstance( "com.appendFilter( "Todos los formatos de imagen".jpge.png") oDlgAbrirArchivo.add( oImagen ) oTam.star. inserta la imagen pasada como argumento en la hoja activa.getCurrentController.Size oDoc = ThisComponent oPaginaDibujo = oDoc.setSize( oTam ) Else 'Si el usuario presiona Cancelar MsgBox "Proceso cancelado" End If End Sub El método para abrir archivos. así nos sirve.ui. para nuestro ejemplos. aquí te muestro una primer forma que nos servirá para nuestros siguientes ejemplos.*. por ejemplo.getDrawPage() oImagen = ThisComponent.dialogs. 'Subrutina para insertar la imagen en la hoja activa Sub InsertaImagen(RutaImagen As String) Dim oDoc As Object Dim oPaginaDibujo As Object Dim oImagen As Object Dim oTam As New com.sun.getCurrentController.star. podrías convertirla en una función para que te devuelva el nombre o nombres de los archivos abiertos. por ahora. la posición y el tamaño.setTitle("Selecciona la imagen a insertar") If oDlgAbrirArchivo.Height = 7500 oImagen. 358 6. 'Función para insertar la imagen en la hoja activa. Sub Imagenes4() Dim sRuta As String sRuta = SelecionarImagen() If sRuta <> "" Then Call InsertarImagen( sRuta ) End If End Sub La subrutina la puedes convertir en función y devolver una referencia a la imagen insertada. crea la subrutina para establecer el tamaño.getDrawPage() oImagen = oDoc. puedes seguir manipulándola.Height = 7500 oImagen.drawing. Sub Dim Dim Dim Imagenes5() sRuta As String oImagen As Object oTam As New com.getActiveSheet. por lo que es importante que lo hagas después de llamar a esta función.Width = 10000 oTam.GraphicObjectShape" ) oImagen.Height = 7500 oImagen.GraphicURL = RutaImagen oPaginaDibujo. de este modo. que servirá para cualquier objeto que soporte estas propiedades.Size sRuta = SelecionarImagen() If sRuta <> "" Then oImagen = getImagen( sRuta ) oTam.awt. Nota que en la función no establecemos el tamaño de la imagen.createInstance( "com.sun.star.createInstance( "com.GraphicObjectShape" ) oImagen.Width = 10000 oTam.sun.add( oImagen ) oTam.sun.star. devuelve la imagen 'nota que no establecemos el tamaño Function getImagen(RutaImagen As String) As Object Dim oDoc As Object Dim oPaginaDibujo As Object Dim oImagen As Object oDoc = ThisComponent oPaginaDibujo = oDoc.setSize( oTam ) End If End Sub Y ya encarrerados.getCurrentController.setSize( oTam ) End Sub Y la probamos.star.GraphicURL = RutaImagen oPaginaDibujo.10 Trabajando con elementos gráficos oImagen = oDoc.drawing.add( oImagen ) getImagen = oImagen End Function Y la prueba. . no importando si el ancla esta a la hoja o a una celda.Width = Ancho oTam. la imagen cambia a la posición de dicha celda.star.getCellByPosition( 4.getCurrentController. las imágenes insertadas. siempre lo hacen ancladas (Anchor) a la celda A1. si cambias el ancla de la imagen a una celda.awt.sun. 7500 ) 'Establecemos la posición de la imagen oPos. 7500 ) 'Establecemos la hoja como ancla oImagen.y = 5000 .getActiveSheet End If End Sub Como ya lo comprobamos.Anchor = ThisComponent. 10000. pero también puedes establecer esta posición.Size oTam.Aprendiendo OOo Basic 359 Sub CambiaTam( Obj As Object.9 ) oImagen. vamos a cambiar esto y por consiguiente la posición de la imagen. Sub Imagenes7() Dim sRuta As String Dim oImagen As Object sRuta = SelecionarImagen() If sRuta <> "" Then oImagen = getImagen( sRuta ) Call CambiaTam( oImagen. 10000.X = 15000 oPos.getActiveSheet. Ancho As Long.setSize( oTam ) End Sub Hasta ahora. 10000.Point sRuta = SelecionarImagen() If sRuta <> "" Then oImagen = getImagen( sRuta ) Call CambiaTam( oImagen.awt.Height = Alto Obj.Anchor = oCelda End If End Sub El ancla también la puedes establecer a la hoja. Sub Dim Dim Dim Imagenes6() sRuta As String oImagen As Object oCelda As Object sRuta = SelecionarImagen() If sRuta <> "" Then oImagen = getImagen( sRuta ) Call CambiaTam( oImagen. Sub Imagenes8() Dim sRuta As String Dim oImagen As Object Dim oPos As New com.sun.star. Alto As Long ) Dim oTam As New com. al modificar esta se modifica la posición oCelda = ThisComponent. 7500 ) 'Establecemos la celda de anclaje.getCurrentController. star. 10000.star. les puedes cambiar el modo de color (GraphicColorMode).SizeProtect = True 'Que se imprima .setPosition( oPos ) End If End Sub 6.star. así mismo.ColorMode.drawing.drawing. Puedes tener varias imágenes con el mismo nombre. cuando insertas o eliminas filas o columnas. Sub Dim Dim Dim Imagenes10() sRuta As String oImagen As Object oPos As New com. sobre todo si manejas muchas imágenes para que se muestre en el navegador.sun.drawing.drawing.sun.star. es importante que lo asignes. también puedes evitar que se mueva (MoveProtect) y que se imprima (Printable). Sub Imagenes9() Dim sRuta As String Dim oImagen As Object sRuta = SelecionarImagen() If sRuta <> "" Then oImagen = getImagen( sRuta ) Call CambiaTam( oImagen. según la siguiente enumeración: com.star.WATERMARK Valor 0 1 2 3 Valor en Interfaz Predeterminado Escala de grises Blanco y negro Filigrana El siguiente ejemplo.MONO com.sun.Printable = False 'Puedes reflejar la imagen .Name = "Imagen09" 'Evitamos que la muevan .GREYS com.drawing.360 oImagen. inserta la imagen varias veces son los diferentes modos.ColorMode com. A las imágenes. 7500 ) With oImagen 'Nombramos la imagen .IsMirrored = True End With End If End Sub El nombre asignado a la imagen (Name).STANDARD com.Point sRuta = SelecionarImagen() If sRuta <> "" Then 'Insertamos la imagen normal oImagen = getImagen( sRuta ) .sun.star. es el nombre que aparecerá en el navegador. es el que puede establecer con el menú contextual de la imagen.sun.MoveProtect = True 'Que cambie su tamaño .ColorMode.awt. la imagen se verá afectada en su tamaño.ColorMode.ColorMode. puedes evitarlo protegiendo su tamaño (SizeProtect).10 Trabajando con elementos gráficos Algunas propiedades interesantes.sun. 5000.sun.GraphicColorMode = com. 3750 ) 361 'Insertamos la misma imagen oImagen = getImagen( sRuta ) Call CambiaTam( oImagen. 5000. 0 ) oImagen.GREYS oImagen = getImagen( sRuta ) Call CambiaTam( oImagen.GraphicColorMode = com. 5000.WATERMARK End If End Sub 'Cambia la posición del objeto Sub CambiaPos( Obj As Object.drawing. 0 ) 'Cambiamos el nivel de transparencia oImagen. Puedes cambiar la transparencia (Transparency) de la imagen. 0 ) 'Cambiamos el modo de color a escala de grises oImagen.drawing.drawing.sun.Y = Y Obj. 3750 ) Call CambiaPos( oImagen. 10000. 5000.ColorMode. X As Long. 5000. no veras la imagen por lo que procura no establecerlo tan alto. Y As Long ) Dim oPos As New com. 0 ) 'Cambiamos el modo de color a marca de agua oImagen.Aprendiendo OOo Basic Call CambiaTam( oImagen.star. este valor va de 0 a 100. Sub Dim Dim Dim Imagenes11() sRuta As String oImagen As Object oPos As New com.GraphicColorMode = com.setPosition( oPos ) End Sub El resultado. 3750 ) Call CambiaPos( oImagen.MONO oImagen = getImagen( sRuta ) Call CambiaTam( oImagen. 3750 ) Call CambiaPos( oImagen. sin transparencia y 100 totalmente transparente.star. 0 ) 'Cambiamos el modo de color a blanco y negro oImagen.X = X oPos. donde 0 es el valor predeterminado.Transparency = 50 oImagen = getImagen( sRuta ) .Point oPos. 3750 ) Call CambiaPos( oImagen.star.awt. 10000. 5000. 5000. 5000.awt.sun.sun. si estableces esta valor en 100 y pierdes la selección. 15000. 3750 ) oImagen = getImagen( sRuta ) Call CambiaTam( oImagen.ColorMode. 5000. 3750 ) Call CambiaPos( oImagen.star.star.ColorMode.Transparency = 25 oImagen = getImagen( sRuta ) Call CambiaTam( oImagen.sun.Point sRuta = SelecionarImagen() If sRuta <> "" Then 'Insertamos la imagen normal oImagen = getImagen( sRuta ) Call CambiaTam( oImagen. de la siguiente manera.awt.awt. 0 ) . 0 ) 'Cambiamos el nivel de luminosidad oImagen. el canal gamma (Gamma).Transparency = 75 End If End Sub 6.Point sRuta = SelecionarImagen() If sRuta <> "" Then 'Insertamos la imagen normal oImagen = getImagen( sRuta ) Call CambiaTam( oImagen. 3750 ) Call CambiaPos( oImagen. Sub Dim Dim Dim Imagenes12() sRuta As String oImagen As Object oPos As New com. 5000. Sub Dim Dim Dim Imagenes13() sRuta As String oImagen As Object oPos As New com. como el contraste (AdjustContrast). pero cambia oImagen. tanto la luminosidad (AdjustLuminance). 3750 ) Call CambiaPos( oImagen. 5000.star. 15000. 3750 ) Call CambiaPos( oImagen. 3750 ) oImagen = getImagen( sRuta ) Call CambiaTam( oImagen. 5000.Gamma = 5 End If End Sub Y por supuesto.362 Call CambiaTam( oImagen. 5000. 10000. 5000.10 Trabajando con elementos gráficos Puedes manipular completamente los colores de una imagen (si sabes por que yo no). de 0. el canal gamma. 0 ) oImagen.sun. 5000. 3750 ) Call CambiaPos( oImagen. 3750 ) oImagen = getImagen( sRuta ) Call CambiaTam( oImagen.sun. 0 ) 'Cambiamos el contraste oImagen. 5000. verde (AdjustGreen) y azul (AdjustBlue). toman valores de 0 a 100.star. 15000. 5000.1 a 10. La luminosidad y el contraste. 5000.AdjustContrast = 50 oImagen = getImagen( sRuta ) Call CambiaTam( oImagen. 3750 ) Call CambiaPos( oImagen.AdjustLuminance = 50 oImagen = getImagen( sRuta ) Call CambiaTam( oImagen. 0 ) 'Cambiamos el canal gamma. también puedes cambiar los canales rojo (AdjustRed).Point sRuta = SelecionarImagen() If sRuta <> "" Then 'Insertamos la imagen normal oImagen = getImagen( sRuta ) Call CambiaTam( oImagen. que no se que sea. 10000. 3750 ) Call CambiaPos( oImagen.CharHeight = 30 . Sub Dim Dim Dim Dim Dim Imagenes15() sRuta As String oImagen As Object oForma As Object oGP As Object mOpc(0) As New com.255. al insertar la imagen.createInstance("com.drawing. 5000.beans. Hidalgo" & Chr(13) & "México" . por ejemplo.star. 7500 ) 'Insertamos texto en la imagen y le cambiamos sus propiedades With oImagen .ParaAdjust = 3 End With End If End Sub Otras propiedades las veremos en el siguiente apartado.255) . 0 ) 'Cambiamos el nivel de azul oImagen. 10000.AdjustRed = 50 oImagen = getImagen( sRuta ) Call CambiaTam( oImagen.CharWeight = 150 . usa el siguiente código. 15000. 0 ) 'Cambiamos el nivel de verde oImagen.GraphicObjectShape") ThisComponent.CharColor = RGB(255.PropertyValue sRuta = SelecionarImagen() If sRuta <> "" Then 'Agregamos una forma a la hoja activa oForma = ThisComponent. como en: Sub Imagenes14() Dim sRuta As String Dim oImagen As Object sRuta = SelecionarImagen() If sRuta <> "" Then oImagen = getImagen( sRuta ) Call CambiaTam( oImagen. 5000.add(oForma) .String = "Apulco.Aprendiendo OOo Basic 'Cambiamos el nivel de rojo oImagen.AdjustGreen = 50 oImagen = getImagen( sRuta ) Call CambiaTam( oImagen. te quedará solo un marco vacío. cuando abras tu archivo. 3750 ) Call CambiaPos( oImagen. como las que hemos visto hasta ahora.sun.AdjustBlue = 50 End If End Sub 363 Mira que divertido queda. la estás vinculando. pero al ser consideradas formas (shapes) comparten con ellas muchas de sus propiedades. Las imágenes insertadas tienen propiedades particulares. para insertar la imagen incrustada en el documento.star. por lo que si cambias el nombre de la imagen origen. en todos los ejemplos anteriores.sun. la mueves o borras. para terminar este tema.getActiveSheet. la posibilidad de agregarles texto.getCurrentController.getDrawPage(). drawing.Name = "URL" mOpc(0).Name = "MimeType" mOpc(1).GraphicObjectShape") Then 'Si es una imagen. pero esa. 10000.storeGraphic( oSel.sun.sun.supportsService("com.Graphic = oGP. por supuesto puedes exportar a otros formatos.getSelection iF oSel.SvxShapeCollection" Then 'Si es una forma. puedes convertir en una función o subrutina para llamarla cuando quieras.PropertyValue 'La selección actual oSel = ThisComponent.graphic.queryGraphic( mOpc ) 'Cambiamos el tamaño Call CambiaTam( oForma.star. por supuesto.star. 7500 ) End If End Sub El cual.Value = "image/jpeg" 'Guardamos la imagen oGP. Sub Dim Dim Dim Dim Imagenes16() sRuta As String oSel As Object oGP As Object mOpc(1) As New com.GraphicProvider") 'Establecemos la ruta mOpc(0). es tu tarea.Name = "URL" mOpc(0). siempre es la primera oSel = oSel.star.star. El siguiente ejemplo es muy divertido. mOpc ) Else MsgBox "Proceso cancelado" End If Else MsgBox "La selección es una forma pero no una imagen" End If Else MsgBox "La selección no es una imagen" End If End Sub La función para devolver la ruta es: 'Función para devolver la ruta y nombre del archivo a guardar 'Puedes mejorarla pasándole los filtros que quieras Function RutaGuardarImagen() As String Dim oDlgGuardarArchivo As Object Dim mArchivo() Dim mDlgOpciones() mDlgOpciones() = Array(2) . solicita una ruta y nombre donde guardar y la guarda si el usuario no cancela la operación.364 6.GraphicProvider") 'Establecemos las propiedades mOpc(0).drawing.graphic.sun. toma la selección y determina si es o no una imagen.getImplementationName = "com.star.sun.beans.Value = sRuta 'Trae la imagen y la carga en la forma oForma.Value = sRuta mOpc(1).10 Trabajando con elementos gráficos 'Servicio para manipulacion de gráficos oGP = createUnoService("com.getByIndex(0) If oSel. en formato “jpg”.getCurrentController.sun.Graphic. obtenemos la ruta y nombre para guardar sRuta = RutaGuardarImagen() If sRuta <> "" Then oGP = createUnoService("com. "*. las subrutinas “CambiaTam” y “CambiaPos”. incluye. por lo que si te muestra un número y aparentemente no hay nada en la hoja.getCurrentController.10.getDrawPage() 'Iteramos en cada forma .ui.getActiveSheet() 'Accedemos a la página de dibujo oPaginaDibujo = oHojaActiva. el limite.dialogs. son soportados por las imágenes.jpg" ) If oDlgGuardarArchivo. que puedes complementar perfectamente con los conocimientos de nuestro próximo apartado. El siguiente ejemplo. las notas de las celdas. Sub Dim Dim Dim Dim Dim AutoFormas2() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oForma As Object co1 As Long oDoc = ThisComponent oHojaActiva = oDoc. cambia el tamaño y la posición de “todos” los objetos gráficos de la hoja y los posiciona en la esquina superior izquierda de la hoja.getDrawPage() 'Mostramos el número de elementos en la página MsgBox oPaginaDibujo. Cada hoja de nuestro archivo. otras veces. veamos.getFiles() RutaGuardarImagen = mArchivo(0) End If End Function Y con esto terminamos el tema de imágenes. donde están todos los elementos gráficos.getCount End Sub La cuenta de los objetos gráficos.Execute() Then mArchivo() = oDlgGuardarArchivo.AppendFilter( "Imagen JPG (. tal vez sea este tu caso. se podría dibujar casi cualquier cosa. ya las hemos usado anteriormente.setTitle("Guardar como") oDlgGuardarArchivo.2 Trabajando con autoformas Con las herramientas de dibujo incluidas en la aplicación. tiene una “página de dibujo virtual” (DrawPage).FilePicker") oDlgGuardarArchivo.getCurrentController.star. usamos: Sub Dim Dim Dim AutoFormas1() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oDoc = ThisComponent oHojaActiva = oDoc. 6. pues muchas de las propiedades y métodos que veremos. incluso.getActiveSheet() 'Accedemos a la página de dibujo oPaginaDibujo = oHojaActiva.sun. porqué.Aprendiendo OOo Basic 365 oDlgGuardarArchivo = CreateUnoService ("com. para acceder a esta hoja. que tienen un tamaño mínimo y no se notan o están posicionadas en zonas de la hoja muy separadas. es tu imaginación.jpg)".Initialize ( mDlgOpciones() ) oDlgGuardarArchivo. como imágenes. hay elementos. aprenderemos a cambiar aquí. obtienes un circulo.add( oForma ) End Sub ¿Adivina que pasa si estableces el mismo alto y ancho?. Para agregar una forma a la página de dibujo y por consiguiente a la hoja activa (puede ser a la hoja que quieras. por ejemplo. Sub AutoFormas3() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent. agregamos un rectángulo a la hoja. la nueva forma se crea con las propiedades predeterminadas. 5000 ) oPaginaDibujo. si establece el mismo ancho y alto.createInstance("com.getCount .getCurrentController. 3000 ) oPaginaDibujo. casi de la que quieras por que en las hojas de calculo no puedes agregar todos los tipos de formas. 0. En el siguiente ejemplo. lo mismo pasa con las elipses.1 oForma = oPaginaDibujo. texto. sombra. en vez de un rectángulo. que siempre muestra las notas cerca de esta.10 Trabajando con elementos gráficos Si en tu hoja hay notas.getActiveSheet. 3000. etc). . una polilínea no puedes agregarla. relleno. 0 ) Next End Sub 6.drawing.sun.sun. es importante que al menos cambies el tamaño de la nueva forma.getByIndex(co1) 'Cambiamos su tamaño Call CambiaTam( oForma.366 For co1 = 0 To oPaginaDibujo. comparten casi todas las mismas propiedades (línea. 5000. Sub AutoFormas4() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.getDrawPage() 'Creamos un circulo oForma = ThisComponent. si no cuando la muestres permanentemente.RectangleShape") Call CambiaTam( oForma.EllipseShape") Call CambiaTam( oForma. 5000. Como con las imágenes.star.drawing. entonces. primero creas una instancia de la forma que quieras. veamos las principales que comparten entre si y después las particulares de algunas.createInstance("com. las cuales. lo cual si puedes hacer en Draw o Impress. es obvia la respuesta.star.getCurrentController. bueno. no cuando pongas el cursor sobre la celda. estas se cambiaran de tamaño pero el cambio de posición solo lo veras reflejado cuando muestres la nota.add( oForma ) End Sub La mayoría de las formas. 3000 ) 'Y su posición Call CambiaPos( oForma.getActiveSheet. se creará del tamaño mínimo.getDrawPage() 'Creamos un rectangulo oForma = ThisComponent. tienes un cuadrado. no necesariamente la activa). le estableces sus propiedades y al final la agregas a la página de dibujo. si no. después de agregar la forma soportada en Calc. DASH Valor 0 1 2 Valor en Interfaz Oculta Solida Guiones El color (LineColor) de la línea es un valor tipo largo (long).getCurrentController.drawing.sun.star.sun. com.LineStyle. esta determinado por la siguiente enumeración. por ello.LineStyle.star. el ancho de la línea se establece en centésimas de milímetro y se reparte de forma equidistante del dentro hacia afuera y dentro de la forma.drawing.NONE com. no desaparece completamente.drawing.sun.10.createInstance("com. mejor usa el estilo si lo que quieres es no mostrar la línea.Rnd()*255. Sub AutoFormas5() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.LineDashName = "Fine Dashed" End Sub Los nombres que puedes establecer son: .getDrawPage() 'Creamos una elipse oForma = ThisComponent.add( oForma ) End Sub El estilo de línea.star. queda visible aun.EllipseShape") Call CambiaTam( oForma.Aprendiendo OOo Basic 367 6.drawing. la primera más sencilla.LineStyle.1 Principales propiedades de línea. si establece el valor en cero la línea no se verá como si establecieras el estilo en oculta (NONE).SOLID com. 5000 ) With oForma 'El estilo de línea . la transparencia (LineTransparence) puede tomar valores de 0 (menos transparencia) a 100 (más transparencia).getDrawPage() 'Seleccionamos el primero objeto de dibujo oForma = oPaginaDibujo.getActiveSheet. estableces el nombre de estilo como en: Sub AutoFormas6() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.LineTransparence = 50 'El ancho de la línea . 10000.drawing.SOLID 'El color de la línea .sun.drawing.2.star.getByIndex(0) 'Establecemos el estilo en guiones oForma.LineWidth = 500 End With oPaginaDibujo.LineStyle com.star.sun.LineStyle = com.star.LineStyle. puedes establecer el estilo de este de dos maneras.drawing.star. si estableces este valor en cero.getCurrentController.sun.LineStyle.LineColor = RGB( Rnd()*255.sun.LineStyle = com.DASH 'Establecemos el estilo oForma.getActiveSheet.Rnd()*255 ) 'La transparencia de la línea . Si estableces el estilo en guiones (DASH). lo más practico es crear una matriz con los nombres.getActiveSheet."2 Dots 1 Dash") oPaginaDibujo = ThisComponent. puedes usar la otra forma de establecer el estilo.getByIndex(0) 'Establecemos el estilo en guiones oForma.sun."Fine Dotted".getDrawPage() 'Seleccionamos el primero objeto de dibujo oForma = oPaginaDibujo. Sub Dim Dim Dim AutoFormas7() oPaginaDibujo As Object oForma As Object mEstilos() mEstilos = Array("Ultrafine Dashed".drawing."Line Style 9"."Fine Dashed (var)"."Fine Dashed".star. creando un estilo completamente nuevo y personalizado. te dará un error en tiempo de ejecución. incluso sus mayúsculas.star.drawing.LineDashName = mEstilos(4) End Sub Recuerda que los estilos de línea. el nombre debe corresponder exactamente.10 Trabajando con elementos gráficos Si las vas a usar seguido. de lo contrario. 1) 2) 3) 4) 5) Número de puntos (Dots) Número de guiones (Dashes) Ancho del punto (DotLen) Distancia en elementos (Distance) Ancho del guión (DashLen) Para crear un estilo similar al anterior. el cual.LineStyle. números y espacios. Sub Dim Dim Dim AutoFormas8() oPaginaDibujo As Object oForma As Object oLineaGuion As Object oLineaGuion = createUnoStruct("com. minúsculas. son completamente personalizables desde la interfaz del usuario.getCurrentController.368 6."Ultrafine Dotted (var)"."3 Dashes 3 Dots (var)". usamos el siguiente código. esta estructurado de la siguiente manera. Si quieres asegurate de que no haya error. por lo que estos nombres pueden cambiar. con el nombre de la interfaz."Ultrafine 2 Dots 3 Dashes"."Line with Fine Dots".DASH 'Establecemos el estilo oForma.Style = 0 .sun.LineDash") 'Todas las medidas en centésimas de milímetro With oLineaGuion .LineStyle = com.Dots = 3 . star.star. establece la línea en un acho bastante visible y nota como cambia.ROUNDRELATIVE Valor 0 1 2 3 Valor en Interfaz Rectangulo Punto Rectangulo.FillStyle.Dashes = 2 .drawing.SOLID com.FillStyle.DashLen = 2000 .LineDash = oLineaGuion End Sub Observa que también aquí tenemos un estilo (Style).2 Principales propiedades de relleno Ahora veamos las principales propiedades de relleno.DashStyle com.Distance = 250 End With oPaginaDibujo = ThisComponent.star.getByIndex(0) oForma.getActiveSheet.DashStyle.star. sin relleno.drawing.sun.sun.FillStyle = 0 End Sub El estilo de fondo (FillStyle).2.NONE com. 6.drawing.star.sun.drawing.DashStyle.sun.getCurrentController.LineStyle.HATCH com.DashStyle.10.sun.DashStyle.sun. esta determinado por la enumeración.getDrawPage() oForma = oPaginaDibujo.star.FillStyle.FillStyle com. La primera y más simple.FillStyle. com.RECTRELATIVE com.ROUND com.star. relativo a la longuitud de la línea Punto.sun.drawing.FillStyle. es.getActiveSheet.DotLen = 500 .star.drawing.sun.star. relativo a la longuitud de la línea Para que notes las diferencias de estos estilos.BITMAP Valor 0 1 2 3 4 Valor en Interfaz Invisible Color Gradiente Trama Bitmap (Imagen) .sun.Aprendiendo OOo Basic 369 .getByIndex(0) 'Establecemos el relleno en invisible oForma.sun.sun.star.star.DASH 'Establecemos el estilo oForma. com.drawing.drawing.getDrawPage() oForma = oPaginaDibujo.drawing.getCurrentController.LineStyle = com.drawing.drawing.GRADIENT com. Sub AutoFormas9() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.drawing.star. de acuerdo a la enumeración.sun.RECT com. getActiveSheet.getByIndex(0) 'Establecemos el relleno en gradiente oForma.drawing. es más sencillo establecerlos.GRADIENT 'El nombre del gradiente oForma. seleccionas la forma. si lo haces con la transparencia.Rnd()*255.FillStyle = com. Sub AutoFormas10() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.getCurrentController.SOLID 'Un color aleatorio oForma.getByIndex(0) 'Establecemos el relleno en color oForma.getDrawPage() oForma = oPaginaDibujo.star. la diferencia será que si lo estableces con el estilo.FillTransparence = 50 End Sub Para establecer el fondo en un gradientes.getCurrentController. el fondo se “quita” y puedes seleccionar las celdas que esten debajo de la forma.star. un valor de 100.Rnd()*255.Rnd()*255 ) End Sub Puedes establecer el porcentaje (0 a 100) de transparencia. si no los ha cambiado el usuario son: Con una matriz para los nombres.getActiveSheet.getCurrentController. al dar clic dentro de la forma. te dará un error en tiempo de ejecución.SOLID 'Un color aleatorio oForma. usamos. Sub AutoFormas12() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent. será similar a establecer el estilo de fondo en invisible (NONE).FillStyle.Rnd()*255 ) 'La transparencia del color oForma.getDrawPage() oForma = oPaginaDibujo.drawing.drawing.star.FillColor = RGB( Rnd()*255.FillStyle = com.370 6.FillStyle.sun.sun. si no.getByIndex(0) 'Establecemos el relleno en color oForma.getActiveSheet.FillGradientName = "Rectangular red/white" End Sub El nombre es el usado por la interfaz del usuario y debe ser exacto.FillStyle.FillStyle = com. Sub AutoFormas11() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.getDrawPage() oForma = oPaginaDibujo. los gradientes predeterminados.sun.FillColor = RGB( Rnd()*255.10 Trabajando con elementos gráficos Establecemos un color aleatorio en la primer forma de la hoja. Sub AutoFormas13() Dim oPaginaDibujo As Object . procura establecer un color de fondo claro.getActiveSheet."Rectangular red/white"."Black 45 Degrees".getByIndex(0) 'Establecemos el relleno en gradiente oForma.getByIndex(0) 'Establecemos el relleno en trama oForma."Red Crossed 45 Degrees".FillStyle."Radial red/yellow"."Blue Crossed 0 Degrees"."Linear yellow/brown".getDrawPage() oForma = oPaginaDibujo."Red Crossed 0 Degrees". también.FillGradientName = mGradiente(4) End Sub Cambiamos de tipo de fondo y establecemos el estilo en trama (HATCH)."Black -45 Degrees".FillStyle."Gradient 5". para que se distinga la trama.FillStyle = com.getByIndex(0) 'Establecemos el relleno en trama oForma.getActiveSheet.getCurrentController."Gradient 4". Puedes combinar el uso de una trama con un fondo de color.getDrawPage() oForma = oPaginaDibujo."Gradient 2"."Gradient 6". Sub Dim Dim Dim AutoFormas15() oPaginaDibujo As Object oForma As Object mTramas() 'Matriz con los nombres de las tramas predeterminadas mTramas = Array("Black 0 Degrees"."Axial light red/white") oPaginaDibujo = ThisComponent.FillStyle.drawing.Aprendiendo OOo Basic Dim oForma As Object Dim mGradiente() 371 'Matriz con los nombres de los gradientes mGradiente = Array("Gradient 1".HATCH 'El nombre de la trama oForma."Linear magenta/green".FillStyle = com.drawing."Black 45 Degrees Wide") oPaginaDibujo = ThisComponent.FillHatchName = mTramas(5) End Sub Que corresponden a.HATCH 'El nombre de la trama oForma."Radial green/black".sun.FillHatchName = "Black 45 Degrees Wide" End Sub Al igual que con los nombres de los gradientes. Sub AutoFormas16() Dim oPaginaDibujo As Object . Sub AutoFormas14() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.sun."Square yellow/white".getDrawPage() oForma = oPaginaDibujo.star."Linear blue/white"."Gradient 3".getActiveSheet.getCurrentController.drawing.getCurrentController.star.sun.GRADIENT 'El nombre del gradiente oForma. son suceptibles de ser modificados por el usuario desde la interfaz del usuario."Blue Triple 90 Degrees".FillStyle = com. estos deben establecerse exactamente como se muestran a continuación y."Ellipsoid blue grey/light blue".star."Black 90 Degrees"."Blue Crossed 45 Degrees". getActiveSheet."Orange".10 Trabajando con elementos gráficos oPaginaDibujo = ThisComponent."Pebbles".FillStyle = com.getDrawPage() oForma = oPaginaDibujo.Rnd()*255 ) End Sub Para establecer una imagen como fondo de una forma.getCurrentController. Sub Dim Dim Dim AutoFormas17() oPaginaDibujo As Object oForma As Object mImagen() mImagen = Array("Empty"."Wet".getDrawPage() oForma = oPaginaDibujo. tienes que cambiar el estilo y establecer el nombre de la imagen."Wall"."Aqua".BITMAP 'El nombre de la imagen oForma.getDrawPage() oForma = oPaginaDibujo."Lawn Artificial".sun."Marble".Rnd()*255."Pattern".getActiveSheet.FillStyle = com."Pattern".getByIndex(0) 'Establecemos el relleno en Imagen oForma."Leaves"."Fiery"."Fiery".HATCH 'El nombre de la trama oForma. desde un archivo de imagen.FillHatchName = "Black 45 Degrees Wide" 'Tambien con color oForma.BITMAP 'El nombre de la imagen oForma.getActiveSheet."Roses") oPaginaDibujo = ThisComponent."Metal"."Lawn Artificial"."Metal".FillStyle. que como en los demás estilos. debe estar escrito correctamente y puede ser cambiado por el usurio desde la interfaz.FillBitmapName = mImagen(15) oForma."Daisy"."Wall".FillStyle."Leaves".FillStyle = com.FillBitmapName = mImagen(10) End Sub Estos nombres corresponden a.drawing.sun."Wet"."Red Wall".FillBackground = True oForma."Space Metal"."Orange"."Linen".star."Red Wall"."Pebbles"."Space"."Linen". Puedes establecer una imagen.star."Roses") oPaginaDibujo = ThisComponent."Space Metal"."Coarse".372 Dim oForma As Object 6."Coarse"."Sky"."Aqua". y al mismo tiempo el nivel de transparencia."Sky". .drawing.drawing."Stone"."Stone"."Space".star.getByIndex(0) 'Establecemos el relleno en trama oForma."Marble".FillStyle.getByIndex(0) 'Establecemos el relleno en Imagen oForma.FillTransparence = 50 End Sub Puedes establecer la imagen."Daisy".sun.getCurrentController.FillColor = RGB( Rnd()*255.getCurrentController. Sub Dim Dim Dim AutoFormas18() oPaginaDibujo As Object oForma As Object mImagen() mImagen = Array("Empty". FillStyle = com. La imagen.drawing.star.sun. no necesariamente tiene que estar en tu equipo. tomado de un archivo de internet oForma.FillStyle.10.Aprendiendo OOo Basic Sub AutoFormas19() Dim oPaginaDibujo As Object Dim oForma As Object 373 oPaginaDibujo = ThisComponent.STRETCH com.drawing.getByIndex(0) oForma. no te dará error.FillBitmapURL = ConvertToURL( "http://www.3 Principales propiedades de sombra Ahora veamos las principales propiedades de la sombra de una forma.star.getCurrentController.sun.jpg" ) 'Es modo con que se muestra oForma.drawing.BITMAP 'El nombre de la imagen.ShadowTransparence = 50 End Sub . com.sun. tomado de un archivo oForma.REPEAT End Sub El modo de imagen.star.getActiveSheet.star. con los tres modos diferentes.BitmapMode.getCurrentController. Sub AutoFormas20() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.getByIndex(0) oForma.BitmapMode.REPEAT com.sun.star.Rnd()*255 ) 'Establecemos el nivel de transparencia de la sombra oForma.getDrawPage() oForma = oPaginaDibujo.2.getActiveSheet.drawing.drawing.Shadow = True 'Establecemos el color de la sombra oForma.FillStyle.drawing.sun.getCurrentController. si la ruta no existe.getDrawPage() oForma = oPaginaDibujo. esta determinado por la enumeración.getActiveSheet.ShadowColor = RGB( Rnd()*255.BITMAP 'El nombre de la imagen. pero obvio.BitmapMode.png" ) End Sub 6.star.sun.FillBitmapURL = ConvertToURL( "/home/mau/fondo.FillStyle = com.getByIndex(0) 'Establecemos que queremos mostrar la sombra oForma.star. puede estar al otro lado del mundo. Sub AutoFormas21() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.sun.universolibre.FillBitmapMode = com.getDrawPage() oForma = oPaginaDibujo.NO_REPEAT Valor 0 1 2 Valor en Interfaz Repetir Ajustar No repetir El mismo fondo en una forma.Rnd()*255.drawing. no te mostrará la imagen.BitmapMode.BitmapMode com.org/archivos/favicon. si se puede mover o no y si se puede cambiar el tamaño o no.Printable = False 'Que no se pueda mover oForma.ShadowXDistance = -500 oForma.ShadowXDistance = 300 oForma.getActiveSheet.MoveProtect = True 'Que no cambie el tamaño oForma.getActiveSheet. la sombra queda “detras” de la forma y es “como” si la ocultaras.Rnd()*255 ) 'Establecemos la distancia X . Sub AutoFormas23() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.getByIndex(0) 'Establecemos que queremos mostrar la sombra oForma. estableces los valores en.10 Trabajando con elementos gráficos Si no quieres mostrarla solo establece la sombra (Shadow) en falso (False).getByIndex(0) oForma. Puedes posicionar la imagen.Rnd()*255.getDrawPage() oForma = oPaginaDibujo.getActiveSheet.10. para posicionarla en el extremo inferior izquierdo.ShadowColor = RGB( Rnd()*255.374 6.Y de la sombra en centésimas de milímetro oForma.4 Otras propiedades de las autoformas Podemos establecer si la forma se va a imprimir o no.getCurrentController.Rnd()*255 ) 'Establecemos la distancia X .getCurrentController.getDrawPage() oForma = oPaginaDibujo. por ejemplo.Y de la sombra en centésimas de milímetro oForma. por ejemplo. Sub AutoFormas22() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent. puedes establecer estas propiedades en valores negativos.2.getByIndex(0) 'Establecemos que no se imprima la forma oForma. en relación a la forma. el color y la transparencia tienen las mismas particularidades ya vistas. con las siguientes propiedades. para establecer la forma en otra posición de la forma.ShadowColor = RGB( Rnd()*255. donde quieras.Rnd()*255. usamos.getCurrentController.ShadowYDistance = 300 End Sub 6.SizeProtect = True .Shadow = True 'Establecemos el color de la sombra oForma. Sub AutoFormas24() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.Shadow = True oForma.ShadowYDistance = 300 End Sub Si establecemos la posición (ShadowXDistance y ShadowYDistance) en 0.getDrawPage() oForma = oPaginaDibujo. para establecer la sombra a 3 milímetros de la forma. asegurate de tener al menos dos formas en tu hoja y de preferencia formas estándar. pero no todas las formas lo soportan.getByIndex(0) oForma2 = oPaginaDibujo. esta propiedad. la unidad también son centésimas de grado.getDrawPage() oForma = oPaginaDibujo.Aprendiendo OOo Basic 375 End Sub Podemos establecer el ángulo de rotación de la forma. es decir.RotateAngle = 4500 End Sub También podemos modificar la inclinación de la forma. quien esta delante de quien.ShearAngle = 1500 End Sub También podemos cambiar el orden de las formas.ZOrder oForma1.getDrawPage() oForma = oPaginaDibujo. Sub AutoFormas26() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.ZOrder = Pos2 oForma2. Sub Dim Dim Dim Dim Dim AutoFormas27() oPaginaDibujo As Object oForma1 As Object oForma2 As Object Pos1 As Integer Pos2 As Integer oPaginaDibujo = ThisComponent.getActiveSheet. este valor solo puede estar comprendido entre 0º y 89º.ZOrder Pos2 = oForma2. el siguiente ejemplo intercambia la posición de las dos primeras formas. La unidad de esta valor son centésimas de grado y el sentido de rotación es inverso al giro de las manecillas del reloj.getCurrentController.getActiveSheet.getDrawPage() oForma1 = oPaginaDibujo. Sub AutoFormas25() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.getByIndex(0) 'Establecemos el ángulo de inclinación oForma.getCurrentController.getActiveSheet.getCurrentController.getByIndex(0) 'Establecemos el ángulo de rotación en 45º 'unidades en centésimas de grado oForma.getByIndex(1) Pos1 = oForma1.ZOrder = Pos1 . algunas formas especiales como rombos o corazones no la soportan. rectángulos o círculos para que veas el efecto. getByIndex(0) ) oGrupoFormas.group( oGrupoFormas ) Else MsgBox "Agrega más formas para poder agrupar" End If End Sub Si el elemento a agregar no existe te dará un error en tiempo de ejecución.supportsService("com.getActiveSheet.getCount .getByIndex(0) 'Checamos que sea un grupo If oForma.Name = "Circulo Azul" End Sub 6. Sub Dim Dim Dim AutoFormas30() oPaginaDibujo As Object oForma As Object co1 As Integer oPaginaDibujo = ThisComponent.5 Agrupando y desagrupando formas Para agrupar formas.getDrawPage() oForma = oPaginaDibujo.add( oPaginaDibujo.sun.add( oPaginaDibujo.getCurrentController.10 Trabajando con elementos gráficos Puedes cambiar el nombre de la forma.getCurrentController. es importante que lo establezcas para que puedas verlo en el navegador (F5) de contenido del archivo.getCurrentController.star.376 End Sub 6. En un grupo puedes editar cada elemento que lo contiene de la siguiente manera.2.GroupShape") Then 'Recorremos todas las formas que contiene For co1 = 0 To oForma.getCount >= 2 Then 'Agregamos las dos primeras oGrupoFormas. Sub AutoFormas28() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.star.getByIndex(0) 'Establecemos el nombre de la forma oForma.getActiveSheet.getDrawPage() oGrupoFormas = createUnoService("com.sun.getByIndex(1) ) 'Las agrupamos oPaginaDibujo.drawing. Sub Dim Dim Dim AutoFormas29() oPaginaDibujo As Object oGrupoFormas As Object oForma As Object oPaginaDibujo = ThisComponent. usamos el siguiente código.10.getDrawPage() 'Accedemos a la primer forma de la hoja oForma = oPaginaDibujo.getActiveSheet.1 .ShapeCollection") 'Necesitamos al menos dos formas para agrupar If oPaginaDibujo.drawing. getByIndex(co1) If oForma. Loop While co1 < oPaginaDibujo.ungroup( oForma ) 'Reiniciamos la cuenta para empezar de cero co1 = 0 Else co1 = co1 + 1 End If 'Cuando co1 = número de formas.star.getCount End If End Sub .getByindex(co1).getCount > 0 Then Do oForma = oPaginaDibujo. este número varia en función de agrupar o desagrupar formas. puedes deducirlo a partir de lo que se comenta en el ejemplo 32 y mejorar este ejemplo para que funcione en todos los casos.Rnd()*255. por eso. lo desagrupamos oPaginaDibujo.GroupShape") Then oPaginaDibujo.getDrawPage() If oPaginaDibujo. se suma a la cuenta de formas de la página de dibujo. te dará un error en un caso determinado.sun.GroupShape") Then 'Si es un grupo. Para desagrupar un grupo. por lo que salimos. Sub AutoFormas31() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent. te desagrupa “todos” los grupos existentes.drawing. Sub Dim Dim Dim Dim AutoFormas32() oPaginaDibujo As Object oForma As Object co1 As Long bHayGrupo As Boolean oPaginaDibujo = ThisComponent. el siguiente ejemplo. tu tarea es averiguar en cual.FillColor = RGB( Rnd()*255.Rnd()*255 ) Call CambiaTam( oForma.sun.drawing.ungroup( oForma ) End If End Sub Toma en cuenta que cuando desagrupas.star.supportsService("com.getDrawPage() oForma = oPaginaDibujo. Rnd()*10000+1000. el número de elementos que contenía el grupo. Rnd()*5000+1000) Next End If End Sub El ejemplo anterior.supportsService("com.getCurrentController.getByindex(co1).Aprendiendo OOo Basic 377 'Cambiamos el color y el tamaño de cada forma aleatoriamente oForma.getByIndex(0) If oForma.getCurrentController. toma en cuenta esto cuando trates de recorrer todas las formas de la página de dibujo.getActiveSheet.getActiveSheet. significa que recorrió todas 'las formas sin encontrar más grupos. usamos el siguiente código. Rnd()*255 ) oPaginaDibujo.createInstance("com.Name = "Type" mOpc(0).getActiveSheet."fontwork-chevron-up".2.sun. Sub Dim Dim Dim Dim Dim FontWork2() oPaginaDibujo As Object oForma As Object mProp(0) As New com.getCurrentController.star. este valor.getDrawPage() 'Agregamos una forma personalizada (CustomShape) oForma = ThisComponent."fontwork-slant-up".star. 15000."fontworkchevron-down".SOLID oForma.CustomShape") 'Cambiamos algunas propiedades conocidas Call CambiaTam( oForma.Name = "TextPath" mOpc(1). no te dará ningún error pero la forma no se insertará.sun. se establecen como una matriz de propiedades.org Basic" 'Esta propiedad es importante.getCurrentController."fontwork-triangle-down".drawing.PropertyValue oPaginaDibujo = ThisComponent.sun."fontwork-arch-left- .10.FillStyle.FillStyle = com."fontwork-fade-up"."fontwork-inflate". muchas posibilidades para personalizar las formas."fontwork-stop"."fontwork-faderight".beans.drawing."fontwork-arch-down-curve". tienes cuarenta estilos para escoger.PropertyValue mTipoFW() oPaginaDibujo = ThisComponent."fontworkcurve-up".String = "OpenOffice.value = mProp() 'Aplicamos estas propiedades personalizadas oForma.Value = "fontwork-wave" 'Establecemos las propiedades de la ruta del texto mOpc(1). debe estar “exactamente” escrito.getDrawPage() oForma = ThisComponent. el color y estilo de relleno. insertamos una forma.Name = "TextPath" mProp(0). si no.sun.378 6. determinará el estilo del FontWork insertado.add( oForma ) 'Establecemos el texto de la forma oForma.beans. el tipo (Type) de la forma."fontwork-fade-up-and-right".Value = True 'Establecemos el tipo de FontWork mOpc(0)."fontwork-arch-up-curve".beans. 4000 ) oForma.star. Sub Dim Dim Dim Dim FontWork1() oPaginaDibujo As Object oForma As Object mProp(0) As New com.Rnd()*255.PropertyValue mOpc(1) As New com."fontwork-fade-left".CustomShape") mTipoFW = Array("fontwork-plain-text"."fontwork-triangle-up".getActiveSheet."fontwork-curve-down".sun. mOpc() ) End Sub La mayoría de las propiedades con las formas FontWork.6 Trabajando con FontWork Para insertar un texto con FontWork.drawing. que es una cadena (string). el color y estilo de línea."fontworkslant-down". En el siguiente ejemplo.star.star.FillColor = RGB( Rnd()*255.sun. si combinas el tamaño."fontwork-wave".sun.PropertyValue mOpc(1) As New com. usamos. le decimos que use una ruta para el texto 'que es lo que le da su particularidad a FontWork mProp(0). tienes muchas.star.star.10 Trabajando con elementos gráficos 6. pero seleccionamos aleatoriamente el tipo del FontWork.createInstance("com.setPropertyValue("CustomShapeGeometry"."fontwork-fade-down"."fontwork-fade-up-and-left".beans. 15000."fontwork-open-circle-pour"."fontwork-circle-pour".Value = True mPropEx(0)."fontwork-circle-curve".Name = "TextPath" ."mso-spt161"."mso-spt165". 4000 ) oForma.String = "OpenOffice.star."mso-spt163"."mso-spt161".PropertyValue mTipoFW() oPaginaDibujo = ThisComponent. insertamos una forma FontWork en 3D.org Basic" mProp(0).sun.sun."fontwork-fade-up".add( oForma ) oForma."mso-spt142"."fontwork-arch-down-pour".Name = "TextPath" mProp(0)."fontwork-faderight". 15000."mso-spt174"."fontwork-stop"."mso-spt159".Rnd()*255.sun."msospt158".FillColor = RGB( Rnd()*255."mso-spt162"."mso-spt167".beans."fontwork-open-circle-curve"."msospt166".drawing."fontwork-open-circle-curve"."fontwork-slant-up"."mso-spt174"."fontwork-arch-left-pour"."fontwork-arch-down-pour".star."mso-spt142".star.Name = "Extrusion" mPropEx(0).beans.star.CustomShape") mTipoFW = Array("fontwork-plain-text".createInstance("com."fontwork-fade-down".getDrawPage() oForma = ThisComponent.SOLID oForma."mso-spt159".Value = mTipoFW( CInt(Rnd()*UBound(mTipoFW)) ) mOpc(1)."fontwork-circle-curve".setPropertyValue("CustomShapeGeometry".getActiveSheet."msospt166". Sub Dim Dim Dim Dim Dim Dim FontWork3() oPaginaDibujo As Object oForma As Object mProp(0) As New com.FillStyle.Value = True 'Establecemos el tipo de FontWork aleatoriamente mOpc(0)."fontwork-arch-down-curve"."fontworkarch-up-pour"."mso-spt164".sun.FillStyle."fontworkcurve-up"."mso-spt162"."fontworkslant-down".PropertyValue mPropEx(0) As New com."fontwork-chevron-up"."fontwork-arch-leftcurve"."mso-spt167".Name = "Type" mOpc(0)."fontwork-arch-right-curve".String = "OpenOffice."mso-spt157"."mso-spt175") Call CambiaTam( oForma.Name = "Type" mOpc(0)."fontworkarch-up-pour"."fontworkchevron-down".drawing.add( oForma ) oForma.FillColor = RGB( Rnd()*255.getCurrentController.Rnd()*255."fontwork-curve-down"."fontwork-arch-rightpour"."mso-spt165"."fontwork-fade-left".sun."fontwork-inflate"."mso-spt163". mOpc() ) End Sub En el siguiente ejemplo."mso-spt175") Call CambiaTam( oForma."fontwork-arch-rightpour".star.Rnd()*255 ) oPaginaDibujo. 4000 ) oForma."fontwork-arch-up-curve".beans.FillStyle = com."mso-spt143".Name = "TextPath" mProp(0)."fontwork-triangle-up"."fontwork-fade-up-and-left"."fontwork-arch-left-pour".drawing."mso-spt157".SOLID oForma."fontwork-triangle-down".PropertyValue mOpc(2) As New com.value = mProp() oForma."fontwork-wave"."mso-spt143"."fontwork-open-circle-pour"."msospt158".Value = True 'Establecemos el tipo de FontWork aleatoriamente mOpc(0).Rnd()*255 ) oPaginaDibujo."fontwork-arch-right-curve".sun.star.FillStyle = com."mso-spt164".Aprendiendo OOo Basic 379 curve".Name = "TextPath" mOpc(1).org Basic" mProp(0).Value = mTipoFW( Rnd()*UBound(mTipoFW) ) mOpc(1)."fontwork-circle-pour"."fontwork-fade-up-and-right". TextShape") Call CambiaTam( oForma.getDrawPage() 'Creamos un marco de texto oForma = ThisComponent. establecer el radio de las esquinas y personalizar el comportamiento del texto que contiene. tienes varias propiedades más para personalizarce completamente. Las líneas tienes propiedades únicas.Rnd()*255 ) 'Establecemos el radio de las esquinas oForma.FillStyle = com. Tanto las propiedades de la ruta del texto (TextPath).2.sun.7 Propiedades particulares de algunas formas Los rectángulos y los marcos de texto.FillStyle.star. describirlas todas sale del propósito de este tema.createInstance("com. El siguiente ejemplo agrega una línea ¿de?. 5000 ) oPaginaDibujo. .Rnd()*255. 6.setPropertyValue("CustomShapeGeometry".10. tu tarea es decirme que distancia tiene la línea.star.10 Trabajando con elementos gráficos Y mira que linda quedo. los dos soportan casi las mismas propiedades. como de la configuración en 3D (Extrusion). mOpc() ) End Sub 6.CornerRadius = 1000 'Establecemos que el texto se adapte al tamaño de la forma oForma.drawing.drawing.value = mProp() mOpc(2).add( oForma ) oForma. son formas muy similares. pero esperamos abordarlas a profundidad en Draw.FillColor = RGB( Rnd()*255.value = mPropEx() oForma.SOLID oForma. claro.TextFitToSize = 1 End Sub Reemplaza TextShape por RectangleShape y veras que sigue funcionando. 10000.380 mOpc(1).sun.Name = "Extrusion" mOpc(2).getActiveSheet. por ejemplo. como la posibilidad de establecer el inicio y el final de forma diferente.setString("Marco con texto" & Chr(13) & "Otra línea") oForma.getCurrentController. te confieso que hice varios intentos hasta que salio esta que me gusto. Sub AutoFormasEspeciales1() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent. 5000 ) oPaginaDibujo. Sub AutoFormasEspeciales3() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.add( oForma ) oForma. como valor Y establecemos 0.Rnd()*255 ) oForma.LineShape") Call CambiaTam( oForma.add( oForma ) oForma.LineStartWidth = 1000 oForma.LineWidth = 200 'Ahora una vertical oForma = ThisComponent.LineShape") Call CambiaTam( oForma. 10000.getDrawPage() 'Creamos una línea oForma = ThisComponent. 0.getDrawPage() 'Creamos una línea horizontal oForma = ThisComponent.getActiveSheet. 5000. En el siguiente ejemplo.sun. establecemos el inicio y el final de la línea.createInstance("com.drawing.LineEndName = "Square 45" End Sub . 10000.Rnd()*255.drawing. con un cuadro a 45º.Rnd()*255 ) oForma.sun.LineWidth = 200 End Sub En el siguiente ejemplo.Rnd()*255.add( oForma ) oForma.Rnd()*255.star.createInstance("com.Rnd()*255.LineWidth = 200 End Sub Observa como hemos logrado dibujar una línea horizontal.Rnd()*255 ) oForma.LineColor = RGB( Rnd()*255.createInstance("com.getActiveSheet.Rnd()*255 ) oForma.sun. 0 ) oPaginaDibujo.LineShape") Call CambiaTam( oForma.LineEndWidth = 1000 'Establecemos el tipo de inicio y fin de línea oForma.LineWidth = 300 'Establecemos el ancho de inicio y final de línea oForma. tan solo pasándole el valor X para cambiar el tamaño.Aprendiendo OOo Basic 381 Sub AutoFormasEspeciales2() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.star. 0 ) oPaginaDibujo.getDrawPage() oForma = ThisComponent.LineShape") Call CambiaTam( oForma. 5000 ) oPaginaDibujo. Sub AutoFormasEspeciales4() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.LineColor = RGB( Rnd()*255. lo que te permite acotar otros elementos.star.drawing.getCurrentController.getActiveSheet.LineColor = RGB( Rnd()*255.getCurrentController.sun.getCurrentController.add( oForma ) oForma. lo contrario para la línea vertical. y. agregamos una línea vertical y otra horizontal.LineColor = RGB( Rnd()*255.drawing.LineStartName = "Square 45" oForma.createInstance("com.star. star.LineWidth = 300 oForma.Value = "heart" oForma. 10000.10 Trabajando con elementos gráficos Ahora.add( oForma ) oForma.star.FillStyle = com.LineWidth = 300 'Establecemos el ancho de inicio y final de línea oForma.FillColor = RGB( Rnd()*255. solo algunos.FillStyle = com.Rnd()*255.LineColor = RGB( Rnd()*255. 5000.add( oForma ) oForma.drawing. 5000.star.SOLID oForma.setPropertyValue("CustomShapeGeometry".Rnd()*255 ) 'Agregamos un hexágono mOpc(0). mOpc() ) oForma = ThisComponent.getCurrentController.Value = "hexagon" oForma.Rnd()*255.getActiveSheet.LineEndWidth = 1000 'Establecemos el tipo de inicio y fin de línea oForma.getDrawPage() oForma = ThisComponent. 5000 ) oPaginaDibujo. 0 ) oPaginaDibujo.FillColor = RGB( Rnd()*255.add( oForma ) oForma. Sub AutoFormasEspeciales5() Dim oPaginaDibujo As Object Dim oForma As Object oPaginaDibujo = ThisComponent.createInstance("com.createInstance("com.sun.SOLID oForma.LineWidth = 300 oForma. 5000 ) oPaginaDibujo.sun.LineWidth = 300 oForma.PropertyValue oPaginaDibujo = ThisComponent.star.Rnd()*255.star.Rnd()*255.drawing.add( oForma ) oForma.getActiveSheet.drawing.star.Rnd()*255 ) oForma.LineEndName = "Arrow" End Sub Para terminar este tema.CustomShape") Call CambiaTam( oForma.setPropertyValue("CustomShapeGeometry".Name = "Type" mOpc(0).getDrawPage() oForma = ThisComponent.Rnd()*255 ) 'Agregamos un corazón mOpc(0).Value = "flowchart-sort" oForma.CustomShape") Call CambiaTam( oForma.LineStartWidth = 1000 oForma.LineStartName = "Arrow" oForma. 5000 ) oPaginaDibujo.Rnd()*255.FillStyle.getCurrentController.LineShape") Call CambiaTam( oForma.sun.drawing.FillStyle = com. establecemos flechas como final de línea.Rnd()*255.CustomShape") Call CambiaTam( oForma.createInstance("com.Rnd()*255 ) oForma.Name = "Type" mOpc(0).createInstance("com.drawing. mOpc() ) .FillStyle.LineColor = RGB( Rnd()*255.sun.beans. Sub Dim Dim Dim AutoFormasEspeciales6() oPaginaDibujo As Object oForma As Object mOpc(0) As New com.Rnd()*255 ) oForma. 5000.382 6.LineColor = RGB( Rnd()*255.Rnd()*255 ) oForma.star.SOLID oForma.drawing.Rnd()*255 ) 'Agregamos el simbolo de ordenar en un diagrama de flujo mOpc(0).star.FillStyle.FillColor = RGB( Rnd()*255.sun.sun.Name = "Type" mOpc(0).drawing.sun. mOpc() ) oForma = ThisComponent.LineColor = RGB( Rnd()*255. veamos como insertar otros tipos de formas.setPropertyValue("CustomShapeGeometry".Rnd()*255.sun. "mso-spt178". "flowchart-summing-junction". "mso-spt33". "left-bracket".star. "flowchart-decision". "fontwork-open-circle-pour". "mso-spt49". "flowchart-stored-data".setPropertyValue("CustomShapeGeometry". "flowchart-process". "flowchart-directaccess-storage". "mso-spt188". "fontwork-curve-up". "flowchart-delay". "round-callout". "flowchart-punched-tape". "fontwork-triangle-down". "rectangular-callout". "fontwork-fadeup-and-right". "mso-spt30". "diamond". "rightarrow". "mso-spt75".star. "mso-spt165". "star8". "quad-arrow". "mso-spt28". "mso-spt163". "msospt189". "mso-spt194". "up-arrow-callout". "ring". "flowchart-preparation". "bracket-pair". "mso-spt175". "fontwork-chevron-down". "right-bracket". "mso-spt167". "mso-spt40". "mso-spt42". "octagon". "mso-spt39". "hexagon". "heart". "smiley". "pentagon". "mso-spt34". "flowchart-sort". "fontwork-circlecurve". "mso-spt38".sun. "left-right-arrow". "mso-spt164". "striped-right-arrow".FillStyle. Sub Dim Dim Dim Dim AutoFormasEspeciales7() oPaginaDibujo As Object oForma As Object mOpc(0) As New com. "mso-spt180". "mso-spt158". "mso-spt202" ) oPaginaDibujo = ThisComponent. "moon". "mso-spt46". "msospt196". "mso-spt35". "parallelogram".Rnd()*255 ) oForma. "mso-spt53". "fontwork-arch-up-pour". "brace-pair".sun. "mso-spt60".Aprendiendo OOo Basic 383 End Sub Como ya lo notaste. "mso-spt52". "bang".FillStyle = com. mOpc() ) End Sub . "lightning".star. "fontwork-fade-up-and-left". "mso-spt43". "linecallout-3". "flowchart-document".Rnd()*255.LineColor = RGB( Rnd()*255. "mso-spt41". "flowchart-multidocument". "mso-spt179". "flowchart-extract". "mso-spt174". "can". "ellipse". "fontworkfade-down". "left-right-arrow-callout". "fontwork-inflate". "fontwork-open-circle-curve". "notched-right-arrow". "mso-spt50". "mso-spt91".Rnd()*255 ) 'Agregamos una forma aleatoria mOpc(0).getActiveSheet. "mso-spt103". "flowchart-terminator". "flowchart-sequential-access".beans. "paper".getCurrentController. "blockarc".drawing. "fontwork-triangle-up". "mso-spt157". "mso-spt20". "round-rectangle". "mso-spt90". "up-arrow". "chevron". "mso-spt197". "mso-spt31". "line-callout-2". "quadarrow-callout". "fontwork-wave". "star5". "left-arrow-callout". "flowchart-display". "mso-spt25". "mso-spt102".getDrawPage() oForma = ThisComponent. "down-arrow-callout". "fontwork-curve-down". "mso-spt36". "fontwork-arch-down-curve". "forbidden". "flowchart-card". "mso-spt182". "mso-spt108". "mso-spt27". "trapezoid". "msospt51". "fontwork-fade-right". "mso-spt54". "flowchartconnector". "mso-spt142". "mso-spt200". "flowchart-or".add( oForma ) oForma. "mso-spt14". "mso-spt71". "pentagon-right". "mso-spt159". "flowchart-manual-operation". "mso-spt195". "mso-spt64". "mso-spt143". "sun".Value = mTipoFormas( CInt(Rnd()*UBound(mTipoFormas)) ) oForma. "fontwork-slant-up". "fontwork-plain-text". "mso-spt26". "fontwork-slant-down". "msospt166". "right-brace". "left-arrow".SOLID oForma.Rnd()*255. "down-arrow". "fontwork-arch-up-curve".sun. "msospt89". "vertical-scroll". "mso-spt162".createInstance("com. hay que indicarle el nombre de la forma especial que queremos agregar. "flowchart-data". "round-rectangular-callout". "mso-spt104". "flowchart-collate".drawing. "mso-spt32". "up-down-arrow-callout". "flowchart-predefined-process". "mso-spt107". "fontworkcircle-pour". "cloud-callout". "cross". "fontwork-fade-left". "flowchart-merge". "flowchartalternate-process". "flowchart-internal-storage".Name = "Type" mOpc(0). "msospt44". "quad-bevel". "fontwork-arch-down-pour". "mso-spt192". "mso-spt19". "cube". "msospt29". "circular-arrow". "mso-spt37". "fontwork-stop". "flowchart-magnetic-disk". "right-triangle". "mso-spt129".LineWidth = 300 oForma. "flowchart-manual-input". "star4". "mso-spt101". "left-brace". "horizontal-scroll". "flowchart-off-page-connector". la cantidad de formas es grande. "mso-spt105". "mso-spt191". "mso-spt45". "mso-spt161". "star24". "fontwork-fade-up". "up-down-arrow". "mso-spt21". "mso-spt100". "mso-spt18". "mso-spt199".FillColor = RGB( Rnd()*255. "mso-spt24".CustomShape") Call CambiaTam( oForma. "mso-spt193". "mso-spt17". "msospt59".PropertyValue mTipoFormas mTipoFormas = Array("rectangle". "fontwork-chevron-up". "isosceles-triangle". "mso-spt201". "line-callout-1". "mso-spt198". compruébalo tu mismo con el siguiente código donde agregamos una forma aleatoria de las diferentes doscientas un posibles. 5000 ) oPaginaDibujo. "mso-spt190". "right-arrow-callout". 5000. 10 Trabajando con elementos gráficos 6. que estas pueden o no necesitar argumentos. Diámetro Perímetro Área = A2 * 2 = PI() * A2 * 2 = PI() * POTENCIA(A2. que las funciones siempre devuelven un valor. que los argumentos son de un tipo y el valor devuelto puede ser de otro. que tengas muy claro. por ejemplo. supongamos las triviales formulas para obtener el diámetro.1416 PerimetroCirculo = Radio * 2 * PI End Function 'Función para obtener el área de un circulo Function AreaCirculo( Radio As Single ) As Double Const PI As Single = 3.11 Funciones personalizadas La posibilidad de implementar nuestras propias funciones.1416 .384 6. asumo que no tienes problemas con la implementación de formulas y funciones en Calc. estas funciones podrían quedar así: Option Explicit 'Función para obtener el diámetro de un circulo Function DiametroCirculo( Radio As Single ) As Double DiametroCirculo = Radio * 2 End Function 'Función para obtener el perímetro de un circulo Function PerimetroCirculo( Radio As Single ) As Double Const PI As Single = 3. es una de las características más ricas de una hoja de calculo. para todo este capitulo. y cuando este sea un error.2) En OOo Basic. el perímetro y el área de un circulo Donde: r D P A = radio = Diámetro = Perímetro = Área radio D=2∗r P=∗D A=∗r2 En Calc. aun. es muy útil. suponiendo que el radio este en la celda A2 las formulas serían. La forma como establecemos los argumentos y el valor devuelto de la función. ahora. Donde: b = Base h = Altura A = Área altura base Nuestra función para calcular el área. Pero las funciones personalizadas son mucho más versátiles. simplemente pasándole un segundo argumento para indicárselo. A= b∗h 2 . con formulas y funciones incorporadas de Calc. las relacionadas con el correcto paso de argumentos y el tipo de valor devuelto. principalmente.Aprendiendo OOo Basic AreaCirculo = PI * Radio ^ 2 End Function 385 Estas funciones. nota como en las tres formulas. tienen las mismas consideraciones presentes en las funciones incorporadas de Calc. donde estamos calculando estos valores. usamos el mismo argumento. Observa la siguiente imagen. los hemos venido usando a lo largo de los temas vistos. se usan exactamente igual que cualquier otra función de Calc. lo que realmente toma la función es el valor de estas celdas. es que. ahora ahora. 'Función para devolver un dato de un círculo 'QueDato puede tener los valores ' 1 = Diámetro ' 2 = Perímetro ' 3 = Área Function Circulo( Radio As Single. y con nuestras funciones personalizadas. la diferencia. es decir. solo el radio. solo “llamábamos” a las funciones desde otras macros. QueDato As Byte ) As Double Const PI As Single = 3. cuya formula es.141592 Dim dTmp As Double Select Case QueDato Case 1 dTmp = Radio * 2 Case 2 dTmp = Radio * 2 * PI Case 3 dTmp = PI * Radio ^ 2 End Select Circulo = dTmp End Function Y el resultado. podemos crear nuestra función para que nos devuelva el valor deseado de los tres. por los dos métodos. quedaría así. las estamos usando desde la hoja de calculo. Cuando le pasas un argumento a una función desde una hoja de calculo (generalmente una referencia a una o varias celdas). no te son desconocidos. vamos a obtener el área de un triángulo. escribiendo su nombre correctamente y pasándole los argumentos correctos. Las funciones personalizadas. Nuestro siguiente ejemplo también es muy simple. DÍA(A2))>HOY().MES(A2).AÑO(HOY()) +1). solo tenemos una fecha. no importa el número de años que lleva contratado. el planteamiento es el siguiente. Donde: A=  S∗ S−a∗ S−b∗S−c a. no es una pregunta ligera. la fecha de contratación del servicio. tenemos que tener muy claro que es lo que queremos obtener y que datos de origen tenemos.386 6.11 Funciones personalizadas 'Función para calcular el área de un triángulo Function AreaTriangulo( B As Single. es decir. b y c = son los lados del triángulo S = Semiperímetro. b As Single. usamos la famosa formula de Herón. el perímetro entre dos A = Área Como función. entre más sencillos. tomate con calma la respuesta de la pregunta.MES(A2).DÍA(A2))-HOY() Esta formula ya es un poco más compleja. Te pongo la formula y antes de que veas la respuesta. no solo puedes manejar números como argumentos. c As Single ) As Double Dim S As Double S = ( a + b + c ) / 2 AreaTrianguloHeron = Sqr( S*(S-a)*(S-b)*(S-c) ) End Function Por supuesto. es resolver problemas. en el siguiente ejemplo. Celda A2 = Fecha de contratación Celda B2 = Días que faltan para renovar La formula de la columna B es: =FECHA(SI(FECHA(AÑO(HOY()). H As Single ) As Double AreaTriangulo = (B * H) / 2 End Function El asunto cambia bastante cuando lo que conocemos son la longitud de los lados del triángulo. para estos casos. 'Función para calcular el área de un triángulo 'con la formula de Herón Function AreaTrianguloHeron( a As Single. nos pide un poco más de esfuerzo para comprenderla. cuidado. pero es un buen ejemplo de lo que hay que hacer cuando queremos hacer una función personalizada. recuerda que el trabajo de programador. ¿que es lo que haces para saber cuantos días faltan para la renovación?.AÑO(HOY()). queremos mostrar en otra celda. una primera aproximación sería. son más fáciles de resolver. se contrato un servicio anual. el número de días que faltan para renovar el servicio. y los problemas. en este caso. 'Función para saber cuantos días faltan para renovar Function DiasParaRenovar( FechaInicial As Date ) As Integer . usamos una fecha como argumento. En la solución de la función comentamos paso a paso la respuesta. trata de hacerla tu mismo. así que. es decir. solo queremos saber cuantos días faltan para la próxima renovación. te pongo el esqueleto de la función y tu la desarrollas.DÍA(A2))HOY() =DIASPARARENOVAR(A2) En nuestro siguiente ejemplo. para saber cuantos días faltan 'Usamos Fix para eliminar las horas y evitar el redondeo iDiferencia = FechaActual . aquí es bastante notable la comodidad de una función personalizada: =FECHA(SI(FECHA(AÑO(HOY()). observa como obtenemos 'el año actual.MES(A2). Day(FechaInicial) ) 'El siguiente paso. significa que la renovación ya paso. devuelve la fecha actual.AÑO(HOY()). la tarea es mostrar el valor de un ángulo. Month(FechaInicial). pero con el año actual.DÍA(A2))>HOY(). grados. es saber si esta fecha actual. Month(FechaInicial). la función Now. minutos o segundos.AÑO(HOY())+1). según el argumento pasado.Aprendiendo OOo Basic Dim FechaActual As Date Dim iDiferencia As Integer 387 'Lo primero que necesitamos es tener la misma fecha inicial 'mismo día y mes. por ejemplo: 125º 45' 35''. lo que logramos con la siguiente función. puede tomar los valores ' 1 = Devuelve los grados ' 2 = Devuelve los minutos ' 3 = Devuelve los segundos Function DatoAngulo( Angulo As String. Min As Byte. configurado correctamente. a partir de la cadena. 'Función para devolver un valor de una ángulo 'El argumento QueValor. Tu tarea es hacer la operación inversa.MES(A2).Fix(Now()) 'Asignamos el resultado DiasParaRenovar = iDiferencia End Function Comparando. QueValor As Byte ) As Integer 'Esta es tu tarea End Function . 'Función para dar formato a valores sexagesimales Function AnguloFormateado( Gra As Integer. Seg As Byte ) As String Dim sTmp As String sTmp = Str(Gra) & "º " & Str(Min) & "' " & Str(Seg) & "''" AnguloFormateado = sTmp End Function Observa como estamos regresando una cadena (String). tenemos como argumentos números y regresamos un texto. con Year obtenemos el año FechaActual = DateSerial( Year(Now()). regresar cualquiera de los tres valores. por lo que se tiene 'que aumentar un año a la fecha actual para obtener la correcta de renovación FechaActual = DateSerial( Year(Now())+1. es mayor o menor al día de hoy If FechaActual < Now() Then 'Si es menor. Day(FechaInicial) ) End If 'Restamos la fecha futura con el día de hoy. es la siguiente. todos los argumentos que le hemos pasado a nuestras funciones. por varios métodos. exactamente. no la incluimos aquí. forzosamente tiene que ser tipo variante (Variant).2 ) 'Vamos sumando los valores dTmp = dTmp + Rango( co1. donde se cuenta con sus coordenadas. Veamos un ejemplo practico donde pasamos como argumento un rango de celdas. pero también puedes pasarle rangos de celdas.1 ) To UBound( Rango. se puede calcular el área de un terreno o de cualquier poligonal cerrada cualquiera. al ser una matriz. los tomará como una matriz de dos dimensiones.. es el siguiente.2 ) To UBound( Rango. cuyo algoritmo. donde.11 Funciones personalizadas Otro ejemplo donde tenemos como argumento un número y regresamos una cadena. dada la extensión de la misma. Hasta ahora.. te invito a que intentes desarrollarla. co2 As Long 'Iteramos en la primer dimensión de la matriz For co1 = LBound( Rango. co2 ) Next co2 Next co1 'Asignamos el resultado SumarRango = dTmp End Function Observa como no establecemos el tipo del argumento Rango. En topografía. esto es por que.1 ) 'Iteramos en la segunda dimensión de la matriz For co2 = LBound( Rango. es que los valores de este rango. nuestra versión de la función SUMA. lo único que tienes que tener en cuenta. para hacer la famosa función que convierte números a letras. han sido celdas individuales. uno de ellos se llama por “Productos Cruzados”. sumamente útil y muy usada en áreas administrativas. 'Función para convertir un número en texto Function NumeroTexto( Num As Byte ) As String Dim sTmp As String Select Case Num Case 0 : sTmp Case 1 : sTmp Case 2 : sTmp Case 3 : sTmp Case 4 : sTmp Case 5 : sTmp Case 6 : sTmp Case 7 : sTmp Case 8 : sTmp Case 9 : sTmp End Select NumeroTexto = sTmp End Function = = = = = = = = = = "Cero" "Uno" "Dos" "Tres" "Cuatro" "Cinco" "Seis" "Siete" "Ocho" "Nueve" ¿Y para que crees que sirve eso?. 'Función para sumar los valores de un rango Function SumarRango( Rango ) As Double Dim dTmp As Double Dim co1 As Long.388 6. esta. espero sea bastante claro en la siguiente imagen. pero si en los archivos de ejemplo que acompañan a este libro.. . no se cual sea la razón de que al acceder a los valores de un rango de celdas por medio de una función.2) Next co1 'Asignamos el resultado AreaPoligono = Abs(Suma1 . pero usando la función mostrada en la celda D218. veremos algunas opciones que afectan a la configuración global de Calc.1) * Rango(co1+1. 'Función para obtener el área de un polígono irregular 'por medio de coordenadas y el método de productos cruzados Function AreaPoligono( Rango ) As Double Dim Suma1 As Double Dim Suma2 As Double Dim co1 As Long 'Calculamos las suma de los productos cruzados For co1 = LBound( Rango. es la única excepción que me he encontrado con el uso de matrices. solo oculta el pequeño cuadro rojo .1 ) To UBound( Rango. cuyo código es el siguiente.1 Suma1 = Suma1 + Rango(co1.showFormulas = True 'Ocultamos los valores cero 'el valor normal es verdadero (True) oCC. tenemos el mismo resultado.showZeroValues = False 'Podemos automáticamente diferenciar los valores de 'formulas con esta propiedad. el limite inferior sea siempre 1 (por ahora). por ejemplo lo que queremos ver y lo que no.getCurrentController() 'Mostramos las formulas en vez de su resultado 'el valor "normal" es falso (False) oCC. observa que para acceder a la segunda dimensión de la matriz.12 Configuración global de Calc En este capitulo. estamos empezando en 1. pero ten cuidado 'no podrás establecer el color de fuente mientras 'esta propiedad este en verdadera (True) oCC.IsValueHighlightingEnabled = True 'Esta propiedad.Suma2) / 2 End Function Muy importante. Sub ConfigurarCalc1() Dim oDoc As Object Dim oCC As Object oDoc = ThisComponent oCC = oDoc.1 ) . en la celda D216 (en rojo). 6.Aprendiendo OOo Basic 389 En la celda D214.2) Suma2 = Suma2 + Rango(co1+1. tenemos el calculo del área. recuerdalo. pero usando todo el desarrollo del método.1) * Rango(co1. los valores los pone 'en azul y las formulas en verde. En el siguiente ejemplo. formas y símbolos de esquema.showCharts = Not oCC.HasVerticalScrollBar oCC. así como los gráficos.showDrawing = Not oCC.IsOutlineSymbolsSet End Sub Ten cuidado con ocultar algunos elementos.showNotes = False End Sub 6.showDrawing 'Los símbolos de esquema y agrupamiento oCC. por ejemplo. los saltos de página se ocultan.showCharts 'Las formas oCC. establecelo en verdadero para volver 'a ver este pequeño cuadro oCC.showGrid 'Las líneas de ayuda cuando se mueve un objeto gráfico oCC.IsOutlineSymbolsSet = Not oCC. pero siguen existiendo. alternamos el valor de las propiedades. en todos los ejemplos siguientes.getCurrentController() 'Ocultamos o mostramos las barras de desplazamiento 'tanto vertical como horizontal oCC.showObjects = Not oCC.HasColumnRowHeaders = Not oCC.showObjects 'Los gráficos oCC.HasHorizontalScrollBar = Not oCC. es decir.ShowAnchor 'Los saltos de página oCC. cambiamos el color de las líneas de división de las celdas y establecemos el zoom con un porcentaje.showHelpLines = Not oCC.390 'que nos indica que una celda tiene una nota.showGrid = Not oCC. si están visibles se ocultan y viceversa: Sub ConfigurarCalc2() Dim oDoc As Object Dim oCC As Object oDoc = ThisComponent oCC = oDoc.ShowPageBreaks 'Los objetos e imagenes oCC.HasColumnRowHeaders 'Las líneas de división de las celdas oCC. si ocultas las etiquetas de las hojas. objetos. la nota 'sigue existiendo.HasHorizontalScrollBar 'Las etiqueas de las hojas oCC.HasSheetTabs = Not oCC.12 Configuración global de Calc También podemos mostrar u ocultar otros elementos de la hoja de calculo.HasVerticalScrollBar = Not oCC. el usuario puede cambiarse aun con la combinación de teclas CTRL+RePag (AvPag).showAnchor = Not oCC.ShowHelpLines 'El icono de anclaje cuando se selecciona un objeto gráfico oCC.HasSheetTabs 'Los encabezados de filas y columnas oCC. .showPageBreaks = Not oCC. ZoomValue = 130 End Sub Si estableces el porcentaje fuera de sus limites (20% a 400%).getFirstVisibleRow & Chr(13) & "Columna: " & oCC. pero me parece que son interesantes de ver.Aprendiendo OOo Basic Sub ConfigurarCalc3() Dim oDoc As Object Dim oCC As Object oDoc = ThisComponent oCC = oDoc.getCurrentController() 'La primer fila y columna visible actuales MsgBox "Fila: " & oCC. este rango se ve afectado por el nivel de zoom establecido en la hoja. como mostramos en el ejemplo.gridColor = RGB(Rnd()*255. puedes establecer 'el porcentaje de zoom entre 20% y 400% oCC. Sub ConfigurarCalc4() Dim oDoc As Object Dim oCC As Object oDoc = ThisComponent oCC = oDoc.getCurrentController() 391 'Puedes cambiar el color de las líneas de división de celdas 'el valor predeterminado es gris claro = 12632256 oCC. Sub Dim Dim Dim ConfigurarCalc5() oDoc As Object oCC As Object oRangoVisible As Object oDoc = ThisComponent oCC = oDoc. Podemos consultar y establecer la primer fila y columna visible.ZoomType = 3 . este se ajustará al más cercano.Rnd()*255) 'Establecer el tipo de Zoom ' 1 = Ancho de página ' 2 = Ajustar al ancho y alto ' 3 = Valor oCC.setFirstVisibleRow( 50 ) oCC. solo tiene efecto sobre una sola hoja.Rnd()*255.getCurrentController() 'Obtenemos el rango visible oRangoVisible = oCC.setFirstVisibleColumn( 10 ) End Sub Podemos obtener el rango visible.ZoomType = 3 'Si lo establece en 3 (valor).getVisibleRange() 'Mostramos su dirección MsgBox DireccionRango( oRangoVisible ) 'Cambiamos el zoom oCC. Las siguientes propiedades. es que podemos establecerlas para que el usuario 'vea lo que queramos que vea oCC.getFirstVisibleColumn 'Lo interesante. EndColumn).getSplitVertical & " pixeles de la parte superior" & Chr(13) & _ "En la columna: " & oCC.getActiveSheet sTmp = oHA.StartRow + 1 & ":" & _ oHA. Sub Dim Dim Dim ConfigurarCalc7() oDoc As Object oCC As Object sInfo As String oDoc = ThisComponent oCC = oDoc.getByIndex(DirRango.ZoomValue = oCC.392 oCC.EndRow + 1 DireccionRango = sTmp End Function Podemos saber si la ventana esta dividida.getByIndex(DirRango.getColumns.getColumns.getSplitHorizontal & " pixeles de la izquierda y" & Chr(13) & _ oCC.getVisibleRange() MsgBox DireccionRango( oRangoVisible ) End Sub Function DireccionRango( DirRango As Object) As String Dim oHA As Object Dim sTmp As String 6.getIsWindowSplit Then 'Las unidades son pixeles oCC.getSplitColumn & " y en la fila: " & oCC.getName() & _ DirRango.getName() & _ DirRango.getCurrentController() 'Consultamos si la ventana esta dividida If oCC.getSplitRow MsgBox sInfo Else MsgBox "La ventana no esta dividida" End If End Sub Por supuesto podemos establecer la división donde quieras.12 Configuración global de Calc oHA = ThisComponent.getIsWindowSplit Then 'Mostramos la información sInfo = "La ventana esta dividida a: " & Chr(13) & _ oCC.getCurrentController. Sub Dim Dim Dim ConfigurarCalc6() oDoc As Object oCC As Object sInfo As String oDoc = ThisComponent oCC = oDoc.ZoomValue + 25 'Volvemos a consultar el rango visible oRangoVisible = oCC.300 ) End If End Sub .getCurrentController() 'Si no esta dividida la dividimos If Not oCC.splitAtPosition( 500.StartColumn). splitAtPosition( 0. por ejemplo. si quiere establecer solo un sentido.300 ) Para eliminar la división: oCC.0 ) Para la horizontal: oCC. si que la ventana se fijara en la posición actual del cursor de celda.splitAtPosition( 500.hasFrozenPanes Then MsgBox "La ventana esta fija" Else MsgBox "La ventana no esta fija" End If End Sub Y establecer la posición de esta.freezeAtPosition( 5.freezeAtPosition( 0. usa el mismo método visto anteriormente: . Sub Dim Dim Dim ConfigurarCalc8() oDoc As Object oCC As Object sInfo As String oDoc = ThisComponent oCC = oDoc. establece la que no quieras en cero. 10) End Sub Al igual que con la ventana dividida.getCurrentController() 'Consultamos si la ventana esta fija If oCC. oCC. aquí se usa la columna y fila deseada. si solo quieres la división vertical usas: oCC. no eliminaras la división. Sub Dim Dim Dim ConfigurarCalc9() oDoc As Object oCC As Object sInfo As String oDoc = ThisComponent oCC = oDoc. 0) Si quieres quitarla.Aprendiendo OOo Basic 393 Si quieres establecer solo un división. establece el otro en cero. si estableces los dos argumentos en ceros.getCurrentController() 'Establecemos la división en la columna 5 y fila 10 oCC.splitAtPosition( 0.0 ) También podemos saber si la ventan esta fija. como se muestra en el siguiente ejemplo: Sub Dim Dim Dim Dim Dim ConfigurarCalc10() oDoc As Object oCC As Object oPanel As Object co1 As Byte sInfo As String oDoc = ThisComponent oCC = oDoc.12 Configuración global de Calc Si divides la ventana por cualquiera de los dos métodos vistos.getRangeAddressesAsString().getCount .EndRow + 1 Case "ScCellRangesObj" sTmp = Join( Split(Rango. y puedes tener acceso a cada rango de cada panel.getColumns().getSpreadsheet.getRangeAddress.getName() & _ Rango.Row + 1 Case "ScCellRangeObj".getColumns(). "ScCellCursorObj" sTmp = Rango.getSpreadsheet.getName() & _ Rango.getColumns(). . estás pueden tener 2 o cuatro partes." & _ Rango. y con esto damos por terminado un nuevo tema.0 ) 6.").".1 'Obtenemos acceso a cada panel oPanel = oCC.getName() & _ Rango.getImplementationName() Case "ScCellObj" sTmp = Rango.394 oCC.StartRow + 1 & ":" & _ Rango.splitAtPosition( 0.hasFrozenPanes Then For co1 = 0 To oCC.getRangeAddress.getCellAddress.getByIndex( co1 ) 'Mostramos su dirección MsgBox "La dirección del Panel " & co1+1 & " es: " & DireccionRango2( oPanel.getByIndex(0).getReferredCells ) Next co1 End If End Sub Function DireccionRango2(Rango As Object) As String Dim sTmp As String Select Case Rango. aquí la repetimos por si no la tienes a mano.getCount()1).getColumns().getName() & ".getName() & ".getByIndex(Rango. cada una de estas partes se llama panel.getIsWindowSplit Or oCC." & _ Rango.getCurrentController() 'La ventans debe estar fija o dividida If oCC.Chr(13) ) End Select DireccionRango2 = sTmp End Function La función anterior ya la hemos usado anteriormente.getByIndex(0). getDrawPage() 'Todos los formularios oFormularios = oPaginaDibujo. veremos como manipular las propiedades más importantes de estos.getName() Next co1 End Sub Como en el ejemplo anterior. donde mostramos los nombres de los formularios existentes en la hoja activa. que sabes agregar los controles a la interfaz del usuario y manipular sus propiedades en tiempo de diseño.getByIndex(co1). con código OOo Basic. en los dos casos el formulario “debe” de existir.1 Formularios (Forms) Los formularios y sus controles. es decir. que son objetos de dibujo con características especiales y la capacidad de poder asociarles la ejecución de macros. tiene propiedades especiales para enlazarse y manipular bases de datos. múltiples tareas. en tiempo de ejecución. a los que tienen poca experiencia con la hoja de calculo ya que nos permite convertir una hoja de Calc. El uso de formularios permite automatizar.1 MsgBox oFormularios. puedes acceder a un formulario por su índice o por su nombre. con el uso de los formularios. por lo que. nos permiten interactuar con el usuario por medio de controles. sobre todo. 7. como en el siguiente ejemplo. aun más. Sub Dim Dim Dim Dim Dim Formularios1() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object co1 As Integer 'El archivo desde donde se llama esta macro oDoc = ThisComponent 'La hoja activa oHojaActiva = oDoc. se colocan sobre la capa de dibujo. es decir. a través de esta hay que acceder a ellos. Asumo que no tienes problemas. aquí. aunque se pueden usar sin ellas.Aprendiendo OOo Basic 395 7 Trabajando con formularios Los formularios. también pueden servir para ayudar al usuario con la manipulación de datos. El formulario y la mayoría de los controles.getForms() 'Iteramos en cada uno mostrando su nombre For co1 = 0 To oFormularios.getCount() .getCurrentController. debes de validarlo como en: Sub Dim Dim Dim Dim Dim Dim Formularios2() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object iNum As Integer sNombre As String 'El archivo desde donde se llama esta macro . en una nueva y completamente personalizada interfaz de usuario.getActiveSheet() 'La página de dibujo oPaginaDibujo = oHojaActiva. como usuario. getActiveSheet() oPaginaDibujo = oHojaActiva.getByIndex(0) MsgBox oFormulario.getActiveSheet() oPaginaDibujo = oHojaActiva.getName() End If End Sub 7.getDrawPage() 'Todos los formularios oFormularios = oPaginaDibujo.getByIndex(0) MsgBox oFormulario.getCount() Then MsgBox oFormularios.getCurrentController.getByIndex(iNum).getDrawPage() oFormularios = oPaginaDibujo.DataSourceName 'Cambiamos la fuente de datos oFormulario.getName() 'Cambiamos el nombre del primer formulario oFormulario.getDrawPage() oFormularios = oPaginaDibujo.getActiveSheet() 'La página de dibujo oPaginaDibujo = oHojaActiva.396 oDoc = ThisComponent 'La hoja activa oHojaActiva = oDoc.getName() End If sNombre = "Directorio" 'Nos aseguramos de que existe el nombre del formulario If oFormularios.getForms() oFormulario = oFormularios.DataSourceName = "Directorio" End Sub .getForms() oFormulario = oFormularios.getByName(sNombre).hasByName(sNombre) Then MsgBox oFormularios.getForms() iNum = 1 'Nos aseguramos de que existe el número de formulario If iNum < oFormularios.setName("Nuevo Formulario") End Sub Puedes cambiar el origen de datos del formulario: Sub Dim Dim Dim Dim Dim Formularios4() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object oDoc = ThisComponent oHojaActiva = oDoc.1 Formularios (Forms) Puedes cambiar el nombre del formulario: Sub Dim Dim Dim Dim Dim Formularios3() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object oDoc = ThisComponent oHojaActiva = oDoc.getCurrentController.getCurrentController. CommandType = 0 'El nombre de la tabla oFormulario. no solo el formulario puede estar vinculado con esta.getActiveSheet() oPaginaDibujo = oHojaActiva.getForms() oFormulario = oFormularios.CommandType = 1 'El nombre de la consulta oFormulario.getForms() oFormulario = oFormularios. pero claro. y el contenido.Command = "qryCiudades" End Sub Por ultimo. puedes establecer el tipo de contenido. no te dará ningún error.DataSourceName = "Directorio" 'Como origen una consulta oFormulario.getActiveSheet() oPaginaDibujo = oHojaActiva. si la fuente de datos no existe. es enlazar una vez al inicio de la configuración de un formulario.Command = "tblCiudades" End Sub En el siguiente ejemplo establecemos una consulta como origen de datos Sub Dim Dim Dim Dim Dim Formularios6() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object oDoc = ThisComponent oHojaActiva = oDoc.getByIndex(0) 'Establecemos la base de datos fuente oFormulario. son nombres de bases de datos registradas en OOo y ya vistas en el capitulo de Bases de datos.getCurrentController. no obtendrás nada de datos. o para corregir desajustes realizados por los usuarios. los nombres de las fuentes de datos. podemos establecer un comando SQL como origen de datos: Sub Formularios7() .getDrawPage() oFormularios = oPaginaDibujo. también pueden estar vinculados a ella. ten cuidado al cambiar la fuente de datos. Sub Dim Dim Dim Dim Dim Formularios5() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object oDoc = ThisComponent oHojaActiva = oDoc.DataSourceName = "Directorio" 'Como origen una tabla oFormulario.getCurrentController. Además de la fuente de datos.Aprendiendo OOo Basic 397 Aquí debes de tener algunas consideraciones importantes. lo más común. por lo que no las repetiremos aquí. los controles del formulario.getDrawPage() oFormularios = oPaginaDibujo. por lo que perderás cualquier vinculo a los datos.getByIndex(0) 'Establecemos la base de datos fuente oFormulario. pues su función es solo mostrar un texto al usuario sin que este pueda modificarlo. un mensaje o el encabezado de un campo. 7.getCurrentController.getDrawPage() oFormularios = oPaginaDibujo.Command = "SELECT * FROM tblContactos" End Sub Todas las precauciones y particularidades vistas en las bases de datos.1 Formularios (Forms) oDoc = ThisComponent oHojaActiva = oDoc.398 Dim Dim Dim Dim Dim oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object 7. Se les puede asociar un evento.createInstance( "com.Form" ) 'Lo agregamos a los formularios oFormularios.getByIndex(0) 'Establecemos la base de datos fuente oFormulario.sun. es mejor que verifiques que el nombre no exista como ya se vio y agregues nombres únicos a la colección de formularios para su fácil identificación. pero no .getActiveSheet() oPaginaDibujo = oHojaActiva. por ejemplo. generalmente un titulo.getCurrentController.2 Etiquetas (Label) Las etiquetas son los controles más simples.getForms() oFormulario = oFormularios. pero no es lo común.getDrawPage() oFormularios = oPaginaDibujo. el clic del ratón.form. Sub Dim Dim Dim Dim Dim Formularios8() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oNuevoFormulario As Object oDoc = ThisComponent oHojaActiva = oDoc. son aplicables a los formularios.DataSourceName = "Directorio" 'Como origen una instrucción SQL oFormulario.getForms() 'Creamos un nuevo formulario oNuevoFormulario = oDoc.component.CommandType = 2 'La instrucción SQL oFormulario. Puedes agregar nuevos formularios a la colección.insertByName("MiDirectorio". por lo que te recomiendo las tengas siempre presentes.getActiveSheet() oPaginaDibujo = oHojaActiva. oNuevoFormulario) End Sub Puedes agregar formularios con el mismo nombre y no te dará ningún error.star. sun.Aprendiendo OOo Basic 399 es usual que se haga. Al ser una forma (shape).sun.Name = "lblId" 'El texto que verá el usuario oNuevaEtiquetaModelo. generalmente son controles estáticos.Y = Y Obj.star. en este caso 0. los controles soportan la mayoría de las . es el índice que tendrá el nuevo control agregado oFormulario.insertByIndex(0.createInstance("com.getDrawPage() oFormularios = oPaginaDibujo.getActiveSheet() oPaginaDibujo = oHojaActiva.component.getForms() oFormulario = oFormularios.add( oNuevaEtiqueta ) End Sub 'Macro para cambiar la posición de un objeto Sub CambiaPos( Obj As Object.awt.ControlShape") 'Cambiamos su tamaño y posicion Call CambiaTam( oNuevaEtiqueta.star.Size oTam.awt. Ancho As Long.sun. Y As Long ) Dim oPos As New com.Width = Ancho oTam.sun.X = X oPos.star. agrega una etiqueta al formulario llamado “MiDirectorio”. el primer argumento.FixedText") 'Establecemos su nombres oNuevaEtiquetaModelo.form.setSize( oTam ) End Sub Las subrutinas para cambiar de posición y tamaño. El siguiente ejemplo.createInstance("com. X As Long.getByName( "MiDirectorio" ) 'Creamos una nueva forma de control oNuevaEtiqueta = oDoc. 5000.Label = "Clave" 'Conectamos la forma con el nuevo control oNuevaEtiqueta.Height = Alto Obj. Sub Dim Dim Dim Dim Dim Dim Dim Etiquetas1() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object oNuevaEtiqueta As Object oNuevaEtiquetaModelo As Object oDoc = ThisComponent oHojaActiva = oDoc.getCurrentController.Control = oNuevaEtiquetaModelo 'Lo agregamos al formulario.Point oPos. Alto As Long ) Dim oTam As New com.setPosition( oPos ) End Sub 'Macro para cambiar el tamaño de un objeto Sub CambiaTam( Obj As Object.drawing. oNuevaEtiquetaModelo) 'Agregamos la forma a la página de dibujo para que sea visible oPaginaDibujo. 1000 ) 'Creamos una nueva etiqueta oNuevaEtiquetaModelo = oDoc. son las mismas usadas en capítulos anteriores. 1500 ) Call CambiaPos( oNuevaEtiqueta. 1000.star. getByName( "MiDirectorio" ) 'Referencia al control llamado lblId olblClave = oFormulario.getByName("lblId") With olblClave . arriba (0). La mayoría de los controles. fuente.2 Etiquetas (Label) propiedades vistas anteriormente (color.Label = "Nuevo texto" End Sub Otras propiedades que puedes manipular en las etiquetas son: Sub Dim Dim Dim Dim Dim Dim Etiquetas3() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object olblClave As Object oDoc = ThisComponent oHojaActiva = oDoc.getCurrentController. por ejemplo.getForms() oFormulario = oFormularios.0) . relleno. línea. para acceder a la etiqueta creada en el ejemplo anterior.getByName("lblId") 'Cambiamos el texto que ve el usuario olblClave.FontName = "Linux Biolinum" .getForms() oFormulario = oFormularios. la vertical. etc). sin borde(0) o 3D (1).getActiveSheet() oPaginaDibujo = oHojaActiva.200.FontHeight = 18 .400 7.200) .0.getActiveSheet() oPaginaDibujo = oHojaActiva.getByName( "MiDirectorio" ) 'Referencia al control llamado lblId olblClave = oFormulario.getDrawPage() oFormularios = oPaginaDibujo.BackgroundColor = RGB(200. cuentan con una propiedad para . usamos el siguiente código.getCurrentController.TextColor = RGB(0.200) . puede tomar los valores. también puede ser.BorderColor = RGB(255. por lo que no las repetiremos aquí y nos centraremos en la forma de manipular las propiedades particulares de cada control desde su “modelo”.Border = 2 . Sub Dim Dim Dim Dim Dim Dim Etiquetas2() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object olblClave As Object oDoc = ThisComponent oHojaActiva = oDoc. la alienación horizontal puede ser a la izquierda (0).0. al centro (1) o a la derecha (2).VerticalAlign = 1 End With End Sub 'La fuente 'El tamaño de fuente 'El color de fondo 'El tipo de borde (2 = plano ) 'El color del borde (solo efectivo si Border = 2) 'El color del texto 'Alineación horizontal 'Alineación vertical El borde (Border).getDrawPage() oFormularios = oPaginaDibujo.Align = 1 . en medio (1) o abajo (2). getDrawPage() oFormularios = oPaginaDibujo.sun. para permitir su interacción con el usuario o no. Sub Dim Dim Dim Dim Dim Dim Dim CuadroTexto1() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object oCuadroTexto As Object oCuadroTextoModelo As Object oDoc = ThisComponent oHojaActiva = oDoc.getByName( "MiDirectorio" ) 'Referencia al control llamado lblId olblClave = oFormulario.Enabled = Not olblClave. en el siguiente ejemplo.star.sun.getForms() oFormulario = oFormularios. en el siguiente ejemplo.Enabled End Sub Esta propiedad es más útil en otro tipo de controles. que en las etiquetas.getByName("lblId") 'Invertimos el valor de la propiedad olblClave.getCurrentController.TextField") 'Establecemos su nombre .createInstance("com.form.getActiveSheet() oPaginaDibujo = oHojaActiva.getCurrentController.star.component. 7. 2000.createInstance("com. 2000 ) 'Creamos un nuevo cuadro de texto oCuadroTextoModelo = oDoc. se invierta el valor de esta propiedad de la misma etiqueta. 800 ) Call CambiaPos( oCuadroTexto.3 Cuadros de texto (TextBox) Los cuadro de texto (TextBox) son controles que nos permiten interactuar con el usuario.getActiveSheet() oPaginaDibujo = oHojaActiva.drawing.getByName( "MiDirectorio" ) 'Creamos una nueva forma de control oCuadroTexto = oDoc.getForms() oFormulario = oFormularios.Aprendiendo OOo Basic 401 activarlos o desactivarlos (Enabled). tanto para mostrar información. agregamos un nuevo cuadro de texto a nuestro formulario. es decir. Sub Dim Dim Dim Dim Dim Dim Etiquetas4() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object olblClave As Object oDoc = ThisComponent oHojaActiva = oDoc.getDrawPage() oFormularios = oPaginaDibujo.ControlShape") 'Cambiamos su tamaño y posicion Call CambiaTam( oCuadroTexto. 10000. como para permitirle modificarla. Border = 1 .Text .FontHeight = 14 .getActiveSheet() oPaginaDibujo = oHojaActiva.getByName("txtNombre") With otxtNombre . oCuadroTextoModelo) 'Agregamos la forma a la página de dibujo para que sea visible oPaginaDibujo.getDrawPage() oFormularios = oPaginaDibujo.getByName( "MiDirectorio" ) 'Referencia al control llamado txtNombre otxtNombre = oFormulario.getCurrentController.Name = "txtNombre" 'Conectamos la forma con el nuevo control oCuadroTexto.3 Cuadros de texto (TextBox) Los cuadros de texto.200) .TextColor = RGB(0.add( oCuadroTexto ) End Sub 7.Control = oCuadroTextoModelo 'Lo agregamos al formulario oFormulario.100.BackgroundColor = RGB(230.230) .getForms() oFormulario = oFormularios.getActiveSheet() oPaginaDibujo = oHojaActiva.402 oCuadroTextoModelo.insertByIndex(0.getCurrentController.getByName("txtNombre") 'Recuperamos el texto del control sInfo = otxtNombre.getForms() oFormulario = oFormularios. Sub Dim Dim Dim Dim Dim Dim Dim CuadroTexto3() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object otxtNombre As Object sInfo As String oDoc = ThisComponent oHojaActiva = oDoc.getDrawPage() oFormularios = oPaginaDibujo.Align = 0 End With End Sub 'La fuente 'El tamaño de fuente 'El color de fondo 'El tipo de borde (1 = 3D ) 'El color del texto 'Alineación horizontal (izquierda) El principal uso de estos controles es recuperar su contenido o establecerlo.230.FontName = "Linux Biolinum" . Sub Dim Dim Dim Dim Dim Dim CuadroTexto2() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object otxtNombre As Object oDoc = ThisComponent oHojaActiva = oDoc.getByName( "MiDirectorio" ) 'Referencia al control llamado txtNombre otxtNombre = oFormulario. comparten algunas propiedades con las etiquetas. solo puedes establecer el campo vinculado (DataField) o la celda vinculada (ValueBinding). por supuesto.VScroll = True .getCurrentController.getByName("txtNombre") With otxtNombre .MaxTextLen = 20 .EchoChar = 42 .DataField = "Nombre" End With End Sub 'El carácter de contraseña 42 = * 'Longitud máxima aceptada 'Si es o no multilínea 'Si se muestra o no la barra de desplazamiento horizontal 'Si se muestra o no la barra de desplazamiento vertical 'Si es imprime o no el control 'Si es o no de solo lectura 'Establece el campo de la base de datos mostrada Algunas de estas propiedades se contraponen.getDrawPage() oFormularios = oPaginaDibujo. solo será efectivo si previamente el formulario se relaciono con una base de datos y con una fuente de datos (tabla.HScroll = False . Si quieres quitar la relación. consulta o instrucción SQL). el usuario no podrá escribir en el.getActiveSheet() oPaginaDibujo = oHojaActiva. si estableces el control en multilínea (MultiLine). tendrá efecto el ultimo que establezcas como en nuestro ejemplo.MultiLine = True . cuentan con muchas más propiedades.Aprendiendo OOo Basic 403 'Lo mostramos MsgBox sInfo 'Solicitamos un nuevo contenido sInfo = InputBox("Escribe un nuevo contenido para el control") 'Y lo establecemos otxtNombre. el nombre del campo “debe existir” en el origen de datos. esto te permite reflejar cualquier cambio que se haga en uno en el otro. Sub Dim Dim Dim Dim Dim Dim CuadroTexto4() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object otxtNombre As Object oDoc = ThisComponent oHojaActiva = oDoc.Printable = True .Text = sInfo End Sub También puedes usar la propiedad String para recuperar o establecer el texto del control. Sub Dim Dim Dim Dim CuadroTexto5() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object . si estableces el control en solo lectura (ReadOnly). establece esta propiedad en vacía. además. por ejemplo. Los cuadros de texto.getForms() oFormulario = oFormularios. Puedes vincular el control con una celda de cualquier hoja.getByName( "MiDirectorio" ) 'Referencia al control llamado txtNombre otxtNombre = oFormulario. El campo vinculado (DataField).ReadOnly = False . el carácter de contraseña (EchoChar) no tiene efecto como tampoco las barras de desplazamiento (Hscroll y Vscroll). 3 Cuadros de texto (TextBox) oDoc = ThisComponent oHojaActiva = oDoc.Name = "BoundCell" mOpc(0).beans.getByName("txtNombre") 'Obtenemos la dirección de la celda B5 oDirCeldaVinculada = oHojaActiva.setValueBinding( oVinculo ) End Sub Puedes activar y desactivar (Enabled) el control.star. es posible convertirlo en cuadro de texto enriquecido.sun.Value = oDirCeldaVinculada 'Creamos la instancia de la celda a vincular oVinculo= oDoc. toma en cuenta que activarlo es diferente de establecerlo en solo lectura (ReadOnly).getActiveSheet() oPaginaDibujo = oHojaActiva.404 Dim Dim Dim Dim Dim oFormulario As Object otxtNombre As Object oDirCeldaVinculada As Object mOpc(0) As New "com.table.Enabled = Not otxtNombre.getCurrentController.4).createInstanceWithArguments("com.getByName("txtNombre") 'Activamos y desactivamos el control otxtNombre.getCellAddress 'Creamos la propiedad para vincular mOpc(0). capaz de mostrar texto con diferentes formatos.star.getByName( "MiDirectorio" ) 'Referencia al control llamado txtNombre otxtNombre = oFormulario.getDrawPage() oFormularios = oPaginaDibujo.getDrawPage() oFormularios = oPaginaDibujo.NamedValue" oVinculo As Object 7. Sub Dim Dim Dim Dim Dim Dim Dim CuadroTexto7() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object otxtNombre As Object oCursor As Object oDoc = ThisComponent . Sub Dim Dim Dim Dim Dim Dim CuadroTexto6() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object otxtNombre As Object oDoc = ThisComponent oHojaActiva = oDoc.getForms() oFormulario = oFormularios.getActiveSheet() oPaginaDibujo = oHojaActiva.CellValueBinding".sun.getByName( "MiDirectorio" ) 'Referencia al control llamado txtNombre otxtNombre = oFormulario.getCellByPosition(1. mOpc()) 'Y la vinculamos al cuadro de texto otxtNombre.getForms() oFormulario = oFormularios.Enabled End Sub Este control.getCurrentController. mover el cursor a este.getCurrentController. Sub Dim Dim Dim Dim Dim CuadroTexto9() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object .getCurrentController. False) End Sub Una tarea muy común al trabajar con controles.getByName( "MiDirectorio" ) otxtNombre = oFormulario. 0. para entrar al modo “vista. usamos el siguiente código. hasta ahora para acceder a los controles de un formulario. solo es posible hacer a través de la “vista” del control. a este modo de acceso se le llama “modelo”.RichText = True 'Creamos un cursor oCursor = otxtNombre. "Primera línea".insertString( oCursor.getDrawPage() oFormularios = oPaginaDibujo.getDrawPage() oFormularios = oPaginaDibujo.getActiveSheet() oPaginaDibujo = oHojaActiva.setFocus() End Sub Observa como accedemos al modo “vista” del control. como posibilidad de ocultar o mostrar el control.insertString( oCursor.Aprendiendo OOo Basic 405 oHojaActiva = oDoc. puedes acceder también al contenido del control con su propiedad Text. pero para usar otras propiedades y métodos. False) 'Insertamos otra línea de texto otxtNombre.getByName( "MiDirectorio" ) 'Referencia al control llamado txtNombre otxtNombre = oFormulario. es enviarles el foco.getByName("txtNombre") 'Establecemos que sea multilínea y que soporte texto enriquecido otxtNombre.Multiline = True otxtNombre. es decir. nos ha bastado como medio el mismo formulario.createTextCursor() 'Insertamos una línea de texto otxtNombre.getForms() oFormulario = oFormularios.getByName("txtNombre") 'Accedemos a la vista del control otxtNombreVista = oDoc. pero algunas otras propiedades solo están disponibles en este modo. "Segunda línea". Sub Dim Dim Dim Dim Dim Dim Dim CuadroTexto8() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object otxtNombre As Object otxtNombreVista As Object oDoc = ThisComponent oHojaActiva = oDoc. Desde el modo “vista”. a través del controlador (getCurrentController) del documento.getControl( otxtNombre ) 'Le enviamos el foco otxtNombreVista. tenemos que aprender un nuevo concepto.getActiveSheet() oPaginaDibujo = oHojaActiva.insertControlCharacter( oCursor. para ello.getCurrentController. False) 'Insertamos un salto de parrafo otxtNombre.getForms() oFormulario = oFormularios. ControlShape") 'Cambiamos su tamaño y posicion Call CambiaTam( oCasilla.getCurrentController.getActiveSheet() oPaginaDibujo = oHojaActiva. 5000 ) 'Creamos una nueva casilla de verificación oCasillaModelo = oDoc. tienen su modo “vista” y la posibilidad de enviar el foco y ocultarlos.getCurrentController.star.component. generalmente se usan para indicar si se hace o no una actividad u opción. el control de todos modos se mostrará.sun.CheckBox") 'Establecemos su nombre oCasillaModelo.406 Dim otxtNombre As Object Dim otxtNombreVista As Object oDoc = ThisComponent oHojaActiva = oDoc.form.getByName( "MiDirectorio" ) 'Creamos una nueva forma de control oCasilla = oDoc. 7.getControl( otxtNombre ) 'Alternamos entre mostrar y ocultar el control otxtNombreVista.4 Casilla de verificación (CheckBox) Las casillas de verificación (CheckBox).sun.getForms() oFormulario = oFormularios. son controles de verdadero o falso.drawing. Sub Dim Dim Dim Dim Dim Dim Dim CasillaVerificacion1() oDoc As Object oHojaActiva As Object oPaginaDibujo As Object oFormularios As Object oFormulario As Object oCasilla As Object oCasillaModelo As Object oDoc = ThisComponent oHojaActiva = oDoc.getDrawPage() oFormularios = oPaginaDibujo.setVisible( Not otxtNombreVista.getCurrentController.createInstance("com.getDrawPage() oFormularios = oPaginaDibujo.getByName("txtNombre") 'Accedemos a la vista del control otxtNombreVista = oDoc.createInstance("com.Control = oCasillaModelo .isVisible ) End Sub 7.getByName( "MiDirectorio" ) otxtNombre = oFormulario.getActiveSheet() oPaginaDibujo = oHojaActiva. El siguiente ejemplo agrega una casilla de verificación a nuestro formulario. Casi todos los controles que veremos.star. 8000. solo tiene efecto en tiempo de “ejecución”. 3000. 800 ) Call CambiaPos( oCasilla.3 Cuadros de texto (TextBox) Toma en cuenta que si el formulario esta en modo “diseño”. es decir. este método.getForms() oFormulario = oFormularios.Name = "chkMayus" 'Y el texto que verá el usuario oCasillaModelo.Label = "Guardar todo en MAYUSCULAS" 'Conectamos la forma con el nuevo control oCasilla. 240) .getCurrentController.getCurrentController.FontHeight = 16 .getByName( "chkMayus" ) 'Alternamos la activación del control ochkMayus.getActiveSheet. este se puede formatear completamente como en las etiquetas (label) y los cuadros de texto (textbox). esta activa o no.getDrawPage.State .220.getByName( "MiDirectorio" ) ochkMayus = oFormulario.insertByIndex(0.getByName( "MiDirectorio" ) ochkMayus = oFormulario.getByName( "chkMayus" ) With ochkMayus .add( oCasilla ) End Sub Al contar con texto para mostrar al usuario.Aprendiendo OOo Basic 407 'Lo agregamos al formulario oFormulario. 1 o 2. Sub CasillaVerificacion2() Dim oFormulario As Object Dim ochkMayus As Object oFormulario = ThisComponent.getActiveSheet.getCurrentController. dependiendo si. se usa la propiedad State. esta puede tomar los valores 0. y de la propiedad de triple estado (TriState).getByName( "chkMayus" ) 'Verificamos el estado de la casilla Select Case ochkMayus.TextColor = RGB(50.Printable = True .Enabled = Not ochkMayus.TriState = False .Align = 0 .VisualEffect = 2 End With End Sub 'Alineación horizontal 'Color de fondo 'Color de la fuente 'Tamaño de la fuente 'Si se imprime el control 'Alineación vertical 'Establece el estado triple 'Formato plano (1 = 3D) Puedes activarlo y desactivarlo.Enabled End Sub Para obtener o establecer el estado del control. oCasillaModelo) 'Agregamos la forma a la página de dibujo para que sea visible oPaginaDibujo.VerticalAlign = 1 .BackgroundColor = RGB(200. que permite tener este control en.getByName( "MiDirectorio" ) ochkMayus = oFormulario.90) .getDrawPage.70. Sub CasillaVerificacion3() Dim oFormulario As Object Dim ochkMayus As Object oFormulario = ThisComponent. activo.getForms.getDrawPage. desactivado o sin selección.getActiveSheet. Sub CasillaVerificacion4() Dim oFormulario As Object Dim ochkMayus As Object oFormulario = ThisComponent.getForms.getForms. Control = oCuadroConFormatoModelo 'Lo agregamos al formulario oFormulario.ControlShape") 'Cambiamos su tamaño y posicion Call CambiaTam( oCuadroConFormato. también las puedes vincular con un campo de datos (DataField) o con una celda (ValueBinding).star..getActiveSheet.FormattedField") 'Establecemos su nombre oCuadroConFormatoModelo.5 Campo formateado (FormattedField) Los campos formateados (FormattedField). con el mismo código de los cuadros de texto.insertByIndex(0. con la diferencia de que estos aceptan todos los formatos que tenemos disponibles en el menú Formato | Celdas.Name = "txtFVentas" 'Conectamos la forma con el nuevo control oCuadroConFormato. Sub CampoFormateado2() .add( oCuadroConFormato ) End Sub Puede usar las mismas propiedades que para los cuadros de texto (TextBox).sun. 7. son controles casi indenticos a los cuadros de texto (TextBox). 8000. Sub Dim Dim Dim CampoFormateado1() oFormulario As Object oCuadroConFormato As Object oCuadroConFormatoModelo As Object oFormulario = ThisComponent.star.State = 1 End Sub 7.getDrawPage.getActiveSheet. aquí vemos las propiedades particulares para este control.form.408 Case 0 MsgBox "La casilla no esta seleccionada" Case 1 MsgBox "La casilla esta seleccionada" Case 2 MsgBox "La casilla no tiene selección" End Select 'La activamos ochkMayus.getCurrentController.4 Casilla de verificación (CheckBox) Las casillas de verificación.getCurrentController. 5000 ) 'Creamos un nuevo campo formateado oCuadroConFormatoModelo = ThisComponent. 800 ) Call CambiaPos( oCuadroConFormato.getForms.createInstance("com. y se les puede establecer un valor máximo y un mínimo.getDrawPage..component. 3000. en la ficha Números.getByName( "MiDirectorio" ) 'Creamos una nueva forma de control oCuadroConFormato = ThisComponent.createInstance("com. oCuadroConFormatoModelo) 'Agregamos la forma a la página de dibujo para que sea visible ThisComponent.drawing.sun. drawing. oBotonComandoModelo) 'Agregamos la forma a la página de dibujo para que sea visible ThisComponent.getByName ( "txtFVentas" ) With otxtfVentas .EffectiveMin = 1 . 3000.sun. Sub Dim Dim Dim BotonComando1() oFormulario As Object oBotonComando As Object oBotonComandoModelo As Object oFormulario = ThisComponent.getByName( "MiDirectorio" ) 'Creamos una nueva forma de control oBotonComando = ThisComponent. 10000 ) 'Creamos un nuevo botón de comando oBotonComandoModelo = ThisComponent. El valor para el formato (FormatKey).getForms.6 Botón de comando (CommandButton) Los botones de comando (CommandButton) son controles generalmente usados para iniciar una acción por que usualmente tienen asociada una macro al evento “clic del ratón”.getCurrentController.Label = "~Guardar" 'Conectamos la forma con el nuevo control oBotonComando.Control = oBotonComandoModelo 'Lo agregamos al formulario oFormulario.getCurrentController.CommandButton") 'Establecemos su nombre oBotonComandoModelo. es el mismo para las celdas.getByName( "MiDirectorio" ) otxtfVentas = oFormulario.EffectiveMax = 100 . la alienación del contenido siempre será a la izquierda.insertByIndex(0. Listar formatos en un archivo de Calc.Aprendiendo OOo Basic Dim oFormulario As Object Dim otxtfVentas As Object 409 oFormulario = ThisComponent.getCurrentController.getActiveSheet. 800 ) Call CambiaPos( oBotonComando.getForms. así como vincularlo con una celda (ValueBinding).star.getActiveSheet.createInstance("com. 7. Veamos como agregar uno a nuestro formulario.FormatKey = 4 End With End Sub 'El 'El 'Si 'El valor mínimo valor máximo se muestra o no el campo giratorio formato para el contenido ( 4 = "#.Spin = True .star. Este control también lo puedes activar y desactivar (Enabled) y establecerle un campo de datos origen (DataField). aunque soportan varios más.getDrawPage.form. 5000.00" ) Si estableces que se muestre el campo giratorio (Spin).getDrawPage.ControlShape") 'Cambiamos su tamaño y posicion Call CambiaTam( oBotonComando.add( oBotonComando ) End Sub .Name = "cmdGuardar" oBotonComandoModelo. puedes obtener estos valores con la macro que te muestro en.sun.##0.component.createInstance("com.getActiveSheet.getDrawPage. la combinación de teclas llevará el cursor a dicho control. 7.getDrawPage.createInstance("com. este método abreviado tiene una función ligeramente diferente.Printable = True End With End Sub 'Alineación horizontal ( 1 = centro ) 'Alineación vertical ( 1 = medio ) 'Color de fondo 'Si es el botón predeterminado 'La fuente 'El tamaño de fuente 'El color del texto 'Si se imprime el control Este control también cuenta con la propiedad para activar o desactivar (Enabled). es decir el cursor.component.7 Botón de opción (OptionButton) Estos controles generalmente trabajan juntos dos o más.ControlShape") 'Cambiamos su tamaño y posicion Call CambiaTam( oBotonOpcion.createInstance("com.FontHeight = 18 .DefaultButton = True .410 7. solo le lleva el foco.20. este.form. si estableces una combinación ya usada en la interfaz del usuario.sun.RadioButton") 'Establecemos su nombre .6 Botón de comando (CommandButton) Observa el símbolo “~” antes del título del botón de comando. 5000.TextColor = RGB(0. pero solo eso. 11000 ) 'Creamos un nuevo botón de opción oBotonOpcionModelo = ThisComponent.250) .getByName( "MiDirectorio" ) 'Creamos una nueva forma de control ocmdGuardar = oFormulario.Align = 1 .getActiveSheet. por ello. 3000. 800 ) Call CambiaPos( oBotonOpcion. en los formularios.240) .sun.getForms.getCurrentController. Sub Dim Dim Dim BotonOpcion1() oFormulario As Object oBotonOpcion As Object oBotonOpcionModelo As Object oFormulario = ThisComponent.230. cuando tiene una macro asociada. generalmente se agregan dos o más como en el siguiente ejemplo. cuando el “foco”.getForms.getDrawPage.FontName = "Linux Biolinum" . ten cuidado.BackgroundColor = RGB(220. Veamos las principales propiedades particulares de este control. esta dentro de algún control del formulario. esta tendrá preferencia.getByName( "MiDirectorio" ) 'Creamos una nueva forma de control oBotonOpcion = ThisComponent.getCurrentController.VerticalAlign = 1 . Sub BotonComando2() Dim oFormulario As Object Dim ocmdGuardar As Object oFormulario = ThisComponent.star. muy útil para deshabilitar momentáneamente su uso. nos permite subrayar la letra inmediata siguiente para usarse como método abreviado de teclado.getByName ("cmdGuardar") With ocmdGuardar . pues permiten seleccionar solo una opción de entre los que haya en el formulario.star.getActiveSheet.drawing. RadioButton") oBotonOpcionModelo. 3000. pero observa que hasta ahora.add( oBotonOpcion ) 'Y un tercero oBotonOpcion = ThisComponent.Label = "Color" 'Conectamos la forma con el nuevo control oBotonOpcion. Al tener texto visible por el usuario.createInstance("com.Label = "Blanco y negro" oBotonOpcion. si quieres que se comporten como un grupo.TextColor = RGB(Rnd*255.Rnd*255.createInstance("com.Rnd*255.BackgroundColor = RGB(Rnd*255.insertByIndex(0.getByIndex(1) ooptEstilo. 13000 ) oBotonOpcionModelo = ThisComponent.getCurrentController.component.form.BackgroundColor = RGB(Rnd*255.getForms.getDrawPage.sun.Rnd*255. estilo de fuente. simplemente estableciendo el mismo nombre para cada grupo agregado.star. oBotonOpcionModelo) 'Agregamos la forma a la página de dibujo para que sea visible ThisComponent.drawing.createInstance("com.getActiveSheet.getDrawPage.Rnd*255) ooptEstilo = oFormulario.Name = "optEstilo" oBotonOpcionModelo.insertByIndex(0.sun.BackgroundColor = RGB(Rnd*255. 12000 ) oBotonOpcionModelo = ThisComponent. en vez de con su nombre.Rnd*255. hemos usado el nombre del control para hacer referencia a el. comparten la mayoría de las propiedades vistas hasta ahora (color de fuente y fondo.TextColor = RGB(Rnd*255.Name = "optEstilo" oBotonOpcionModelo.insertByIndex(0.star.Control = oBotonOpcionModelo oFormulario.getByIndex(2) ooptEstilo.Rnd*255. 5000. etc).Control = oBotonOpcionModelo oFormulario.add( oBotonOpcion ) 'Agregamos un segundo control oBotonOpcion = ThisComponent.Label = "Escala de grises" oBotonOpcion. tamaño de fuente. pero a estos controles les hemos dado el mismo nombre.createInstance("com.star.getActiveSheet.Rnd*255) ooptEstilo. Sub BotonOpcion2() Dim oFormulario As Object Dim ooptEstilo As Object oFormulario = ThisComponent.ControlShape") Call CambiaTam( oBotonOpcion.add( oBotonOpcion ) End Sub Observa que a los tres les hemos establecido el mismo nombre.getByName( "MiDirectorio" ) ooptEstilo = oFormulario.sun.ControlShape") Call CambiaTam( oBotonOpcion.RadioButton") oBotonOpcionModelo.getCurrentController.Name = "optEstilo" oBotonOpcionModelo. 5000.Rnd*255) ooptEstilo. para distinguirlos.drawing. como en el siguiente ejemplo. oBotonOpcionModelo) ThisComponent.Aprendiendo OOo Basic oBotonOpcionModelo.component. 3000.getByIndex(0) ooptEstilo.form.getDrawPage.Rnd*255) 'Color de fondo 'Color de la fuente 'Color de fondo 'Color de la fuente 'Color de fondo .getCurrentController. esto es importante. puedes crear tantos grupos de controles de botón de opción (OptionButton) como quieras.star.Control = oBotonOpcionModelo 411 'Lo agregamos al formulario oFormulario. ahora accederemos a ellos con su índice.Rnd*255) ooptEstilo = oFormulario.getActiveSheet. oBotonOpcionModelo) ThisComponent.sun.getActiveSheet. de este modo. 800 ) Call CambiaPos( oBotonOpcion.getDrawPage. 800 ) Call CambiaPos( oBotonOpcion.getCurrentController. como en el ejemplo siguiente: Sub Dim Dim Dim BotonOpcion3() oFormulario As Object oGrupoEstilo() As Object oBoton As Object oFormulario = ThisComponent. tienes que tener visible la barra de herramientas “Campos de control de formulario”. .State Then 'Mostramos el que este seleccionado MsgBox "Opción seleccionada: " & oBoton.getCurrentController.getForms.Rnd*255) End Sub 7. que solo uno de ellos puede tener en verdadero (True). después solo sigue la secuencia de la imagen siguiente. oGrupoEstilo) 'Iteramos entre los elementos del grupo For Each oBoton In oGrupoEstilo() 'Cambiamos el color de fondo aleatoriamente oBoton. visualmente en la interfaz de Calc.BackgroundColor = RGB(Rnd*255.7 Botón de opción (OptionButton) 'Color de la fuente Y con justa razón te preguntarás.getDrawPage. para ello se consulta su propiedad State. en el navegador de formularios. esta seleccionado. para ver esta ventana.getGroupByName("optEstilo". ¿como se que índice tiene cada control?. Con código.getDrawPage. así como vincularlo con una celda (ValueBinding). cuando se asocia una macro al evento clic de los botones de opción. puedes acceder a los controles por el nombre del grupo.getCurrentController.412 ooptEstilo.getForms.TextColor = RGB(Rnd*255.getGroupByName("optEstilo". es muy sencillo saber cual es el que esta seleccionado.Label Exit For End If Next End Sub Como veremos más adelante. sin recorrer uno a uno. visible desde el menú Ver | Barra de herramientas ->.getByName( "MiDirectorio" ) 'Accedemos al grupo completo oFormulario. Sub Dim Dim Dim BotonOpcion4() oFormulario As Object oGrupoEstilo() As Object oBoton As Object oFormulario = ThisComponent. dentro del grupo.Rnd*255) Next End Sub Lo importante de los botones de opción (Optionbutton) es saber cual de ellos.getByName( "MiDirectorio" ) oFormulario. oGrupoEstilo) For Each oBoton In oGrupoEstilo() 'Consultamos el estado del botón If oBoton. Estos controles también cuenta con la propiedad de activarse o desactivarse (Enabled) y la capacidad para establecerle un campo de datos origen (DataField).Rnd*255. puedes hacerlo de varias maneras.Rnd*255.getActiveSheet.getActiveSheet. getActiveSheet. 10000 ) 'Creamos un nuevo cuadro de lista oCuadroListaModelo = ThisComponent.getDrawPage.createInstance("com. 3000.drawing.getForms. agregamos un nuevo control de lista a nuestro formulario.getDrawPage.BackgroundColor = RGB(Rnd*255.ListBox") 'Establecemos su nombre oCuadroListaModelo. Sub Dim Dim Dim CuadroLista1() oFormulario As Object oCuadroLista As Object oCuadroListaModelo As Object oFormulario = ThisComponent. oCuadroListaModelo) 'Agregamos la forma a la página de dibujo para que sea visible ThisComponent.Border = 2 .getByName( "lstCiudades" ) With olstCiudades .sun.Rnd*255.Rnd*255) .getDrawPage. son controles usados generalmente para mostrar un listado y poder seleccionar una o varias opciones dependiendo de sus propiedades.Rnd*255.getActiveSheet.add( oCuadroLista ) End Sub Las propiedades principales de este control son.getActiveSheet. en el siguiente ejemplo.Aprendiendo OOo Basic 413 7. 5000 ) Call CambiaPos( oCuadroLista.getCurrentController.getForms. Sub CuadroLista2() Dim oFormulario As Object Dim olstCiudades As Object oFormulario = ThisComponent.star. 5000.getByName( "MiDirectorio" ) 'Creamos una nueva forma de control oCuadroLista = ThisComponent.MultiSelection = True End With End Sub 'Color de fondo 'Tipo de borde ( 1 = 3D ) 'Solo si Border = 2 'Si es desplegable 'Si se permite la multiselección .8 Cuadro de lista (ListBox) Los cuadros de lista (ListBox).star.Dropdown = False .createInstance("com.component.ControlShape") 'Cambiamos su tamaño y posicion Call CambiaTam( oCuadroLista.insertByIndex(0.BorderColor = RGB(Rnd*255.Name = "lstCiudades" 'Conectamos la forma con el nuevo control oCuadroLista.Rnd*255) .getCurrentController.getCurrentController.sun.getByName( "MiDirectorio" ) olstCiudades = oFormulario.Control = oCuadroListaModelo 'Lo agregamos al formulario oFormulario.form. Value = oDirCeldaVinculada 'Creamos la instancia de la celda a vincular createInstanceWithArguments oVinculo= ThisComponent.NamedValue" oVinculo As Object oFormulario = ThisComponent. Sub Dim Dim Dim CuadroLista3() oFormulario As Object olstCiudades As Object mDatos() oFormulario = ThisComponent.CellValueBinding". si quieres un cuadro combinado.getCellByPosition(3.StringItemList = mDatos() End Sub Este control acepta también como origen de datos un campo de bases de datos (DataField).sun.getCurrentController.getCurrentController. Haya varias formas de agregar elementos a un cuadro de lista.414 7. tanto para el valor seleccionado (ValueBinding).getForms. con lo que se comportará de forma similar al cuadro combinado (ComboBox).Name = "CellRange" mOpc(0).createInstanceWithArguments("com.getByName( "lstCiudades" ) 'Obtenemos la dirección de la celda B5 oDirCeldaVinculada = ThisComponent.getCellAddress 'Creamos la propiedad para vincular mOpc(0).sun.setListEntrySource( oVinculo ) End Sub . te mostrará una flecha para desplegar el contenido.getActiveSheet."Bogota".getCurrentController.getByName( "MiDirectorio" ) olstCiudades = oFormulario.24). la primera y más sencilla es agregar una matriz de datos. "Madrid".star.Name = "BoundCell" mOpc(0).CellRangeListSource".getActiveSheet. Otra forma es vincular el control con un origen de celdas."Lima") olstCiudades.sun.getByName( "MiDirectorio" ) olstCiudades = oFormulario."Buenos Aires". mOpc()) 'Y la vinculamos al cuadro de lista olstCiudades.getDrawPage.8 Cuadro de lista (ListBox) Si estableces que el control sea desplegable (Dropdown).Value = oRangoOrigen 'Creamos el vinculo oVinculo= ThisComponent.table.getDrawPage.star.getActiveSheet. mOpc()) 'Lo vinculamos al cuadro de lista olstCiudades.getCellRangeByName("D27:D40").getForms. mi recomendación es establecer esta propiedad siempre en falso (False). Sub Dim Dim Dim Dim Dim Dim CuadroLista4() oFormulario As Object olstCiudades As Object oDirCeldaVinculada As Object oRangoOrigen As Object mOpc(0) As New "com. como para los valores mostrados (ListEntrySource).table. usa el control visto en el siguiente tema.setValueBinding( oVinculo ) 'Establecemos el rango de celdas origen oRangoOrigen = ThisComponent.getActiveSheet.star.createInstanceWithArguments("com.getByName( "lstCiudades" ) mDatos = Array("Mexico".getRangeAddress mOpc(0).beans.getCurrentController. getByName( "lstCiudades" ) 'Accedemos a la vista del control a través del controlador del documento olstCiudadesVista = ThisComponent.getByName( "MiDirectorio" ) . para acceder a este modo.getDrawPage.getControl( olstCiudades ) 'Y podemos enviar el foco.getActiveSheet. si quieres agregarlos al final.getCurrentController.getActiveSheet. tenemos que saber cuantos elementos ya existen en la lista.getControl( olstCiudades ) Do 'Solicitamos un elemento sInfo = Trim( InputBox("Escribe la ciudad a agregar")) 'Si esta vacio salimos If sInfo = "" Then Exit Do 'Lo agregamos como primer elemento olstCiudadesVista. Sub Dim Dim Dim Dim CuadroLista6() oFormulario As Object olstCiudades As Object olstCiudadesVista As Object sInfo As String oFormulario = ThisComponent.getCurrentController.getCurrentController. con hacer referencia al control a través del formulario nos era suficiente.getDrawPage.setFocus() End Sub En el acceso “vista”. repasemos un concepto para el acceso a propiedades y métodos de los controles. tenemos una serie de métodos y propiedades para manipular completamente los elementos de un cuadro de lista (ListBox). Sub Dim Dim Dim Dim CuadroLista7() oFormulario As Object olstCiudades As Object olstCiudadesVista As Object sInfo As String oFormulario = ThisComponent.getDrawPage.getByName( "MiDirectorio" ) olstCiudades = oFormulario. que te devuelve el número total de elementos actuales en el cuadro de lista.getByName( "MiDirectorio" ) olstCiudades = oFormulario.getForms. Sub Dim Dim Dim CuadroLista5() oFormulario As Object olstCiudades As Object olstCiudadesVista As Object oFormulario = ThisComponent. es decir.getActiveSheet. hasta ahora. Para agregar elementos usamos el método addItem de la siguiente manera.getForms. esto lo logramos con la propiedad ItemCount.getForms. 0) Loop End Sub El código anterior siempre agregará los nuevos elementos al inicio de la lista.getCurrentController.getCurrentController. el cursor a el olstCiudadesVista. pero algunas propiedades y métodos solo están disponibles en el modo de acceso “vista”.Aprendiendo OOo Basic 415 Otra forma es agregar (y quitar) los elementos de forma dinámica. veamos los más importantes.getByName( "lstCiudades" ) olstCiudadesVista = ThisComponent. para lograr esto. usamos el siguiente código. a esta forma de referencia se le llama de acceso al “modelo”.addItem( sInfo. 4) If iRes = 6 Then 'Quitamos el ultimo elemento de la lista olstCiudadesVista.getByName( "MiDirectorio" ) olstCiudades = oFormulario. en plural.getByName( "MiDirectorio" ) olstCiudades = oFormulario.getItem( olstCiudadesVista.getCurrentController.getCurrentController. pero es más que suficiente.getItemCount-1 ). olstCiudadesVista.addItems( sInfo.getByName( "lstCiudades" ) olstCiudadesVista = ThisComponent.getForms.getActiveSheet.getControl( olstCiudades ) Do sInfo = Trim( InputBox("Escribe la ciudad a agregar")) If sInfo = "" Then Exit Do 'Lo agregamos como ultimo elemento olstCiudadesVista.getControl( olstCiudades ) iRes = MsgBox( "¿Estas seguro de borrar el siguiente elemento? = " & olstCiudadesVista.1 ) End If iRes = MsgBox( "¿Estas seguro de borrar el siguiente elemento? = " & olstCiudadesVista. 4) If iRes = 6 Then 'Quitamos el primer elemento de la lista olstCiudadesVista.getDrawPage.getControl( olstCiudades ) sInfo = Array("Barcelona".removeItems( 0."Montevideo".getCurrentController.getItemCount-1.getByName( "lstCiudades" ) olstCiudadesVista = ThisComponent.removeItems( olstCiudadesVista. Sub Dim Dim Dim Dim CuadroLista8() oFormulario As Object olstCiudades As Object olstCiudadesVista As Object sInfo() oFormulario = ThisComponent.getCurrentController.1 ) End If End Sub .addItem( sInfo.getForms. vamos a eliminar elementos de la lista. 0) End Sub Observa que el método es addItems.getItem( 0 ). Solo puedes agregar matrices de una sola dimensión.ItemCount) Loop End Sub También podemos agregar una matriz completa.getActiveSheet.416 7. Sub Dim Dim Dim Dim CuadroLista9() oFormulario As Object olstCiudades As Object olstCiudadesVista As Object iRes As Integer oFormulario = ThisComponent. para ellos existe un solo método.getByName( "lstCiudades" ) olstCiudadesVista = ThisComponent.getDrawPage. Ahora."Arequipa") 'Agregamos una matriz completa olstCiudadesVista.8 Cuadro de lista (ListBox) olstCiudades = oFormulario.getCurrentController. para ello tenemos varios métodos.getByName( "lstCiudades" ) olstCiudadesVista = ThisComponent. solo eliminamos un elemento.getDrawPage. En los dos ejemplos anteriores. . dejarla en blanco para empezar de nuevo.getForms.Aprendiendo OOo Basic 417 El método para eliminar elementos (removeItems). preguntar al usuario si esta seguro de realizarla.getByName( "MiDirectorio" ) olstCiudades = oFormulario. las posiciones del cuadro de lista. veremos como devolver todos los elementos de la lista (getItems).getActiveSheet. Ya vimos como devolver un elemento de la lista (getItem). es decir. el primero (0) y el ultimo (getItemCount-1). Sub Dim Dim Dim Dim CuadroLista10() oFormulario As Object olstCiudades As Object olstCiudadesVista As Object iRes As Integer oFormulario = ThisComponent.getControl( olstCiudades ) 'Devolvemos todos los elementos a una matriz mDatos() = olstCiudadesVista. contamos el total de elemento y le restamos uno para obtener el índice del ultimo elemento.getCurrentController.getByName( "MiDirectorio" ) olstCiudades = oFormulario. Sub Dim Dim Dim Dim Dim CuadroLista11() oFormulario As Object olstCiudades As Object olstCiudadesVista As Object mDatos() co1 As Integer oFormulario = ThisComponent.getControl( olstCiudades ) iRes = MsgBox( "¿Estas seguro de borrar TODOS los elementos de la lista?". veamos. como en las matrices. siempre empieza en cero. requiere de dos argumentos. este método siempre te devuelve un texto (string) con el contenido del elemento indicado.removeItems( 0. el segundo argumento es el número total de elementos a borrar.getItemCount ) End If End Sub Recuerda que es una buena practica de programación.getCurrentController.getActiveSheet. simplemente pasándole el índice del elemento a mostrar.getItems() 'Mostramos los elementos en la matriz For co1 = LBound(mDatos) To Ubound(mDatos) MsgBox mDatos(co1) Next co1 End Sub Un punto importante es saber que elemento o elementos selecciono el usuario. sobre todo si son de borrado. Con estos argumentos en posible limpiar la lista completa. es decir. el primero es la posición del primer elemento a borrar. cuando se realizan operaciones que no se puedan deshacer.getForms.getDrawPage.getCurrentController. Observa como le mostramos al usuario el elemento a borrar con el método getItem.getByName( "lstCiudades" ) olstCiudadesVista = ThisComponent. ahora.getCurrentController. olstCiudadesVista. 4 ) If iRes = 6 Then 'Quitamos todos los elementos de la lista olstCiudadesVista. también es posible seleccionar elementos por código. el método getSelectedItemPos.getActiveSheet.getControl( olstCiudades ) 'Obtenemos el elemento seleccionado sSeleccionado = olstCiudadesVista. Para finalizar de ver las propiedades y métodos más importantes de los cuadros de lista (ListBox). tienes que usar otros métodos.418 Sub Dim Dim Dim Dim Dim CuadroLista12() oFormulario As Object olstCiudades As Object olstCiudadesVista As Object sSeleccionado As String iPos As Integer 7.getByName( "MiDirectorio" ) olstCiudades = oFormulario.getCurrentController.getSelectedItems() 'Obtenemos la posición del los elementos seleccionados mPos() = olstCiudadesVista.getCurrentController.getCurrentController.getSelectedItem() 'Obtenemos la posición del elemento seleccionado iPos = olstCiudadesVista.getByName( "lstCiudades" ) olstCiudadesVista = ThisComponent. Sub Dim Dim Dim CuadroLista14() oFormulario As Object olstCiudades As Object olstCiudadesVista As Object .getSelectedItemsPos() For co1 = LBound(mPos) To UBound(mPos) 'Mostramos la información MsgBox "Esta seleccionado: " & mSeleccionados(co1) & " en la posición " & mPos(co1) Next co1 End Sub Observa que en los dos casos estamos obteniendo matrices de datos.getSelectedItemPos() 'Mostramos la información MsgBox "Esta seleccionado: " & sSeleccionado & " en la posición " & iPos End Sub Estos métodos siempre te devolverán un solo elemento.getDrawPage. Sub Dim Dim Dim Dim Dim Dim CuadroLista13() oFormulario As Object olstCiudades As Object olstCiudadesVista As Object mSeleccionados() As String mPos() As Integer co1 As Integer oFormulario = ThisComponent.getDrawPage.getByName( "lstCiudades" ) olstCiudadesVista = ThisComponent.getForms.getCurrentController.getControl( olstCiudades ) 'Obtenemos los elementos seleccionados mSeleccionados() = olstCiudadesVista.8 Cuadro de lista (ListBox) oFormulario = ThisComponent. si el cuadro de lista (ListBox) tiene activada la propiedad para selecciones múltiples (MultiSelection).getActiveSheet. veamos como. si el cuadro de lista (ListBox) no tiene “ningún” elemento seleccionado.getForms. te devolverá un valor negativo de -1.getByName( "MiDirectorio" ) olstCiudades = oFormulario. getActiveSheet. el resultado será diferente.getDrawPage. claro. True) 'Seleccionamos el ultimo elemento de la lista olstCiudadesVista.getForms.getByName( "lstCiudades" ) olstCiudadesVista = ThisComponent.selectItemPos(0. por supuesto. True) End Sub Si el elemento no existe.getDrawPage.getByName( "MiDirectorio" ) olstCiudades = oFormulario. dependiendo de la propiedad de multiselección (MultiSelection).getCurrentController.selectItemPos(olstCiudadesVista.getForms. ¿verdad?.getByName( "MiDirectorio" ) olstCiudades = oFormulario. True) End Sub Por ultimo. seleccionamos el primero y el ultimo elemento. si esta en verdadero (True).getByName( "MiDirectorio" ) olstCiudades = oFormulario. También puedes seleccionar varios elementos al mismo tiempo.5) 'Seleccionamos los elementos de la matriz olstCiudadesVista.getControl( olstCiudades ) 'Seleccionamos el elemento "Lima" olstCiudadesVista.getActiveSheet. Sub Dim Dim Dim Dim CuadroLista15() oFormulario As Object olstCiudades As Object olstCiudadesVista As Object mSeleccionar() oFormulario = ThisComponent.getCurrentController. con los métodos aprendidos en este tema. True) End Sub En el ejemplo.3.getActiveSheet. si esta en falso (False).getItemCount-1. si la multiselección (MultiSelection) esta en verdadero (True). Sub Dim Dim Dim CuadroLista16() oFormulario As Object olstCiudades As Object olstCiudadesVista As Object oFormulario = ThisComponent. la selección se sumará a lo ya seleccionado. la selección reemplazará a la anterior.getByName( "lstCiudades" ) olstCiudadesVista = ThisComponent.Aprendiendo OOo Basic 419 oFormulario = ThisComponent.getForms.getDrawPage.getCurrentController.getCurrentController. no selecciona nada.getCurrentController. puedes seleccionar un elemento por su contenido en vez de por su posición como en el siguiente ejemplo.getControl( olstCiudades ) 'Seleccionamos el primer elemento de la lista olstCiudadesVista.getControl( olstCiudades ) mSeleccionar() = Array(1.selectItem("Lima". .getByName( "lstCiudades" ) olstCiudadesVista = ThisComponent. Este control también acepta la activación o desactivado por código (Enabled).selectItemsPos(mSeleccionar().getCurrentController. puedes asegurarte de que si exista. sobre todo con el cuadro de lista (ListBox).sun.createInstance("com. tenemos el número de líneas que muestra cuando se despliega el control.ComboBox") 'Establecemos su nombre oCuadroCombinadoModelo.component.getActiveSheet.getDrawPage."Belice".420 7.9 Cuadro combinado (ComboBox) 7.getActiveSheet. para agregar este control a nuestro formulario.getDrawPage.insertByIndex(0. comparten con estos la mayoría de sus propiedades y métodos.MaxTextLen = 20 'El máximo de caracteres a aceptar End With End Sub . cuentan con una flecha en el extremo derecho para desplegar el contenido de la lista.getForms. 3000. Como propiedades particulares de este.getDrawPage.getByName( "MiDirectorio" ) ocboPaises = oFormulario. pues esta.9 Cuadro combinado (ComboBox) Los cuadro combinados (ComboBox).getCurrentController. 10000 ) 'Creamos un nuevo cuadro combinado oCuadroCombinadoModelo = ThisComponent.star. permanece oculta y solo es visible el elemento actualmente seleccionado."Nicaragua") With ocboPaises .Control = oCuadroCombinadoModelo 'Lo agregamos al formulario oFormulario. Sub Dim Dim Dim CuadroCombinado2() oFormulario As Object ocboPaises As Object mDatos() oFormulario = ThisComponent.getCurrentController. oCuadroCombinadoModelo) 'Agregamos la forma a la página de dibujo para que sea visible ThisComponent. Sub Dim Dim Dim CuadroCombinado1() oFormulario As Object oCuadroCombinado As Object oCuadroCombinadoModelo As Object oFormulario = ThisComponent.form.Name = "cboPaises" oCuadroCombinadoModelo.createInstance("com.getCurrentController.sun.getForms.DropDown = True 'Conectamos la forma con el nuevo control oCuadroCombinado.StringItemList = mDatos() .ControlShape") 'Cambiamos su tamaño y posicion Call CambiaTam( oCuadroCombinado. 700 ) Call CambiaPos( oCuadroCombinado.getByName( "MiDirectorio" ) 'Creamos una nueva forma de control oCuadroCombinado = ThisComponent.drawing. usamos. 5000.LineCount = 5 'El número de líneas a mostrar cuando se despliegue .add( oCuadroCombinado ) End Sub Al ser una combinación de los controles mencionados (ListBox y TextBox).star.getActiveSheet."El Salvador".getByName("cboPaises") 'Agregamos datos al cuadro combinado mDatos() = Array("México". son una combinación de un cuadro de lista (ListBox) y un cuadro de texto (TextBox). puesto que este control trabaja de forma un poco diferente. 15000 ) 'Creamos un nuevo botón de selección oBotonSeleccionModelo = ThisComponent. que puedes cambiar. puede cambiar. excepto los relacionados con la selección de elementos (selectItem. se usan exactamente los mismo métodos que en el cuadro de lista (ListBox).getCurrentController. puede tener dos vertientes.getByName("cboPaises") 'Mostramos el elemento seleccionado MsgBox ocboPaises.Text 'Cambiamos el texto ocboPaises.component. selectItemsPos).sun.getByName( "MiDirectorio" ) ocboPaises = oFormulario.getForms.getByName( "MiDirectorio" ) 'Creamos una nueva forma de control oBotonSeleccion = ThisComponent.getActiveSheet.sun.createInstance("com. el control puede tener un valor diferente a los de la lista de elementos. 4000.star. dependiendo de tus necesidades.SpinButton") 'Establecemos su nombre oBotonSeleccionModelo.getCurrentController. 700 ) Call CambiaPos( oBotonSeleccion.createInstance("com. 3000. Sub Dim Dim Dim BotonSeleccion1() oFormulario As Object oBotonSeleccion As Object oBotonSeleccionModelo As Object oFormulario = ThisComponent. sin olvidar que hay que hacerlo desde el modo “vista” del control. cuando se selecciona un elemento de la lista (no es posible hacer multiselecciones).star.getDrawPage. por ello generalmente trabaja en conjunto con otro. tu determinaras si permites esto o no.getDrawPage. Con los métodos vistos.Name = "spnEdad" . usamos.Text = InputBox("Escribe un nuevo valor para el control") End Sub La posibilidad de agregar elementos diferentes a los de la lista. este valor se establece como valor de su propiedad Text.getForms. Sub Dim Dim Dim CuadroCombinado3() oFormulario As Object ocboPaises As Object sDato As String oFormulario = ThisComponent. la perspectiva de una u otra. esto es.form. la primera (negativa) puede ser que se capture un dato no deseado. la segunda (positiva) es que el usuario puede agregar elementos nuevos directamente. para agregar uno al formulario.drawing. selectItemPos.10 Botón de selección (SpinButton) Este control nos permite aumentar o disminuir el valor de otro control (o celda). Puedes usar la activación o desactivación para este control (Enabled) 7.getActiveSheet.ControlShape") 'Cambiamos su tamaño y posicion Call CambiaTam( oBotonSeleccion.Aprendiendo OOo Basic 421 Para agrega y eliminar elementos de este control. Border = 2 .SpinValueMax = 20 .SpinIncrement = 2 End With End Sub 'Color de fondo 'Tipo de borde ( 2 = Plano. Sub BotonSeleccion3() Dim oFormulario As Object Dim ospnEdad As Object oFormulario = ThisComponent.getDrawPage.getForms. Para obtener el valor actual del control.SpinValueMin = 0 .getByName("spnEdad") MsgBox "Valor actual del control = " & ospnEdad. así como ocultarlo. Sub BotonSeleccion2() Dim oFormulario As Object Dim ospnEdad As Object oFormulario = ThisComponent. solo si Border = 2 'Orientación 1 = vertical.add( oBotonSeleccion ) End Sub Las principales propiedades de este control son.Rnd*255) . usamos.Rnd*255. 0 = horizontal 'Si se imprime el control 'Color del símbolo (las flechas) 'Valor mínimo 'Valor máximo 'Incremento De forma predeterminada.Rnd*255.getActiveSheet.Orientation = 1 .getActiveSheet. 1 = 3D ) 'Color del borde.getActiveSheet.Control = oBotonSeleccionModelo 'Lo agregamos al formulario oFormulario. oBotonSeleccionModelo) 'Agregamos la forma a la página de dibujo para que sea visible ThisComponent. . si cambias su orientación (Orientation) a vertical.Rnd*255) .getCurrentController.Printable = True . tienes que cambiar su tamaño.10 Botón de selección (SpinButton) 'Conectamos la forma con el nuevo control oBotonSeleccion.Rnd*255) .getByName( "MiDirectorio" ) ospnEdad = oFormulario.getForms.getByName("spnEdad") With ospnEdad .422 7.BorderColor = RGB(Rnd*255. así como la activación y desactivación (Enabled).getDrawPage.SymbolColor = RGB(Rnd*255.Rnd*255.getCurrentController. recordando que estas dos ultimas propiedades. de forma que quede más alto que ancho. también el envío del foco.getCurrentController. el control se agrega en forma horizontal.getDrawPage.getByName( "MiDirectorio" ) ospnEdad = oFormulario. veras un control totalmente desajustado.spinValue End Sub Este control acepta la vinculación con una celda (ValueBinding).insertByIndex(0. si no. están accesibles desde el modo “vista” del control.BackGroundColor = RGB(Rnd*255. Sub Dim Dim Dim BarraDesplazamiento1() oFormulario As Object oBarraDesplazamiento As Object oBarraDesplazamientoModelo As Object oFormulario = ThisComponent.insertByIndex(0.Name = "sbKm" 'Conectamos la forma con el nuevo control oBarraDesplazamiento. . oBarraDesplazamientoModelo) 'Agregamos la forma a la página de dibujo para que sea visible ThisComponent.getByName( "MiDirectorio" ) 'Creamos una nueva forma de control oBarraDesplazamiento = ThisComponent.getCurrentController.createInstance("com. 10000.getByName("sbKm") With osbKm .sun.ScrollValueMin = 1 . pero se usa para desplazamientos más grandes.getCurrentController.getDrawPage.form.component.getActiveSheet. usamos.Control = oBarraDesplazamientoModelo 'Lo agregamos al formulario oFormulario. 15000 ) 'Creamos una nueva barra de desplazamiento oBarraDesplazamientoModelo = ThisComponent.drawing.sun. 700 ) Call CambiaPos( oBarraDesplazamiento.getActiveSheet.ScrollValueMax = 1000 End With End Sub 'Cambio grande 'Cambio pequeño 'Valor mínimo 'Valor máximo El cambio grande (BlockIncrement) se da cuando presionamos un área libre de la barra de desplazamiento y el cambio pequeño (LineIncrement) cuando presionamos las flechas de los extremos.BlockIncrement = 25 .star. veamos las propiedades particulares de este control.star.createInstance("com.Aprendiendo OOo Basic 423 7.ControlShape") 'Cambiamos su tamaño y posicion Call CambiaTam( oBarraDesplazamiento.getActiveSheet. Para conocer el valor actual de la barra de desplazamiento. para agregar una a nuestro formulario.getCurrentController.getForms.add( oBarraDesplazamiento ) End Sub Sus propiedades son muy similares al botón de selección (SpinButton). usamos el siguiente código.getByName( "MiDirectorio" ) osbKm = oFormulario.getDrawPage.ScrollBar") 'Establecemos su nombre oBarraDesplazamientoModelo.getForms. 3000.getDrawPage. por que tiene una área para de trabajo más grande.11 Barra de desplazamiento (ScrollBar) Este control es muy similar al botón de selección (SpinButton).LineIncrement = 5 . Sub BarraDesplazamiento2() Dim oFormulario As Object Dim osbKm As Object oFormulario = ThisComponent. getDrawPage. así como ocultarlo.12 Otros controles Hasta aquí.add( oNuevoControl ) End Sub Y sus principales propiedades. se tienen que establecer desde el modo “vista” del control. 17000 ) 'Agregamos un nuevo botón gráfico oNuevoControlModelo = ThisComponent.Control = oNuevoControlModelo oFormulario.getCurrentController.sun.getActiveSheet.star. veamos las principales características de cada uno. pero existen otro conjunto de controles que podemos usar y a los cuales tenemos acceso desde la barra de herramientas “Campos de control de formulario”. Sub BotonGrafico2() Dim oFormulario As Object .getByName( "MiDirectorio" ) osbKm = oFormulario.form. 7.createInstance("com. 2000.11 Barra de desplazamiento (ScrollBar) oFormulario = ThisComponent.ControlShape") Call CambiaTam( oNuevoControl.getActiveSheet.sun.drawing.getDrawPage.ImageButton") oNuevoControlModelo.insertByIndex(0.424 Sub BarraDesplazamiento3() Dim oFormulario As Object Dim osbKm As Object 7.star. oNuevoControlModelo) ThisComponent.getCurrentController. como se muestra en la siguiente imagen.1 Botón gráfico (ImageButton) Este control nos permite tener una imagen como fondo de el.ScrollValue End Sub Este control acepta la vinculación con una celda (ValueBinding).getDrawPage. así como la activación y desactivación (Enabled). Estos controles amplían las posibilidades para mostrar y controlar nuestros datos.getForms.getByName( "MiDirectorio" ) oNuevoControl = ThisComponent. 7.createInstance("com. son los controles estándar presentes en los formularios. 5000 ) Call CambiaPos( oNuevoControl. el envío del foco.getByName("sbKm") MsgBox "Valor actual = " & osbKm.getCurrentController.getActiveSheet. Sub Dim Dim Dim BotonGrafico1() oFormulario As Object oNuevoControl As Object oNuevoControlModelo As Object oFormulario = ThisComponent.12.getForms. 5000.Name = "ibFoto" oNuevoControl.component. getCurrentController.getByName("icProductos") With oControl .getByName("ibFoto") With oControl .createInstance("com.jpg") 'La ruta de la imagen a mostrar .getDrawPage.jpg") 'La ruta de la imagen a mostrar . 18000 ) 'Agregamos un nuevo control de imagen oNuevoControlModelo = ThisComponent.add( oNuevoControl ) End Sub Puedes asignarle una imagen de forma dinámica.getDrawPage.ScaleImage = True 'Si se va a escalar la imagen .ImageURL = ConvertToURL("/home/mau/foto.getByName( "MiDirectorio" ) oControl = oFormulario.ScaleImage = True 'Si se va a escalar la imagen .getForms. así como hacerlo invisible o enviarle el foco.component.getCurrentController. si el campo es una imagen.createInstance("com. 2000.ImageURL = ConvertToURL("/home/mau/foto.getDrawPage.Aprendiendo OOo Basic Dim oControl As Object 425 oFormulario = ThisComponent.ControlShape") Call CambiaTam( oNuevoControl.sun.star.Control = oNuevoControlModelo oFormulario. oNuevoControlModelo) ThisComponent.2 Control de imagen (ImageControl) Este control es muy similar al botón gráfico (ImageButton).getActiveSheet.Name = "icProductos" oNuevoControl.12. usamos. es que a este control le puedes asignar el campo de una fuente de datos (DataField).getCurrentController.drawing. la diferencia.insertByIndex(0. Sub ControlImagen2() Dim oFormulario As Object Dim oControl As Object oFormulario = ThisComponent. Para agregar uno al formulario.star.getDrawPage.sun.getActiveSheet.DatabaseImageControl") oNuevoControlModelo.getForms.getByName( "MiDirectorio" ) oControl = oFormulario.getByName( "MiDirectorio" ) oNuevoControl = ThisComponent. 6000.getForms. 7.ScaleMode = 2 'El modo de escalar ( 2 = Ajustar al control) End With End Sub En su modo “vista”. podemos habilitar o deshabilitarlo. 6000 ) Call CambiaPos( oNuevoControl.getActiveSheet.ScaleMode = 2 'El modo de escalar ( 2 = Ajustar al control) .getCurrentController. la mostrará en el control.form.getActiveSheet. Sub Dim Dim Dim ControlImagen1() oFormulario As Object oNuevoControl As Object oNuevoControlModelo As Object oFormulario = ThisComponent. 426 End With End Sub 7. 18000 ) 'Agregamos un nuevo control de selección de archivo oNuevoControlModelo = ThisComponent. puedes enviarle el foco.Control = oNuevoControlModelo oFormulario. tamaño.12 Otros controles En el modo “vista”. deshabilitarlo y hacerlo invisible. para agregar un nuevo control.star.getActiveSheet. etc). usamos. color. Sub Dim Dim Dim SeleccionArchivo1() oFormulario As Object oNuevoControl As Object oNuevoControlModelo As Object oFormulario = ThisComponent.getActiveSheet.sun. de este modo.createInstance("com.getDrawPage.getCurrentController.form.component. puedes usar la mayor parte de las propiedades vistas para los controles que aceptan cadenas (fuente.getByName( "MiDirectorio" ) oNuevoControl = ThisComponent. puedes establecer una ruta por default.getDrawPage.getDrawPage.getForms.3 Selección de archivo (FileSelection) Control que nos permite mostrar el cuadro de dialogo común para seleccionar un archivo. Sub SeleccionArchivo2() Dim oFormulario As Object Dim oControl As Object oFormulario = ThisComponent. oNuevoControlModelo) ThisComponent.getActiveSheet.getForms.ControlShape") Call CambiaTam( oNuevoControl.add( oNuevoControl ) End Sub Al contar con un área de texto.getCurrentController.FileControl") oNuevoControlModelo.DefaultText = "/home/mau" End Sub Para devolver el archivo seleccionado.getCurrentController. no el archivo en si. cuando se abra el dialogo. se abrirá en este directorio.getByName("fcArchivo") oControl.12. solo te devuelve la ruta del archivo. 700 ) Call CambiaPos( oNuevoControl. 2000.drawing. Sub SeleccionArchivo3() Dim oFormulario As Object Dim oControl As Object . se usa su propiedad Text.getByName( "MiDirectorio" ) oControl = oFormulario.insertByIndex(0. 7.sun. 10000.Name = "fcArchivo" oNuevoControl.createInstance("com.star. Sub CampoFecha2() Dim oFormulario As Object Dim oControl As Object oFormulario = ThisComponent.getByName( "MiDirectorio" ) oControl = oFormulario.star.star. 7.getByName( "MiDirectorio" ) oNuevoControl = ThisComponent.Spin = True End With End Sub 'Fecha mínima 'Fecha máxima 'Formato mostrado 'Si es desplegable 'Si muestra el campo giratorio .4 Campo de fecha (DateField) Este control nos permite trabajar con fechas de una forma muy sencilla. oNuevoControlModelo) ThisComponent.getActiveSheet. en formato de fecha pero no deja de ser texto.ControlShape") Call CambiaTam( oNuevoControl.component.getForms. incluso podemos mostrar un calendario para seleccionar fechas.getActiveSheet.drawing. fuente.getDrawPage. ya vistas en otros controles.Control = oNuevoControlModelo oFormulario.sun. Veamos las propiedades particulares de este control. 18000 ) 'Agregamos un nuevo campo de fecha oNuevoControlModelo = ThisComponent. etc). Se agrega de la siguiente manera.DateMax = 20091231 .getForms.Name = "dfNacimiento" oNuevoControl.Text End Sub Puede recibir el foco y hacerse invisible a través del modo “vista”. 2000.sun.getActiveSheet. 5000.createInstance("com.getByName("fcArchivo") MsgBox "Archivo seleccionado: " & oControl.insertByIndex(0.getDrawPage. 700 ) Call CambiaPos( oNuevoControl.add( oNuevoControl ) End Sub Al ser un campo con texto.getCurrentController.DateMin = 19000101 .DateFormat = 0 . tamaño.getCurrentController.Dropdown = True .getByName("dfNacimiento") With oControl .getDrawPage.getCurrentController.form.12.DateField") oNuevoControlModelo.getForms.getCurrentController. Sub Dim Dim Dim CampoFecha1() oFormulario As Object oNuevoControl As Object oNuevoControlModelo As Object oFormulario = ThisComponent.createInstance("com.getActiveSheet.Aprendiendo OOo Basic 427 oFormulario = ThisComponent.getByName( "MiDirectorio" ) oControl = oFormulario.getDrawPage. cuenta con toda las propiedades para manipularlo (color. pero tienes que darle el formato exacto. después el mes y por ultimo el día.428 7. puedes activarlo o desactivarlo (Enabled) y hacerlo invisible."YYYYMMDD") La propiedad para mostrar la flecha desplegable (Dropdown). pero primero va el año. Sub CampoFecha3() Dim oFormulario As Object Dim oControl As Object oFormulario = ThisComponent. si no. En su modo de “vista”.12 Otros controles Observa la forma “sui generis” de establecer los valores de las propiedades para el valor de la fecha mínima (DateMin) y máxima (DateMax) del control.getActiveSheet. te será más conveniente usar una u otra forma. . La propiedad para establecer el formato (DateFormat).getCurrentController. te dará fechas erróneas. pero no implementa la posibilidad de vincularlo a una celda.Date 'Devuelve el contenido del control como texto MsgBox oControl. pero más adelante aprenderemos a hacerlo directamente con código.getByName("dfNacimiento") 'Devuelve la fecha seleccionada como número MsgBox oControl. si las vas a establecer de forma dinámica.Text End Sub Dependiendo del formato que hayas establecido. permite al usuario mostrar un calendario para seleccionar la fecha.DateMax = Format(Now. puedes tomar los siguientes valores enteros: Nombre Estándar (corto) Estándar (corto YY) Estándar (corto YYYY) Estándar (largo) DD/MM/YY MM/DD/YY YY/MM/DD DD/MM/YYYY MM/DD/YYYY YYYY/MM/DD YY-MM-DD YYYY-MM-DD Valor 0 1 2 3 4 5 6 7 8 9 10 11 Ejemplo 20/09/09 20/09/09 20/09/2009 domingo 20 de septiembre de 2009 20/09/09 09/20/09 09/09/20 20/09/2009 09/20/2009 2009/09/20 09-09-20 2009-09-20 Para obtener la fecha actual del control puedes hacerlo de dos maneras. esto será en función de tus necesidades. . Puedes vincularlo a un campo de datos origen (DataField).getByName( "MiDirectorio" ) oControl = oFormulario.getForms.getDrawPage. puedes hacerlo a través de una cadena (string). es un número. oNuevoControlModelo) ThisComponent. el formato solo acepta cuatro valores.getForms.TimeMin = 8300000 . tiene que ser HoraMinutosSegundos.getByName("tfEntrada") With oControl . formato 12 horas sin segundos (3) y formato 12 horas con segundos (4).Spin = True End With End Sub 'La hora mínima 8:30 'La hora máxima 15:00 '24 hr con segundos 'Muestra el control giratorio El formato para la hora mínima (TimeMin) y máxima (TimeMax).drawing.TimeFormat = 1 . formato 24 horas sin segundos (0). Sub CampoHora3() Dim oFormulario As Object Dim oControl As Object oFormulario = ThisComponent.getActiveSheet. 5000.12. Sub CampoHora2() Dim oFormulario As Object Dim oControl As Object oFormulario = ThisComponent. y los segundos debe ser cuatro dígitos. formato 24 horas con segundos (1).getCurrentController.TimeMax = 15000000 .star.5 Campo de hora (TimeField) Este control es muy similar al campo de fecha (DateField) pero para manejar valores de hora.createInstance("com.TimeField") oNuevoControlModelo.getDrawPage.getActiveSheet.getDrawPage.createInstance("com.getByName( "MiDirectorio" ) oNuevoControl = ThisComponent.Name = "tfEntrada" oNuevoControl. 700 ) Call CambiaPos( oNuevoControl.star.sun. veamos como agregar uno nuevo en nuestro formulario. 20000 ) 'Agregamos un nuevo campo de hora oNuevoControlModelo = ThisComponent.component.getActiveSheet.add( oNuevoControl ) End Sub Y sus propiedades particulares.getDrawPage.getDrawPage.getByName( "MiDirectorio" ) .getActiveSheet. Sub Dim Dim Dim CampoHora1() oFormulario As Object oNuevoControl As Object oNuevoControlModelo As Object oFormulario = ThisComponent.sun.getForms. 2000. tienes dos opciones.Aprendiendo OOo Basic 429 7.insertByIndex(0.getCurrentController.getByName( "MiDirectorio" ) oControl = oFormulario.ControlShape") Call CambiaTam( oNuevoControl.getForms.Control = oNuevoControlModelo oFormulario. Para recuperar el valor actual del control.getCurrentController.form.getCurrentController. Control = oNuevoControlModelo oFormulario.component.add( oNuevoControl ) End Sub Recuerda que todos los controles donde se muestre información al usuario.getByName("tfEntrada") 'Devuelve la fecha seleccionada como número MsgBox oControl.ShowThousandsSeparator = True 'El 'El 'El 'Si 'Si valor mínimo valor máximo salto entre valores muestra el control giratorio muestra el separador de miles .ValueMax = 500 . 2000. 7.getActiveSheet. comparten un mínimo de propiedades (color.12.sun.getDrawPage.Text End Sub 7. Las propiedades particulares de este control son: Sub CampoNumerico2() Dim oFormulario As Object Dim oControl As Object oFormulario = ThisComponent.12 Otros controles En su modo de “vista”. etc).createInstance("com.star.ValueMin = 100 . pero no implementa la posibilidad de vincularlo a una celda.getByName("nfPesos") With oControl .ControlShape") Call CambiaTam( oNuevoControl.430 oControl = oFormulario. fuente.NumericField") oNuevoControlModelo. en el siguiente ejemplo agregamos un nuevo control al formulario.getForms.Time 'Devuelve el contenido del control como texto MsgBox oControl.getByName( "MiDirectorio" ) oControl = oFormulario. 5000.getDrawPage.getForms.Name = "nfPesos" oNuevoControl.drawing. 700 ) Call CambiaPos( oNuevoControl.getByName( "MiDirectorio" ) oNuevoControl = ThisComponent.getDrawPage.getActiveSheet.6 Campo numérico (NumericField) Este control permite manejar únicamente números. Sub Dim Dim Dim CampoNumerico1() oFormulario As Object oNuevoControl As Object oNuevoControlModelo As Object oFormulario = ThisComponent.form.getCurrentController.getActiveSheet.ValueStep = 2 .Spin = True . 20000 ) 'Agregamos un nuevo campo numérico oNuevoControlModelo = ThisComponent.insertByIndex(0. Puedes vincularlo a un campo de datos origen (DataField).star.getCurrentController. puedes activarlo o desactivarlo (Enabled) y hacerlo invisible. oNuevoControlModelo) ThisComponent.createInstance("com.getCurrentController.sun. CurrencyField") oNuevoControlModelo.7 Campo moneda (CurrencyField) Este control es casi idéntico al campo numérico (NumericField).form.star. Para agregar un control de este tipo a nuestro formulario.star.DecimalAccuracy = 2 End With End Sub 431 'El número de decimales El separador de miles (ShowThousandsSeparator).getActiveSheet.getDrawPage.add( oNuevoControl ) End Sub Las propiedades particulares de este control son.getForms. usamos el siguiente código.component.createInstance("com.getByName( "MiDirectorio" ) oControl = oFormulario.drawing.getActiveSheet.ControlShape") Call CambiaTam( oNuevoControl.12. Sub CampoNumerico3() Dim oFormulario As Object Dim oControl As Object oFormulario = ThisComponent.getDrawPage.sun. con al diferencia de que puede mostrar un símbolo de moneda en su formato.createInstance("com.insertByIndex(0. será el mismo configurado en la interfaz del OOo. así como con un campo de datos.Aprendiendo OOo Basic .getCurrentController. oNuevoControlModelo) ThisComponent.Value End Sub Este control si acepta la vinculación con una celda.Control = oNuevoControlModelo oFormulario. Sub Dim Dim Dim CampoMoneda1() oFormulario As Object oNuevoControl As Object oNuevoControlModelo As Object oFormulario = ThisComponent.sun.getCurrentController. 2000.getByName("nfPesos") 'Devolvemos el valor del control MsgBox "El valor actual del control es = " & oControl.getActiveSheet.getDrawPage. 700 ) Call CambiaPos( oNuevoControl. 5000. 20000 ) 'Agregamos un nuevo campo moneda oNuevoControlModelo = ThisComponent. 7.Name = "cfIngresos" oNuevoControl.getCurrentController. Sub CampoMoneda2() Dim oFormulario As Object .getForms.getByName( "MiDirectorio" ) oNuevoControl = ThisComponent. 12.star.12 Otros controles oFormulario = ThisComponent.getDrawPage. Sub CampoMoneda3() Dim oFormulario As Object Dim oControl As Object oFormulario = ThisComponent.Value End Sub Este control solo acepta el vinculo con un campo de datos.getDrawPage.getByName( "MiDirectorio" ) oNuevoControl = ThisComponent.form.sun. 2000.PrependCurrencySymbol = True .Spin = True .PatternField") oNuevoControlModelo.drawing.star. para agregar uno a nuestro formulario.getDrawPage.Name = "pfRFC" .ShowThousandsSeparator = True . usamos. 700 ) Call CambiaPos( oNuevoControl.8 Campo enmascarado (PatternField) Este control permite establecer una mascara de entrada para los datos del usuario.ValueMax = 1000 .getActiveSheet. pues permite limitar de forma muy estricta lo que este captura.ControlShape") Call CambiaTam( oNuevoControl.432 Dim oControl As Object 7.DecimalAccuracy = 2 End With End Sub 'El símbolo de moneda 'Muestra el símbolo a la izquierda 'El valor mínimo 'El valor máximo 'El salto entre valores 'Si muestra el control giratorio 'Si muestra el separador de miles 'El número de decimales Para recuperar el valor actual del control usamos.getByName( "MiDirectorio" ) oControl = oFormulario.getActiveSheet.getByName("cfIngresos") With oControl .ValueMin = 0 . 5000.getCurrentController.component.sun. es muy útil en entornos con usuarios con poca experiencia. 20000 ) 'Agregamos un nuevo campo enmascarado oNuevoControlModelo = ThisComponent.getActiveSheet.createInstance("com.ValueStep = 5 .getForms.getForms.getForms.getCurrentController. 7.createInstance("com.getByName( "MiDirectorio" ) oControl = oFormulario.getByName("cfIngresos") 'Devolvemos el valor del control MsgBox "El valor actual del control es = " & oControl. Sub Dim Dim Dim CampoEnmascarado1() oFormulario As Object oNuevoControl As Object oNuevoControlModelo As Object oFormulario = ThisComponent.getCurrentController.CurrencySymbol = "B$" . La mascara de caracteres.Control = oNuevoControlModelo oFormulario. de acuerdo a la siguiente tabla. Se permiten todos los caracteres imprimibles.EditMask = "AAAALNNNNNNLCCC" . 0 a 9. y todos los dígitos. Se permiten letras de la A a la Z. todas se convierten a mayúsculas.getActiveSheet.LiteralMask = "____-______-___" .getByName("pfRFC") With oControl . Solo se permiten los números dígitos.getCurrentController.getDrawPage. Se permiten letras de la A a la Z. mientras no capture nada en las respectivas posiciones.getByName( "MiDirectorio" ) oControl = oFormulario.Aprendiendo OOo Basic 433 oNuevoControl. es esencial que trabajen todas juntas. el cursor pasa al siguiente caracter editable.getDrawPage.getForms. la primera es autodescriptiva pero es muy importante que tenga la longitud exacta de la mascara de entrada (EditMask) y de la mascara de caracteres (LiteralMask).StrictFormat = True End With End Sub 'Longitud máxima del contenido 'Mascara de entrada 'Mascara de caracteres 'Control de formato Estas cuatro propiedades.add( oNuevoControl ) End Sub Este control tiene pocas propiedades particulares. Sub CampoEnmascarado2() Dim oFormulario As Object Dim oControl As Object oFormulario = ThisComponent. oNuevoControlModelo) ThisComponent. es lo que ve el usuario. se respetan mayúsculas y minúsculas. y todos los dígitos. se muestra tal cual. todas las letras pasan a mayúsculas.MaxTextLen = 15 .getActiveSheet. pero son vitales para su correcto funcionamiento. se respetan mayúsculas y minúsculas. En la mascará de entrada (EditMask) determinamos que puede y que no puede capturar el usuario en esa exacta posición del caracter. no puede editarse. Se permiten letras de la A a la Z. Caracter L a A c C N X Restricción El caracter de esta posición. Posición Mascara de entrada Mascara de caracteres 123456789012345 AAAALNNNNNNLCCC ____-______-___ . 0-9. al llegar a esta posición.getCurrentController. Se permiten letras de la A a la Z.insertByIndex(0. 0-9. para que funcione el control de formato (StrictFormat) debe estar en verdadero esta propiedad. 434 7. usamos.Name = "gbEstadoCivil" oNuevoControl.getCurrentController.createInstance("com. oNuevoControlModelo) ThisComponent.component. Sub CuadroGrupo2() Dim oFormulario As Object Dim oControl As Object oFormulario = ThisComponent.form.insertByIndex(0.Text End Sub Este control soporta la vinculación con un campo de datos (DataField).getCurrentController. Sub CampoEnmascarado3() Dim oFormulario As Object Dim oControl As Object oFormulario = ThisComponent.getActiveSheet.12 Otros controles Para regresar el valor capturado. generalmente se usa con grupos de botones de opción (OptionButton) aunque los puedes usar con cualquier otro grupo de controles.Label = "Estado civil" End Sub .getDrawPage. 20000 ) 'Agregamos un nuevo campo enmascarado oNuevoControlModelo = ThisComponent.getActiveSheet. 2000.createInstance("com.Control = oNuevoControlModelo oFormulario.GroupBox") oNuevoControlModelo.getForms.getActiveSheet.ControlShape") Call CambiaTam( oNuevoControl.getForms.star.getByName("gbEstadoCivil") 'Establecemos el titulo del control oControl. Para agregar uno al formulario.getDrawPage.getActiveSheet. 5000.add( oNuevoControl ) End Sub Para establecer el titulo del control usamos.sun.getByName("pfRFC") MsgBox "Valor actual del control: " & oControl.sun.getByName( "MiDirectorio" ) oControl = oFormulario. 7.getDrawPage.12. usamos. Sub Dim Dim Dim CuadroGrupo1() oFormulario As Object oNuevoControl As Object oNuevoControlModelo As Object oFormulario = ThisComponent.getCurrentController. 5000 ) Call CambiaPos( oNuevoControl.drawing.getByName( "MiDirectorio" ) oNuevoControl = ThisComponent.9 Cuadro de grupo (GroupBox) Este control solo es de apoyo visual para enmarcar otros grupos de controles.getDrawPage.getCurrentController.star.getForms.getByName( "MiDirectorio" ) oControl = oFormulario. add( oNuevoControl ) End Sub 7. para agregarla al formulario usamos.createInstance("com.Control = oNuevoControlModelo oFormulario.insertByIndex(0.star.getDrawPage. Sub Dim Dim Dim BarraNavegacion1() oFormulario As Object oNuevoControl As Object oNuevoControlModelo As Object oFormulario = ThisComponent. no podrás enlazarlo por código.Control = oNuevoControlModelo oFormulario.component.getDrawPage. 3000.component.getCurrentController.star. 10000. oNuevoControlModelo) ThisComponent.getCurrentController. para agregar una al formulario.createInstance("com. 1000 ) Call CambiaPos( oNuevoControl. 3000. 10000 ) Call CambiaPos( oNuevoControl.ControlShape") Call CambiaTam( oNuevoControl.drawing.getCurrentController. el formulario previamente debe estar enlazado con los datos origen.sun.createInstance("com.sun. por ahora.10 Control de tablas (TableControl) Este control nos permite mostrar una tabla.getDrawPage.sun. por ahora solo funciona en tiempo de diseño y el asistente de controles debe estar activado.Name = "gcContactos" oNuevoControl. controlar la navegación entre los registros.getActiveSheet.add( oNuevoControl ) .createInstance("com.getActiveSheet.NavigationToolBar") oNuevoControlModelo.getActiveSheet. usamos el siguiente código.ControlShape") Call CambiaTam( oNuevoControl.getForms. 20000. pero. 25000 ) 'Agregamos un nuevo campo enmascarado oNuevoControlModelo = ThisComponent.getCurrentController.Name = "navBarra" oNuevoControl. oNuevoControlModelo) ThisComponent.Aprendiendo OOo Basic 435 7.star.GridControl") oNuevoControlModelo. cuando el formulario esta enlazado a una base de datos.star.12.getByName( "MiDirectorio" ) oNuevoControl = ThisComponent.getByName( "MiDirectorio" ) oNuevoControl = ThisComponent. Sub Dim Dim Dim TablaControl1() oFormulario As Object oNuevoControl As Object oNuevoControlModelo As Object oFormulario = ThisComponent. consulta o instrucción SQL para enlazar bases de datos.drawing.form.getDrawPage.insertByIndex(0.getForms.sun.11 Barra de navegación Este control permite.getActiveSheet. 20000 ) 'Agregamos un nuevo campo enmascarado oNuevoControlModelo = ThisComponent.12.form. Rnd*255) 'Color de texto . editar y borrar registros.Rnd*255. agregar. y trabajo. casi todo el conocimiento adquirido en este capitulo. Sub BarraNavegacion2() Dim oFormulario As Object Dim oControl As Object oFormulario = ThisComponent. Con esto terminamos con el manejo de formularios y sus controles.Rnd*255) 'Color de fondo .BackgroundColor = RGB(Rnd*255. generalmente se muestran los cuatro. también. por supuesto.436 End Sub 7. tu decides que es lo que más te conviene. pero requiere.TextColor = RGB(Rnd*255. .getActiveSheet. en donde aprenderemos el manejo de cuadros de diálogo. hemos visto la forma de agregarlos por código y manipular las principales propiedades de cada uno.Border = 2 'Borde plano .getCurrentController.ShowFilterSort = True 'Muestra los iconos para ordenar y filtrar End With End Sub Si estableces las ultimas cuatro propiedades en falso (False). te permite.ShowRecordActions = True 'Muestra los iconos para manipular registros . Grande = 1 .12 Otros controles Las propiedades particulares de este control son.getByName("navBarra") With oControl .IconSize = 0 'Pequeño = 0.ShowNavigation = True 'Muestra las flechas de navegación .getForms.getDrawPage.getByName( "MiDirectorio" ) oControl = oFormulario.Rnd*255. nos será de mucha utilidad para el siguiente. esto te permite un mayor control de los datos. en ocasiones es útil deshabilitar estos y controlar estas acciones por código.ShowPosition = True 'Muestra la información actual del cursor . el icono para manipular los registros (ShowRecordActions). solo veras un marco sin ninguna utilidad. muchas más líneas de código. Aprendiendo OOo Basic 437 8 Trabajando con cuadros de dialogo . 438 9 Trabajando con eventos 9 Trabajando con eventos Hemos llegado a un tema central en la programación de OOo. tiene que responder a la pregunta ¿cuando?. . ¿cuando queremos que se ejecute una macro?. central por que una gran parte de la programación en OOo. Para establecer el nivel de seguridad de las macros.. por ello. no tomes como un tema menor el de la seguridad. queda a tu criterio establecer el nivel adecuado para tu área y entorno de trabajo. da un clic en el botón de comando Seguridad de macro. dentro de la sección OpenOffice. ve al menú Herramientas | Opciones.. selecciona la rama Seguridad y dentro de las opciones mostradas. es decir.Aprendiendo OOo Basic 439 10 Apéndices 10. el nivel Medio es más que suficiente..1 Seguridad en macros Como ya lo habrás notado.org. El nivel de confianza es bastante explicito y creo que no requiere aclaraciones. asegúrate de que las macros que estás activando y ejecutando sean de una fuente confiable. . para los fines didácticos de estos apuntes. el limite para lo que se puede hacer con macros es solo tu conocimiento y tu imaginación.. Cuidado con esto.440 10. se abrirán los archivos con las macros activadas de forma predeterminada sin pedirte confirmación. puedes agregar tantas rutas como quieras. puedes agregar su ubicación como un origen de confianza. .1 Seguridad en macros Si no quieres que te muestre el cuadro de dialogo de confirmación cada vez que abres tu archivo de trabajo. asegurate de establecer solo rutas de verdadera confianza. en el mismo cuadro de dialogo anterior pero en la ficha Orígenes de Confianza. como dicen en mi pueblo -sobre advertencia no hay engaño-. desde las cuales. tampoco llamarla sin los argumentos correctos: . esta es una lista incompleta de los más comunes. solo te mostrare la imagen del código con el error. para estos ejemplos.2 Errores más comunes en tiempo de diseño Como ya explicamos en el tema 4. espero que los títulos sean lo suficientemente claro para tu consulta: ● No puede haber una macro sin nombre ● Toda macro debe cerrarse con End Sub ● No puede haber dos macro o funciones con el mismo nombre ● No puedes ejecutar directamente una macro que requiera argumentos ● Por supuesto.10.Aprendiendo OOo Basic 441 10. este tipo de errores solo se producen mientras programamos y en ese momento hay que corregirlos. recuerda que también termina en Then ● La estructura Do. te cuidado de establecer siempre la condición de terminación del bucle.2 Errores más comunes en tiempo de diseño Si usas Option Explicit (como “debe” ser). sino ● ● Todas las estructuras deben ir completas. aquí falta Then al If ● Por supuesto también debe llevar su correspondiente End If ● Si usas ElseIf. tienes que declara todas tus variables. si no lo haces no te dará un error y puedes quedar dentro de un bucle infinito . siempre debe cerrarse con Loop.442 10. deben estar completa.Aprendiendo OOo Basic 443 ● La estructura Select debe terminar en Case ● Y no te olvides de establecer la variable a evaluar ● Y cerrar con su respectivo End Select ● Los ciclos For. con su correspondiente To ● Y su respectivo Next ● Se requiere el uso de Dim para declarar variables . sobrepasar los limites que acepta un tipo de dato ● Debes de declarar las correspondientes etiquetas en On Error Goto y Goto ● La macro o función llamada debe existir . es decir. tienes que establecer correctamente el tipo de información que guardas en estas variables ● Este es muy común.444 10.2 Errores más comunes en tiempo de diseño ● Algunos datos no soportan la conversión de datos implícita. definir dos vece la misma variable ● No puedes dividir por cero Debes de usar la instrucción Exit. Do. con su correspondiente predicado Sub. For o Function y dentro de la estructura correspondiente correcta ● ● Otra muy común. dentro de la misma macro. todas las instrucciones y funciones de OOo Basic.Aprendiendo OOo Basic ● 445 No puedes hacer referencia al indice de una matriz fuera de sus rangos declarados ● No puedes. tienes que llamarlas con sus correctos argumentos . openoffice.org http://download. no necesitas derechos de administrador: .org/3. Para instalar sigue leyendo: Desde una terminal ve hasta la ubicación donde descargaste el archivo anterior y ejecutalo.html Tienes que seleccionar el archivo correcto para tu sistema operativo.1.0/sdk.446 10.3 Instalando SDK 10. en nuestro caso usaremos la versión para Linux.3 Instalando SDK Lo primero que necesitamos es descargarlo desde la página de OpenOffice. etc). Muévete hasta el directorio recién creado y veras una carpeta que se llama DEBS (o RPMS seǵun el que hayas descargado). así que dale una ruta sencilla o donde te sea cómodo encontrarlo.1-sdk_3. de lo contrario te dirá que ya existe y no te descompactara el archivo.deb O desde una interfaz gráfica si tu distribución la implementa: Ahora puedes abrir tu navegador favorito y abrir el archivo . dentro de ella el archivo ooobasis3. que sabes.rpm Si tienes una distribución que use DEBs (Ubuntu. etc). OpenSuse. puedes instalar desde la línea de comandos: sudo dpkg -i ooobasis3.0-11_amd64.1.0-11_amd64. tienes que darle un directorio nuevo.1-sdk_3.0-11_amd64. lo instalas con: rpm -i ooobasis3. si tienes una distribución que soporte RMPs (Fedora. esto es solo para descomprimir el archivo.1.1-sdk_3. Debian.1.Aprendiendo OOo Basic 447 Como notaras te pide un directorio.deb. es un archivo para instalar. co1+1 ).DBG_Properties.0.DBG_Methods.3 Instalando SDK file:///opt/openoffice/basis3. 0 ).getCellByPosition( 1. entre otras herramientas y ejemplos. a2() As String co1 As Integer.org 10. sTmp As String sRuta = "private:factory/scalc" oDoc = StarDesktop.Sheets().4 Mostrar información de un objeto en un archivo de Calc Sub Dim Dim Dim Dim Dim ObtenerDatos( Objeto As Object ) sRuta As String oDoc As Object mArg() a1() As String.Sheets(). tendrás la referencia completa del API de OpenOffice.Sheets().getCellByPosition( 0. ":" ) a2 = Split( Trim(a1(1)). ":" ) a2 = Split( Trim(a1(1)).getByIndex(0). Len(sTmp)-1 ) oDoc." ) oDoc.setString( a1(0) ) For co1 = LBound( a2 ) To UBound( a2 ) sTmp = Trim(a2(co1)) If Left( sTmp. "."_default". 1) = Chr(10) Then sTmp = Right( sTmp.getCellByPosition( 0. 0 ).1/sdk/index. Len(sTmp)-1 ) oDoc.getByIndex(0).setString( sTmp ) Next co1 If Right( sTmp.setString( a1(0) ) .LoadComponentFromURL( sRuta. co1 ). ".Sheets().setString( sTmp ) a1 = Split( Objeto.getByIndex(0).getByIndex(0).html Donde.getCellByPosition( 0. 1) = Chr(10) Then sTmp = Left( sTmp.448 10." ) oDoc.mArg ) a1 = Split( Objeto. co1 ).sheet.getRandbetween com.Analysis.addin.getByIndex(0).Sheets(). 0 ).addin.5 Formulas de Calc español-ingles Nº 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Español ABS ACOS ACOSH ACOT ACOTH ACTUAL AHORA ALEATORIO ALEATORIO.setString( sTmp ) Next co1 End Sub Asegurate de pasarle como parámetro una variable de objeto. 1) = Chr(10) Then sTmp = Right( sTmp.sheet.sun. si el objeto no implementa métodos.DateFunctions.addin.sheet.getCellByPosition( 1. co1+1 ).getCellByPosition( 2.DBG_SupportedInterfaces.star.sheet.LIN AMORTIZ.Analysis.setString( sTmp ) Next co1 If Right( sTmp.setString( sTmp ) a1 = Split( Objeto. Chr(10) ) oDoc.sun.getCellByPosition( 2.PROGRE AMORTIZACION AÑO AÑOS ÁRABE ÁREAS ASC ASENO Ingles ABS ACOS ACOSH ACOT ACOTH CURRENT NOW RAND com.ENTRE AMORTIZ.addin. co1 ).getAmordegrc PPMT YEAR com. Len(sTmp)-1 ) oDoc. Sub Pruebas Dim obj As Object obj = ThisComponent Call ObtenerDatos ( obj ) End Sub 10.getByIndex(0).star. 1) = Chr(10) Then sTmp = Left( sTmp.Sheets().getCellByPosition( 1.star.setString( a1(0) ) For co1 = LBound( a2 ) To UBound( a2 ) sTmp = Trim(a2(co1)) If Left( sTmp.getAmorlinc com.Sheets(). Len(sTmp)-1 ) oDoc. Len(sTmp)-1 ) oDoc.getByIndex(0).star. pero te creará el archivo con al menos las propiedades que implementa.Aprendiendo OOo Basic 449 For co1 = LBound( a2 ) To UBound( a2 ) sTmp = Trim(a2(co1)) If Left( sTmp. ":" ) a2 = Split( Trim(a1(1)).getDiffYears ARABIC AREAS ASC ASIN .sun.Sheets(). 1) = Chr(10) Then sTmp = Right( sTmp.sun. la macro te dará un error y se detendrá.Analysis.getByIndex(0). sheet.star.getConvert EUROCONVERT .Analysis.star.sun.Analysis.getBin2Oct CRITBINOM LOOKUP HLOOKUP VLOOKUP com.sheet.star.sheet.star.CORREL COEFICIENTE.Analysis.HEX BIN.Analysis.sun.sun.Analysis.star.addin.EURO Ingles ASINH ATAN ATAN2 ATANH B BAHTTEXT BASE DCOUNT DCOUNTA DSTDEV DSTDEVP DGET DMAX DMIN DPRODUCT DAVERAGE DSUM DVAR DVARP com.sheet.getBesselk com.sun.OCT BINOM.DE.Analysis.addin.sun.addin.DEC BIN.Analysis.star.star.getBesseli com.star.sheet.ASIMETRIA COEFICIENTE.star.Analysis.sheet.R2 COINCIDIR COLUMNA COLUMNAS COMBINAR COMBINAR2 COMPACTAR COMPLEJO CONCATENAR CONTAR CONTAR.sun.addin.sun.sheet.star.addin.getReceived CHAR CELL CHISQDIST CHISQINV com.star.addin.CRIT BUSCAR BUSCARH BUSCARV CANTIDAD.Analysis.A.sun.Analysis.sun.sheet.sheet.addin.SI CONTARA CONVERTIR CONVERTIR_ADD CONVERTIR.getBin2Hex com.addin.sun.getBin2Dec com.addin.A.450 10.5 Formulas de Calc español-ingles Nº 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 Español ASENOH ATAN ATAN2 ATANH B BAHTTEXT BASE BDCONTAR BDCONTARA BDDESVEST BDDESVESTP BDEXTRAER BDMAX BDMIN BDPRODUCTO BDPROMEDIO BDSUMA BDVAR BDVARP BESSELI BESSELJ BESSELK BESSELY BIN.getQuotient CODE CORREL SKEW RSQ MATCH COLUMN COLUMNS COMBIN COMBINA TRIM com.sheet.addin.getComplex CONCATENATE COUNT COUNTBLANK COUNTIF COUNTA CONVERT com.getBessely com.addin.Analysis.getBesselj com.sun.RECIBIDA CARÁCTER CELDA CHISQDIST CHISQINV COCIENTE CÓDIGO COEF.BLANCO CONTAR.A.sheet. DIAS.Analysis.FECHA.addin.BIN DEC.EXP DISTR.DIAS CUPON.F.Analysis.F DISTR.star.star.star.addin.getDaysInMonth ADDRESS WEIBULL BETADIST BETAINV BINOMDIST EXPONDIST FDIST FINV GAMMADIST GAMMAINV HYPGEOMDIST CHIDIST LOGNORMDIST NORMDIST NORMSDIST NORMSINV NORMINV .NORM DISTR.sun.addin.OCT DECIMAL DELTA DERECHA DESREF DESVEST DESVESTA DESVESTP DESVESTPA DESVIA2 DESVPROM DÍA DIA.getNetworkdays DAYS360 WEEKDAY com.sun.JI DISTR.LOG.star.sheet.L1 CUPON.sheet.INV Ingles COS COSH COT COTH COVAR GROWTH QUARTILE com.LAB DÍAS DIAS.INV DISTR.getWorkday DAYS com.NORM.addin.addin.sheet.BETA DISTR.NORM DISTR.getDec2Oct DECIMAL com.INV DISTR.getDec2Bin com.addin.Analysis.sun.sun.Analysis.sheet.NORM.DateFunctions.Analysis.HEX DEC.sun.sheet.A.star.Analysis.Analysis.NUM CURTOSIS DB DDB DDE DEC.L2 CUPON.LAB DÍAS360 DÍASEM DÍASENAÑO DÍASENMES DIRECCIÓN DIST.BETA.getCoupdays com.star.Analysis.BINOM DISTR.A.WEIBULL DISTR.Analysis.star.L2 CUPON.getDec2Hex com.sheet.star.getCoupnum KURT DB DDB DDE com.addin.sheet.star.sheet.getCoupdaysnc com.Analysis.INV DISTR.sheet.sheet.sun.INV DISTR.getDaysInYear com.sun.addin.star.DateFunctions.Analysis.sun.addin.DIAS.sun.sun.getCouppcd com.NORM.sheet.A.ESTAND DISTR.addin.addin.addin.Aprendiendo OOo Basic 451 Nº 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 Español COS COSH COT COTH COVAR CRECIMIENTO CUARTIL CUPON.sun.Analysis.sun.getDelta RIGHT OFFSET STDEV STDEVA STDEVP STDEVPA DEVSQ AVEDEV DAY com.addin.getCoupdaybs com.star.star.star.GAMMA DISTR.star.ESTAND.sheet.L1 CUPON.sun.getCoupncd com.sun.HIPERGEOM DISTR.addin.sheet.GAMMA.FECHA.sheet. sun.sun.BIN HEX.Analysis.star.star.sheet.star.sheet.sheet.sun.sheet.sheet.LINEAL ESTIMACIÓN.addin.Analysis.star.addin.sheet.addin.star.getEomonth FISHER FORMULA com.sheet.getFactdouble FALSE DATE com.getHex2Oct .A.star.star.sheet.LOGARÍTMICA EXP EXTRAE FACT FACT.star.A.sheet.Analysis.ERROR.star.addin.IMPAR_ADD ESAÑOBISIESTO ESBLANCO ESERR ESERROR ESFÓRMULA ESIMPAR ESLOGICO ESNOD ESNOTEXTO ESNÚMERO ESPAR ESPAR_ADD ESREF ESTEXTO ESTILO ESTIMACIÓN.sun.Analysis.sun.sheet.addin.LN GAUSS GETPIVOTDATA GRADOS HALLAR HEX.Analysis.sheet.addin.5 Formulas de Calc español-ingles Nº 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 Español DISTR.getIsodd com.addin.sheet.getDuration com.sun.INV DOMINGOPASCUA DURACION_ADD DURACION.sun.addin.A.Analysis.MES FISHER FORMULA FRAC.DEC HEX.Analysis.sun.DateFunctions.OCT Ingles TDIST TINV EASTERSUNDAY com.sun.Analysis.MES FECHANÚMERO FIJO FILA FILAS FIN.T.Analysis.getHex2Dec com.ERROR FUN.getMduration VDB CHOOSE FIND INT STEYX com.star.star.getErf com.DOBLE FALSO FECHA FECHA.AÑO FRECUENCIA FUN.Analysis.XY ES.Analysis.COMPL GAMMA GAMMA.sun.sheet.Analysis.sun.addin.sun.star.star.getYearfrac FREQUENCY com.addin.Analysis.getErfc GAMMA GAMMALN GAUSS GETPIVOTDATA DEGREES SEARCH com.sheet.getHex2Bin com.getIsLeapYear ISBLANK ISERR ISERROR ISFORMULA ISODD ISLOGICAL ISNA ISNONTEXT ISNUMBER ISEVEN com.sun.T DISTR.addin.452 10.star.TÍPICO.addin.sun.getIseven ISREF ISTEXT STYLE LINEST LOGEST EXP MID FACT com.addin.getEdate DATEVALUE FIXED ROW ROWS com.addin.MODIF DVS ELEGIR ENCONTRAR ENTERO ERROR. ESIMO.sun.sheet.ACUM.SENO IM.addin.addin.star.Analysis.M_ADD MÁX MÁXA Ingles HYPERLINK SHEET SHEETS HOUR TIMEVALUE TODAY EXACT com.M M.EXP IM.getImconjugate com.Analysis.sun.C.star.LOG2 IM.SUSTR IMAGINARIO ÍNDICE INDIRECTO INFO INT.sheet.LN IM.1 LOG10 GCD com.EJE INTERVALO.Analysis.getImreal com.MENOR LARGO LETRA.sun.sheet.sheet.getTbilleq com.sheet.getAccrint com.sun.REAL IM.addin.A.addin.LOG IZQUIERDA JERARQUÍA JIS K.star.getImsqrt com.Analysis.star.star.addin.addin.Analysis.sheet.sun.addin.sun.RENDIMIENTO INTERSECCIÓN.MAYOR K.star.RENDTO LIMPIAR LN LOG LOG10 M.sheet.EFECTIVO_ADD INT.SUM IM.DE.star.addin.Analysis.Analysis.sun.sheet.Analysis.sheet.Analysis.sheet.Analysis.Analysis.TES.PRODUCT IM.star.D_ADD M.addin.EQV.sun.sheet.getAccrintm EFFECTIVE com.ESIMO.star.PAGO.Analysis.sun.addin.getImsum com.star.star.Analysis.Analysis.DIV IM.DE.addin.Analysis.Analysis.C.sheet.sheet.CONJUGADA IM.ACUM INT.addin.sheet.TES.sheet.addin.star.addin.addin.BONO LETRA.CONFIANZA INV.sun.sheet.addin.COS IM.getImlog10 com.addin.PRECIO LETRA.sun.getImproduct com.addin.sheet.sun.C.getTbillprice com.addin.POT IM.getImsub com.Analysis.sheet.sun.getImexp com.sheet.Analysis.sun.star.addin.sun.sun.sheet.DIR INT.Analysis.star.star.sun.Analysis.D M.star.Analysis.Analysis.addin.Analysis.sheet.getImargument com.sheet.getImcos com.TES.addin.sun.sun.getImln com.sun.addin.getGcd LCM com.EFECTIVO INT.sun.star.addin.sun.getLcm MAX MAXA .DE.sun.sheet.sun.getImabs com.ABS IM.getImdiv com.RAIZ2 IM.star.getEffect ISPMT ZGZ INTERCEPT CONFIDENCE LOGINV LEFT RANK JIS LARGE SMALL LEN com.V INT.star.star.addin.sheet.Aprendiendo OOo Basic 453 Nº 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 Español HIPERVÍNCULO HOJA HOJAS HORA HORANÚMERO HOY IGUAL IM.LOG10 IM.star.Analysis.getImsin com.getImlog2 com.ANGULO IM.star.Analysis.star.getImaginary INDEX INDIRECT INFO com.sheet.C.star.star.getImpower com.sun.getTbillyield CLEAN LN LOG(. getCumipmt CUMPRINC com.Analysis.Analysis.getDiffMonths MIN MINA LOWER MINUTE MINVERSE MIRR MMULT MODE DOLLAR com.getOct2Dec com.addin.sheet.star.sun.O.star.addin.ENTRE PAGO.addin.getPricedisc .IGUAL MAYÚSC MDETERM MEDIA.sun.ENTRE_ADD PAGO.star.Analysis.INT.sheet.getOct2Bin com.Analysis.getPrice com.sheet.star.addin.getGestep UPPER MDETERM TRIMMEAN HARMEAN GEOMEAN MEDIAN MONTH com.ARMO MEDIA.SUPERIOR MUNITARIA N NEGBINOMDIST NO NOD NOMPROPIO NORMALIZACIÓN NPER NSHORA NUM.getWeeknum OR com.DEC OCT.addin.sun.sheet.getDollarde com.sun.sun.PRINC.getCumprinc IPMT PEARSON SLOPE PERCENTILE PERMUT PERMUTATIONA PHI PI DURATION POISSON POWER com.addin.HEX PAGO PAGO.sun.sheet.Analysis.star.sheet.sun.sun.454 10.star.addin.star.addin.star.DESCUENTO Ingles com.Analysis.GEOM MEDIANA MES MESES MÍN MÍNA MINUSC MINUTO MINVERSA MIRR MMULT MODA MONEDA MONEDA.DEC MONEDA.star.sun.addin.getOct2Hex PMT CUMIPMT com.sun.PRINC.Analysis.ACOTADA MEDIA.sheet.Analysis.getMultinomial FLOOR CEILING MUNIT N NEGBINOMDIST NOT NA PROPER STANDARDIZE NPER TIME com.DateFunctions.star.BIN OCT.A.sheet.star.DE.SEMANA_ADD O OCT.INFERIOR MÚLTIPLO.addin.addin.FRAC MULTINOMIAL MÚLTIPLO.sheet.sun.addin.addin.star.5 Formulas de Calc español-ingles Nº 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 Español MAYOR.A.Analysis.sheet.getDollarfr com.sheet.sun.Analysis.sheet.Analysis.ENTRE PAGO.A.star.sheet.sun.Analysis.ENTRE_ADD PAGOINT PEARSON PENDIENTE PERCENTIL PERMUTACIONES PERMUTACIONESA PHI PI PLAZO POISSON POTENCIA PRECIO PRECIO.INT. sun.getSqrtpi PERCENTRANK com.PER.star.DateFunctions.DESC RENDTO.sheet.PAR REDONDEAR REDONDEAR.Analysis.JI PRUEBA.IRREGULAR.getOddfprice com.2 PRECIO.sun.PER.addin.SERIES SUMAR.getYielddisc com.sheet.Aprendiendo OOo Basic 455 Nº 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 Español PRECIO.star.JI.addin.DateFunctions.getOddlyield com.Analysis.addin.VENCIMIENTO PROBABILIDAD PRODUCTO PROMEDIO PROMEDIOA PRONÓSTICO PRUEBA.star.sun.star.addin.1 PRECIO.sun.sheet.star.addin.getYield com.sun.star.star.F PRUEBA.INV PRUEBA.SI SUMAX2MASY2 SUMAX2MENOSY2 SUMAXMENOSY2 SUSTITUIR SYD T Ingles com.DateFunctions.Analysis.sun.sheet.addin.sheet.star.Z RADIANES RAÍZ RAIZ2PI RANGO.getYieldmat REPT MOD ROMAN com.sun.sun.star.Analysis.Analysis.DEL.sun.Analysis.getPricemat PROB PRODUCT AVERAGE AVERAGEA FORECAST FTEST FISHERINV CHITEST CHIINV TTEST ZTEST RADIANS SQRT com.AÑO SEMANAS SEMANASENAÑO SENO SENOH SI SIGNO SLN SUBTOTALES SUMA SUMA.MULT REDONDEA.sheet.addin.PER.getOddlprice com.sun.star.addin.addin.MAS REDONDEAR.1 RENDTO.VENCTO REPETIR RESIDUO ROMANO ROT13 SEGUNDO SEM.sun.T PRUEBA.getMround ODD EVEN ROUND ROUNDUP ROUNDDOWN REPLACE com.CUADRADOS SUMA.IRREGULAR.addin.sun.PRODUCTO SUMA.getSeriessum SUMIF SUMX2PY2 SUMX2MY2 SUMXMY2 SUBSTITUTE SYD T .sun.sheet.Analysis.Analysis.PERCENTIL REDOND.MENOS REEMPLAZAR RENDTO RENDTO.sheet.PER.star.sheet.sheet.sheet.addin.sheet.star.getDiffWeeks com.getWeeksInYear SIN SINH IF SIGN SLN SUBTOTAL SUM SUMSQ SUMPRODUCT com.addin.getOddfyield com.IMPAR REDONDEA.INV PRUEBA.star.star.sheet.IRREGULAR.FISHER.Analysis.addin.2 RENDTO.sheet.Analysis.Analysis.addin.sun.getRot13 SECOND WEEKNUM com.IRREGULAR. sheet.table.addin.sun.addin.sheet.star. en el original se muestran los nombres de las fuentes en un cuadro de mensaje. con unos pequeños cambios las mostramos en un archivo nuevo de Calc.getIntrate NOMINAL com.6 Listar fuentes en un archivo de Calc La siguientes macros están basadas en la que muestra Andrew Pitonyak en su excelente libro de macros (ve la bibliografía).sheet.star.Analysis.PER Y Ingles TAN TANH RATE com.addin.star.PLAN VNA VNA.sun.beans.NOMINAL TASA.Analysis.getXirr TRANSPOSE TRUNC PV VALUE VAR VARA VARP VARPA TRUE FV com.star. esta primera te muestra el nombre de la fuente junto con los estilos o variantes que soporta.sun.sun. 'Original de Andrew Pitonyak 'Estas versiones Mauricio Baeza Sub ListarFuentes1() Dim oToolkit As Object Dim oDevice As Object Dim oFontDescriptors As Object Dim co1 As Long Dim mArg() Dim oNuevoDocumento As Object Dim Campos(0) As New com.getNominal TREND TEXT TYPE ERRORTYPE IRR com.PropertyValue .Analysis.5 Formulas de Calc español-ingles Nº 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 Español TAN TANH TASA TASA.Analysis.sheet.sun.star.DE.getXnpv AND 10.sun.PER TRANSPONER TRUNCAR VA VALOR VAR VARA VARP VARPA VERDADERO VF VF.getFvschedule NPV com.ERROR TIR TIR.sun.addin.getDisc com.NO.addin.Analysis.sheet.Analysis.456 10.INT TASA.star.addin. Las dos son muy parecidas.sheet.TableSortField Dim aSD(0) As New com.star.star.NOMINAL_ADD TENDENCIA TEXTO TIPO TIPO.NO.DESC TASA.sun. getCellByPosition(0.setString( "Fuente" ) For co1 = LBound(oFontDescriptors) To UBound(oFontDescriptors) .collapseToCurrentRegion() .getCellByPosition(0.getCellByPosition(2. averiguamos cuantas filas quedaron oCursor = .removeByIndex(0.0).getColumns().1) 'Como filtramos.ContainsHeader = True oFD.setString( oFontDescriptors(co1).Field = 0 Campos(0).CopyOutputData = True oFD. Sub Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim ListarFuentes2() oToolkit As Object oDevice As Object oFontDescriptors As Object co1 As Long mArg() oNuevoDocumento As Object oFD As Object oCursor As Object Campos(0) As New com.co1+1).getCellByPosition(1.getCellByPosition(0.setString( "Nº" ) .TableSortField aSD(0) As New com.createCursorByRange( .awt.star.getByIndex(0) . excepto que solo te muestra el nombre de la fuente.0).star. mArg() ) With oNuevoDocumento.0) ) oCursor.loadComponentFromURL( "private:factory/scalc".setString( "Fuente" ) For co1 = LBound(oFontDescriptors) To UBound(oFontDescriptors) .sun.Toolkit") oDevice = oToolkit. "_default".PropertyValue oToolkit = CreateUnoService("com.FontDescriptors() oNuevoDocumento = StarDesktop. sin variantes.getByIndex(0) .0). 0) oFontDescriptors = oDevice.getCellRangeByName( "A1:A" & CStr(co1+1) ).loadComponentFromURL( "private:factory/scalc".createScreenCompatibleDevice(0.getCellRangeByName( "B1:B" & CStr(co1+1) ).star.Value = Campos() .getCellByPosition(1.IsAscending = True aSD(0).getCellByPosition(0.getCellRangeByName( "A1:A" & CStr(co1+1) ).SkipDuplicates = True oFD. columna A .0).star.OutputPosition = .sun.sun.filter( oFD ) 'Eliminamos los datos originales. etc).awt.FontDescriptors() oNuevoDocumento = StarDesktop. "_default".co1+1). mArg() ) With oNuevoDocumento. 0) oFontDescriptors = oDevice.StyleName ) Next Campos(0).getSheets().createFilterDescriptor( True ) oFD.table.Name & " " & oFontDescriptors(co1).getSheets().sort( aSD() ) .setString( oFontDescriptors(co1).sun. cursiva.getCellAddress() .getCellByPosition(1.OptimalWidth = True End With End Sub La segunda es similar.Toolkit") oDevice = oToolkit.beans. 0.Name = "SortFields" aSD(0).co1+1).setValue( co1+1 ) .Aprendiendo OOo Basic 457 oToolkit = CreateUnoService("com.getCellRangeByName("A1:B1"). 0.Name ) Next 'Con un filtro obtenemos registros unicos en la columna C oFD = .getColumns().createScreenCompatibleDevice(0. esto es por que la mayoría de estas variantes las establecemos por código con otros métodos y propiedades (negrita. lang.getCellRangeByName("A1:B1").getCellRangeByName( "B1:B" & CStr(oCursor.Name = "SortFields" aSD(0).fillAuto( 0.getCount) ).OptimalWidth = True End With End Sub 10.getNumberFormats() 'Obtenemos todas las claves de los formatos mClaves = oFormatos.getCount) ). 0.getCellByPosition( 0. Esta macro puede tener dos pequeñas mejoras que te quedan de tarea. en la columna de ejemplos.0).getSheets(). podrás ver en la columna E un ejemplo de cada formato. pero podrías implementar la copia de estos formatos para que se vea el resultado. "_default".IsAscending = True aSD(0).co1 ).False ) For co1 = LBound( mClaves ) To UBound( mClaves ) 'Obtenemos cada formato oFormato = oFormatos.sort( aSD ) 'Insertamos la numeracion de las fuentes .getByIndex(0) 'Obtenemos los formatos del documento pasado oFormatos = Documento.getCellByPosition(0. pues el nuevo documento no tiene estos formato.queryKeys( 0. mArg() ) With oNuevoDocumento. excepto los de la categoría Definidas por el usuario.Value = Campos() . puedes discriminar los documentos para que solo soporte los que tengan el método getNumberFormats y segundo. primero. si le pasas un documento nuevo.getCellRangeByName("A2:A" & CStr(oCursor. esto es normal.getRows.6 Listar fuentes en un archivo de Calc 'Ordenamos los nombres de las fuentes Campos(0).Type Case 2 : sTipo = "Fecha" Case 4 : sTipo = "Tiempo" Case 6 : sTipo = "Fecha Tiempo" Case 8 : sTipo = "Moneda" .getCellByPosition(0.458 10.7 Listar formatos en un archivo de Calc Solo tienes que pasarle la referencia al documento del cual te interese ver sus propiedades.getRows.setValue( 1 ) .1). 1 ) 'Autoajustamos el ancho de las columnas .Field = 0 Campos(0).star. mArg() Dim oFormato As Object Dim co1 As Integer Dim aLocal As New com.loadComponentFromURL( "private:factory/scalc". si le pasas alguno de tus documento. incluirá todos tus formato personalizados.Locale Dim oNuevoDocumento As Object Dim sTipo As String 'Para escribir los formatos en un nuevo documento de Calc oNuevoDocumento = StarDesktop. siempre te devolverá los mismos formatos.setString( "Nº" ) . 'Basada en el original de Andrew Pitonyak 'Esta versión Mauricio Baeza Sub Todos_Los_Formatos(Documento As Object) Dim oFormatos As Object Dim mClaves.getByKey( mClaves(co1) ) 'Numero secuencial .sun.setValue( co1+1 ) 'Definimos la categoria del formato Select Case oFormato.getColumns.aLocal. OptimalWidth = True Next End With End Sub .Aprendiendo OOo Basic 459 Case 16 : sTipo = "Numero" Case 32 : sTipo = "Cientifico" Case 64 : sTipo = "Fraccion" Case 128 : sTipo = "Porcentaje" Case 256 : sTipo = "Texto" Case 1024 : sTipo = "Logica" Case 2048 : sTipo = "Indefinida" Case Else : sTipo = "Definido por el usuario" End Select .co1 ).setValue( co1+100+(Rnd*1000) ) 'Le establecemos el formato correspondiente .getCellRangeByName( "A1:E1" ).co1 ).setString( oFormato.getCellByPosition( 4.FormatString ) 'y su clave correspondiente .getCellByPosition( 4.NumberFormat = mClaves(co1) 'Ajustamos el ancho de las columnas .co1 ).setString( sTipo ) 'Escribimos la cadena del formato .getCellByPosition( 3.co1 ).getColumns.getCellByPosition( 2.getCellByPosition( 1.setValue( mClaves(co1) ) 'Escribimos un numero aleatorio entre 100 y 1000 .co1 ). La Guía de programación de StarOffice 8 para BASIC.sun.ooomacros. esperemos pronto tenerlo de vuelta. cuidado. www. eso si.org.com. es la falta de documentación es español.460 11 Bibliografía 11 Bibliografía Una de las motivaciones de este libro. es solo un conjunto bastante grande de ejemplos.org El libro de Andrew Pitonyak si bien no es para novatos ya es todo un clásico en la red.com/app/docs/doc/819-0439 . este libro le debe mucho a sus ejemplos: www.org/oo. es esencial para introducirte en la programación con OOo Basic: http://docs. no es un libro que pueda tomarse como guia para aprender desde cero.ar/ooo NOTA: al día de hoy 02-Sep-09.org/en/forum/viewforum.pitonyak. en su página encontraras interesantes ejemplos de código en OOo Basic.sun.openoffice.com/app/docs/doc/819-1327?l=es En ingles: En los foros de ayuda de OpenOffice. son realmente escasos los sitios que tratan la programación con OOo Basic en nuestro idioma. siempre dispuesto a ayudar en las listas de correo.php StarOffice 8 Programming Guide for BASIC http://docs.arielconstenlahaile.php?f=20 Un sitio con muchas macros de todos los niveles y sabores: www. pero serán incomprensibles si no tienes las bases elementales. En español: Ariel Constela es un excelente compañero. se publica mucho código interesante y siempre hay gente dispuesta a ayudarte: http://user.services. muy buenos. el sitio esta desactivado. .........12 I Standard......................................................................9 M módulos....................................................9 IDE...................................Aprendiendo OOo Basic 461 12 Índice Alfabético B bibliotecas..................................................................10 S ........
Copyright © 2024 DOKUMEN.SITE Inc.