Trabajando con Apache OpenOffice

From Apache OpenOffice Wiki
< ES‎ | Manuales‎ | GuiaAOO‎ | TemasAvanzados‎ | Macros‎ | Python
Revision as of 04:54, 25 April 2013 by Mauriciobaeza (Talk | contribs)

Jump to: navigation, search


Conceptos iniciales

Este es el tema más importante para crear macros, de forma sencilla, pero se ven las bases para trabajar con todo AOO, por eso es importante no avanzar en estas notas, sin antes haber comprendido a cabalidad los temas presentes.

UNO (Universal Network Objects), es la especificación que da acceso a todos los objetos de Apache OpenOffice.

El API (Application Programer Interface) de Apache OpenOffice proporciona el acceso a toda la funcionalidad de AOO, independientemente del lenguaje.

La comunicación entre objetos UNO se basa en interfaces de objeto. Las interfaces pueden ser vistos desde el exterior o el interior de un objeto y proporcionan formas de ver o manipular el objeto.

Los servicios son agrupaciones lógicas de interfaces, son la forma en que un mismo objeto pueda ofrecer la funcionalidad de varias interfaces.

Los servicios se pueden implementar en librerías compartidas llamadas componentes UNO, con Python podemos crear componentes nuevos y generalmente el usuario final las recibe como una extensión OXT.

Los modulos pueden agrupar submodulos, servicios, excepciones, constantes, enumeraciones, etc, se utilizan para especificar bloques coherentes en la API, esto permite tener un APi bien estructurada.


Creando servicios

Para crear un servicio, usamos la fabrica de servicios (com.sun.star.lang.XMultiComponentFactory), una interfaz especial para crear nuevos servicios, pero para llegar a ella, tenemos que hacerlo a traves de la interfaz ComponentContext (com.sun.star.uno.XComponentContext), como puedes verlo en la siguiente imagen.

ComponentContext y ServiceManager


En pyUNO tenemos dos formas de acceder a esta interfaz, las dos son equivalentes por lo que puedes usar la que prefieras. En la introducción a Python se mencionó que la mayoría de sus herramientas están disponibles en librerias, estás librerias tienen que importarse antes de poder usarse, en nuestro caso importaremos la librería uno que nos da acceso (entre otras cosas) al contexto de ejecución de AOO.

import uno
 
def pruebas():
    ctx1 = XSCRIPTCONTEXT.getComponentContext()
    ctx2 = uno.getComponentContext()
    return

Template:Documentation/Note


Ahora si, podemos acceder a la fábrica de servicios con el método getServiceManager().

import uno
 
def pruebas():
    ctx = uno.getComponentContext()
    sm = ctx.getServiceManager()
    return


Pero... ¿como sabemos que este objeto (ComponentContext) tiene este método getServiceManager()? porque lo estamos demostrando, si, también por eso, pero también porque puedes ver su documentación (com.sun.star.uno.XComponentContext) en el API de AOO, pero más importante aún, porque podemos hacer que el mismo objeto te diga todo lo que sabe hacer. Para ello haremos uso de una magnifica extensión que te tiene que acompañar el resto de tus días como programador de macros Python, nos referimos a MRI. Instala (tal vez tengas que reiniciar AOO para poder usarla) y la probamos de la siguiente manera.

import uno
 
def pruebas():
    ctx = uno.getComponentContext()
    # llamamos a la extensión MRI y le pasamos el objeto a inspeccionar
    mri(ctx)
    sm = ctx.getServiceManager()
    return 
 
def mri(target):
    ctx = uno.getComponentContext()
    sm = ctx.getServiceManager()    
    mri = sm.createInstanceWithContext('mytools.Mri', ctx)
    mri.inspect(target)
    return


Observa en la imágen siguiente, como hemos seleccionado los métodos del objeto y nos lista todos los que tenga, hemos remarcado el que por ahora nos interesa getServiceManager(), observa al final de la línea que efectivamente este método nos devuelve una instancia de la interfaz com.sun.star.lang.XMultiComponentFactory.

Usando la extensión MRI


La gran ventaja de usar esta extensión (que por cierto esta hecha en Python), es que siempre te devolverá la información directamente del objeto, a esto se le llama instrospección. Acostumbrate a usarla.

Ahora si, ya podemos crear una instancia de cualquier servicio o interfaz disponible en AOO, por ejemplo, el servicio com.sun.star.frame.Desktop.

import uno
 
def pruebas():
    ctx = uno.getComponentContext()
    sm = ctx.getServiceManager()
    desktop = sm.createInstanceWithContext('com.sun.star.frame.Desktop', ctx)
    return


Existe una forma alternativa de crear este servicio, usando XSCRIPTCONTEXT de la siguiente manera.

    XSCRIPTCONTEXT.getDesktop()

Template:Documentation/Note


¿Y para que sirve este servicio? Entre otras cosas para crear nuevos documentos.

nuevo = desktop.loadComponentFromURL('private:factory/scalc', '_default', 0, ())

Más adelante veremos a detalle este método y otros relacionados con los documentos de AOO.


El servicio com.sun.star.frame.Desktop es la instancia de la administración central para todas las aplicaciones AOO. Todas las ventanas de la aplicación AOO se organizan en una jerarquía de marcos que contienen componentes visibles.

Desktop administra los componentes y marcos.

Para los fines de crear macros es suficiente que recuerdes que, Desktop es el marco raíz de toda la jerarquía de documentos.


Para crear la instancia del servicio com.sun.star.frame.Desktop usamos un contexto y usamos el método createInstanceWithContext. Otros servicios no requieren de contexto para ser instanciados y usados, por ejemplo, el servicio com.sun.star.util.PathSettings que nos sirve para obtener las rutas de trabajo actuales en AOO, para estos casos usamos el método createInstance.

    rutas = sm.createInstance('com.sun.star.util.PathSettings')
    # mostramos la ruta de trabajo del usuario
    print (rutas.Work)


Ahora que ya sabemos instanciar servicios, veamos de nuevo nuestra macro para mostrar un mensaje en pantalla y analicemosla línea a línea para que veas que sencillo es, además, nos servirá para ver otros detalles al programar con Python en AOO. La macro tiene ahora unos ligeros cambios para que trabaje mejor y para explicar algunas cosas, veamos cuales.

def msgbox(message):
    from com.sun.star.awt import Rectangle
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK
 
    if not isinstance(message, (unicode, str)):
        message = str(message)
    ctx = uno.getComponentContext()
    sm = ctx.getServiceManager()
    toolkit = sm.createInstanceWithContext('com.sun.star.awt.Toolkit', ctx)
    MsgBox = toolkit.createMessageBox(
                                    toolkit.getDesktopWindow(),
                                    Rectangle(),
                                    'infobox',
                                    BUTTONS_OK,
                                    'pyUNO',
                                    message)
    return MsgBox.execute()


En la primer línea declaramos nuestra macro, su nombre y los argumentos que necesita, en este caso solo uno message que será el mensaje a mostrar.

def msgbox(message):


En la segunda línea, estamos importando (import) la estructura Rectangle desde (from) el modulo com.sun.star.awt.module-ix.

    from com.sun.star.awt import Rectangle

Las estructuras son un conjunto de valores relacionados, valores que pueden ser de tipos diferentes, pero que son mostrados como una unidad lógica, por ejemplo, la estructura com.sun.star.awt.Rectangle hace referencia a un área rectangular estableciendo su posición y tamaño, en este caso, solo sirve para cumplir los argumentos del método para mostrar nuestro mensaje.


En la tercer línea, hacemos otra importación, pero esta vez la hacemos de una constante, específicamente la constante para mostrar el botón Aceptar (OK), estas constantes las puedes ver aquí: com.sun.star.awt.MessageBoxButtons

    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK



La cuarta línea esta vacía solo para separar la parte de importacion con el resto del código. En la siguiente línea hacemos una validación del argumento pasado a nuestra macro, si el argumento no es una instancia de la clase unicode o de la clase str, entonces la convertimos a str, esto nos permite pasar a nuestra macro, listas, tuplas, diccionarios y practicamente cualquier objeto, del cual, podremos ver su representación en texto, muchas veces, con información bastante útil.

    if not isinstance(message, (unicode, str)):
        message = str(message)


La siguiente línea ya la hemos estudiado, creamos una instancia del contexto donde se ejecuta AOO.

    ctx = uno.getComponentContext()


La siguiente línea también ya la hemos estudiado, creamos una instancia de la fabrica de servicios, una de las instancias más importantes y que usaras constantemente.

    sm = ctx.getServiceManager()


En la siguiente línea creamos una instancia con contexto de un nuevo servicio com.sun.star.awt.Toolkit, este servicio sirve, entre otras muchas cosas para crear ventanas y mensaje de texto, como el de nuestra macro.

    toolkit = sm.createInstanceWithContext('com.sun.star.awt.Toolkit', ctx)


En la penultima línea, usamos el método createMessageBox del servicio com.sun.star.awt.Toolkit para crear nuestro cuadro de mensaje, todos los argumentos de este método puedes verlo aquí: com.sun.star.awt.XMessageBoxFactory, pero aquí los explicamos uno a uno.

    MsgBox = toolkit.createMessageBox(
                                    toolkit.getDesktopWindow(),
                                    Rectangle(),
                                    'infobox',
                                    BUTTONS_OK,
                                    'pyUNO',
                                    message)

Aunque veas muchas líneas, el interpete la considera una sola, esto se logra al estar todos los argumentos entre paréntesis.

  • El primer argumento es la ventana padre (parent) donde será mostrado el cuadro de mensaje.
  • El segundo argumento es el área rectangular del cuadro de mensaje.
  • El tercer argumento es el tipo de mensaje, dependiendo de este argumento se muestra el icono correspondiente, los valores permitidos son: infobox, warningbox, errorbox, querybox y messbox, si usas infobox, el siguiente argumento es ignorado.
  • El cuarto argumento sirve para mostrar botones de comando diferentes, como: Si, No, Cancelar, etc, que están establecidos en las constantes vistas más arriba.
  • El quinto argumento es el título del cuadro de mensaje.
  • Y por ultimo, el mensaje a mostrar, el cual ya validamos.


En la ultima línea al mismo tiempo que mostramos (ejecute) estamos retornando el cuadro de mensaje, esto nos da la posibilidad de capturar el botón al que le haya dado click el usuario, lo cual, veremos más adelante.

    return MsgBox.execute()

El documento activo

Tenemos dos formas de acceder al documento activo.

    doc1 = XSCRIPTCONTEXT.getDocument()
    doc2 = desktop.getCurrentComponent()
 
    print (doc1.getIdentifier())
    print (doc2.getIdentifier())

Template:Documentation/Note


Los documentos abiertos

Rutas de archivos y directorios

Creando nuevos documentos

Abriendo, guardando y cerrando documentos

Algunas tareas comunes en documentos

Personal tools