introducción

a

openOffice.org basic

por

Noelson Alves Duarte

Índice

1 Macros OpenOffice.org Basic	5

1.1 Introducción	5

1.2 Creando la Primera Macro	5

1.3 Ejecutando la Primera Macro	7

1.4 Compartiendo una Macro	9

2Diálogos Personalizados	11

2.1 Introducción	11

2.2 Creando un Cuadro de Diálogo	11

2.3 Manejando Eventos del Cuadro de Diálogo	14

3 Pilotos Automáticos	17

3.1 Introducción	17

3.2 Creando un Piloto Automático	17

3.3 Manipulando Eventos del Piloto Automático	19

4 Introducción al API de OpenOffice.org	21

4.1 Introducción	21

4.2 Creando un nuevo documento	23

5 Trabajando con Documentos	25

5.1 Cargando Documentos	25

5.2 Guardando Documentos	27

5.3 Imprimiendo Documentos	28

5.4 Cerrando Documentos	30

5.5 Identificando los Documentos Abiertos	31

6 Documentos de Writer	33

6.1 Introducción	33

6.2 Editando texto	33

6.3 Moviéndose por el texto	34

6.4 Formateando texto	38

6.5 Formateando con estilo	40

6.6 Obteniendo el objeto seleccionado	44

6.7 Localizando objetos	46

6.8 Búsqueda y Reemplazo	47

6.9 Insertando objetos	49

6.10 Tablas	50

7 Documentos de Calc	57

7.1 Introducción	57

7.2 Hojas de cálculo	57

7.3 Editando	59

7.4 Navegando por las Celdas	61

7.5 Obteniendo objetos seleccionados	63

7.6 Formateando	64

7.7 Búsqueda y Reemplazo	70

7.8 Ordenando	71

7.9 Filtrando dados	73

7.10 Insertando Subtotales	74

7.11 Gráficos	76

8 Más información	81

8.1 En la red	81

8.2 Con el autor	82

9 Créditos, Agradecimientos, Licencia	83

9.1 Créditos	83

9.2 Agradecimientos	83

9.3 Licencia	83

Presentación

Este documento es el resultado de mi esfuerzo por aprender OpenOffice.org Basic.

Está enfocado, principalmente, en las extensiones del lenguaje Basic para OpenOffice.org, es de­cir, en la API de OpenOffice.org. Siendo así, no se abordan las características básicas del len­guaje de programación Basic.

Si usted ha programado anteriormente o conoce alguno de los “sabores” Basic y desea escribir macros para OpenOffice.org éste es un buen punto de partida. Si no, le recomiendo buscar algún curso en la red y familiarizarse con el lenguaje Basic antes de aventurarse en OOo Basic. Es muy impor­tante dominar los fundamentos de un lenguaje de programación.

Todos los ejemplos del código fuente se comprobaron con OpenOffice.org, versión 1.0.1, excep­to los pequeños bloques de código fuera de las subrutinas.

Para utilizar adecuadamente este texto, OpenOffice.org debe estar instalado en su ordenador. Tras el Capítulo 3, recomiendo que usted instale, también, el Manual de Referencia de la API de OpenOffice.org (consulte el capítulo 8. Más Informaciones). El Manual de Referencia se actua­liza periódicamente y su versión actualizada está disponible también para consultas “on-line”.

Espero disponer de tiempo para continuar aprendiendo y adquiriendo informaciones útiles para los programadores que, como yo mismo, no dominan la lengua inglesa. Por lo tanto, periódica­mente, busque nuevas versiones de este documento.

Como resultado de un proceso de aprendizaje, esta Introducción..., seguramente, contiene algunos errores e inconsistencias; espero contar con su ayuda para corregirlos.

20 de junio de 2003

El Autor

Macros OpenOffice.org Basic

Introducción

Una macro es un programa escrito en lenguaje OpenOffice.org Basic con el objetivo de auto­matizar tareas de OpenOffice.org

El lenguaje OpenOffice.org Basic mantiene las principales características de las versiones ac­tuales de BASIC en lo referente a sintaxis, tipos de datos, operadores, comandos, funciones internas y organización general del programa. Además, OpenOffice.org Basic permite el ac­ceso a una gran cantidad de objetos, con sus métodos y propiedades, específicos de OpenOffice.

OpenOffice.org posee un IDE (Integrated Development Environment – Entorno de Desarrollo Integrado) completo, que incluye: edición de código fuente, verificación de errores, creación de cuadros de diálogo y administración de librerías.

Creando la Primera Macro

Nuestra macro será bien sencilla. El operador escribirá una frase en un cuadro de texto, y se­guidamente esta frase se añadirá a la posición actual del cursor de texto del documento acti­vo de Writer.

Para comenzar:

a) Ejecute Writer, cree un nuevo documento y sálvelo como Primera_Macro.sxw.

b) En la barra de menú seleccione Herramientas => Macros => Macro. Aparecerá el cua­dro de diálogo Macro.

Observe la jerarquía Macro desde, en el área izquierda del cuadro de diálogo; en ella tene­mos dos entradas principales: soffice y Primera_Macro.sxw, ambas son recipientes o conte­nedores para bibliotecas. Un nivel por debajo de las dos entradas tenemos la biblioteca Stan­dard. Dentro de soffice => Standard tenemos el módulo Module1.

El recipiente soffice, que siempre se cargará con OpenOffice.org, contiene bibliotecas globa­les usadas en todos los documentos de OpenOffice.org. Observe que algunas bibliotecas de sof­fice están desactivadas.

Cada documento abierto tiene su propio contenedor con una biblioteca Standard. En la figura 1 siguiente, el único documento abierto es Primera_Macro.sxw.

La lista Macros existentes en, en el centro del cuadro de diálogo, muestra los nombres de los procedimientos (subrutinas y funciones) del módulo seleccionado. El cua­dro de texto Nom­bre de la macro muestra el nombre del procedimiento seleccionado. Al se­leccionar el nom­bre de un procedimiento, se activan los botones Ejecutar, Asignar y Editar.

Figura 1: Diálogo Macro

Figura 2: IDE Basic

Seguimos con la creación de nuestra primera macro:

a) Seleccione la biblioteca Standard de Primera_Macro.sxw.

b) Pulse sobre el botón Nuevo para crear un nuevo módulo.

c) Aparece el cuadro de entrada Módulo Nuevo, sugiriendo el nombre Module1.

d) Pulse Aceptar para crear un nuevo módulo. El IDE de Basic ha sido cargado.

e) Observe, en el editor Basic, la definición de una subrutina Sub Main ... End Sub. Vea tam­bién que la pestaña Module1 está activa.

f) Escriba (o copie y pegue) el código fuente mostrado abajo entre las lineas Sub Main y End Sub.

Dim oDocumento as Object

Dim oTexto as Object

Dim oCursorVista as Object

Dim oCursor as Object

Dim sInsertar as String

' solicita el texto

sInsertar = InputBox("Introduzca el texto:", "Insertar Texto", "")

' comprueba que se escribió algo

if sInsertar = "" then

exit sub

endif

' obtiene el modelo de documento

oDocumento = ThisComponent

' obtiene el servicio Text del documento

oTexto = oDocumento.getText()

' obtiene la posición del cursor en el GUI y crea un cursor de texto

oCursorVista = oDocumento.getCurrentController().getViewCursor()

oCursor = oTexto.createTextCursorByRange(oCursorVista.getStart())

' inserta el texto en la posición actual del cursor

oTexto.insertString(oCursor, sInsertar, FALSE)

Ya terminamos nuestra primera macro. Recuerde que está incluida en el documento Primera_Macro.sxw.

Ejecutando la Primera Macro

Antes de continuar, analizaremos la ventana del IDE Basic. Tenemos, en la parte inferior iz­quierda de la ventana una área denominada Observador y otra, Llamadas, a la derecha. Las utilizaremos para observar los valores de las variables y las llamadas a procedimientos, res­pectivamente, durante la ejecución de la macro.

Veamos, también la finalidad de algunos iconos de la ventana del IDE Basic:

Ejecutar – ejecuta una macro hasta encontrar un Punto de ruptura.

Punto de ruptura – define un punto de interrupción.

Paso a paso – ejecuta una macro, línea a línea.

Detener – termina la ejecución de una macro. Se activa al iniciarse la ejecución de la macro.

Macros – permite seleccionar una macro para su ejecución.

Guardar el texto fuente como... – salva el módulo actual como un archivo Basic.

Insertar el texto fuente - inserta el código fuente de un archivo Basic.

Ha llegado el momento de probar el funcionamiento de nuestra macro:

a) En el editor Basic, desplace el cursor de texto a la línea sInsertar = InputBox( ... ). Pulse en el icono Punto de ruptura. Aparecerá una marca de color rojo a la izquierda de la línea.

b) En el campo Observador, escriba sInsertar y pulse Enter, para inspeccionar el valor de la variable durante la ejecución de la macro. Observe que se activa el icono Borrar observa­dor, a la derecha del campo.

c) Pulse sobre el icono Ejecutar. Se inicia la ejecución de la macro, deteniéndose en el Punto de ruptura; observe la flecha amarilla a la izquierda de la instrucción.

d) Pulsando en el icono Paso a paso, siga la ejecución de la macro. Cuando se muestre la ca­ja de entrada, introduzca su nombre y pulse el botón Aceptar. Continúe la ejecución pulsando Paso a paso hasta el final, en que se desactivará el icono Parar.

Cambie a la ventana de documento Primera_Macro.sxw y observe como se insertó su nombre en la posición del cursor, tal como deseábamos.

Si ocurrió algún error, revise el código fuente.

En el caso de que utilicemos una macro frecuentemente, podemos configurar OpenOffice.org para ejecutarla más fácilmente. En la opción del menú Herramientas => Configurar, dispo­nemos de las pestañas Menú – Teclado – Barras de símbolos, donde es posible asociar ma­cros a opciones de menús, a iconos de la barra de herramientas, a una combinación de teclas o a un evento de OpenOffice.org.

Antes de finalizar esta sección, vuelva a la ventana del IDE Basic, para simular un error en nuestro código fuente:

a) En la penúltima línea de código – oTexto.insertString(...) – altere el nombre de la variable oCursor por oCurso.

b) Ejecute la macro. Aparece un cuadro con un mensaje de error y un botón Aceptar. Obser­ve que la flecha de seguimiento de la ejecución se vuelve roja en la línea donde ha ocurrido el error. Tras aceptar el mensaje, finaliza la ejecución de la macro y la línea con el error perma­nece seleccionada.

Figura 3: Error de ejecución

c) Sustituya el nombre erróneo de la variable oCurso por el correcto oCursor. Cierre el IDE Basic.

Guarde el documento Primera_Macro.sxw.

En el próximo paso, veremos como hacer disponible una macro para todos los documentos de OpenOffice.org.

Compartiendo una Macro

Las macros de una biblioteca del contenedor soffice / Standard se cargan conjuntamente con OpenOffice.org. Las que se incluyen en las bibliotecas de cualquier otro documento, se cargan con el mismo. En consecuencia, estarán disponibles para ejecución solamente cuando el do­cumento esté abierto.

En esta sección, veremos como exportar una macro de un documento a la aplicación OpenOffice.org para que su ejecución sea posible desde cualquier documento, no tan sólo desde el documento original. Ahora mostraremos los pasos necesarios para efectuar la tarea.

Para que la macro de un documento esté disponible para cualquier otro documento de OpenOffice.org, siga los pasos siguientes:

a) Desde el documento Primera_Macro.sxw, seleccione Herramientas => Macros => Ma­cro.y pulse Administrar

b) En el cuadro de diálogo Administrar, pulse la pestaña Bibliotecas.

Figura 4. Administrar Bibliotecas

c) Seleccione, en el cuadro de lista Aplicación / Documento, la entrada soffice y pulse el botón Adjuntar.

d) Se mostrará un diálogo Abrir Archivo. Localice y seleccione cualquier documento que contenga la biblioteca de macros que desea compartir y pulse en el botón Abrir.

e) Aparecerá el diálogo Insertar Bibliotecas. Observe que las bibliotecas existentes en el ar­chivo están marcadas para compartir. Desmarque las que no desea compartir y pulse Acep­tar.

Figura 5. Añadir bibliotecas

Tras esta operación la biblioteca se habrá añadido al recipiente soffice. Normalmente, solo las macros de la biblioteca Standard se cargan con OpenOffice.org. Para cargar alguna otra bilbioteca, escoja Herramientas => Macros => Macro, seleccione el recipiente y haga una doble pulsación de ratón sobre el nombre de la biblioteca.

Para las bibliotecas Standard, el método de exportación no funciona adecuadamente, pues el recipiente soffice posee su propia bibliotecas Standard. En este caso debemos usar los recur­sos de edición del IDE Basic para compartir la macro.

Active el IDE Basic y cree un nuevo módulo en la biblioteca Standard del recipiente soffice. Seguidamente, abra el documento con la macro y, en el IDE Basic, active el módulo que con­tiene la macro a compartir, seleccione toda la macro y copie; cambie al nuevo módulo en sof­fice / Standard y pegue la macro copiada; guarde todo y cierre OpenOffice. Ahora su macro forma parte de la biblioteca Standard de soffice y está disponible para su ejecución en OpenOffice.org.

Si es su intención desarrollar macros para uso compartido, cree bibliotecas propias para ellas, sobretodo si usan diálogos. Para crear una nueva biblioteca, en el diálogo Administrar (figura 4), pulse sobre el botón Nuevo, emerge el diálogo Nueva Biblioteca, en el cuadro de texto introduzca un nombre para su biblioteca y pulse sobre el botón Aceptar.

El SDK (Software Delevopment Kit) de OpenOffice.org proporciona la herramienta pkgchk para empaquetamiento de macros, y su uso está fuera del ámbito de esta Introducción. Con­sulte la Developers Guide para obtener información más detallada.

Diálogos Personalizados

Introducción

OpenOffice.org Basic permite la creación de Cuadros de Diálogo Personalizados, gracias a un poderoso e intuitivo editor de Diálogos que incorpora.

Los Cuadros de Diálogo son una excelente solución para interactuar con el usuario, permitien­do que el programador diseñe una interface gráfica consistente para obtener o mostrar infor­maciones al operador.

Creando un Cuadro de Diálogo

Figura 6: Editor de Diálogos

El Cuadro de Diálogo que vamos a crear será bien simple. Realmente, tan sólo sustituiremos el cuadro de entrada usado en nuestra primera macro por un cuadro de diálogo personalizado.

Antes de comenzar, precisamos recuperar nuestro archivo Primera_Macro.sxw:

a) Cargue OpenOffice.org.

b) Abra el archivo Primera_Macro.sxw.

c) Desde el menú, escoja Herramientas => Macros => Macro, seleccione el Module1 de nuestra macro y puse sobre editar para activar el IDE Basic.

d) Pulse con el botón secundario del ratón sobre la pestaña Module1. En el menú contextual seleccione Insertar => Diálogo. Aparece el editor de cuadros de diálogo Basic, con un diálo­go vacío. Observe que se ha creado una página denominada Dialog1.

e) Pulse sobre el icono Campos de control . Aparecerá un cuadro con diversos iconos. Arrastre este cuadro para que quede situado a la derecha del cuadro de diálogo.

Veamos la finalidad de algunos de los iconos existentes en el cuadro de Controles.

Etiqueta – usado para colocar etiquetas en el cuadro de diálogo.

Botón – usado para colocar botones en el cuadro de diálogo.

Campo de texto – permite insertar un cuadro de texto en un diálogo.

Propiedades – muestra la ventana de propiedades del control seleccionado. Se activará cada vez que seleccionemos un control. Además de la edición de las propiedades, permite asociar procedimientos (código) a los eventos ocurridos en el control.

Activar el modo de prueba– muestra el cuadro de diálogo como si estuviese en ejecución.

Insertar controles en un cuadro de diálogo es una operación en tres pasos:

activar el icono del control en el cuadro de controles;

definir un área del cuadro de diálogo donde ubicar el control. Para esto presione el botón principal del ratón y arrastre formando un rectángulo; entonces, libere el botón del ratón;

definir las propiedades del control.

Cuando añadimos un control al cuadro de diálogo, OpenOffice.org Basic automáticamente define un valor predefinido para cada propiedad. Para mostrar las propiedades de un control selec­cionado, pulse sobre el icono Propiedades o efectúe una doble pulsación sobre el mis­mo. Observe que la ventana Propiedades, dispone de una barra de desplazamiento vertical.

Vamos a trabajar en nuestro cuadro de diálogo:

a) Seleccione el cuadro de diálogo vacío, pulsando en su borde exterior. Observe las marcas que aparecen en su perímetro. Podemos usar estas marcas para redimensionar nuestro cuadro de diálogo.

b) Pulse sobre el icono Propiedades para mostrar su ventana como en la figura 7. En el cam­po Titulo – pestaña General – escriba Insertar Frase y pulse Intro. Aparte la ventana de for­ma que le permita ver el cuadro de diálogo y observe su título.

c) Añada un control Etiqueta al cuadro de diálogo. Para ello, pulse en el icono Etiqueta, y a continuación defina un rectángulo en la parte superior del cuadro de diálogo. Defina su pro­piedad Título con el texto Introduzca el texto.

Figura 7: Ventana Propiedades

d) Coloque un Campo de Texto en el cuadro, por debajo de la etiqueta. Observe su propie­dad Nombre: TextField1. En el código fuente, nos referimos a un control por su propiedad Nombre, de ahí su importancia. Observe, también que este control no tiene la propiedad Tí­tulo.

e) Colocaremos dos botones, alineados horizontalmente, en la parte inferior del cuadro de diá­logo, bajo el campo de texto. Defina sus títulos como Aceptar y Cancelar.

Figura 8: Cuadro de Diálogo Insertar Frase

f) Ajuste el cuadro de diálogo y sus controles de modo que queden con la apariencia de la fi­gura 8.

Finalmente, terminamos nuestro cuadro de diálogo. Verificaremos su apariencia en ejecu­ción; para ello pulse sobre el icono Activar el modo de prueba en el cuadro de controles y, tras observar el resultado, ciérrelo para regresar al editor.

En la próxima sección, daremos funcionalidad a nuestro cuadro de diálogo.

Manejando Eventos del Cuadro de Diálogo

Veamos como el cuadro de diálogo que acabamos de proyectar interactuará con el operador: tras la aparición del cuadro de diálogo, el operador debe introducir el texto y después pulsar el botón Aceptar o puede, simplemente, presionar el botón Cancelar. Para cada una de estas dos acciones (y muchas otras), el sistema emite mensajes de eventos.

Para dar funcionalidad al cuadro de diálogo, necesitamos interceptar los eventos que nos inte­resan, es decir, la pulsación del botón Aceptar o Cancelar, para efectuar seguidamente el pro­ceso necesario.

El IDE Basic permite la asociación de procedimientos a eventos de controles mediante la ventana Propiedades y su pestaña Eventos. La palabra procedimientos ya nos indica que ne­cesitaremos código fuente.

En el IDE Basic, seleccione el módulo Module1.

En el editor de código Basic, introduzca (o copie y pegue) el código fuente siguiente, antes de Sub Main.

Private oDialogo as Variant

Sub dlgEjecutaDialogo

oDialogo = createUnoDialog(DialogLibraries.Standard.Dialog1)

oDialogo.execute()

End Sub

Sub dlgCancelaDialogo

oDialogo.endExecute()

End Sub

Sub dlgInsertarFrase

Dim oDocumento as Object

Dim oTexto as Object

Dim oCursorVista as Object

Dim oCursor as Object

Dim sFrase as String

oDialogo.endExecute()

' observe la referencia al control TextField1 del cuadro de diálogo

sFrase = oDialogo.Model.TextField1.Text

if sFrase = "" then

exit sub

endif

' obtiene el modelo de documento

oDocumento = ThisComponent

' obtiene el servicio Text en el documento

oTexto = oDocumento.getText()

' obtiene la posición do cursor en la GUI y crea un cursor de texto

oCursorVista = oDocumento.getCurrentController().getViewCursor()

oCursor = oTexto.createTextCursorByRange(oCursorVista.getStart())

' inserta el texto en la posición actual del cursor

oTexto.insertString(oCursor, sFrase, FALSE)

End Sub

En el código anterior, declaramos una variable oDialogo (Private oDialogo as Variant) fuera de los procedimientos, lo que la vuelve visible para todo el módulo Module1.

Antes de mostrar el cuadro de dialogo, creamos un objeto oDialogo con createUnoDialog() y, para ejecutarlo, llamamos a su método execute. Para cerrar el cuadro de diálogo llamamos a su método endExecute (es llamado en dos procedimientos). Los objetos UNO (creados con createUno) se deben declarar como de tipo Variant y no Object.

A continuación, asociaremos los procedimientos a los eventos del cuadro de diálogo.

Seleccione la página Dialog1 para activar el editor de cuadros de diálogo.

Figura 9: Diálogo Asignar macro

En nuestro cuadro de dialogo, seleccione el botón Aceptar y pulse sobre el icono Propieda­des. Surge la ventana Propiedades, pulse la pestaña Acontecimientos (Eventos), y seguida­mente el botón a la derecha del campo de evento Al ejecutar. Aparecerá la ventana Asig­nar macro con el evento Al ejecutar seleccionado. En el árbol Macros, expanda las entra­das Primera_Macro.sxw y Standard y pulse en Module1. Al aparecer la relación de proce­dimientos del módulo, seleccione el procedimiento dlgInsertarFrase y pulse sobre el botón Asignar. Para cerrar la ventana pulse el botón Aceptar.

Ahora, repita los pasos anteriores para asignar el procedimiento dlgCancelaDialogo al evento Al ejecutar del botón Cancelar.

Para OpenOffice.org Basic, el primer procedimiento en el módulo es el punto de entrada de la macro. Por tanto, el procedimiento Sub dlgEjecutaDialogo se ejecutará automáticamente to­das las veces que llamemos a nuestra macro.

Pruebe la macro y el cuadro de diálogo personalizado, pulsando sobre el icono Ejecutar, en la barra de herramientas del IDE Basic. Introduzca una frase cualquiera en el cuadro de texto del diálogo y pulse Aceptar. Tras la ejecución de la macro, verifique que la frase fue añadida correctamente al documento.

En el próximo capítulo, transformaremos nuestro sencillo cuadro de diálogo en un Piloto Au­tomático.

Pilotos Automáticos

Introducción

Un Piloto Automático es un Diálogo mostrado en varios pasos. Es una forma eficiente de guiar al usuario en la ejecución de una tarea.

OpenOffice.org trae de serie varios Pilotos Automáticos. Compruebe el funcionamiento de uno de ellos, seleccionando Archivo => Piloto Automático => Carta.

Creando un Piloto Automático

En esta sección, veremos como transformar el cuadro de diálogo personalizado del capítulo anterior en un Piloto Automático.

La idea general es, en un primer paso, obtener la frase, y en un segundo paso, solicitar una po­sición para insertar la frase introducida. Para dar este efecto paso a paso, OpenOffice.org per­mite la creación de cuadros de diálogo con múltiples páginas. El diálogo con la propiedad Página igual a 1 será mostrado primero, el de página 2 a continuación, y así sucesivamente.

Los controles de OpenOffice.org Basic tienen una propiedad Página (Step), que controla en que página del cuadro de diálogo será mostrado. Así, los controles con la propiedad Página igual a 1 serán visibles en el diálogo de la página 1, aquellos con Página igual a 2 se mos­trarán con el diálogo de la página 2, y así en adelante. Un control se mostrará en todos los pa­sos cuando su propiedad Página sea igual a 0.

El último diálogo accedido en el editor de diálogos, independientemente del número de su pá­gina será el primero en ser mostrado en la ejecución de la macro. Consecuentemente, después de diseñar los diálogos del Piloto Automático, regrese al diálogo de la página 1. Si usted de­fine la propiedad Página de un cuadro de diálogo con valor 0, se mostrarán todos los controles de todas las páginas.

En la transformación del diálogo en Piloto Automático, necesitaremos algunos otros controles y también alterar algunas propiedades de los controles existentes.

Cargue Writer, abra el documento Primera_Macro.sxw, seleccione Herramientas => Ma­cros => Macro, navegue hasta el módulo Primera_Macro – Standard – Module1 y pulse Editar para activar el IDE Basic.

Pulse sobre la pestaña Dialog1, activando el Editor de Diálogos y redimensione el dialogo, haciéndolo más largo. Seleccione los botones Aceptar y Cancelar (pulse Aceptar, presione la tecla Shift y pulse en Cancelar) y mueva estos dos botones hacia la derecha.

En la barra de herramientas del IDE Basic, pulse el icono Controles y ubique el cuadro de controles al lado del dialogo.

Pulse en el icono Botón, en el cuadro de controles y añada dos nuevos botones en el dialogo, a la misma altura del botón Aceptar, más a su izquierda.

Seleccione el botón CommandButton3, pulse en el icono Propiedades, defina la propiedad Título como << Anterior, y cambie el valor de la propiedad Activado a No.

Seleccione el botón CommandButton4 y defina su propiedad Título como Próximo >>.

Seleccione el botón Aceptar y modifique su Título a Finalizar.

Seleccione el diálogo (pulsando en su borde) y defina su propiedad Página (Step) como 1 (uno).

Seleccione el control Etiqueta y defina su propiedad Página como 1 (uno).

Seleccione el control Cuadro de texto y defina su propiedad Página como 1 (uno).

Ahora, retoque la primera página del Piloto Automático, dejándola de forma parecida a la si­guiente figura:

Figura 10: Primera Página del Diálogo del Piloto Automático

Bien, sigamos con nuestro proyecto, diseñando la Página 2 del Piloto Automático.

Seleccione el diálogo y altere la propiedad Página en 2 (dos). Observe que los controles Eti­queta y Cuadro de Texto desaparecen, pues ellos pertenecen a la Página 1. Los botones, que tienen la página igual a 0 (cero), continúan visibles.

Añada una Etiqueta en la parte superior izquierda del diálogo y defina su Titulo como Selec­cione una posición. Observe que la propiedad página es igual a 2 (dos), el mismo valor del diálogo.

Pulse sobre el icono Botón de Opción, en el cuadro de controles, y ponga tres botones de op­ción en la parte superior derecha del diálogo, uno bajo el otro.

Defina el Título del primer botón de opción como En la posición del cursor y su propiedad Estado en Seleccionado. Defina el Título del segundo botón de opción como Al principio del documento. Defina el Título del tercer botón de opción como Al final del documento.

Ahora, ajuste los controles de la segunda página del Piloto Automático, para que adopte una apariencia similar a la de la siguiente figura. Observe que el botón de opción En la posición del cursor aparece activada por omisión. La activación o desactivación de los botones Ante­rior y Siguiente se efectuará en tiempo de ejecución, por el código fuente que más adelante insertaremos.

Figura 11: Segunda Página del Diálogo del Piloto Automático.

Para finalizar el diseño del Piloto Automático, seleccione el diálogo y regrese a la Página 1 (uno), pues OpenOffice.org, por omisión, mostrará la última página accedida desde el Editor de Diálogos.

En la próxima sección, añadiremos el código fuente necesario para dar funcionalidad al Piloto Automático.

Manipulando Eventos del Piloto Automático

Nuestro Piloto Automático tiene dos nuevos botones (Anterior y Siguiente) y necesitamos có­digo fuente para interceptar o procesar sus eventos.

Active el IDE Basic y su editor e introduzca (o copie y pegue) el código siguiente encima de Sub Main.

Sub dlgSiguienteDialogo

oDialogo.Model.Step = 2

oDialogo.Model.CommandButton3.Enabled = true

oDialogo.Model.CommandButton4.Enabled = false

End Sub

Sub dlgAnteriorDialogo

oDialogo.Model.Step = 1

oDialogo.Model.CommandButton3.Enabled = false

oDialogo.Model.CommandButton4.Enabled = true

End Sub

Antes de insertar la frase, necesitamos verificar la posición, seleccionada en el segundo paso, (botones de opción) y tratar esa selección adecuadamente.

Inserte el código siguiente en Sub dlgInsertarFrase, a continuación de la línea oCursor = oTexto.CreateTextCursorByRange(...) y antes de la línea oTexto.insertString(...).

' la posición de la frase es en el inicio o en el final

if oDialogo.Model.OptionButton2.State = 1 then

oCursor.gotoStart(FALSE)

elseif oDialogo.Model.OptionButton3.State = 1 then

oCursor.gotoEnd(FALSE)

endif

Ahora, conectaremos los procedimientos con los eventos que nos interesan.

Cambie al editor de diálogos.

Seleccione el botón Anterior y pulse en el icono Propiedades. En la ventana Propiedades, pulse la pestaña Acontecimientos (Eventos) y seguidamente pulse el botón a la derecha del campo del evento Al Ejecutar. En la ventana Asignar macros, expanda la entrada Pri­mera_Macro.sxw y Standard de la lista Macros y pulse en Module1. En la relación de su­brutinas, seleccione el procedimiento dlgAnteriorDialogo y pulse el botón Asignar. Pulse Aceptar para cerrar la ventana.

Siguiendo los mismos pasos detallados anteriormente, asigne el procedimiento dlgSiguiente­Dialogo al evento Al Ejecutar del botón Siguiente.

Ejecute la macro y compruebe que todo ocurrió como se esperaba.

Ahora, ya puede usted aventurarse a escribir sus propias macros. Como punto de partida, consulte el próximo capítulo en busca de información complementaria.

Introducción al API de OpenOffice.org

Introducción

La clave para la creación de programas que usan la API de OpenOffice.org son los servicios.

Un servicio es una especificación de un objeto, que engloba un conjunto de interfaces y pro­piedades. Una interfaz es una colección de métodos. Una propiedad es un valor que deter­mina una característica de un servicio y está formada por un nombre y un valor.

Para crear un servicio, usamos la función Basic createUnoService(), que devuelve un objeto que soporta el servicio, o Null si no fuese posible la creación. Por ejemplo, para obetener el servicio Desktop usamos la llamada:

oDesktop = createUnoService( “com.sun.star.frame.Desktop” )

El argumento de la función es la especificación completa para el servicio. Todas las referen­cias a servicios comienzan por com.sun.star, seguido por el nombre del módulo, en este caso frame y, finalmente, por el nombre del servicio Desktop. Observe también que la especifica­ción se pasa como una cadena de caracteres “com.sun.star.frame.Desktop”.

Tras la llamada podemos verificar si el servicio fue creado con:

If isNull( oDesktop ) Then

' Error en la creación del servicio

End If

Existen servicios que son dependientes de un contexto. Por ejemplo, usted no puede crear una celda fuera de una hoja de cálculo. Otros servicios no necesitan un ambiente para operar. Existen, además, servicios que no ofrecen ninguna interfaz, sirviendo únicamente para obte­ner y definir propiedades.

Basic ofrece dos propiedades que facilitan el acceso a los servicios:

StarDesktop – es el equivalente al objeto devuelto por una llamada a la función createUno­Service(“com.sun.star.frame.Desktop”). Introduzca el siguiente código en una nueva subruti­na, ejecute y observe el resultado:

MsgBox StarDesktop.Dbg_SupportedInterfaces

'

' es lo mismo que:

'

Dim oDesktop

oDesktop = CreateUnoService( "com.sun.star.frame.Desktop" )

MsgBox oDesktop.Dbg_SupportedInterfaces

ThisComponent – devuelve el objeto documento que contiene el código Basic; existe sola­mente en documentos Writer, Calc, Impress o Draw. Algunas de sus interfaces dependen del tipo de documento.

Dim oDocumento As Object

oDocumento = ThisComponent

OpenOffice.org Basic tiene tres propiedades muy útiles para la inspección de objetos:

Dbg_SupportedInterfaces

devuelve las interfaces soportadas por el objeto

Dbg_Properties

devuelve las propiedades del objeto

Dbg_Methods

devuelve los métodos soportados por el objeto

Para obtener estas propiedades, use la forma Objeto.Propiedad. Por ejemplo, compruebe las interfaces soportadas por el modelo de documento ejecutando el siguiente código:

Sub Main

MsgBox ThisComponent.Dbg_SupportedInterfaces

End Sub

La interfaz com.sun.star.lang.XServiceInfo posee los siguientes métodos, útiles para inspec­ción de servicios:

getImplementationName ( ) As String

devuelve el nombre de implementación del servicio

supportsService (sNombre As String ) As Boolean

devuelve True (Verdadero) si el servicio sNombre es soportado

supportedServiceNames ( ) As String ()

devuelve un conjunto de cadenas con los nombres de los servicios soportados, incluso los in­directos.

Para obtener o especificar valores de propiedades, tenemos dos casos:

a) si el número de propiedades es fijo, entonces usamos simples asignaciones de Basic, como:

Dim nColorAntiguo As Long

nColorAntiguo = oRectangleShape.FillColor

oRectangleShape.FillColor = RGB(255,0,0)

b) si es una secuencia, debemos definir un array antes de manipular las propiedades:

Dim mPropArchivo(1) As New com.sun.star.beans.PropertyValue

mPropArchivo(0).Name = "FilterName"

mPropArchivo(0).Value = "swriter: StarWriter 5.0"

mPropArchivo(1).Name = "AsTemplate"

mPropArchivo(1).Value = True

La secuencia com.sun.star.beans.PropertyValue implementa el servicio MediaDescriptor, que describe cómo y dónde un recurso debe ser cargado o salvado. Observe como las propiedades se definen por un par Name y Value.

A continuación, analizaremos un ejemplo de código que usa algunos de estos conceptos.

Creando un nuevo documento

Desarrollaremos, ahora, una subrutina para crear un nuevo documento a partir de un plantilla existente. El código fuente Basic, en filas generales, necesita tratar los dos detalles siguien­tes:

a) obtener el camino completo para la plantilla;

b) cargar el archivo, informando a OpenOffice.org que se trata de una plantilla;

La siguiente subrutina Sub creaNuevoDocumento, ejecuta estas tareas apropiadamente.

' -------------------------------------------------

' Crea un nuevo documento a partir de una plantilla

' -------------------------------------------------

Sub creaNuevoDocumento

Dim oDesktop As Variant

Dim oDocumento As Object

Dim mPropArchivo(0) As New com.sun.star.beans.PropertyValue

Dim sUrl As String

' crea el objeto oDesktop

oDesktop = createUnoService("com.sun.star.frame.Desktop")

' define la URL del Archivo modelo, MODIFÍQUELO según su sistema

sUrl = "file:///D:/nad/openoffice/documentation.stw"

' define la propiedad AsTemplate como True (Verdadero)

mPropArchivo(0).Name = "AsTemplate"

mPropArchivo(0).Value = True

' crea el objeto oDocumento

oDocumento = oDesktop.loadComponentFromURL(sUrl,"_blank",0,mPropArchivo())

' INSERTAR CÓDIGO PARA SALVAR AQUÍ

End Sub

Las filas iniciada por la orden Dim declaran todas las variables usadas por la subrutina.

Para cargar un archivo, usamos el método loadComponentFromURL( ), que es definido por una interfaz del servicio Desktop. Luego, necesitamos un objeto UNO Desktop, declarado en la línea Dim oDesktop As Variant. Aquí, el tipo Variant sigue una recomendación de la Guía de Desarrolladores para la declaración de objetos UNO.

La variable sUrl (tipo String) recibe una especificación completa del camino para el archivo. Se pasará como argumento del método loadComponentFromURL( ).

El método loadComponentFromURL( ) devuelve un objeto Document. La línea Dim oDocumento As Object reserva memoria para este objeto.

El método loadComponentFromURL( ) recibe una secuencia de propiedades como argumento. La línea Dim mPropArchivo declara y define un array para esta secuencia. La definición del objeto se hace con el operador New seguido del tipo de objeto (As New com.sun.star.beans.­PropertyValue).

La línea oDesktop = createUnoService(...) se encarga de la creación del objeto Desktop.

La línea oDocumento = oDesktop.loadComponentFromURL(...) carga el documento de acuer­do con los argumentos y devuelve un objeto de tipo Document. Observe que la secuencia mPropArchivo se pasa como argumento seguida de ( ). El argumento “_blank” significa que se creará una nueva ventana para el documento.

Ahora, introduzca la Sub creaNuevoDocumento, alterando la variable sUrl para que conten­ga una vía de acceso completa a una plantilla de texto en su sistema, y ejecute la macro para ver el resultado.

En el próximo capítulo aprenderemos más sobre programación con documentos de OpenOffice.org.

Trabajando con Documentos

Cargando Documentos

Para cargar o crear un documento de OpenOffice.org debemos:

a) Crear un objeto Desktop

Dim oDesktop As Variant

oDesktop = createUnoService(“com.sun.star.frame.Desktop”)

b) Definir una URL

Debe usted proveer una cadena de caracteres como especificación completa de la ruta de ac­ceso al documento; en caso de estar abriendo un documento existente, en la forma:

file:///ruta_completa_del_archivo

Para nuevos documentos, creados a partir del modelo patrón, existen URL's predefinidas que deben usarse según el tipo del documento:

URL	Descrição
private:factory/swriter	Crea un nuevo documento de Writer
private:factory/scalc	Crea un nuevo documento de Calc
private:factory/sdraw	Crea un nuevo documento de Draw
private:factory/simpress	Crea un nuevo documento de Impress

c) Definir las propiedades del descriptor de medios

El descriptor de medios es un servicio (com.sun.star.document.MediaDescriptor) que define como un recurso debe ser cargado. Las propiedades del descriptor se definen en una secuen­cia com.sun.star.beans.PropertyValue. Declare un array para la secuencia, según el número de propiedades a modificar, tal como sigue:

' declara un array vacío, para poderlo pasar como argumento

Dim mPatron()

' define un array para 1 propiedad (índice 0)

Dim mPropiedades(0) As New com.sun.star.beans.PropertyValue

mPropiedades(0).Name = "AsTemplate"

mPropiedades(0).Value = True

' define un array para 2 propiedades (índices 0 y 1)

Dim mPropiedades(1) As New com.sun.star.beans.PropertyValue

Siguen las descripciones para algunas de las posibles propiedades (existen varias):

Propriedade	Tipo	Descrição
AsTemplate	boolean	Si es True (Verdadero) crea un nuevo documento, a partir del documento cargado, aunque éste no sea una plantilla. Si fuese una plantilla y AsTemplate como False, el documento será cargado para su edi­ción.
FilterName	String	Define un filtro para ser usado para abrir o salvar un documento.
JumpMark	String	Tras su carga, salta a una determinada posición (celda, marcador, etc.).
Overwrite	boolean	Sobreescribe un documento al salvar. Por omisión, True (Verdadero).
ReadOnly	boolean	Define si el documento debe ser de sólo lectura o lectu­ra / escritura.
Unpacked	boolean	Al escribir el documento, no será compactado (zip).
Password	String	Contraseña para escribir o abrir un documento.

d) Definir la ventana de destino

Es el “marco” donde el documento será cargado o creado; si ya existe una ventana con el nombre especificado, ésta es la que se usará, sino se creará una nueva.

Los nombres predefinidos que siguen nunca se deben usar como nombre de ventana: “_blank”; “_default”; “_self”; “_parent”; “_top” y “_beamer”. Use “_blank” para crear una nueva ventana.

e) Definir el “flag” (bandera) de búsqueda

Es una constante que define el tipo de algoritmo usado para encontrar la ventana de destino. Utilice el valor 0 para no tenerla en cuenta.

f) Llamar al método loadComponentFromURL()

Este método, del objeto Desktop, carga el componente definido por la URL, dentro de la ven­tana de destino. Veamos los detalles:

loadComponentFromURL( URL As String,

MarcoDestino As String,

FlagBusca As Long,

Propiedades As <com.sun.star.beans.PropertyValue> )

El valor de retorno es un objeto XComponent o Null en caso de error.

Este es un ejemplo de llamada al método:

oDocumento = oDesktop.loadComponentFromURL(sUrl, "_blank", _

0, mPropArquivo())

Esto es todo, analice nuevamente el código de Sub creaNuevoDocumento, del capítulo ante­rior.

Guardando Documentos

Para salvar un documento, debemos:

(los puntos a), b) y c) siguientes ya se vieron en la sección 5.1 Cargando documentos)

a) Crear un objeto Document

Normalmente, mediante una llamada a loadComponentFromURL( ) o a ThisComponent.

b) Definir una URL

Se trata de la ruta completa del recurso.

c) Definir sus propiedades

Son las propiedades del descriptor de medios.

d) Llamar al método adecuado

Lo documentos de OpenOffice.org soportan los siguientes métodos para salvar componentes:

store ( )

storeAsURL ( sURL As String, Propriedades As <com.sun.star.beans.PropertyValue> )

storeToURL ( sURL As String, Propriedades As <com.sun.star.beans.PropertyValue> )

El método store ( ) simplemente sobreescrive un archivo y no se debe usar en un nuevo docu­mento sin nombre.

El método storeAsURL ( ) recibe dos argumentos y funciona como el comando Guardar Co­mo de OpenOffice.org.

El método storeToURL ( ) recibe dos argumentos, salva el contenido del documento en sURL y no altera el archivo original. Útil para exportar archivos.

Ejemplos de llamadas:

' salva un documento que ya existe

ThisComponent.store ( )

' o suponiendo que oDocumento fue definido

oDocumento.store ( )

Los documentos abiertos con loadComponentURL ( ), deben usar los métodos storeAsURL o storeToURL.

Como ejemplo, introduzca (o copie y pegue) el siguiente código fuente, tras la línea

' INSERTAR CÓDIGO PARA SALVAR AQUÍ

de Sub creaNuevoDocumento ( ), edite la variable sUrl de acuerdo con su sistema, ejecute la macro y verifique que un nuevo archivo fue escrito en sURL.

' ------------------------

' Escribe el nuevo archivo

' ------------------------

' Define la URL del nuevo archivo (MODIFÍQUELO según su sistema)

sUrl = "file:///D:/nad/openoffice/nuevo_texto.sxw"

' define la propiedad Overwrite como False

mPropArchivo(0).Name = "Overwrite"

mPropArchivo(0).Value = FALSE

' escribe el nuevo documento

oDocumento.storeAsURL(sUrl, mPropArchivo())

Tenemos, también los métodos siguientes, relacionados con la tarea de salvar archivos:

isModified() As Boolean

Devuelve True (Verdadero) si el recurso fue modificado; si no, devuelve False.

hasLocation ( ) As Boolean

Devuelve True (Verdadero) si el archivo ya existe (fue grabado); de lo contrario devuelve False.

GetLocation ( ) As String

Devuelve un String con la URL del recurso.

isReadonly ( ) As Boolean

Devuelve True (Verdadero) si el recurso está abierto para sólo lectura, en caso contrario de­vuelve False.

A continuación, tenemos un fragmento de código más elaborado para salvar archivos:

If (oDocumento.isModified) Then

If (oDocumento.hasLocation And (Not oDocumento.isReadOnly)) Then

oDocumento.store()

Else

oDocumento.storeAsURL(sURL, mPropArquivo())

End If

End If

Imprimiendo Documentos

El servicio OfficeDocument contiene la interfaz XPrintable, que provee los siguientes méto­dos para impresión y definición de impresora en OpenOffice.org:

getPrinter ( ) As Variant < com::sun::star::beans::PropertyValue >

setPrinter ( aImpressora As Variant < com::sun::star::beans::PropertyValue >)

print ( xOpcoes As Variant < com::sun::star::beans::PropertyValue >)

Analicemos las características y llamadas de cada uno de estos métodos.

getPrinter () As Variant < com::sun::star::beans::PropertyValue >

Este método devuelve una secuencia con el descriptor de la impresora corriente. El descriptor (PrinterDescriptor) contiene el nombre de la impresora y las definiciones de la impresora según la siguiente tabla:

Propiedad	Descripción
Name	Una cadena (String) con el nombre de la impresora.
PaperOrientation	Contiene la orientación del papel
PaperFormat	Especifica un tamaño de papel predefinido o definido por el usuario
PaperSize	Especifica el tamaño de papel en 1/100 mm.
IsBusy	True (Verdadero) si la impresora está ocupada; False en caso contrario
CanSetPaperOrientation	True (Verdadero) si la impresora permite cambiar la orientacióndel papel
CanSetPaperFormat	True (Verdadero) si la impresora permita cambiar el for­mato de papel
CanSetPaperSize	True (Verdadero) si la impresora permite cambiar el ta­maño del papel

Las últimas cuatro propiedades son de sólo lectura..

Veamos un ejemplo que accede a las propiedades de la impresora actual:

Sub obtieneDescriptorImpresora

Dim oDoc As Object

Dim oDescImpr As Variant

Dim sMsg As String

oDoc = ThisComponent

' obtiene array de estructuras PrinterDescriptor

oDescImpr = oDoc.getPrinter()

' obtiene tamaño del array de estructuras

iNumEstructuras% = UBound(oDescImpr)

' extrae los nombres de las propiedades de la impresora

For n = 0 To iNumEstructuras%

sMsg=sMsg + oDescImpr(n).Name + " "

Next n

' muestra los nombres de las propiedades

MsgBox sMsg,0,"Propiedades Impresora"

' obtiene y muestra el valor de la propiedad PageFormat

' A3=0; A4=1; Letter/Carta=5; ...

MsgBox oDescImpr(2).Value

' comprueba si PageFormat se puede modificar

If oDescImpr(6).Value Then

MsgBox "Formato de Página, ¡puede ser modificado!"

' entonces lo modifica a A4

oDescImpr(2).Value = 1

Else

MsgBox "Formato de Página, ¡no puede ser modificado!"

End If

' muestra nuevamente el valor de PageFormat

MsgBox oDescImpr(2).Value

End Sub

El código anterior llama al método getPrinter ( ) para obtener las propiedades de la impresora actual. Seguidamente, en el bucle For ... Next, extrae los nombres de cada propiedad. Y, a continuación, obtiene y altera el formato de página, si es posible.

setPrinter ( aImpresora As Variant < com::sun::star::beans::PropertyValue >)

Asigna una nueva impresora al documento. Puede implicar un reformateado.

Las propiedades de la impresora son las mismas que las de la tabla anterior.

print ( xOpciones As Variant < com::sun::star::beans::PropertyValue >)

Imprime el documento según las opciones de impresión (PrintOptions) en xOpciones. Estas opciones se describen en la siguiente tabla:

Opción	Descripción
CopyCount	( Int ) Especifica el número de copias a imprimir
FileName	Cadena con el nombre de un archivo para la impresión
Collate	Si True (Verdadero) todo el documento se imprimirá an­tes de la siguiente copia; de lo contrario, imprime todas las copias página a página
Pages	Una cadena con las páginas que deben imprimirse, por ejemplo: “1;3;5-8;12”

Veamos algunos ejemplos de código fuente. Para imprimir un documento:

' imprimir el documento con las definiciones actuales

Dim aOpciones ()

oDocumento.print ( aOpciones() )

Para imprimir solamente las páginas 1; 3; 5-8 e 12.

Dim aOpciones(0)

aOpciones(0).Name = "Page"

aOpciones(0).Value = "1;3;5-8;12"

ThisComponent.print ( aOpciones() )

Para imprimir en una impresora diferente de la predefinida, usted necesita alterar la propiedad “Name” de la impresora y llamar a setPrinter definiendo una nueva impresora, tal como sigue:

Dim mImpresora(0) As New com.sun.star.beans.PropertyValue

Dim aOpciones() ' solamente para pasar el argumento

'

mImpresora(0).Name="Name"

mImpresora(0).value="Segunda_Impresora"

' define una nueva Impresora para el objeto,

' puede ocurrir un reformateado del documento

oDocumento.setPrinter = mImpresora()

' imprime con las opciones predefinidas

oDocumento.print( aOpciones() )

Cerrando Documentos

Para cerrar un documento, debemos considerar dos casos:

a) Abierto con loadComponentFromURL( )

Vimos que este método devuelve un objeto XComponent. La interfaz de este servicio provee el método dispose( ), que se usa para cerrar un componente, su llamada es simple:

oDocumento.dispose()

Añada la línea anterior tras la última linea de Sub creaNuevoDocumento( ), ejecute la macro y observe el resultado.

b) Abierto por la interfaz de usuario de OpenOffice.org

Si el documento se cargó con la orden Archivo => Abrir de OpenOffice.org y no hubiese una definición de un objeto Document, use la propiedad ThisComponent, como sigue:

ThisComponent.dispose()

Atención: el método dispose( ) descarta todas las modificaciones efectuadas en el documento. Por consiguiente, antes de llamarlo, asegúrese de guardarlas. O, mejor incluso, use isModified( ) pa­ra alertar al usuario.

Existen maneras más seguras para controlar el cierre de componentes, pero están más allá del ámbito de esta Introducción.

Identificando los Documentos Abiertos

Todos los documentos abiertos son administrados por el objeto Desktop. Cada documento es considerado un componente de este objeto, sin embargo, no todo componente es un documen­to. Por ejemplo, si tenemos una hoja de cálculo y un documento de texto abiertos, con el Na­vegador de Fuentes de Datos activo, existen tres componentes en el Desktop, de los cua­les sólo dos son documentos.

La Sub muestraComponentes, a continación, obtiene una enumeración de los componentes activos, verifica cuales son modelos de documentos y muestra información sobre su tipo.

Sub muestraComponentes

Dim oComponentes As Variant

Dim oComp As Variant

Dim sURL As String

Dim sTipo As String

oComponentes = StarDesktop.getComponents().createEnumeration()

n = 0

Do While (oComponentes.hasMoreElements())

oComp = oComponentes.nextElement()

' no todos los componentes son modelos con una URL

If HasUnoInterfaces(oComp, "com.sun.star.frame.XModel") Then

sURL = oComp.getURL()

If oComp.SupportsService("com.sun.star.sheet.SpreadsheetDocument") Then

sTipo = "Calc"

ElseIf oComp.SupportsService("com.sun.star.text.TextDocument") Then

sTipo = "Writer"

ElseIf oComp.SupportsService("com.sun.star.drawing.DrawingDocument") Then

sTipo = "Draw"

ElseIf oComp.SupportsService("com.sun.star.formula.FormulaProperties") Then

sTipo = "Math"

Else

sTipo = "Otro"

End If

MsgBox sTipo + Chr$(13) + sURL

End If

n = n + 1

Loop

MsgBox "Componentes: " + Str$(n)

End Sub

Analice atentamente el código anterior, que muestra importantes aspectos de la programa­ción del API de OpenOffice.org. Observe como se crea una enumeración y como recorremos sus elementos.

Tras la identificación de un documento, usted puede, por ejemplo, ordenar su impresión o su cierre, además de manipular su contenido, aplicando las técnicas que serán vistas en los próxi­mos capítulos.

Documentos de Writer

Introducción

En este capítulo, veremos como efectuar tareas simples de procesamiento de texto como: edi­ción, formateo, búsqueda y reemplazo.

Abordaremos la cuestión mediante ejemplos prácticos, con una breve explicación de los as­pectos más importantes.

Un documento de Writer contiene principalmente texto, organizado en párrafos y tablas. Además de estos elementos básicos, soporta marcos, objetos incrustados, campos, imágenes, marcadores, índices y muchos otros objetos. Estos datos conforman un modelo de docu­mento.

Mediante el modelo, podemos manipular los datos independientemente de su representación visual. Para manejar el aspecto visual del documento, el modelo dispone de un objeto con­trolador.

Algunos elementos de un documento (gráficos, marcos, etc) son nombrados y están anclados en un párrafo, carácter o página. Los párrafos no reciben ni nombre ni índice, de modo que su acceso debe ser secuencial.

Editando texto

Antes de comenzar a editar el texto de un documento, debemos tener en mente lo siguiente:

a) Crear una instancia del componente a editar, es decir, un objeto que represente el documen­to de Writer;

b) Obtener el contenido a editar, en este caso, un objeto con el texto del documento;

c) Hacer la edición del contenido, usando los métodos apropiados.

Cree un nuevo documento de Writer, vaya al IDE Basic, introduzca el siguiente código y eje­cute Sub editaTexto para ver el resultado

Sub editaTexto

Dim oDoc As Object

Dim oTxt As Object

Dim oTxtRange As Object

Dim sStr As String

oDoc = ThisComponent

oTxt = oDoc.getText()

sStr = "Esta es una "

oTxt.setString( sStr )

oTxtRange = oTxt.getEnd()

sStr = "cadena de caracteres "

oTxtRange.setString( sStr )

End Sub

En este ejemplo, usamos la interfaz XTextRange para editar texto. Sus métodos son:

getText( ) As Text

devuelve un objeto Text

getString( ) As String

devuelve un String contenido en el objeto

setString( sStr As String )

define un String con el contenido del objeto

getStart( ) As Object <TextRange >

devuelve un objeto TextRange apuntando al inicio del objeto que le llama

getEnd( ) As Object <TextRange>

devuelve un objeto TextRange apuntando al final del objeto que le llama

Inicialmente, llamamos al método getText( ), que devuelve un objeto Text, paso correspon­diente al punto b) anterior.

Seguidamente, en la línea oTxt.setString(sStr), definimos una cadena de caracteres para nues­tro objeto Text, esto quiere decir que todo el contenido del documento – objeto oTxt – será sustituido por la cadena sStr de setString. Antes de insertar más texto, precisamos obtener el final del contenido de oTxt con la llamada al método getEnd( ) y usar este nuevo objeto – TextRange – para insertar más texto. A través del método getStart( ), podríamos insertar tex­to al principio del contenido.

Observe, además, que las variables de los servicios Text y TextRange se declaran como Object.

Atención, oTxt también es un TextRange, así que podemos sustituir la variable oTxtRange por el encadenamiento de métodos siguiente:

oTxt.getEnd ().setString ( sStr )

Este proceso de edición es muy limitado. Tan sólo podemos sustituir todo el contenido del texto e insertar texto al inicio o final del documento. Veamos como mejorar esto en la próxi­ma sección.

Moviéndose por el texto

Para aumentar la flexibilidad en la edición de texto, el modelo de documento nos ofrece dos tipos de cursor: un cursor de texto y un cursor de vista. El primero opera sobre el contenido del documento independientemente de la interfaz gráfica, y el segundo representa el cursor vi­sible en la interfaz gráfica. Usted puede crear tantos cursores como desee.

El alcance de un cursor tiene un inicio y un final, que puede abarcar un rango variable de tex­to o coincidir en un mismo punto. El alcance del cursor puede ser expandido con el desplaza­miento del mismo.

En Writer, además del cursor de texto, tenemos también: cursor de palabra, cursor de senten­cia y cursor de párrafo, todos ellos derivados del cursor de texto.

Veamos, ahora, las interfaces y métodos usados para flexibilizar la edición de texto.

La interfaz XSimpleText, derivada de XTextRange, se usa en la creación del cursor de texto, en la inserción de cadenas y de caracteres de control, y posee los siguientes métodos::

createTextCursor ( ) As Object <TextCursor>

Devuelve un objeto cursor de texto (al principio del contenido).

createTextCursorByRange (aPos As TextRange) As Object <TextCursor>

Crea un objeto cursor de texto en la posición especificada por el argumento.

insertString(aPos As TextRange, sStr As String, bFlag As Boolean)

Inserta la cadena en la posición. Si bFlag fuese True (Verdadero) el contenido de aPos será sustituido por sStr; si no, sStr se añadirá al final de aPos.

insertControlCharacter( aPos As TextRange, iChar As Integer, bFlag As Boolean )

Insertar un carácter de control en la posición aPos.

El servicio TextCursor, a través de la interfaz XTextCursor, suministra métodos para el con­trol del estado y movimiento del cursor.

a) Métodos para mover el cursor:

goLeft (iNumChar As Integer, bExpande As Boolean) As Boolean

mueve el cursor a la izquierda iNumChar caracteres

goRight (iNumChar As Integer, bExpande As Boolean) As Boolean

mueve el cursor a la derecha iNumChar caracteres

gotoStart (bExpande As Boolean)

mueve el cursor al principio del texto

gotoEnd (bExpande As Boolean)

mueve el cursor al final del texto

gotoRange (xRange As <TextRange>, bExpande As Boolean)

mueve o expande el cursor sobre el objeto TextRange

En todos los métodos anteriores, si bExpande es True (Verdadero) se expandirá el alcance del cursor.

b) Métodos para controlar el estado del cursor:

collapseToStart ( )

mueve la posición de final del cursor hasta el inicio del mismo

collapseToEnd ( )

mueve la posición de inicio del cursor hasta el final del mismo

isCollapsed ( ) As Boolean

devuelve True (Verdadero) si coinciden las posiciones inicial y final del cursor.

Las interfaces XWordCursor, XSentenceCursor e XparagraphCursor, todas ellas derivadas de XTextCursor, también proporcionan métodos para control y movimiento del cursor.

a) Métodos de XWordCursor:

gotoNextWord (bExpande As Boolean) As Boolean

gotoPreviousWord (bExpande As Boolean) As Boolean

gotoEndOfWord (bExpande As Boolean) As Boolean

gotoStartOfWord (bExpande As Boolean) As Boolean

isStartOfWord ( ) As Boolean

isEndOfWord ( ) As Boolean

b) Métodos de XSentenceCursor:

gotoNextSentence (Expande As Boolean) As Boolean

gotoPreviousSentence (bExpande As Boolean) As Boolean

gotoStartOfSentence (bExpande As Boolean) As Boolean

gotoEndOfSentence (bExpande As Boolean) As Boolean

isStartOfSentence ( ) As Boolean

isEndOfSentence ( ) As Boolean

c) Métodos de XParagraphCursor:

gotoStartOfParagraph (bExpande As Boolean) As Boolean

gotoEndOfParagraph (bExpande As Boolean) As Boolean

gotoNextParagraph (bExpande As Boolean) As Boolean

gotoPreviousParagraph (bExpande As Boolean) As Boolean

isStartOfParagraph ( ) As Boolean

isEndOfParagraph ( ) As Boolean

Antes de presentar un ejemplo, veamos los caracteres de control que pueden ser insertados en un documento de Writer. En la interface gráfica, se les denomina caracteres no imprimibles y tienen funciones especiales en la presentación final del documento.

Para facilitar su empleo, estos caracteres están definidos como constantes, en el grupo de constantes com.sun.star.text.ControlCharacter. Pueden ser insertados en el texto con el méto­do insertControlCharacter ( ) o como parte del contenido de una cadena, en este caso, usando su código Unicode.

Esta es una relación de los caracteres de control con sus respectivos códigos:

Constante	Descripción	Cód. Unicode
PARAGRAPH_BREAK	Inserta un salto de párrafo	0x000D
LINE_BREAK	Salto de línea dentro de un párrafo	0x000A
HARD_HYPHEN	Guión protegido; no lo modifica la separación silábica.	0x2011
SOFT_HYPHEN	Marca una posición preferida para la separación silá­bica.	0x00AD
HARD_SPACE	Espacio protegido, con tamaño fijo.	0x00A0
APPEND_PARAGRAPH	Añade un nuevo párrafo	No tiene

Finalizaremos la sección con un ejemplo demostrando el uso de algunos de los conceptos y métodos presentados.

Active el IDE Basic, introduzca el siguiente código y ejecute la subrutina Sub procesaTexto. La macro inserta texto, caracteres de control y un salto de página en un nuevo documento sin nombre. Después, selecciona y sustituye dos palabras por una cadena vacía.

Sub procesaTexto

Dim oDesktop As Variant

Dim oDoc As Object

Dim oCursor As Object

Dim oTexto As Object

Dim mPropArchivo()

Dim sStr As String

oDesktop = createUnoService("com.sun.star.frame.Desktop")

oDoc = oDesktop.loadComponentFromURL("private:factory/swriter",_

"_blank", 0, mPropArchivo())

oTexto = oDoc.getText()

oCursor = oTexto.createTextCursor()

sStr = "Éste es el texto del primer párrafo del documento"

With oTexto

' inserta el texto en la posición actual del cursor

.insertString(oCursor, sStr, False)

' insertar un salto de párrafo

.insertControlCharacter(oCursor,_

com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, False)

.insertString(oCursor, "Éste es el segundo párrafo", False)

.insertControlCharacter(oCursor, _

com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, False)

End With

' inserta una nueva página

oCursor.gotoStartOfParagraph(True)

oCursor.breakType = com.sun.star.style.BreakType.PAGE_BEFORE

oTexto.insertString(oCursor, "Estoy en una nueva página.", False)

' mueve el cursor sin expansión

oCursor.gotoStart(False)

oCursor.gotoNextWord(False)

oCursor.gotoNextWord(False)

oCursor.gotoNextWord(False)

' mueve el cursor expandiendo, selecciona “texto de”

oCursor.gotoNextWord(True)

oCursor.gotoNextWord(True)

' sustituye el texto entre el principio y el final del cursor

oTexto.insertString(oCursor, "", True)

End Sub

En el código anterior, estudie el empleo del argumento bExpande (True o False), pues es muy importante.

Otro aspecto es la inserción de salto de página. No existe un carácter de control para salto de página o columna. Esa es una propiedad del párrafo. Observe que usamos oCursor para defi­nir una propiedad del párrrafo (oCursor.breakType). Esto es posible porque el objeto Text­Cursor hereda las características de TextRange.

Los posibles valores para la propiedad breakType (salto de página y columna) se enumeran en com.sun.star.style.BreakType, aquí usamos PAGE_BEFORE.

Finalmente, observe en el nuevo documento que el cursor de vista se encuentra al final del mismo, a pesar de la última acción (selección y reemplazo) ha ocurrido en el primer párrafo, lo que demuestra la independencia entre el cursor de texto y la interfaz gráfica.

Recuerde, además, que el acceso a la interfaz gráfica se da a través del controlador del modelo de documento. El código fuente de la subrutina dlgInsertarFrase, del Capítulo 3 (Piloto Au­tomático), muestra como acceder al controlador y crear un cursor de vista.

Formateando texto

Es ésta otra tarea común en procesamiento de textos. Tenemos dos maneras de abordar el for­mateo del texto: la primera es aplicar las caracterísiticas deseadas directamente sobre el objeto, sobreescribiendo las definiciones básicas; por ejemplo, seleccionar un párrafo y cambiar su ajuste; la segunda consiste en aplicar un estilo predefinido de formateo, por ejemplo, seleccionar un párrafo y cambiar su estilo de Predefinido a Título.

En principio, vamos a demostrar el primer enfoque. Existe una gran cantidad de propiedades relacionadas con el formato, como propiedades de caracteres y de párrafos.

El servicio com.sun.star.style.CharacterProperties define las propiedades comunes de ca­racteres. Veamos algunas de ellas:

Propiedad	Descripción
CharFontName	Especifica el nombre de estilo de la fuente
CharFontStyleName	Contiene el nombre de estilo de la fuente
CharFontFamily	La familia de la fuente (com.sun.star.awt.FontFamily)
CharHeight	Valor de la altura de los caracteres en puntos
CharUnderline	Valor del carácter subrayado (com.sun.star.awt.Underline)
CharWeight	Valor del peso de la fuente (com.sun.star.awt.FontWeight)
CharPosture	Valor de inclinación de fuente (com.sun.star.awt.FontSlant)
CharFlash	Si True (Verdadero), el carácter parpadea. Es opcional
CharStrikeout	Tipo de tachado del carácter (com.sun.star.awt.FontStrikeout)
CharRotation	Rotación del carácter en grados

En la tabla anterior, las referencias al módulo com.sun.star.awt, contienen posibles valores para las respectivas propiedades de los caracteres.

El servicio com.sun.star.style.ParagraphProperties define las propiedades de los párrafos. La siguiente tabla, presenta algunas:

Propiedad	Descripción
ParaAdjust	Define el tipo de alineación horizontal (com.sun.star.style.ParagraphAdjust)
ParaBackColor	Contiene el color de fondo, es opcional
ParaLastLineAdjust	Define la alineación horizontal de la última línea
ParaLeftMargin	Especifica la sangría izquierda en 1/100 mm ( As Long )
ParaRightMargin	Especifica la sangría derecha en 1/100 mm ( As Long )
ParaTopMargin	Define el espacio anterior al párrafo en1/100 mm (As Long)
ParaBottomMargin	Define el espacio posterior al párrafo en 1/100 mm (As Long)
ParaStyleName	Contiene el nombre de estilo del párrafo actual; es opcional.
LeftBorder	Define borde izquierdo; opcn. (com.sun.star.table.BorderLine )
RightBorder	Define borde derecho; opcn. (com.sun.star.table.BorderLine )
TopBorder	Define borde superior; opcn. (com.sun.star.table.BorderLine )
BottomBorder	Define borde inferior; opcn. (com.sun.star.table.BorderLine )
BorderDistance	Distancia del borde al objeto
ParaFirstLineIndent	Sangría de primera línea, es opcional.
ParaVertAlignment	Alineación vertical (com.sun.star.text.ParagraphVertAlign)

Nuevamente, las referencias com.sun.star contienen posibles valores para las respectivas pro­piedades, generalmente un valor de 0 a n para constantes. Veamos algunas de ellas:

Constantes de com.sun.star.style.ParagraphAdjust: LEFT, RIGHT, BLOCK, CENTER e STRETCH.

Constantes de com.sun.star.text.ParagraphVertAlign: AUTOMATIC, BASELINE, TOP, CENTER e BOTTOM.

Existen muchas otras propiedades para caracteres y párrafos, una consulta a la Guía para De­sarrolladores o al Manual de Referencia, ambos de Sun Microsystems Inc., es indispensable para quienes deseen programar en OpenOffice.org

Volvamos a nuestro último ejemplo Sub procesaTexto. Deseamos cambiar la inclinación y color de fuente de la palabra “segundo” y, también, el estilo de un párrafo de estilo Título. Introduzca el siguiente código, tras la última línea de la subrutina, ejecútela y observe el re­sultado.

' ----------------------

' código para formateado

' ----------------------

oCursor.gotoNextParagraph(FALSE)

oCursor.gotoNextWord(False)

oCursor.gotoNextWord(False)

oCursor.gotoNextWord(False)

oCursor.gotoNextWord(True)

oCursor.CharPosture = com.sun.star.awt.FontSlant.REVERSE_ITALIC

oCursor.CharColor = RGB(255,0,0)

' aplica estilo de párrafo

oCursor.gotoNextParagraph(FALSE)

oCursor.paraStyleName = "Heading"

Observe la asignación a la propiedad CharPosture de un valor enumerado REVERSE_ITALIC y, además, la modificación del estilo de párrafo a “Heading”. Tratándose de programa­ción, los nombres permanecen en inglés, difiriendo de los nombres que nos muestra OpenOffice.org en el Catálogo de Estilos.

Formateando con estilo

Veamos, ahora, el segundo enfoque para formateado, que es la aplicación de un estilo al obje­to. Siempre que sea posible, formatee sus documentos usando este método. Esto facilita futu­ras modificaciones, pues basta cambiar las características de un estilo para que se modifiquen todos los objetos formateados con él.

El módulo com.sun.star.style provee diversas interfaces para formateo, definición y acceso a los estilo usados por OpenOffice.org.

Writer dispone de diversos tipos de estilos. Tenemos estilos de párrafo, estilos de carácter, estilos de numeración y estilos de marco. Todos ellos agrupados dentro de la Familia de Esti­los:

Familia de Estilos

Estilos de Páginas	( estilo_1, estilo_2, ..., estilo_n )

Estilos de Párrafo	( estilo_1, estilo_2, ..., estilo_n )

Estilos de Carácter	( estilo_1, estilo_2, ..., estilo_n )

Estilos de Marco	( estilo_1, estilo_2, ..., estilo_n )

Estilos de Numeración	( estilo_1, estilo_2, ..., estilo_n )

El servicio com.sun.star.style.StyleFamilies contiene las familias de estilos de un documen­to; para obtener esta colección haga:

Dim oFamiliasEstilos As Object

oFamiliasEstilos = ThisComponent.getStyleFamilies()

En un documento de texto, una llamada al método getElementNames () devuelve un array con los nombres de las siguientes familias:

CharacterStyles	- estilos de carácter

ParagraphStyles	- estilos de párrafo

FrameStyles	- estilos de marco

PageStyles	- estilos de página

NumberingStyles	- estilos de numeración

El servicio com.sun.star.style.StyleFamily contiene los estilos de una misma familia; para obtener esta colección, use el acceso por nombre con getByName(“NombreDeFamilia”):

oEstParrafo = ThisComponent.StyleFamilies.getByName(“ParagraphStyles”)

El servicio com.sun.star.style.Style define las características de un estilo; para obtener un es­tilo, use el acceso por índice, por ejemplo, si se definió el objeto oEstParrafo anterior:

oEstilo = oEstParrafo (1)

devuelve el segundo estilo dentro de la colección de estilos de párrafo.

La API de OpenOffice.org provee interfaces para facilitar el acceso a los elementos de una colección. Al trabajar con estilos necesitamos conocer los métodos:

con.sun.star.container.XNameAcess

getByName (sNombre As String ) As Variant

getElementNames ( ) As aStrings ( )

hasByName ( sNombre As String ) As Boolean

con.sun.star.container.XIndexAcess

getCount ( ) As Long

getByIndex ( nIndice As Long ) As Variant

con.sun.star.container.XNameContainer

insertByName ( sNombre As String, oElemento As Variant)

removeByName ( sNombre As String )

El servicio com.sun.star.style.PageStyle define las propiedades más comunes de la página; a continuación tenemos algunas:

Propiedad	Descripción
BackColor	Valor Long del color de fondo de página
LeftMargin	Valor Long del margen izquierdo en 1/100 mm
RightMargin	Valor Long del margen derecho en 1/100 mm
TopMargin	Valor Long del margen superior en 1/100 mm
BottomMargin	Valor Long del margen inferior en 1/100 mm
IsLandscape	Si la orientación es horizontal o apaisada, True (Verdadero)
PageStyleLayout	Determina el diseño de página del estilo (com.sun.star.style.Pa­geStyleLayout)
Size	Valores Long especificando el tamaño del papel (Size.Width e Size.Height)
Width	Valor Long especificando el ancho de la página en 1/100 mm
Height	Valor Long especificando la altura de la página en 1/100 mm
HeaderLeftMargin	Valor Long especificando el margen izquierdo del encabezado en 1/100 mm
HeaderRightMargin	Valor Long definiendo el margen derecho del encabezado en 1/100 mm
HeaderIsOn	Determina si el encabezado está activo (True / False)
FooterLeftMargin	Valor Long especificando el margen izquierdo del pie de página en 1/100 mm
FooterRightMargin	Valor Long especificando el margen derecho del pie de página en 1/100 mm
FooterIsOn	Determina si el pie de página está activo (True / False)

Vamos a un ejemplo. Queremos mostrar el número de estilos de página disponibles en un do­cumento, sus nombres y propiedad Size del estilo de página Predefinido (Standard). Los pa­sos básicos serán:

a) obtener las familias de estilos del documento;

b) obtener los estilos de página;

c) obtener un array con los nombres de estilos de página;

d) usar un índice para extraer cada uno de los nombres;

e) obtener la página predefinida, usando el acceso por nombre.

La siguiente subrutina Sub muestraEstilosPagina implementa nuestro ejemplo:

Sub muestraEstilosPagina

Dim oDoc As Object

Dim oFamiliaEstilos As Object

Dim oEstilosPagina As Object

Dim oPaginaPredefinida As Object

Dim mNombresEstilosPagina As Variant

Dim sEstilo As String

Dim sMsg As String

oDoc = ThisComponent

' obtiene la Familia de Estilos (observe el uso de oDoc)

oFamiliaEstilos = oDoc.StyleFamilies

' obtiene los Estilos de Página

oEstilosPagina = oFamiliaEstilos.getByName("PageStyles")

' muestra el número de Estilos de Página

MsgBox oEstilosPagina.Count

' obtiene y muestra los nombres de los Estilos de Página

mNombresEstilosPagina = oEstilosPagina.getElementNames()

For n = LBound(mNombresEstilosPagina) To UBound(mNombresEstilosPagina)

sMsg=sMsg + mNombresEstilosPagina(n) + " "

Next n

MsgBox sMsg,0,"Estilos de Páginas"

' obtiene el Estilo de Página Predefinido (Standard)

oPaginaPredefinida = oEstilosPagina.getByName("Standard")

' comprobando el tamaño de página

lAnchoPag = oPaginaPredefinida.Size.Width

lAltoPag = oPaginaPredefinida.Size.Height

MsgBox Str$(lAnchoPag) + " " + Str$(lAltoPag)

End Sub

A destacar, el acceso mediante índice dentro del bucle For ... Next, el acceso nominal al estilo de página “Standard” y el acceso a la propiedad Size.

Observe, también, la llamada al método getStylesFamilies():

oFamiliaEstilos = oDoc.StylesFamilies

en OpenOffice.org Basic usted puede omitir el get y el set al programar propiedades.

Este ejemplo puede usarse como modelo para diversas operaciones con estilos.

Durante el formateo de texto, es habitual la creación y aplicación de nuevos estilos. Esta es una tarea fácil de ejecutar dentro de una macro. Para ello seguiremos los pasos:

a) Obtener las familias de estilos del documento;

b) Obtener la familia del grupo donde será creado el nuevo estilo;

c) Crear una instancia de objeto del nuevo estilo;

d) Añadir el nuevo estilo al grupo;

e) Especificar las propiedades del nuevo estilo;

f) Aplicar el nuevo estilo.

Volveremos a tomar la subrutina Sub procesaTexto y añadiremos un nuevo estilo de párrafo. Introduzca (o copie y pegue) el siguiente código, tras la última línea de la Sub procesaTexto, ejecute la macro y observe las definiciones de estilo del primer párrafo del documento.

' ------------------------

' código para nuevo estilo

' ------------------------

Dim oFamiliasEstilos As Object

Dim EstilosParrafo As Object

Dim oNuevoEstilo As Object

' obtiene las familias de Estilos

oFamiliasEstilos = oDoc.StyleFamilies

' obtiene los estilos de párrafo

EstilosParrafo = oFamiliasEstilos.getByName("ParagraphStyles")

' crea un nuevo estilo de párrafo

oNuevoEstilo = oDoc.createInstance("com.sun.star.style.ParagraphStyle")

' añade el nuevo estilo con el nombre "nuevo_estilo"

EstilosParrafo.insertByName("nuevo_estilo",oNuevoEstilo)

' especifica las propiedades del estilo

oNuevoEstilo.Name = "nuevo_estilo"

oNuevoEstilo.CharFontName = "Arial"

oNuevoEstilo.CharHeight = 16

oNuevoEstilo.ParaAdjust = com.sun.star.style.ParagraphAdjust.CENTER

oNuevoEstilo.CharWeight = com.sun.star.awt.FontWeight.BOLD

' entonces, aplica el nuevo estilo al primer párrafo

oCursor.gotoStart(FALSE)

oCursor.gotoEndOfParagraph(TRUE)

oCursor.paraStyleName = "nuevo_estilo"

Del código anterior, observe la creación de un nuevo objeto, en este caso una instancia de un estilo de párrafo, mediante la llamada al método createInstance(...), así como la definición de las propiedades del nuevo estilo.

Obteniendo el objeto seleccionado

La API de OpenOffice.org permite que una macro obtenga el contenido de una selección para aplicar alguna acción sobre el mismo. La interfaz com.sun.star.frame.XModel provee el si­guiente método, que devuelve uno o más objetos como la selección actual del controlador ac­tual:

getCurrentSelection ( ) As Object

El objeto devuelto es del tipo com.sun.star.uno.XInterface y depende del contenido de la se­lección.

Contenido de la selección	Objeto devuelto
Texto	Uno o más objetos apuntando a TextRange
Celdas de tabla	Un objeto apuntando a un cursor de tabla
Cuadro de texto	Un objeto apuntando a un cuadro de texto
Gráfico	Un objeto apuntando a un gráfico
Diseño	Uno o más objetos apuntando a ShapeCollection

Para selección de texto, el método getCurrentSelection ( ) opera de la siguiente manera:

a) si no hay nada seleccionado, devuelve un objeto TextRange con la posición actual del cur­sor de vista;

b) en una selección simple, devuelve un objeto TextRange con la selección;

c) en una selección múltiple, devuelve objetos TextRange con el cursor de vista para cada una de las selecciones.

En el siguiente ejemplo, obtenemos una o más cadenas seleccionadas, y las ponemos en color rojo:

Sub procesaSeleccion

Dim oDoc As Object

Dim oSel As Object

Dim oCurTxt As Object

oDoc = ThisComponent

oSel = oDoc.getCurrentSelection()

For i = 0 To oSel.Count-1

oCurTxt = oSel(i)

oCurTxt.CharColor = RGB(255,0,0)

Next i

MsgBox oSel.Count

End Sub

Observe el acceso a los objetos seleccionados a través de un índice y la creación de un cursor de texto antes del cambio de color.

Para extraer la cadena seleccionada, llame al método getString(), como sigue:

sCadena = oSel(i).getString()

El método getString() devuelve una cadena vacía para el primer objeto en los casos a) y c) anteriores. Inserte el código inferior en el bucle For ... Next de procesaSeleccion y observe la salida:

MsgBox Str$(i) + ": " + oSel(i).getString()

Si quiere usted efectuar alguna acción en la palabra sobre el cursor de vista, haga:

If Len(oSel(0).getString())= 0 Then

oCurTxt = oSel(0).Text.createTextCursorByRange(oSel(0).getStart())

oCurTxt.gotoStartOfWord(False)

oCurTxt.gotoEndOfWord(True)

End If

Analice como se crea el cursor de texto. Seguidamente, como ejercicio, haga que la Sub pro­cesaSeleccion aplique un color también en la palabra sobre el cursor de vista.

La API de OpenOffice.org tiene, también, la interfaz com.sun.star.view.XSelectionSupplier, que implementa algunos métodos de selección para la interfaz gráfica, entre ellos:

select ( oObjeto As Object ) As Boolean

si es posible, selecciona el objeto oObjeto en la interfaz gráfica.

getSelection ( ) oObjeto As Variant

obtiene la selección en la interfaz gráfica, puede devolver un objeto o una colección de obje­tos.

Estos métodos pueden ser llamados mediante el controlador actual del modelo (vea la sección de código más adelante).

Existen, además, dos métodos que pueden ser útiles para la identificación del contenido selec­cionado, son:

getImplementationName ( ) As String

devuelve el nombre de la implementación del objeto

getName ( ) As String

devuelve el nombre del objeto, si el mismo estuviese nombrado, caso de gráficos y tablas.

Dim oControlador As Object

oControlador = oDoc.getCurrentController()

oSel = oControlador.getSelection()

sNomeImpl = oSel.getImplementationName()

sNome = oSel.getName()

Ahora, modifique Sub procesaSeleccion, para avisar al usuario cuando él seleccione algo diferente de texto (pista: use getImplementationName).

Localizando objetos

Un documento de Writer puede contener otros objetos además de texto, como gráficos, tablas, campos, cajas de texto, etc. Para cada tipo existe una interfaz con métodos que devuelven una colección con los objetos existentes en el documento. He aquí algunos:

getTextTables ( ) As <com.sun.star.container.XNameAccess >

getTextFrames ( ) As <com.sun.star.container.XNameAccess >

getGraphicObjects ( ) As <com.sun.star.container.XNameAccess >

getTextSections ( ) As <com.sun.star.container.XNameAccess >

getBookMarks ( ) As <com.sun.star.container.XNameAccess >

getTextFields ( ) As <com.sun.star.container.XEnumerationAccess >

getFootNotes ( ) As <com.sun.star.container.XIndexAccess >

getEndNotes ( ) As <com.sun.star.container.XIndexAccess >

getDocumentIndexes ( ) As <com.sun.star.container.XIndexAccess >

La interfaz XNameAccess implementa los siguientes métodos:

getByName (sNombreDelObjeto As String ) As Variant

devuelve el objeto nombrado

getElementNames ( ) As String ()

devuelve una secuencia de cadenas con los nombres de los objetos de la colección

hasByName ( sNombre As String ) As Boolean

devuelve True (Verdadero) si el objeto de nombre sNombre existe en la colección

La interfaz XIndexAccess define los métodos siguientes:

getByIndex ( iIndice As Long ) As Object

devuelve el objeto en la posición iIndice de la colección

getCount ( ) As Long

devuelve el número de objetos de la colección

La interfaz XEnumerationAccess define el métido:

createEnumeration ( ) As Object <com.sun.star.container.XEnumeration>

devuelve un objeto XEnumeration

La interfaz XEnumeration implementa os métodos siguientes:

hasMoreElements ( ) As Boolean

devuelve True (Verdadero) si aún existen elementos en la colección

nextElement ( ) As Variant

devuelve el siguiente elemento.

La localización es sencilla, basta llamar al método apropiado y a continuación, usar el acceso nominal o indexado para obtener el objeto.

La subrutina siguiente, Sub localizaGraficos, muestra los nombres de todas las imágenes del documento:

Sub localizaGraficos

Dim oGraficos As Object

Dim oGrafico As Object

Dim n As Integer

oGraficos = ThisComponent.getGraphicObjects()

For n = 0 To oGraficos.Count -1

oGrafico = oGraficos (n)

MsgBox oGrafico.getName()

Next n

MsgBox "Gráficos en el documento: " + Str$(oGraficos.Count)

End Sub

Para eliminar una imagen de su documento, puede usted usar el siguiente bloque de código:

oGrafico = oGraficos.getByName (“Gráfico2”)

oGrafico.dispose ()

Como ejemplo de como trabajar con enumeraciones, mediante el siguiente código mostrare­mos el comando de cada uno de los campos de un documento:

Sub localizaCampos

Dim oCampos As Object

Dim oCampo As Object

Dim n As Integer

oCampos = ThisComponent.getTextFields().createEnumeration()

n = 0

Do While (oCampos.hasMoreElements())

oCampo = oCampos.NextElement()

MsgBox oCampo.getPresentation(True)

n = n + 1

Loop

MsgBox "Campos en el documento: " + Str$(n)

End Sub

Observe como la creación y el acceso a los elementos de una enumeración es secuencial y no indexada o nominal. El método getPresentation() devuelve el contenido de un campo si el ar­gumento es False.

Generalmente, para recuperar el objeto que nos interesa dentro de la colección devuelta por uno de los métodos anteriores, necesitamos conocer su nombre o su posición dentro de la co­lección.

Búsqueda y Reemplazo

La API de OpenOffice.org tiene mecanismos avanzados para la búsqueda y sustitución de tex­to en un documento.

Para localizar y sustituir texto debemos: crear un descriptor de búsqueda o reemplazo; es­pecificar sus propiedades y llamar al método apropiado.

La interfaz com.sun.star.util.XSearchable proporciona los siguientes métodos de búsqueda:

createSearchDescriptor ( ) As Object <SearchDescriptor>

crea un descriptor de búsqueda para recibir las propiedades de la búsqueda.

FindAll ( oDescriptor As Object ) As Object <com.sun.star.container.XIndexAccess>

devuelve una colección de TextRange con todos los resultados de la búsqueda.

FindFirst ( oDescriptor As Object ) As Object <com.sun.star.uno.XInterface>

devuelve un TextRange con el primer resultado de la búsqueda

FindNext ( oInicio As Object, oDescriptor As Object ) As Object <Xinterface>

devuelve un TextRange con el siguiente resultado de la búsqueda. El argumento oInicio será el punto de partida para la búsqueda, normalmente el resultado de la última llamada a Find­First o FindNext.

El servicio SearchDescriptor tiene los siguientes métodos:

getSearchString ( ) As String

obtiene la cadena de búsqueda

setSearchString ( sCadena As String )

especifica la cadena de búsqueda

He aquí algunas de sus propiedades:

Propiedad	Descripción
SearchBackwards	Si True (Verdadero) busca hacia el principio del documento
SearchCaseSensitive	Si True considera mayúsculas / minúsculas
SearchWords	Si True busca palabras completas
SearchStyles	Si True busca por un estilo

En el siguiente ejemplo vamos a localizar, en el documento, todas las ocurrencias de la cade­na “( )” y pondremos su color de fuente en Rojo. Introduzca el código siguiente y ejecute la su­brutina.

Sub buscaTodas

Dim oDoc As Object

Dim oDescBusca As Object

oDoc = ThisComponent

oDescBusca = oDoc.createSearchDescriptor()

oDescBusca.SearchWords = True

oDescBusca.setSearchString ("( )")

oResultado = oDoc.findAll( oDescBusca )

For n% = 0 To oResultado.Count - 1

oResultado(n%).CharColor = RGB(255,0,0)

Next

MsgBox "Ocurrencias de " + oDescBusca.getSearchString() + _

" " + Str$(oResultado.Count)

End Sub

La tarea anterior, también puede ser completada mediante el uso de los métodos findFirst y findNext:

oResultado = oDoc.findFirst( oDescBusca )

Do Until IsNull(oResultado)

oResultado.CharColor = RGB(250,100,50)

oResultado = oDoc.findNext(oResultado, oDescBusca )

Loop

La sustitución de texto está implementada por la interfaz XReplaceable, que hereda las carac­terísticas de XSearchable. Ella proporciona los métodos:

createReplaceDescriptor ( ) As Object <com.sun.star.util.XReplaceDescriptor>

devuelve un descriptor de reemplazo para las propiedades

replaceAll ( xDescriptor As Object <com.sun.star.util.XReplaceDescriptor>) As Long

busca y reemplaza todas las ocurrencias, devolviendo el total de sustituciones efectuadas.

El servicio ReplaceDescriptor tiene métodos para las propiedades de cadena:

getReplaceString ( ) As String

obtiene la cadena de reemplazo

setReplaceString ( sCadena As String )

especifica la cadena de reemplazo

Veamos un ejemplo sencillo de búsqueda y reemplazo:

Sub sustituyeTodas

Dim oDoc As Object

Dim oDescriptor As Object

oDoc = ThisComponent

oDescriptor = oDoc.createReplaceDescriptor()

oDescriptor.setSearchString( "( )" )

oDescriptor.setReplaceString( "()" )

n = oDoc.replaceAll(oDescriptor)

MsgBox n

End Sub

Observe que no disponemos de un método para el reemplazo interactivo. Sin embargo, a través de búsqueda y edición es posible implementar facilmente este procedimiento.

Insertando objetos

Abordaremos rápidamente otra tarea común en procesamiento de textos. La inserción de ob­jetos de origen externo como gráficos y documentos, en un documento de Writer.

Insertar un documento de texto es muy fácil, basta con crear un cursor de texto y llamar al método:

insertDocumentFromURL ( sURL As String, mPropiedades ( ) As Object )

Los argumentos de este método son idénticos a los ya vistos en la sección 5.1 Cargando Do­cumentos.

Dim oCursorTxt As Object

Dim mPropiedades ( )

Dim sURL As String

oCursorTxt = ThisComponent.createTextCursor ( )

' sURL = “ruta_de_acceso_completa_del_archivo”

oCursorTxt.insertDocumentFromURL ( sURL, mPropriedades() )

Para insertar en la posición del cursor de la interfaz gráfica, cree el cursor de texto a partir del cursor de vista.

La inserción de imágenes es un poco más complicada, para ello usted debe:

a) crear un objeto gráfico;

b) definir sus propiedades;

c) insertar el objeto.

Observe la subrutina Sub insertarGrafico siguiente:

Sub insertarGrafico

Dim oTxt As Object

Dim oCursorTxt As Object

Dim oGrafico As Object

Dim sURL As String

oTxt = ThisComponent.getText()

oCursorTxt = oTxt.createTextCursor()

oGrafico = ThisComponent.createInstance("com.sun.star.text.GraphicObject")

sURL = "file:///D:/NAD/OPENOFFICE/HOWTO/FIGURAS/DIALOGO.JPG"

oGrafico.GraphicURL = sURL

oGrafico.AnchorType = com.sun.star.text.TextContentAnchorType.AT_PARAGRAPH

oTxt.insertTextContent(oCursorTxt.getStart(), oGrafico, False)

End Sub

La llamada al método createInstance ( ) crea el objeto gráfico, después definimos las propie­dades GraphicURL e AnchorType y, finalmente, insertamos el gráfico llamando al método insertTextContent ( ) con los argumentos adecuados.

La propiedad AnchorType puede asumir, además, los siguientes valores: AT_CHARACTER, AT_PAGE e AS_CHARACTER.

El API de OpenOffice.org (versión 1.0.1) salva en el documento la URL del gráfico. En con­secuencia si usted lo cambia de su ubicación original, Writer no sabrá como encontrarlo.

Tablas

Una tabla es un conjunto de celdas organizadas en filas y columnas, donde cada celda tiene un nombre, normalmente indicado por letras y números. Las letras se refieren a las columnas y los números a las filas. No obstante, si existiesen celdas unidas o divididas, el concepto de columna podrá desaparecer y el esquema de nominación se complica.

Una celda puede contener texto simple (cadenas y números), gráficos, fórmulas y campos con varias características de formateo.

Una tabla recibe un nombre único en el documento, pudiendo servir como origen para gráfi­cos, tener su contenido ordenado y formatearse automáticamente.

El API de OpenOffice.org tiene diversos servicios e interfaces para manejar tablas, veremos las principales.

La interfaz com.sun.star.text.XTextTable se encarga de la administración de las tablas en un documento y contiene los siguientes métodos:

initialize ( nFilas As Long, nColumnas As Long)

Inicializa una tabla , recibe el número de filas y columnas como argumentos.

getCellNames ( ) As Object < Strings >

obtiene los nombres de las celdas, devolviendo un conjunto de cadenas

getCellByName ( sNombreCelda As String ) As Object < com.sun.star.table.XCell >

obtiene la celda nombrada en el argumento, devolviendo un objeto XCell

getRows ( ) As Object < com.sun.star.table.XTableRows >

obtiene las filas de la tabla, devolviendo un objeto XTableRows.

getColumns ( ) As Object < com.sun.star.table.XTableColumns >

obtiene las columnas de la tabla, devolviendo un objeto XTableColumns.

createCursorByCellName ( sNombreCelda As String ) As Object < XTextTableCursor >

crea un cursor de tabla, ubicado en la celda nombrada en el argumento

El servicio TextTable posee diversas propiedades, he aquí algunas de ellas:

Propiedad	Descripción
LeftMargin	Contiene el margen izquierdo de la tabla, valor Long
RightMargin	Contiene el margen derecho de la tabla, valor Long
Split	Un valor False impide la división de la tabla en dos pági­nas
TableBorder	Contiene la descripción del borde de la tabla
TableColumnSeparators	Contiene la descripción de los separadores de columnas de la tabla
BackGraphicURL	Contiene la URL del gráfico de fondo de la celda

Las interfaces XTableRows e XTableColumns, devueltas por los métodos getRows () y get­Columns (), además, proveen de los siguientes métodos:

insertByIndex ( nIndice As Long, nTotal As Long )

removeByIndex ( nIndice As Long, nTotal As Long )

getElementType ( ) As Type

hasElements ( ) As Boolean

getByIndex ( ) As Variant

getCount ( ) As Long

La interfaz XTextTableCursor, devuelta por el método createCursorByCellName, además posee los métodos:

getRangeName ( ) As String

Devuelve la extensión de celdas del cursor, es decir, los nombres de las celdas superior iz­quierda e inferior derecha, por ejemplo A2:D25 (observe el separador : ).

goLeft ( nCuanto As Integer, bExpande As Boolean ) As Boolean

goRight ( nCuanto As Integer, bExpande As Boolean ) As Boolean

goUp ( nCuanto As Integer, bExpande As Boolean ) As Boolean

goDown ( nCuanto As Integer, bExpande As Boolean ) As Boolean

gotoStart ( bExpande As Boolean )

gotoEnd ( bExpande As Boolean )

Métodos para movimiento y selección, nCuanto es la cantidad de celdas y, si bExpande fuese True (Verdadero), extiende la selección durante el desplazamiento del cursor.

gotoCellByName (sNombreCelda As String, bExpande As Boolean ) As Boolean

Desplaza el cursor hasta la célula nombrada en el argumento.

mergeRange ( ) As Boolean

splitRange ( nCuanto As Integer, bHoriz As Boolean ) As Boolean

Métodos para unir y dividir celdas

Mediante el servicio TextTableCursor podemos efectuar el formateado de las celdas, pues él incluye también los servicios CharacterProperties y ParagraphProperties.

La interfaz com.sun.star.table.XCellRange define los siguientes métodos para manejar las celdas:

getCellByPosition ( nColumna As Long, nLinea As Long ) As Object < XCell >

getCellRangeByPosition ( nIzq, nSup, nDer, nInf ) As Object < XCellRange >

getCellRangeByName ( sRango As String ) As Object < XCellRange >

El servicio com.sun.star.table.CellRange incluye com.sun.star.table.CellProperties, que de­fine las propiedades de una o más celdas. Veamos algunas:

Propiedad	Descripción
CellBackColor	Valor Long con el color del fondo de la celda
HoriJustify	Alineación horizontal del contenido de la celda (enum CellHori­Justify)
VertJustify	Alineación vertical del contenido de la celda (enum CellVertJus­tify)
IsTextWrapped	Si True (Verdadero), el ajusta la fila automáticamente
Orientation	Orientación del contenido de la celda (enum CellOrientation)
RotateAngle	Define la rotación del contenido de la celda (en 1/100 de gra­dos)
TableBorder	Describe el borde del conjunto de celdas (struct TableBorde)
TopBorder	Describe el borde superior de cada celda (struct BorderLine)
BottomBorder	Describe el borde inferior de cada celda (struct BorderLine)
LeftBorder	Describe el borde izquierdo de cada celda (struct BorderLine)
RightBorder	Describe el borde derecho de cada celda (struct BorderLine)
NumberFormat	Índice del formato numérico usado en las celdas (servicio Num­berFormatter)
CellProtection	Describe la protección de la celda (servicio CellProtection)

La interfaz com.sun.star.table.XCell ofrece los métodos siguientes para manipular el conte­nido de una celda:

getFormula ( ) As String

setFormula ( sFormula As String )

métodos para obtener o definir la fórmula de una celda

getValue ( ) As Double

setValue ( nValor As Double )

métodos para obtener o definir el valor de una celda

getType ( ) As Long < com.sun.star.table.CellContentType >

devuelve el tipo de contenido de una celda, como enumeración de CellContentType

getError ( ) As Long

devuelve el error de una celda, útil para rastrear errores en fórmulas

El nombre de una tabla puede ser obtenido o definido con los métodos siguientes, de la inter­faz com.sun.star.container.XNamed:

getName ( ) As String

setName ( sNombreTabla As String )

El contenido de una tabla puede ser ordenado con la interfaz com.sun.star.util.XSortable y sus métodos:

createSortDescriptor ( ) As Variant <com.sun.star.beans.PropertyValue>

devuelve un descriptor para las propiedades de ordenación

sort (xDescriptor As Variant <com.sun.star.beans.PropertyValue> )

ejecuta la ordenación, según el descriptor

Siguen algunas de las propiedades del descriptor de ordenación (SortDescriptor):

Propiedades	Descripción
IsCaseSensitive	Si True (Verdadero), considera mayúsculas / minúsculas
SortAscending	Si True (Verdadero), ordenación ascendente
SortColumns	Si True (Verdadero) ordena por columnas, sino, lo hace por filas

El servicio com.sun.star.table.TableSortDescriptor incluye el servicio SortDescriptor y po­see las propiedades siguientes:

Propiedades	Descripción
SortFields	Describe los campos de ordenación <com.sun.star.util.SortField>
MaxFieldCount	Define el número máximo de campos, propiedad de sólo lectura
Orientation	Define la orientación de la ordenación <com.sun.star.table.TableOrientation>
ContainsHeader	Si True (Verdadero), trata la primera fila como títulos, sin ordenarla.

Ha llegado el momento de presentar un ejemplo. Inicialmente, crearemos, inicializaremos e insertaremos una tabla con cinco filas y tres columnas, al inicio del documento actual. Des­pués definiremos los títulos de las columnas. Escriba el siguiente código, ejecútelo y observe el resultado:

Sub creaTabla

Dim oTxt As Object

Dim oTab As Object

'

' crea, inicializa e inserta la tabla al principio del documento

oTxt = ThisComponent.getText()

oTab = ThisComponent.createInstance("com.sun.star.text.TextTable")

oTab.initialize(5,3)

oTxt.insertTextContent(oTxt.createTextCursor(), oTab, FALSE)

'

' rellena los títulos de las columnas (celdas A1, B1 e C1 )

Dim oCelda As Object

oCelda = oTab.getCellByName("A1")

oCelda.setString("Columna A")

oCelda = oTab.getCellByName("B1")

oCelda.setString("Columna B")

oCelda = oTab.getCellByName("C1")

oCelda.setString("Columna C")

End Sub

Primero creamos el objeto tabla con createInstance (), después definimos las filas y columnas con initialize (), insertamos la tabla en el documento con una llamada al método insertText­Content ( ) y, entonces, obtenemos cada una de las celdas del encabezado y especificamos su contenido.

El siguiente bloque de código demuestra el empleo del cursor de tabla, navegación, formateo y unión de celdas. Añádalo a Sub creaTabla.

'

' crea un cursor de tabla en la celda CellNames(0) = A1

Dim oCurTab As Object

oCurTab = oTab.createCursorByCellName(oTab.CellNames(0))

' selecciona las celdas A1, B1 e C1

oCurTab.gotoStart(FALSE)

oCurTab.goRight(2, True)

' Aplica el estilo de párrafo Título en la selección

oCurTab.paraStyleName = "Heading"

' muestra el nombre de la extensión seleccionada (rango)

' Observe la forma en que se representa (invertida)

MsgBox oCurTab.getRangeName()

'

' nombra las celdas a partir de la línea 2 y

' escribe el número de fila en la columna C

Dim sNombres() As Variant

Dim sNombreCelda As String

sNombres = Array("A","B","C")

For i% = 1 To 4

For j% = 1 To 3

sNombreCelda = sNombres(j%-1)+ Str$(i%+1)

oCelda = oTab.getCellByName(sNombreCelda)

If (j% - 1 = 2) Then

' define un valor numérico para la celda

oCelda.setValue(i% + 1)

Else

oCelda.setString(sNombreCelda)

End If

Next j%

Next i%

'

' define una fórmula (suma de C2 hasta C4) para la celda C5

oCelda = oTab.getCellByName("C5")

oCelda.setFormula("sum <C2:C4>")

'

' une las celdas A5 y B5 y cambia su contenido

oCurTab.gotoCellByName("A5", False)

oCurTab.goRight(1, True)

oCurTab.mergeRange()

oCelda = oTab.getCellByName("A5")

oCelda.setString("Total")

Observe la creación del cursor de tabla con createCursorByCellNames (...), el uso del cursor para formateo, el uso de los métodos setValue () y setFormula () y la selección y unión de las celdas A5 y B5.

En el siguiente bloque de código, veremos la ordenación de una extensión de celdas (A2:C4) de nuestra tabla. Basta insertar el código en Sub creaTabla y ejecutarla nuevamente para ver el resultado.

'

' ordena de A2 hasta C4

Dim oCampoOrd(0) As New com.sun.star.util.SortField

Dim oDescrOrd As Variant

Dim oRango As Object

'

' especifica el rango a ordenar

oRango = oTab.getCellRangeByName("A2:C4")

' define el campo de ordenación y sus propiedades

oCampoOrd(0).Field = 0

oCampoOrd(0).SortAscending = False

oCampoOrd(0).FieldType = com.sun.star.util.SortFieldType.ALPHANUMERIC

' crea el descriptor de ordenación

oDescrOrd = oTab.createSortDescriptor()

' define las propiedades del descriptor

oDescrOrd(0).Name = "SortFields"

oDescrOrd(0).Value = oCampoOrd()

oDescrOrd(1).Name = "ContainsHeader"

oDescrOrd(1).Value = False

oDescrOrd(2).Name = "SortColumns"

oDescrOrd(2).Value = False

' ordena el rango

oRango.sort(oDescrOrd())

Observe que comenzamos por la declaración de las variables, creamos un rango de celdas con una llamada al método getCellRangeByName (), definimos las propiedades del campo de or­denación, creamos el descriptor y definimos sus propiedades (el campo de ordenación es una propiedad del descriptor) y, finalmente, invocamos el método sort () para ejecutar su tarea.

Antes de terminar esta sección, veamos como se obtiene el acceso a las tablas existentes en un documento de texto. El proceso es el mismo visto en la sección 6.7 Localizando Objetos.

El método getTextTables () de la interfaz XTextTablesSupplier devuelve una colección con­teniendo las tablas del documento. Este procedimiento recorre el documento de inicio a fin.

getTextTables () As Object <com.sun.star.container.XNameAccess>

El ejemplo inferior muestra la localización de las tablas de un documento, después obtiene las colecciones de filas y columnas de la tabla de nombre “Tabla3”

Sub localizaTablas

Dim oTablas As Object

Dim oTabla As Object

Dim oFilas As Object

Dim oColumnas As Object

Dim n As Integer

oTablas = ThisComponent.getTextTables()

For n = 0 To oTablas.Count -1

oTabla = oTablas.getByIndex(n)

MsgBox oTabla.getName()

Next n

MsgBox "Tablas en el documento: " + Str$(oTablas.Count)

'

If (oTablas.hasByName ("Tabla3")) Then

oTabla = oTablas.getByName("Tabla3")

oFilas = oTabla.getRows()

oColumnas = oTabla.getColumns()

MsgBox Str$(oFilas.Count)+" - "+Str$(oColumnas.Count)

End If

End Sub

Recuerde que, para acceder a una tabla, usted debe conocer su nombre o su índice dentro de la colección, y, seguidamente, llamar al método getByName () o getByIndex ().

Tras obtener la tabla deseada, use las técnicas ya presentadas para editar su contenido.

Documentos de Calc

Introducción

Un documento de Calc contiene una o más hojas de cálculo. Cada hoja de cálculo está forma­da por celdas organizadas en filas y columnas, de modo parecido a una tabla de Writer. Estas celdas contienen, básicamente, texto, que puede representar una cadena de caracteres, un va­lor numérico, un campo o una fórmula.

Cada uno de los elementos citados (documento, hoja de cálculo y celda), posee características propias. Algunas pueden ser modificadas como, por ejemplo, el estilo de página, el formato numé­rico, de párrafo y de fuente.

Además de tareas comunes de edición, podemos aplicar al contenido de una hoja de cálculo operaciones como ordenación, filtro, totalización, generación de gráficos, etc.

En una hoja de cálculo también podemos insertar objetos como imágenes, diseños, datos de una fuente externa y objetos OLE.

Como usted ya habrá observado, dada la riqueza y la potencia de las operaciones con docu­mentos de Calc, su programación es un asunto extenso. En las próximas secciones, intentare­mos presentar lo básico.

Hojas de cálculo

Las funciones básicas, ya abordadas en el capítulo 5. Trabajando con Documentos, pueden ser usadas también con documentos de Calc. Así, está sección cubrirá algunas operaciones sobre las hojas de cálculo de un documento de Calc.

El módulo com.sun.star.sheet, de la API de OpenOffice.org contiene los principales servi­cios, interfaces y grupos de constantes relacionados con hojas de cálculo.

El servicio SpreadsheetDocument representa el modelo de un documento de Calc, conte­niendo atributos y una o más hojas. La interfaz XSpreadsheetDocument provee del método getSheets ( ), que devuelve una colección con las hojas del documento.

getSheets ( ) As Object <com.sum.star.sheet.XSpreadsheets>

Los objetos de esta colección pueden ser accedidos por sus nombres o índices. Podemos, también, crear una enumeración y usar el acceso secuencial.

La interfaz XSpreadsheets, devuelta por getSheets ( ), especifica los métodos siguientes:

insertNewByName ( sNombre As String, iPosicion As Integer )

moveByName ( sNombre As String, iDestino As Integer )

copyByName ( sNombreOrigen As String, sNombreCopia As String, iPosicion As Integer )

Para fijar los conceptos anteriores, en el siguiente ejemplo, crearemos un documento y efec­tuaremos algunas operaciones con hojas.

Sub creaDocCalc

Dim oDesk As Variant

Dim oDoc As Object

Dim mProp() As Variant

Dim sURL As String

' crea documento de Calc

oDesk = createUnoService("com.sun.star.frame.Desktop")

sUrl = "private:factory/scalc"

oDoc = oDesk.LoadComponentFromURL(sUrl,"_blank",0,mProp())

' muestra la propiedad decimales predefinida en el documento

MsgBox oDoc.StandardDecimals

'

' navega por las hojas existentes en el documento

Dim oHojas As Object

Dim oHoja As Object

Dim sMsg As String

'

oHojas = oDoc.getSheets()

sMsg = ""

For n=0 To oHojas.Count - 1

oHoja = oHojas.getByIndex(n)

sMsg = sMsg + oHoja.getName() + Chr$(13)

Next n

MsgBox sMsg + Str$(oHojas.Count)

' acceso nominal

If oHojas.hasByName("Hoja2") Then

oHoja = oHojas.getByName("Hoja2")

MsgBox oHoja.PageStyle

End If

' inserta una hoja al principio

oHojas.insertNewByName("Hoja4",0)

MsgBox oHojas.Count

' mueve al final

oHojas.moveByName("Hoja4",4)

End Sub

Observe los argumentos para la creación del documento, el acceso a los objetos de la colec­ción y el uso de los métodos para insertar y mover una hoja de cálculo.

El servicio SpreadsheetView suministra funcionalidades relacionadas con la vista actual de un documento de Calc. Incluye el servicio SpreadsheetViewSettings, que especifica algunas propiedades de cada una de las hojas del documento y, su interfaz XspreadsheetView, aporta los métodos a seguir para la definición de la hoja activa en el documento:

getActiveSheet ( ) As Object < XSpreadsheet >

setActiveSheet ( oHoja As Object < XSpreadsheet >)

Recuerde que las operaciones relacionadas con la interfaz gráfica son administradas por el ob­jeto controlador del documento.

Introduzca el código fuente siguiente al final de Sub creaDocCalc, ejecute y observe el resul­tado

' activa la Hoja4 en la GUI

If oHojas.hasByName("Hoja4") Then

MsgBox oDoc.getCurrentController().getActiveSheet().getName()

oHoja = oHojas.getByName("Hoja4")

oDoc.getCurrentController().setActiveSheet(oHoja)

End If

Inicialmente mostramos el nombre de la hoja activa y, entonces, seleccionamos la hoja de nombre Hoja4.

Como se mostró en el capítulo 5. Documentos de Writer, podemos modificar el contenido de un documento independientemente de la interfaz gráfica.

Editando

Para editar el contenido de una o más celdas, debemos tener en mente lo siguiente:

a) obtener la hoja donde se encuentran las celdas a editar;

b) obtener un rango conteniendo las celdas a editar, este paso es opcional, pues una hoja es un rango de celdas;

c) obtener la celda a editar;

d) especificar el contenido de la celda.

El ítem a) se debe solucionar con el uso del método getSheets (), asociado al acceso nominal, indexado o enumerado, como se ha visto en la sección anterior.

Las herramientas para solucionar los ítems b), c) y d) también se presentaron en la sección 6.10 Tablas e involucra los métodos de las interfaces XCellRange e XCell.

Métodos de la interfaz com.sun.star.table.XCellRange:

getCellByPosition ( nColumna As Long, nFila As Long ) As Object < XCell >

getCellRangeByPosition ( nIzq, nSup, nDer, nInf ) As Object < XCellRange >

getCellRangeByName ( sRango As String ) As Object < XCellRange >

Debemos recordar que la posición de una celda, dentro de un rango, es relativa al inicio del rango.

Métodos de la interfaz com.sun.star.table.XCell:

getFormula ( ) As String

setFormula ( sFormula As String )

getValue ( ) As Double

setValue ( nValor As Double )

getType ( ) As Long < com.sun.star.table.CellContentType >

getError ( ) As Long

Para recordarlo, veamos un ejemplo de edición del contenido de las celdas de una hoja. Intro­duzca el código inferior, ejecútelo y observe el resultado.

Sub editaHoja

Dim oDesk As Variant

Dim oDoc As Object

Dim mProp() As Variant

Dim sURL As String

'

' crea documento de Calc

oDesk = createUnoService("com.sun.star.frame.Desktop")

sUrl = "private:factory/scalc"

oDoc = oDesk.LoadComponentFromURL(sUrl, "_blank", 0, mProp())

'

' edita celdas de la hoja

Dim oHoja As Object

Dim oCelda As Object

Dim sTitCol() As String

' escribe los títulos de las columnas

sTitCol = Array ("CÓDIGO","MATERIAL","CANTIDAD","P. UNIT","P. TOTAL")

oHoja = oDoc.getSheets().getByIndex(0)

For i% = 0 To 4

oCelda = oHoja.getCellByPosition(i%, 0)

oCelda.setString(sTitCol(i%))

Next i%

'

' rellena las celdas con texto, valor y fórmula

For i% = 1 To 6

For j% = 0 To 4

oCelda = oHoja.getCellByPosition(j%, i%)

If (j% = 0) Then

If i% < 4 Then

oCelda.setString("A" + Str$(i%))

Else

oCelda.setString("A" + Str$(i%-3))

End If

ElseIf (j% = 1) Then

oCelda.setString("Material de construcción " + Str$(i%))

ElseIf (j% = 2) Then

oCelda.setValue(i% * j%)

ElseIf (j% = 3) Then

oCelda.setValue(100 * Rnd())

Else

sFila = Trim$(Str$(i%+1))

sFormula = "=C" + sFila + " * " + "D" + sFila

oCelda.setFormula(sFormula)

End If

Next j%

Next i%

' resumo

oCelda = oHoja.getCellByPosition(0, 7)

oCelda.setString("COSTE TOTAL")

'

sFormula = "=Sum(E1:E6)"

oCelda = oHoja.getCellByPosition(4, 7)

oCelda.setFormula(sFormula)

'

End Sub

Observe que, en la segunda llamada del método setFormula(), definimos la fórmula usando el nombre de una función en inglés. Para utilizar los nombres de las funciones mostrados por la interfaz gráfica, use la propiedad FormulaLocal, del servicio com.sun.star.sheet.SheetCell., por ejemplo:

oCelda = oHoja.getCellByPosition(4, 7)

sFormula = "=Suma(E1:E6)"

oCelda.FormulaLocal = sFormula

El servicio SheetCell define las siguientes propiedades:

Propiedad	Descripción
Position	Sólo lectura, posición de la celda en la hoja
Size	Sólo lectura, tamaño de la celda en 1/100 mm
FormulaLocal	Cadena con el nombre local de la fórmula
FormulaResultType	Sólo lectura, tipo de resultado de una fórmula
ConditionalFormat	Definiciones de formateo condicional de la celda
ConditionalFormatLocal	Definiciones locales de formateo condicional de la celda
Validation	Definiciones de validación de la celda
ValidationLocal	Definiciones locales de validación de la celda

En la próxima sección, trataremos de la creación y empleo de un cursor, otra funcionalidad de los documentos de Calc.

Navegando por las Celdas

Una celda o un rango de celdas se identifica por su dirección, que está formada por los índices de la hoja, columna inicial, fila inicial, columna final y fila final. La interfaz XCellRangeAd­dressable define el siguiente métodos para la recuperación de esta dirección:

getRangeAddress ( ) As Object < com.sun.star.table.CellRangeAddress >

devuelve una estructura CellRangeAddress con los elementos Sheet, StartColumn, StartRow, EndColumn e EndRow.

En una hoja de cálculo también podemos crear un cursor. Este cursor es un rango de celdas con funcionalidades para navegación, formateo y edición, entre otras.

El servicio Spreadsheet, por medio de la interfaz XSpreadsheet, define los siguientes méto­dos para la creación de un cursor de celdas:

createCursor ( ) As Object < XSheetCellCursor >

devuelve un cursor de celda conteniendo toda la hoja de cálculo.

createCursorByRange (oRango As Object < XSheetCellCursor > )

devuelve un cursor de celda conteniendo el rango de celdas del argumento.

El servicio SheetCellCursor provee de toda la funcionalidad para operar con un cursor de celda. El posee las interfaces XSheetCellCursor y XUsedAreaCursor, además de soportar los servicios table.CellCursor e SheetCellRange.

La interfaz XSheetCellCursor define los siguientes métodos para contraer o expandir el cur­sor:

collapseToCurrentRegion ()

collapseToCurrentArray ()

collapseToMergedArea ()

expandToEntireColumns ()

expandToEntireRows ()

collapseToSize ( nColumnas As Long, nFilas As Long )

Los siguientes métodos, de la interfaz XUsedAreaCursor, son útiles cuando deseamos operar sobre el área utilizada de una hoja de cálculo. Por ejemplo, identificar la última celda con los datos de una hoja.

gotoStartOfUsedArea ( bExpande As Boolean )

gotoEndOfUsedArea ( bExpande As Boolean )

La interfaz XCellCursor, del servicio CellCursor, provee los siguientes métodos, ya explica­dos en la sección 6.10 Tablas del capítulo 6. Documentos de Writer.

gotoStart ( )

gotoEnd ( )

gotoNext ( )

gotoPrevious ( )

gotoOffSet ( nDesplazColumna As Long, nDesplazFila As Long )

Para demostrar el uso de un cursor, introduzca el siguiente código y ejecútelo para observar el resultado.

Sub creaCursorCeldas

Dim oDesk As Variant

Dim oDoc As Object

Dim mProp() As Variant

Dim sURL As String

'

' crea documento de Calc

oDesk = createUnoService("com.sun.star.frame.Desktop")

sUrl = "private:factory/scalc"

oDoc = oDesk.LoadComponentFromURL(sUrl, "_blank", 0, mProp())

'

' trabaja con un cursor

Dim oHojas As Object

Dim oCursor As Object

oHojas = oDoc.getSheets().getByIndex(0)

oCursor = oHojas.createCursorByRange(oHojas.getCellByPosition(0,0))

' soporta XSpreadSheet

MsgBox oCursor.getSpreadsheet().getName()

' edita algunas celdas

' observe que la posición de la celda es relativa

oCursor.getCellByPosition(0,0).setFormula("Celda A1")

oCursor.gotoNext()

oCursor.getCellByPosition(0,0).setFormula("Celda B1")

oCursor.gotoNext()

oCursor.getCellByPosition(0,0).setFormula("Celda C1")

' mueve el cursor 5 celdas hacia abajo

oCursor.gotoOffSet(0,5)

oCursor.getCellByPosition(0,0).setFormula("Abajo de C1")

oCursor.CharHeight = 16

' obtiene toda el área en uso

oCursor.gotoStartOfUsedArea(False)

oCursor.gotoEndOfUsedArea(True)

' obtiene y muestra la dirección del cursor (índices)

oEnd = oCursor.getRangeAddress()

MsgBox Str$(oEnd.Sheet)+Str$(oEnd.StartColumn)+Str$(oEnd.StartRow)

MsgBox Str$(oEnd.Sheet)+Str$(oEnd.EndColumn)+Str$(oEnd.EndRow)

End Sub

Aquí hemos usado el método createCursorByRange ( ), pero podríamos haber usado createCursor ( ). Observe que, para definir el contenido de una celda, debemos obtenerla llamando al método getCellByPosition ( ), con la posición relativa al inicio del rango de celdas del cur­sor. Observe, además, como se da la selección e identificación del área usada por la hoja de cálculo.

Obteniendo objetos seleccionados

Los principales métodos para obtener el contenido de una selección se definen en la interfaz com.sun.star.frame.XModel, son los siguientes:

getCurrentSelection ( ) As < com.sun.star.uno.XInterface >

devuelve la selección en el controlador actual o Null si no existe un controlador.

getCurrentController ( ) As < com.sun.star.frame.XController >

devuelve el controlador del modelo o Null si ningún controlador está registrado.

Diversas situaciones de selección pueden ocurrir, por ejemplo: la selección de un rango de celdas, la selección de un gráfico, etc. A continuación, presentamos las más comunes.

El código siguiente define un objeto celda con la primera celda del rango.

' para una celda: com.sun.star.sheet.SheetCell

oCel = ThisComponent.getCurrentSelection().getCellByPosition(0,0)

La siguiente parte de código obtiene un rango de celdas contínuas y muestra los índices de ho­ja, columna inicial y final, fila inicial y final.

' para un rango: com.sun.star.sheet.CellRange

oRango = oDoc.getCurrentSelection()

oEnd = oRango.getRangeAddress()

MsgBox Str$(oEnd.Sheet)+Str$(oEnd.StartColumn)+Str$(oEnd.StartRow)

MsgBox Str$(oEnd.EndColumn)+Str$(oEnd.EndRow)

Podemos, además, seleccionar rangos de celdas no contínuas, en una misma hoja o en hojas diferentes, el bloque de código siguiente resuelve esta situación. En un documento de Calc, seleccione rangos no contiguos, llame a la macro y ejecútela para ver la salida.

Sub seleccionRangos

Dim oDoc As Object

Dim oRangos As Object

oDoc = ThisComponent

' oRangos soporta com.sun.star.sheet.SheetCellRanges

oRangos = oDoc.getCurrentSelection()

MsgBox oRangos.getCount()

oEnd = oRangos.getRangeAddresses()

For n=0 To UBound(oEnd)

MsgBox Str$(oEnd(n).Sheet)+Str$(oEnd(n).StartColumn)+Str$(oEnd(n).StartRow)

Next n

MsgBox oRangos.getRangeAddressesAsString()

End Sub

El método getCurrentSelection( ) maneja otros objetos, como gráficos o diseños. Podemos usar el método getImplementationName( ) o supportsService( ), para intentar una identifica­ción inicial del objeto seleccionado.

Además, disponemos de la interfaz com.sun.star.view.XSelectionSupplier, que define méto­dos de selección para la interfaz gráfica, entre ellos:

select ( oObjeto As Object ) As Boolean

si es posible, selecciona el objeto oObjeto en la interfaz gráfica.

getSelection ( ) oObjeto As Variant

obtiene la selección en la interfaz gráfica, devolviendo un objeto o una colección de objetos.

Estos métodos pueden ser llamados mediante el objeto controlador del modelo, como se ve a continuación:

' selecciona un rango de celdas en la hoja de cálculo

'

oDoc = ThisComponent

oCtr = oDoc.getCurrentController()

oHoja = oDoc.Sheets(0)

oRango = oHoja.getCellRangeByPosition (0, 1, 4, 6)

If (oCtr.select(oRango)) Then

MsgBox "Seleccionado en la vista"

Else

MsgBox "No seleccionado"

End If

La API de OpenOffice ofrece otras funcionalidades como la selección de un rango durante la ejecución de una macro, que serán abordadas en otras secciones de este documento.

Formateando

La presentación final de un trabajo es muy importante y Calc ofrece una vasta gama de posi­bilidades para auxiliarnos en el formateo de nuestros documentos.

Formateando Párrafos y Caracteres

Inicialmente, podemos aplicar al contenido de una celda las técnicas de formateo de párrafos y caracteres. Los principales servicios, ya presentados en la sección 6.4 Formateando Texto del capítulo anterior, son :

com.sun.star.style.ParagraphProperties

com.sun.star.style.CharacterProperties

El servicio com.sun.star.table.TableRow define las siguientes propiedades para formateo de filas:

Propiedad	Descripción
Height	Define la altura de la fila en 1/100 mm
OptimalHeight	Si True (Verdadero), ajusta automáticamente la altura de la fila
IsVisible	Si False, oculta la fila
IsStartOfNewPage	Si True (Verdadero), inserta un salto de página vertical en esta fila

El servicio com.sun.star.table.TableColumn define las siguientes propiedades para formateo de columnas:

Propiedad	Descripción
Width	Define el ancho de columna en 1/100 mm
OptimalWidth	Si True (Verdadero), ajusta automáticamente el ancho de la columna
IsVisible	Si False, oculta la columna.
IsStartOfNewPage	Si True (Verdadero), inserta un salto de página horizontal en esta columna

Otras propiedades para el formateo de celdas están cubiertas por los servicios:

com.sun.star.table.CellProperties

com.sun.star.table.TableBorder

com.sun.star.table.BorderLine

El servicio CellProperties contiene diversas propiedades. Las más importantes se vieron en la sección 6.10 Tablas del capítulo 6. Documentos de Writer.

Aplicaremos algún formato al ejemplo creado por Sub editaHoja. Añada el siguiente código fuente al final de la subrutina, ejecute la macro y observe la salida:

' Formateo

Dim oRango As Object

Dim oFila As Object

Dim oColumna As Object

'

' formatea párrafos y caracteres

oRango = oHoja.getCellRangeByPosition(0, 0, 5, 0)

oRango.CharHeight = 12

oRango.CharWeight = com.sun.star.awt.FontWeight.BOLD

oRango.ParaAdjust = com.sun.star.style.ParagraphAdjust.CENTER

' ajusta la altura de la fila 1

oFila = oHoja.getRows().getByIndex(0)

oFila.OptimalHeight = True

' ajusta el ancho de la columna B

oColumna = oHoja.getColumns().getByIndex(1)

oColumna.OptimalWidth = True

A destacar en este ejemplo el método de recuperación de filas y columnas, mediante acceso indexado.

Uniendo Celdas

En una hoja de cálculo podemos unir celdas, la interfaz com.sun.star.util.XMergeable define los siguientes métodos con esta finalidad:

merge ( bUnion As Boolean )

Si bUnion es True (Verdadero) une el área del objeto, sino divide

getIsMerged ( ) As Boolean

Devuelve True (Verdadero) cuando el área del objeto está unida, sino devuelve False

Insertando Bordes

Otro aspecto importante en la presentación de una hoja de cálculo es la colocación de los bor­des en torno a las celdas. El servicio CellProperties contiene las siguientes propiedades que definen el tipo de borde de una celda o rango de celdas:

Propiedad	Descripción
TableBorder	Define el borde de una celda o rango de celdas
TopBorder	Define el borde superior de cada celda del rango
BottomBorder	Define el borde inferior de cada celda del rango
RightBorder	Define el borde derecho de cada celda del rango
LeftBorder	Define el borde izquierdo de cada celda del rango

El principal elemento de cada una de estas propiedades es la estructura BorderLine, conte­niendo, entre otros, los campos Color y OuterLineWidth para el color y el grueso del la lí­nea. Para la propiedad TableBorder, podemos definir cuatro líneas: TopLine, BottomLine, RightLine y LeftLine.

Siguiendo con nuestro ejemplo, uniremos algunas celdas, y después, definiremos los bordes para nuestra hoja. Añada el siguiente código a la subrutina Sub editaHoja y observe el resul­tado de la ejecución:

' une celdas

oRango = oHoja.getCellRangeByPosition(0, 7, 3, 7)

oRango.merge(True)

' Define Borde

Dim oBorde As New com.sun.star.table.TableBorder

Dim oLinBorde As New com.sun.star.table.BorderLine

'

oRango = oHoja.getCellRangeByPosition(0, 0, 4, 7)

' define el grosor y color de la línea de borde

oLinBorde.OuterLineWidth = 30

oLinBorde.Color = CLng( "&H000099" )

oRango.setPropertyValue("TopBorder", oLinBorde)

oRango.setPropertyValue("RightBorder", oLinBorde)

oRango.setPropertyValue("LeftBorder", oLinBorde)

oRango.setPropertyValue("BottomBorder", oLinBorde)

' defina y aplica la propiedad TableBorder

oLinBorde.OuterLineWidth = 100

oLinBorde.Color = CLng( "&HAABBCC" )

oBorde.TopLine = oLinBorde

oBorde.BottomLine = oLinBorde

oBorde.RightLine = oLinBorde

oBorde.LeftLine = oLinBorde

oBorde.IsTopLineValid = True

oBorde.IsBottomLineValid = True

oBorde.IsRightLineValid = True

oBorde.IsLeftLineValid = True

oRango.setPropertyValue("TableBorder", oBorde)

Inicialmente definimos los bordes de todas las celdas de oRango, después aplicamos un borde al rango. Observe los campos Is...Valid definidos como True.

Formato Numérico

OpenOffice.org posee diversas categorías de formato numérico. Cada categoría posee diver­sos formatos predefinidos. Mediante la interfaz XNumberFormatsSupplier podemos leer, mo­dificar e añadir nuevos formatos a nuestros documentos.

La interfaz XNumberFormatsSupplier contiene los métodos siguientes:

getNumberFormats ( ) As Object < com.sun.star.util.XNumberFormats >

getNumberFormatsSettings ( ) As Object < com.sun.star.beans.XPropertySet >

Entre los métodos de la interfaz XNumberFormats, tenemos:

getByKey (nClave As Long) As Object < XPropertySet >

queryKeys (nCategoria As Long, nLocal As Long, bInsertar As Boolean) As aArray ( )

queryKey (sFormato As String, nLocal As Long, bBusca As Boolean) As Long

addNew ( sFormato As String, nLocal As Long ) As Long

La interfaz com.sun.star.util.XNumberFormatTypes contiene métodos para obtener el índi­ce de algunos formatos predefinidos. Aquí usaremos el método:

getStandardFormat (nTipo AS Long, nLocal As Long) As Long

El grupo de constantes com.sun.star.util.NumberFormat define valores para, entre otras, las siguientes categorías: DATE, TIME, CURRENCY, NUMBER, DATETIME.

El servicio CellProperties contiene la propiedad NumberFormat, que define el tipo de for­mato numérico de una celda o rango de celdas.

Veamos un ejemplo ilustrativo. En un documento de Calc, cree la macro siguiente, ejecútela y observe el resultado.

Sub muestraFormatosNumericos

Dim oDoc As Object

Dim oFormatos As Object

Dim mClaves As Variant

Dim mProp As Variant

Dim oLocal As New com.sun.star.lang.Locale

oDoc = ThisComponent

oFormatos = oDoc.getNumberFormats()

oSettings = oDoc.getNumberFormatSettings()

oInfo = oSettings.getPropertySetInfo()

oProp = oInfo.getProperties()

MsgBox UBound(oProp)

For n = 0 To UBound(oProp)

MsgBox oProp(n).Name

Next n

mClaves = oFormatos.queryKeys(0, oLocal, FALSE)

MsgBox UBound(mClaves)

mProp = oFormatos.getByKey(11).getPropertyValues()

' obtiene los nombres de las propiedades

sMsg = ""

For n=0 To UBound(mProp)

sMsg = sMsg + mProp(n).Name + Chr$(13)

Next n

MsgBox sMsg

' muestra el valor de FormatString

MsgBox mProp(0).Value

End Sub

Ahora, regresemos a nuestra subrutina Sub editaHoja para aplicar formatos numéricos en al­gunas celdas. Añada el siguiente código, ejecútelo y observe la salida:

' Formatos Numéricos

Dim oFormatos As Object

Dim aLocal() As New com.sun.star.lang.Locale

' obtiene los formatos numéricos del modelo

oFormatos = oDoc.getNumberFormats()

' obtiene el índice del formato predefinido para MONEDA

n% = oFormatos.getStandardFormat( _

com.sun.star.util.NumberFormat.CURRENCY, aLocal())

' obtiene un rango de celdas

oRango = oDoc.getSheets().getByIndex(0).getCellRangeByPosition(3,1,4,6)

' modifica el formato predefinido para MONEDA

oRango.NumberFormat = n%

' obtiene una celda y la formatea como MONEDA

oCelda = oHoja.getCellByPosition(4, 7)

oCelda.NumberFormat = n%

Observe la declaración de los objetos, el uso del método getStandardFormat ( ) y el uso de la propiedad NumberFormat para modificar el formato de las celdas.

Formato Condicional

El servicio com.sun.star.sheet.SheetCellRange contiene las siguientes propiedades para el formato condicional:

conditionalFormat	- define condiciones para formato condicional

conditionalFormatLocal	- define condiciones locales para formato condicional

La interfaz XSheetConditionalEntries provee los métodos siguientes para operaciones con condiciones de formateado:

addNew ( mCond () As < com.sun.star.beans.PropertyValue > )

el argumento mCond es un array con las siguientes entradas:

- “Operator” con los posibles valores definidos en com.sun.star.sheet.ConditionOperator:

NONE, EQUAL, NOT_EQUAL, GREATER, GREATER_EQUAL,

LESS, LESS_EQUAL, BETWEEN, NOT_BETWEEN, FORMULA

- “Formula1” conteniendo una cadena con un valor o fórmula

- “Formula2” conteniendo un valor o fórmula, usada cuando el operador es BETWEEN

- “StyleName” conteniendo un nombre de estilo de formato de celda

removeByIndex ( nIndice As Long )

elimina la condición nIndice

clear ( )

limpia las condiciones actuales para el formato

Añada el código siguiente al final de Sub editaHoja, ejecútelo y observe la salida:

' FORMATO CONDICIONAL

'

Dim mCond(2) As New com.sun.star.beans.PropertyValue

Dim oEntradas As Variant

' obtiene un rango de celdas

oRango = oDoc.getSheets().getByIndex(0).getCellRangeByPosition(4,1,4,6)

' obtiene el formato condicional actual

oEntradas = oRango.getPropertyValue("ConditionalFormat")

' define las propiedades de una condición para formateo

mCond(0).Name = "Operator"

mCond(0).Value = com.sun.star.sheet.ConditionOperator.GREATER

mCond(1).Name = "Formula1"

mCond(1).Value = "500"

mCond(2).Name = "StyleName"

mCond(2).Value = "Result"

' limpia las condiciones existentes

oEntradas.clear()

' añade una nueva condición

oEntradas.addNew(mCond())

' aplica el formato condicional

oRango.setPropertyValue("ConditionalFormat", oEntradas)

En este código, aplicamos el estilo “Resultado” si el valor de la celda es mayor de 500,00 €.

También podemos aplicar estilos de formato de celdas definidos por los usuarios.

Búsqueda y Reemplazo

La búsqueda y reemplazo, en un documento de Calc, funciona de modo semejante a lo visto en la sección 6.8 Búsqueda y Reemplazo, del capítulo 6. Documentos de Writer.

Recordando, la interfaz com.sun.star.util.XSearchable proporciona los métodos de búsque­da siguientes:

createSearchDescriptor ( ) As Object <SearchDescriptor>

FindAll ( oDescriptor As Object ) As Object <com.sun.star.container.XIndexAccess>

FindFirst ( oDescriptor As Object ) As Object <com.sun.star.uno.XInterface>

FindNext ( oInicio As Object, oDescriptor As Object ) As Object <Xinterface>

El servicio SearchDescriptor tiene los siguientes métodos:

getSearchString ( ) As String

setSearchString ( sCadena As String )

He aquí algunas de sus propiedades:

Propiedad	Descripción
SearchBackwards	Si True (Verdadero), busca hacia el principio del documento.
SearchCaseSensitive	Si True (Verdadero), considera mayúsculas/minúsculas.
SearchWords	Si True (Verdadero), localiza tan sólo las celdas con el texto exacto sin más, si no, localiza también las celdas donde el texto forma parte del contenido.
SearchStyles	Si True (Verdadero), busca por un estilo de celda.

Veamos un ejemplo de búsqueda: cree un nuevo documento de Calc, rellene algunas celdas con el texto “TOTAL” y “TOTAL GENERAL”, seguidamente cree la macro inferior y ejecu­te.

Sub buscaTexto

Dim oDoc As Object

Dim oDescBusca As Object

Dim oHoja As Object

oDoc = ThisComponent

oHoja = oDoc.Sheets(0)

oDescBusca = oHoja.createSearchDescriptor()

oDescBusca.SearchWords = True

oDescBusca.setSearchString ("TOTAL")

oResultado = oHoja.findFirst( oDescBusca )

i = 0

Do Until IsNull(oResultado)

oResultado.CharColor = RGB(250,100,50)

oResultado = oHoja.findNext(oResultado, oDescBusca )

i = i + 1

Loop

MsgBox "Ocurrencias de "+oDescBusca.getSearchString() + " " + Str$(i)

End Sub

Ahora, cambie la propiedad SearchWords a False y ejecute nuevamente la macro observan­do su resultado.

La sustitución de texto se implementa por la interfaz XReplaceable, que hereda las caracterís­ticas de XSearchable. Ella proporciona los métodos:

createReplaceDescriptor ( ) As Object <com.sun.star.util.XReplaceDescriptor>

replaceAll ( xDescriptor As Object <com.sun.star.util.XReplaceDescriptor>) As Long

El servicio ReplaceDescriptor tiene métodos para obtener y asignar la cadena de reemplazo:

getReplaceString ( ) As String

setReplaceString ( sCadena As String )

He aquí una búsqueda y reemplazo sencillas, en el mismo documento del ejemplo anterior:

Sub reemplazaTexto

Dim oDoc As Object

Dim oDescriptor As Object

Dim oHoja As Object

oDoc = ThisComponent

oHoja = oDoc.Sheets(0)

oDescriptor = oHoja.createReplaceDescriptor()

oDescriptor.setSearchString( "TOTAL GENERAL" )

oDescriptor.setReplaceString( "Total" )

n = oHoja.replaceAll(oDescriptor)

sMsg = oDescriptor.getSearchString()+" por "+oDescriptor.getReplaceString()

MsgBox sMsg + " = " + Str$(n)

End Sub

Observe que debemos ejecutar la búsqueda y reemplazo en un rango de celdas. En los ejem­plos utilizamos toda la hoja de cálculo.

Ordenando

Para la ordenación de un rango de celdas, debemos utilizar los mismos conceptos y servicios ya presentados en la sección 6.10 Tablas, del capítulo 6. Documentos de Writer.

A continuación, detallamos los principales métodos y propiedades utilizados en esta tarea.

Métodos de la interfaz com.sun.star.util.XSortable:

createSortDescriptor ( ) As Variant <com.sun.star.beans.PropertyValue>

sort (xDescriptor As Variant <com.sun.star.beans.PropertyValue> )

Algunas de las propiedades del descriptor de ordenación (SortDescriptor):

Propiedad	Descripción
IsCaseSensitive	Si True (Verdadero), considera mayúsculas / minúsculas
SortAscending	Si True (Verdadero), ordenación ascendente
SortColumns	Si True (Verdadero) ordena por columnas, sino, lo hace por filas

El servicio com.sun.star.table.TableSortDescriptor incluye el servicio SortDescriptor y po­see las propiedades siguientes:

Propiedad	Descripción
SortFields	Describe los campos de ordenación <com.sun.star.util.Sort­Field>
MaxFieldCount	Define el número máximo de campos, propiedad de sólo lectura
Orientation	Define la orientación de la ordenación <com.sun.star.table.Ta­bleOrientation>
ContainsHeader	Si True (Verdadero), trata la primera fila como títulos, sin orde­narla.

En el siguiente bloque de código, veremos la ordenación de un rango de celdas (A2:E7), del documento creado por la subrutina Sub editaHoja. Introduzca el siguiente código al final de la macro, ejecute y observe la salida.

' ============================

' ORDENANDO UN RANGO DE CELDAS

' ============================

Dim oCampoOrd(0) As New com.sun.star.util.SortField

Dim oDescrOrd As Variant

'

' define el rango a ser ordenado (A2:E7)

oRango = oDoc.getSheets().getByIndex(0).getCellRangeByPosition(0,1,4,6)

' define el campo de ordenación y sus propiedades

oCampoOrd(0).Field = 0

oCampoOrd(0).SortAscending = True

oCampoOrd(0).FieldType = com.sun.star.util.SortFieldType.ALPHANUMERIC

' crea el descriptor de ordenación

oDescrOrd = oRango.createSortDescriptor()

' define as propiedades del descriptor

oDescrOrd(0).Name = "SortFields"

oDescrOrd(0).Value = oCampoOrd()

oDescrOrd(1).Name = "ContainsHeader"

oDescrOrd(1).Value = False

oDescrOrd(2).Name = "SortColumns"

oDescrOrd(2).Value = False

' ordena el rango

oRango.sort(oDescrOrd())

Observe que comenzamos por la declaración de variables, creamos un rango de celdas con una llamada al método getCellRangeByPosition (), definimos sus propiedades (el campo de ordenación es una propiedad del descriptor) y, finalmente, invocamos el método sort () para ejecutar su tarea.

Filtrando dados

En esta sección, veremos los principales servicios e interfaces relacionados con la aplicación de filtros a un rango de celdas.

La interfaz com.sun.star.sheet.XSheetFilterable especifica los métodos siguientes:

createFilterDescriptor ( bVacio As Boolean ) As Object < XSheetFilterDescriptor >

crea un descriptor vacío si bVacio es True, si no, preserva las informaciones

filter ( oDescriptor As Object < XSheetFilterDescriptor > )

aplica el filtro al rango de celdas

El servicio SheetFilterDescriptor controla las condiciones de la operación de filtro. He aquí algunas de sus propiedades:

Propiedad	Descripción
IsCaseSensitive	Si True (Verdadero), distingue mayúsculas y minúsculas
SkipDuplicates	Si True (Verdadero), se omitirán las entradas duplicadas
Orientation	Filtra por Filas o Columnas ( TableOrientation )
ContainsHeader	La primera fila o columna es un encabezado
CopyOutputData	Si True (Verdadero), el resultado se copiará en otro lugar
OutputPosition	Lugar para la copia ( estructura CellAddress )

La interfaz XSheetFilterDescriptor contiene los siguientes métodos para obtener y definir los campos con los criterios del filtro:

getFilterFields ( ) aCampos () As Object < TableFilterField >

devuelve los campos con los criterios de filtrado

setFilterFields ( aCampos () As Object < TableFilterField > )

define los campos con los criterios de filtrado

A estructura com.sun.star.table.TableFilterField contiene los siguientes elementos:

Connection	- como será la conexión con la condición anterior ( Or / And )

Field	- la columna usada en la condición

Operator	- operador condicional ( FilterOperator )

IsNumeric	- si True (Verdadero), el valor del campo (Field) es numérico

NumericValue	- valor del campo, a usar si IsNumeric es True (Verdadero)

StringValue	- cadena de caracteres, a usar si IsNumeric es False

Los pasos necesarios para filtrar datos en una hoja de cálculo son:

a) obtener el rango de celdas a filtrar;

b) definir la estructura de los campos con los criterios de filtro;

c) crear y definir los datos del descriptor del filtro;

d) aplicar el filtro.

Veamos una sección de código que aplica un filtro sencillo en un rango de celdas.

Sub aplicaFiltro

Dim oDoc As Object

Dim oHoja As Object

Dim oRango As Object

Dim oDescFiltro As Variant

Dim oCamposFiltro(0) As New com.sun.star.sheet.TableFilterField

oDoc = ThisComponent

oHoja = oDoc.getSheets().getByIndex(0)

oRango = oHoja.getCellRangeByPosition(0,1,4,6)

' define la estructura TableFilterField

oCamposFiltro(0).Field = 4

oCamposFiltro(0).IsNumeric = True

oCamposFiltro(0).Operator = _

com.sun.star.sheet.FilterOperator.GREATER_EQUAL

oCamposFiltro(0).NumericValue = 300

' crea el descriptor de filtro vacío (True)

oDescFiltro = oRango.createFilterDescriptor (True)

' define el campo de filtro

oDescFiltro.setFilterFields (oCamposFiltro())

' aplica el filtro

oRango.filter (oDescFiltro)

'

MsgBox "OK para filtrar Caracteres"

' redefine la estructura TableFilterField

oCamposFiltro(0).Field = 0

oCamposFiltro(0).IsNumeric = False

oCamposFiltro(0).Operator = com.sun.star.sheet.FilterOperator.GREATER

oCamposFiltro(0).StringValue = "A 1"

' crea un descriptor de filtro vacío (True)

oDescFiltro = oRango.createFilterDescriptor (True)

' define o campo de filtro

oDescFiltro.setFilterFields (oCamposFiltro())

' aplica o filtro

oRango.filter (oDescFiltro)

End Sub

Si quiere usted probar este código, inserte esta macro en el documento generado por la subrutina Sub editaHoja y ejecútela, observando la salida. Observe que la estructura TableFilterField puede tener más de un campo con criterios de filtro.

Intente añadir código para copiar el resultado del filtro en la Hoja2 del documento.

Insertando Subtotales

Las operaciones de totalización sobre un rango de celdas, son tremendamente prácticas. La API de OpenOffice.org ofrece diversos servicios e interfaces para la programación de subtota­les.

La interfaz XSubTotalCalculatable define los siguientes métodos:

createSubTotalDescriptor ( bVacio As Boolean ) As Object < XSubTotalDescriptor >

crea un descriptor de subtotal vacío si bVacio es True, sino, preserva los datos anteriores

applySubTotals ( oDesc As Object < XSubTotalDescriptor >, bReemplaza As Boolean )

aplica el subtotal, si bReemplaza es True, el resultado anterior será sustituido

removeSubTotals ( )

elimina los subtotales del objeto

El servicio SubTotalDescriptor es una representación de como se crearán los subtotales. A continuación, algunas de sus propiedades:

Propiedad	Descripción
InsertPageBreaks	Inserta un salto de página después de cada subtotal
IsCaseSensitive	Considera letras mayúsculas y minúsculas
EnableUserSortList	Si True (Verdadero) permite la definición de una lista para la or­denación
UserSortListIndex	La lista a ordenar, si EnableUserSortList es True (Verdadero)
EnableSort	Define si el contenido de los campos estará ordenado
SortAscending	Si True (Verdadero), la ordenación será creciente (depende de EnableSort )

Además de las propiedades anteriores, el descriptor debe contener los campos de subtotales. La interfaz XSubTotalDescriptor proporciona métodos para añadir o eliminar campos:

addNew ( aColumnas() As < SubTotalColumn >, nColGrupo As Long)

añade los campos al descriptor, nColGrupo especifica la columna base para la agrupación

clear ( )

elimina todos los campos de subtotales del objeto

La estructura com.sun.star.sheet.SubTotalColumn contiene los elementos:

Column	- índice de la columna a subtotalizar

Function	- el tipo de subtotal, definido en com.sun.star.sheet.GeneralFunction

Los pasos necesarios para añadir filas con subtotales en un rango son:

a) obtener el rango de celdas a totalizar;

b) definir la estructura de los campos de subtotal;

c) crear y definir los datos del descriptor de subtotal;

d) aplicar la operación de subtotal.

Veamos un segmento de código que aplica un subtotal en un rango de celdas.

Sub aplicaSubTotal

Dim oDoc As Object

Dim oHoja As Object

Dim oRango As Object

Dim oDescSubTotal As Variant

Dim oCamposSubTotal(0) As New com.sun.star.sheet.SubTotalColumn

oDoc = ThisComponent

oHoja = oDoc.getSheets().getByIndex(0)

oRango = oHoja.getCellRangeByPosition(0,0,4,6)

' define a estructura SubTotalColumn

oCamposSubTotal(0).Column = 4

oCamposSubTotal(0).Function = com.sun.star.sheet.GeneralFunction.SUM

' crea un descriptor de subtotal

oDescSubTotal = oRango.createSubTotalDescriptor (True)

' añade el campo subtotal y la columna base

oDescSubTotal.addNew (oCamposSubTotal(), 0)

' aplica el subtotal

oRango.applySubTotals(oDescSubTotal, True)

End Sub

Para comprobar este código, cree una macro en el documento generado por Sub editaHoja, ejecútelo y analice el resultado.

Gráficos

Un gráfico es un documento incrustado en otro documento de OpenOffice.org. La API de OpenOffice.org contiene diversos servicios e interfaces para la generación de gráficos, a partir de los datos contenidos en una hoja de cálculo.

El servicio com.sun.star.table.TableCharts soporta los métodos de las interfaces XTable­Charts, XIndexAccess y XEnumerationAccess.

Métodos de la interfaz com.sun.star.table.XTableCharts:

addNewByName ( sNombre As String,

oArea As Object < com.sun.star.awt.Rectangle >,

oRango ( ) As Object < com.sun.star.table.CellRangeAddress >,

bTitCol As Boolean, bTitLin As Boolean )

Añade el gráfico a la colección de gráficos de la hoja. Sus argumentos son:

sNombre	- el nombre del gráfico

oArea	- el área (rectángulo) donde se dibujará el gráfico

oRango	- el rango de celdas con los datos

bTitCol	- si True (Verdadero), los datos de la fila superior constituirán la leyenda

bTitLin	- si True (Verdadero), la primera columna formará los títulos del eje

removeByName ( sNombre As String )

elimina el gráfico con el nombre sNombre de la colección.

El servicio com.sun.star.table.TableChart soporta la interfaz XTableChart con los métodos:

getHasColumnHeaders ( ) As Boolean

setHasColumnHeaders ( bTituloColumna As Boolean )

getHasRowHeaders ( ) As Boolean

setHasRowHeaders ( bTituloColumna As Boolean )

getRanges ( ) As sRangos ( ) < CellRangeAddress >

setRanges ( sRangos ( ) As Object < CellRangeAddress > )

Un documento gráfico contiene una referencia para un origen de datos, un diagrama y algunas propiedades como título, subtítulo y leyenda. El servicio ChartDocument es el modelo de documento gráfico y soporta las interfaces XChartDocument, XPropertySet y XMultiServi­ceFactory. El mismo posee las siguientes propiedades:

HasMainTitle	- Si True (Verdadero), muestra el título principal

HasSubTitle	- Si True (Verdadero), muestra el subtítulo

HasLegend	- Si True (Verdadero), muestra la leyenda

La interfaz com.sun.star.chart.XChartDocument proporciona los métodos:

getTitle ( ) As < com.sun.star.drawing.XShape >

getSubTitle ( ) As < com.sun.star.drawing.XShape >

getLegend ( ) As < com.sun.star.drawing.XShape >

getArea ( ) As < com.sun.star.beans.XPropertySet >

getDiagram ( ) As < com.sun.star.chart.XDiagram >

setDiagram ( oDiagrama As < com.sun.star.chart.XDiagram >)

getData ( ) As < com.sun.star.chart.XChartData >

attachData ( oDatosExternos As < com.sun.star.chart.XChartData >)

El diagrama es el objeto que contiene la forma del gráfico, basada en el servicio Diagram y sus interfaces XDiagram y XPropertySet. Diferentes tipos de diagramas pueden ser creados con el método createInstance (), de la interfaz XMultiServiceFactory. He aquí algunos ser­vicios para tipos de diagramas:

com.sun.star.chart.BarDiagram

com.sun.star.chart.LineDiagram

com.sun.star.chart.PieDiagram

com.sun.star.chart.AreaDiagram

com.sun.star.chart.XYDiagram

Podemos modificar la propiedad Diagram de un gráfico con el siguiente código:

oDiagrama = oGraf.createInstance("com.sun.star.chart.PieDiagram")

oGrafico.setDiagram ( oDiagrama )

El servicio com.sun.star.chart.Diagram tiene las siguientes propiedades:

DataRowSource	- define si las series de datos están orientadas en filas o columnas

DataCaption	- define como se mostrará la leyenda de los datos

Para crear un gráfico debemos seguir los siguientes pasos:

a) definir los datos a mostrar por el gráfico;

b) definir el área rectangular donde se diseñará el gráfico;

c) añadir el gráfico a la colección;

d) recuperar el objeto gráfico incrustado;

e) definir las propiedades del gráfico.

Veamos un ejemplo sencillo. Introduzca la macro siguiente y, tras ejecutarla, observe la sali­da:

Sub creaGrafico

Dim oDesk As Variant

Dim oDoc As Object

Dim mProp() As Variant

Dim sURL As String

' crea documento de Calc

oDesk = createUnoService("com.sun.star.frame.Desktop")

sUrl = "private:factory/scalc"

oDoc = oDesk.LoadComponentFromURL(sUrl, "_blank", 0, mProp())

' edita celdas de la hoja de cálculo

Dim oHoja As Object

Dim oCelda As Object

Dim sTitCol() As String

' escribe los títulos de las columnas

sTitCol = Array ("Período","Ordenador","Periférico","Servicio","Total")

oHoja = oDoc.getSheets().getByIndex(0)

For i% = 0 To 4

oCelda = oHoja.getCellByPosition(i%, 0)

oCelda.setString(sTitCol(i%))

Next i%

' rellene las celdas con texto, valor y fórmula

For i% = 1 To 4

For j% = 0 To 4

oCelda = oHoja.getCellByPosition(j%, i%)

If (j% = 0) Then

oCelda.setString(Str$(i%) + "º Trim")

ElseIf (j% > 0 And j < 4) Then

oCelda.setValue(1000 * Rnd())

Else

sRango = "B" + Trim$(Str$(i%+1)) + ":" + "D" + Trim$(Str$(i%+1))

sFormula = "=Suma(" + sRango + ")"

oCelda.FormulaLocal = sFormula

End If

Next j%

Next i%

'

' inserta un gráfico de columnas

Dim oRect As New com.sun.star.awt.Rectangle

Dim oFinRango(0) As New com.sun.star.table.CellRangeAddress

Dim oGraficos As Object

' define el nombre del gráfico

sNombre = "Trimestral"

' define la dirección del rango de celdas con los datos

oFinRango(0).Sheet = 0

oFinRango(0).StartColumn = 0

oFinRango(0).StartRow = 0

oFinRango(0).EndColumn = 3

oFinRango(0).EndRow = 4

' define el área del gráfico

oRect.X = 1000

oRect.Y = 3000

oRect.Width = 12000

oRect.Height = 12000

' obtiene la colección de gráficos de la Hoja1

oGraficos = oHoja.Charts

' añade un gráfico a la colección

oGraficos.addNewByName(sNombre, oRect, oFinRango(), True, True)

' define las propiedades(Titulo)

oGraf = oGraficos.getByName(sNombre).getEmbeddedObject()

oGraf.Title.String = "Facturación Trimestral"

oGraf.HasSubTitle = True

oGraf.SubTitle.String = "Año 2003"

End Sub

Comenzamos rellenando las celdas con los datos, después definimos el nombre del gráfico, el rango de las celdas con los datos y el área donde se dibujará el gráfico. Tras estos pasos preli­minares, obtenemos la colección de gráficos de la hoja y añadimos nuestro gráfico a la colec­ción, con una llamada al método addNewByName ( ). Finalmente, obtenemos el objeto grá­fico incrustado, con una llamada el método getByName ( ) asociada al método getEmbedde­dObject ( ) y, entonces, modificamos algunas propiedades del gráfico.

Aprovechando el ejemplo anterior, mostraremos como modificar la propiedad Diagram de un gráfico. Añada el siguiente código al final de Sub creaGrafico y ejecútelo para crear un grá­fico de pastel (circular), representando los datos de la fila 2 de la hoja de cálculo.

' Creando un gráfico do tipo circular

Dim oRangoCirc(1) As New com.sun.star.table.CellRangeAddress

'

MsgBox "Aceptar para un gráfico Circular"

' elimina el gráfico de barras

oGraficos.removeByName(sNombre)

sNombre = "GrafCirc"

' define la dirección del rango de las celdas con leyendas

oRangoCirc(0).Sheet = 0

oRangoCirc(0).StartColumn = 0

oRangoCirc(0).StartRow = 0

oRangoCirc(0).EndColumn = 3

oRangoCirc(0).EndRow = 0

' define la dirección del rango con datos

oRangoCirc(1).Sheet = 0

oRangoCirc(1).StartColumn = 0

oRangoCirc(1).StartRow = 1

oRangoCirc(1).EndColumn = 3

oRangoCirc(1).EndRow = 1

' añade un gráfico a la colección

oGraficos.addNewByName(sNombre, oRect, oRangoCirc(), True, True)

' define las propiedades

oGraf = oGraficos.getByName(sNombre).getEmbeddedObject()

oGraf.Diagram = oGraf.createInstance("com.sun.star.chart.PieDiagram")

oGraf.Diagram.DataRowSource = com.sun.star.chart.ChartDataRowSource.ROWS

oGraf.Title.String = "1º Trimestre – 2003"

Observe que tenemos un array de estructuras CellRangeAddress, donde el primer elemento contiene los datos de la leyenda del gráfico y el segundo los datos a ser representados. Obser­ve también el cambio de la propiedad Diagram con una llamada al método createInstance ( ) y la modificación de la propiedad DataRowSource del diagrama.

Compruebe, además, que el hecho de poder definir un array CellRangeAddress, indica que podemos tener rangos de celdas, contiguas o no, conteniendo los datos a representar gráfica­mente.

Más información

En la red

OpenOffice.org :

http://www.openoffice.org

http://www.openoffice.org.br (en portugués - Brasil)

http://es.openoffice.org (en español)

Proyecto de Documentación de OpenOffice.org:

http://documentation.openoffice.org

API de OpenOffice.org http://api.openoffice.org

Este es el sitio indicado para los interesados en el desarrollo con OpenOffice.org. Además del SDK, usted encontrará:

OpenOffice.org 1.0.2 – Developers Guide (~ 12 Mb )

Manual de Referencia de la API OpenOffice.org (~ 8 Mb )

StarOffice Programmers Tutorial (~ 1 Mb )

Ejemplos de la Developers Guide (~ 1 Mb )

Sun Microsystems http://docs.sun.com/db/doc/817-1826-10

El enlace apunta a StarOffice 6.0 Software Basic Programmer's Guide, un manual introductorio bastante interesante.

OOoDocs.Org http://www.ooodocs.org

Documentación y notícias sobre o OpenOffice.org.

OOoMacros http://ooomacros.sourceforge.net

Repositorio de modelos, macros y asistentes para OpenOffice.org. Descargue todas las ma­cros y estudie su código para aprender más.

OOExtras http://ooextras.sourceforge.net

Abundantes modelos, plantillas, macros e imágenes para añadir a la galería. Vale la pena curiosear por aquí.

Pitonyak.org www.pitonyak.org/

Andrew Pitonyak y sus colaboradores merecen nuestra gratitud. Esta página contiene un excelente documento sobre macros y lenguaje Basic. Consúltela periódicamente.

Con el autor

Acepto solicitudes de correcciones, inclusión de nuevos tópicos, contribuciones o aclaracio­nes sobre OpenOffice.org Basic. Envíe un mensaje a:

noelsonduarte@globo.com

Créditos, Agradecimientos, Licencia

Créditos

Autor del diseño gráfico del modelo: Mirto Silvio Busico <m.busico@ieee.org>

Autor del texto explicativo del modelo: Gianluca Turconi <luctur@openoffice.org>

La traducción al español y adaptación de pantallazos a OOo 1.1 ha sido perpetrada por Ismael Fanlo <ifanlo@tiscali.es>

Agradecimientos

A Sun Microsystems, Inc por el apoyo para la creación y desarrollo de OpenOffice.org.

A Sun Microsystems, Inc, una vez más, por hacer disponible la documentación sobre la API de OpenOffice.org, sin la cual este trabajo no sería posible.

A todos los voluntarios que, con su trabajo, contribuyen al crecimiento de OpenOffice.org.

Licencia

Se permite la copia, distribución y / o modificación de este documento, bajo los términos de la GNU Free Documentation License, Versión 1.1 o una versión posterior publicada por la Free Software Foundation. Una copia de la licencia a compaña a este documento, consulte el ar­chivo FDL.TXT. Si usted no recibió una copia de este archivo, por favor informe al autor o al webmaster del sitio donde obtuvo este documento.

Copyright © 2003 Noelson Alves Duarte.

N. del T.: Esta traducción española ha sido adaptada a la versión 1.1, por cuyo motivo las capturas de pantalla y al­gunos menús, pueden diferir de los que se mostraban en la obra original, elaborada a partir de la versión 1.0.1. Además, la inclusión en la más reciente versión de OpenOffice.org de una potente grabadora de macros (no tratada en esta Introducción), abre perspecti­vas insospechadas para los usuarios, al permitirles crear sus macros sin necesidad de ser expertos progra­madores.

N. del T.: Todo lo que se describe acerca de las posibilidades de ordenación dentro de la tabla, está comprobado en OpenOffice.org versión 1.0.3, pero en la versión 1.1.RC no funciona. Todavía no tenemos claro si responde a alguna modificación en la API, o algún otro tipo de error. En posteriores versiones de este documento quedará debidamente aclarada esta cuestión.

N. del T.: Este código funciona perfectamente en la versión 1.0.3 de OpenOffice.org, pero en el momento de escribir la traducción, adaptándola a la versión 1.1.RC3 nos hemos encontrado con que no funciona. En posteriores revisiones del presente documento quedará debidamente aclarada esta cuestión.

N. del T. Para esta sección rige lo que ya comentamos hablando de la ordenación de tablas en Writer. Los métodos descritos son válidos en las versiones 1.0.x de OpenOffice.org, pero no funcionan en la versión 1.1.RC. En posteriores revisiones de la presente Introducción... dejaremos el tema suficientemente concretado.

Versión 1

Introducción a OpenOffice.org Basic	4

4	Introducción a OpenOffice.org Basic

Noelson Duarte

2003-04-04T11:48:23

Ismael Fanlo