Diferencia entre revisiones de «Usuario:Luis.perez/pyunoaytozgz/pyuno»

De WikiEducator
Saltar a: navegación, buscar
m (Página creada con '{{MiTitulo|PyUNO: Macros y componentes para OpenOffice/LibreOffice con Python}} {{Recursos de la Web |Title=Documentación y recursos generales| === Documentación === * Guía …')
 
m
Línea 1: Línea 1:
 
{{MiTitulo|PyUNO: Macros y componentes para OpenOffice/LibreOffice con Python}}
 
{{MiTitulo|PyUNO: Macros y componentes para OpenOffice/LibreOffice con Python}}
  
 +
== Documentación ==
 
{{Recursos de la Web |Title=Documentación y recursos generales|
 
{{Recursos de la Web |Title=Documentación y recursos generales|
=== Documentación ===
+
;Documentación
 
* Guía oficial de desarrollo de OpenOffice: http://wiki.openoffice.org/wiki/Documentation/DevGuide
 
* Guía oficial de desarrollo de OpenOffice: http://wiki.openoffice.org/wiki/Documentation/DevGuide
 
* Recopilación de enlaces a docs sobre PyUNO http://wiki.openoffice.org/wiki/Python
 
* Recopilación de enlaces a docs sobre PyUNO http://wiki.openoffice.org/wiki/Python
 
* En castellano: http://wiki.openoffice.org/wiki/OOoES/Desarrollo/PyUNO_ES
 
* En castellano: http://wiki.openoffice.org/wiki/OOoES/Desarrollo/PyUNO_ES
  
=== Api ===
+
;Api
 
* Libreoffice: http://api.libreoffice.org/docs/common/ref/com/sun/star/module-ix.html
 
* Libreoffice: http://api.libreoffice.org/docs/common/ref/com/sun/star/module-ix.html
 
* Openoffice: http://www.openoffice.org/api/docs/common/ref/com/sun/star/text/module-ix.html
 
* Openoffice: http://www.openoffice.org/api/docs/common/ref/com/sun/star/text/module-ix.html
  
=== Ejemplos ===
+
;Ejemplos
 
* Ejemplos de la guia de desarrollo: http://api.libreoffice.org/examples/DevelopersGuide/examples.html
 
* Ejemplos de la guia de desarrollo: http://api.libreoffice.org/examples/DevelopersGuide/examples.html
 
* Snippets de código: http://codesnippets.services.openoffice.org/index.xml
 
* Snippets de código: http://codesnippets.services.openoffice.org/index.xml
  
 +
}}
 +
 +
== Instalación de Libreoffice (Ubuntu) ==
 +
* Basta con tener instalado libreoffice si solo se van a hacer macros.
 +
* Si se van a crear componentes instalar adicionalmente el paquete libreoffice-dev
 +
<source lang="bash">
 +
$ apt-get install libreoffice-dev
 +
</source>
 +
 +
== Introducción al API de Openoffice: conceptos ==
 +
 +
==== Interfaces ====
 +
 +
* Un conjunto de métodos y/o atributos que exponen funcionalidad. Aspectos de la implementación de un objeto.
 +
* En el api de UNO, todos los nombres de interfaces empiezan con X
 +
* Todos los interfaces extienden XInterface
 +
 +
==== Servicios ====
 +
* Servicios "New-style": Especifica que objetos que implementan un determinado interfaz (ej:  com.sun.star.bridge.XUnoUrlResolver), estarán disponibles bajo un determinado nombre (ej: com.sun.star.bridge.UnoUrlResolver) en el service manager del component context (ver más adelante). Para que un objeto que implementa un servicio pueda implementar varios aspectos o interfaces, el interfaz que implementa heredará de varios otros interfaces.
 +
 +
* Servicios "Old-style": Los servicios oldstyle pueden verse como un conjunto de interfaces y/o propiedades.
 +
** Pueden o no exponerse a través del service manager, servir como base de otros servicios (en el new-style, el mecanismo preferido para proporcionar servicios base es implementar interfaces que heredan de varios interfaces), o simplemente servir para agrupar un conjunto de propiedades.
 +
** Pueden implementar interfaces opcionales
 +
** Pueden incluir otros servicios, lo que significa que expondrán el conjunto de sus interfaces y de los otros servicios.
 +
 +
Obtener un servicio a través del serviceManager:
 +
<source lang="python">
 +
  desktop = serviceManager.createInstanceWithContext("com.sun.star.frame.Desktop", context)
 +
</source>
 +
'' Más adelante se hablará del serviceManager y del component context''
 +
 +
Obtener los nombres de servicio que soporta un objeto
 +
 +
<source lang="python">
 +
obj.getSupportedServiceNames()
 +
</source>
 +
 +
 +
{{Reflexion|
 +
Debido a la existencia de servicios old-style, hay que tener cuidado a la hora de interpretar el api: Algunos servicios no pueden ser instanciados directamente con el service manager
 +
* Porque son conjuntos de propiedades
 +
* Porque solo sirven como servicios base de otros servicios
 +
* O necesitan un tratamiento especial. Ej: ''com.sun.star.text.TextDocument'' no puede instanciarse directamente, se obtiene a través de ''loadComponentFromUrl()'' de  ''com.sun.star.frame.XComponentLoader''
 +
}}
 +
 +
 +
==== Propiedades ====
 +
* Pares de nombre-valor que expone un servicio.
 +
* Normalmente suelen ser utilizados para atributos no estructurales (ej: color, tamaño, pero no objetos padre o hijos)
 +
* Se suelen acceder mediante ''com.sun.star.beans.XPropertySet'', pero también en algunos casos, a través de ''com.sun.star.beans.XPropertyAccess'' ó ''com.sun.star.beans.XMultiPropertySet''
 +
 +
Obtener propiedad (XPropertySet):
 +
<source lang="python">
 +
sheet.getPropertyValue("IsVisible")
 +
</source>
 +
 +
Establecer propiedad:
 +
<source lang="python">
 +
sheet.setPropertyValue("IsVisible", False)
 +
</source>
 +
 +
Obtener propiedades de un objeto:
 +
<source lang="python">
 +
propsinfo = sheet.getPropertySetInfo()
 +
props = propsinfo.getProperties()
 +
for prop in props:
 +
    print(prop)
 +
</source>
 +
 +
==== Singletons ====
 +
 +
* Implementación de interface del que solo existe una instancia accesible desde el component context.
 +
 +
==== Componentes / extensiones ====
 +
* Son librerías que contienen implementaciones de uno o varios servicios en cualquiera de los lenguajes que soporta UNO
 +
 +
==== Estructuras, Constantes, y Enumeraciones ====
 +
* Estructuras: Conjunto de miembros, similar a la estructuras en C. Soportan herencia simple.
 +
:Instanciando una estructura:
 +
<source lang="python">
 +
  import uno
 +
  uno.createUnoStruct("com.sun.star.beans.PropertyValue")
 +
</source>
 +
* Constants: tipo que agrupa varios valores constantes
 +
:Obteniendo el valor de una constante
 +
<source lang="python">
 +
  import uno
 +
  uno.getConstantByName("com.sun.star.sheet.ConditionOperator.GREATER")
 +
</source>
 +
* Enum: Similar a una enumeración en c++
 +
<source lang="python">
 +
</source>
 +
 +
==== Módulos ====
 +
 +
* Espacios de nombres, similares a los namespaces de C++ o a los paquetes en Java. Agrupan servicios, interfaces, structs...
 +
 +
=== ComponentContext ===
 +
* Objeto con el que se obtene el singleton de ServiceManager
 +
* Puede obtenerse dependiendo de si el código a ejecutar va a ser una macro o un componente.
 +
 +
=== ServiceManager ===
 +
* Objeto con el que se instancian servicios
 +
<source lang="python">
 +
serviceManager = ctx.ServiceManager
 +
</source>
 +
 +
 +
== Macros ==
 +
 +
Son pequeños programas que usan el api UNO para automatizar tareas en documentos
 +
 +
Ejemplo:
 +
 +
<source lang="python">
 +
import uno
 +
 +
def holaMundoCalc():
 +
    # Accedemos al modelo del documento actual
 +
    model = XSCRIPTCONTEXT.getDocument()
 +
    # Accedemos a la primer hoja del documento
 +
    hoja = model.getSheets().getByIndex(0)
 +
    # Accedemos a la celda A1 de la hoja
 +
    celda = hoja.getCellRangeByName("A1")
 +
    # Escribimos en la celda
 +
    celda.setString("Hola Mundo en Python")
 +
    return None
 +
</source>
 +
 +
* XSCRIPTCONTEXT:  variable global en el script que contiene Document (el objeto que representa un documento), Desktop y ComponentContext
 +
* Por defecto todas las funciones del script se exportan como macros. Para limitarlos:
 +
<source lang="python">
 +
  g_exportedScripts = (holaMundoCalc, ) # solo expondrá holaMundoCalc, aunque haya otras funciones
 +
</source>
 +
* El comentario de una función se muestra como descripción de la macro en el diálogo de macros
 +
 +
 +
==== Ejecución de macros ====
 +
 +
Puede hacerse a través del díalogo ''tools -> macros -> run macro...''
 +
o a través de ''tools -> macros -> organize macros -> python...''
 +
 +
==== Distribución de macros ====
 +
 +
Existen varios modos de distribuir una macro
 +
* En directorio de usuario:
 +
** ~/.openoffice.org/3/:user/Scripts/python
 +
** ~/.config/libreoffice/3/user/Scripts/python
 +
* En directorio compartido (para todos los usuarios)
 +
** /usr/lib/libreoffice/share/Scripts/python
 +
** /usr/lib/openoffice/share/Scripts/python
 +
* Embebido en documentos:
 +
# Descomprimir documento con unzip
 +
# Incluir el script en cualquier ruta bajo el directorio Scripts
 +
# Modificar META-INF/manifest.mf, incluyendo referencia al script:<source lang="xml"><manifest:file-entry manifest:media-type="" manifest:full-path="Scripts/python/mostrarversion.py"/></source>
 +
# Volver a comprimir el documento
 +
* Empaquetado
 +
:Se creará una estructura de archivos:
 +
<source lang="bash">
 +
  /description.xml
 +
  /Scripts/python/holamundo.py
 +
  /META-INF/manifest.mf
 +
</source>
 +
 +
:Donde description.xml sirve para dar información sobre el paquete (ver 2_simplemacropkg), y manifest.mf referencia la ruta base de los scripts del siguiente modo:
 +
<source lang="xml">
 +
<manifest:manifest>
 +
<manifest:file-entry manifest:media-type="application/vnd.sun.star.framework-script" manifest:full-path="Scripts"/>
 +
</manifest:manifest>
 +
</source>
 +
 +
== Transformando código Java a Python: diferencias ==
 +
 +
Una buena forma de aprender sobre UNO es mediante los ejemplos que hay disponibles. Lamentablemente la mayoría de código es Java o C++.
 +
* La primera diferencia es obvia: python no es estáticamente tipado
 +
* Para obtener y usar un servicio, no es necesario instanciar el servicio y luego hacer un UnoRuntime.queryInterface para obtener el interface deseado del tipo correcto. Basta con instanciar el servicio o componente, y usarlo directamente. Ej:
 +
<source lang="java">
 +
  // doc es un objeto documento
 +
  XSpreadsheetDocument xSpreadsheetDocument = (XSpreadsheetDocument)
 +
UnoRuntime.queryInterface(XSpreadsheetDocument.class, doc);
 +
 +
  XSpreadsheets xSpreadsheets = xSpreadsheetDocument.getSheets();
 +
  xSpreadsheets.insertNewByName("MySheet", (short)0);
 +
</source>
 +
Esto se traduce a:
 +
<source lang="python">
 +
  xSpreadsheets = doc.getSheets()
 +
  xSpreadsheets.insertNewByName("MySheet", 0)
 +
</source>
 +
 +
* Los arrays y listas se transforman de y hacia python como tuplas, NO como listas!.
 +
<source lang="java">
 +
  com.sun.star.beans.PropertyValue[] conditions = new com.sun.star.beans.PropertyValue[1];
 +
  conditions[0] = condition1
 +
  conditions[1] = condition2
 +
  obj.metodoquerecibeprops(conditions)
 +
</source>
 +
: Lo anterior en python sería:
 +
<source lang="python">
 +
  conditions = (condition1, condition2)
 +
  obj.metodoquerecibeprops(conditions)
 +
</source>
 +
 +
 +
== Calc: Api ==
 +
 +
{{Ejemplo|Ejemplos del api de calc
 +
Leer y ejecutar paso a paso la macro del ejemplo 3_calc_api.
 +
}}
 +
 +
== Componentes y extensiones en PyUNO ==
 +
 +
:
 +
{{Recursos de la Web |Title=Documentación|
 +
;Documentación
 +
http://wiki.openoffice.org/wiki/Documentation/DevGuide/WritingUNO/Writing_UNO_Components
 +
http://wiki.openoffice.org/wiki/Documentation/DevGuide/Extensions/
 +
http://wiki.openoffice.org/wiki/Documentation/DevGuide/WritingUNO/Writing_the_Specification -> especificación de UNO IDL
 +
;Ejemplo
 +
http://www.biochemfusion.com/doc/Calc_addin_howto.html
 
}}
 
}}

Revisión de 08:45 23 ene 2013


Documentación



Instalación de Libreoffice (Ubuntu)

  • Basta con tener instalado libreoffice si solo se van a hacer macros.
  • Si se van a crear componentes instalar adicionalmente el paquete libreoffice-dev
$ apt-get install libreoffice-dev

Introducción al API de Openoffice: conceptos

Interfaces

  • Un conjunto de métodos y/o atributos que exponen funcionalidad. Aspectos de la implementación de un objeto.
  • En el api de UNO, todos los nombres de interfaces empiezan con X
  • Todos los interfaces extienden XInterface

Servicios

  • Servicios "New-style": Especifica que objetos que implementan un determinado interfaz (ej: com.sun.star.bridge.XUnoUrlResolver), estarán disponibles bajo un determinado nombre (ej: com.sun.star.bridge.UnoUrlResolver) en el service manager del component context (ver más adelante). Para que un objeto que implementa un servicio pueda implementar varios aspectos o interfaces, el interfaz que implementa heredará de varios otros interfaces.
  • Servicios "Old-style": Los servicios oldstyle pueden verse como un conjunto de interfaces y/o propiedades.
    • Pueden o no exponerse a través del service manager, servir como base de otros servicios (en el new-style, el mecanismo preferido para proporcionar servicios base es implementar interfaces que heredan de varios interfaces), o simplemente servir para agrupar un conjunto de propiedades.
    • Pueden implementar interfaces opcionales
    • Pueden incluir otros servicios, lo que significa que expondrán el conjunto de sus interfaces y de los otros servicios.

Obtener un servicio a través del serviceManager:

  desktop = serviceManager.createInstanceWithContext("com.sun.star.frame.Desktop", context)

Más adelante se hablará del serviceManager y del component context

Obtener los nombres de servicio que soporta un objeto

 obj.getSupportedServiceNames()



Icon reflection.gif

Reflexión

Debido a la existencia de servicios old-style, hay que tener cuidado a la hora de interpretar el api: Algunos servicios no pueden ser instanciados directamente con el service manager

  • Porque son conjuntos de propiedades
  • Porque solo sirven como servicios base de otros servicios
  • O necesitan un tratamiento especial. Ej: com.sun.star.text.TextDocument no puede instanciarse directamente, se obtiene a través de loadComponentFromUrl() de com.sun.star.frame.XComponentLoader




Propiedades

  • Pares de nombre-valor que expone un servicio.
  • Normalmente suelen ser utilizados para atributos no estructurales (ej: color, tamaño, pero no objetos padre o hijos)
  • Se suelen acceder mediante com.sun.star.beans.XPropertySet, pero también en algunos casos, a través de com.sun.star.beans.XPropertyAccess ó com.sun.star.beans.XMultiPropertySet

Obtener propiedad (XPropertySet):

 sheet.getPropertyValue("IsVisible")

Establecer propiedad:

 sheet.setPropertyValue("IsVisible", False)

Obtener propiedades de un objeto:

 propsinfo = sheet.getPropertySetInfo()	
 props = propsinfo.getProperties()
 for prop in props:
     print(prop)

Singletons

  • Implementación de interface del que solo existe una instancia accesible desde el component context.

Componentes / extensiones

  • Son librerías que contienen implementaciones de uno o varios servicios en cualquiera de los lenguajes que soporta UNO

Estructuras, Constantes, y Enumeraciones

  • Estructuras: Conjunto de miembros, similar a la estructuras en C. Soportan herencia simple.
Instanciando una estructura:
  import uno
  uno.createUnoStruct("com.sun.star.beans.PropertyValue")
  • Constants: tipo que agrupa varios valores constantes
Obteniendo el valor de una constante
  import uno
  uno.getConstantByName("com.sun.star.sheet.ConditionOperator.GREATER")
  • Enum: Similar a una enumeración en c++
 

Módulos

  • Espacios de nombres, similares a los namespaces de C++ o a los paquetes en Java. Agrupan servicios, interfaces, structs...

ComponentContext

  • Objeto con el que se obtene el singleton de ServiceManager
  • Puede obtenerse dependiendo de si el código a ejecutar va a ser una macro o un componente.

ServiceManager

  • Objeto con el que se instancian servicios
 serviceManager = ctx.ServiceManager


Macros

Son pequeños programas que usan el api UNO para automatizar tareas en documentos

Ejemplo:

 import uno
 
 def holaMundoCalc():
     # Accedemos al modelo del documento actual 
     model = XSCRIPTCONTEXT.getDocument()
     # Accedemos a la primer hoja del documento
     hoja = model.getSheets().getByIndex(0)
     # Accedemos a la celda A1 de la hoja
     celda = hoja.getCellRangeByName("A1")
     # Escribimos en la celda
     celda.setString("Hola Mundo en Python")
     return None
  • XSCRIPTCONTEXT: variable global en el script que contiene Document (el objeto que representa un documento), Desktop y ComponentContext
  • Por defecto todas las funciones del script se exportan como macros. Para limitarlos:
  g_exportedScripts = (holaMundoCalc, ) # solo expondrá holaMundoCalc, aunque haya otras funciones
  • El comentario de una función se muestra como descripción de la macro en el diálogo de macros


Ejecución de macros

Puede hacerse a través del díalogo tools -> macros -> run macro... o a través de tools -> macros -> organize macros -> python...

Distribución de macros

Existen varios modos de distribuir una macro

  • En directorio de usuario:
    • ~/.openoffice.org/3/:user/Scripts/python
    • ~/.config/libreoffice/3/user/Scripts/python
  • En directorio compartido (para todos los usuarios)
    • /usr/lib/libreoffice/share/Scripts/python
    • /usr/lib/openoffice/share/Scripts/python
  • Embebido en documentos:
  1. Descomprimir documento con unzip
  2. Incluir el script en cualquier ruta bajo el directorio Scripts
  3. Modificar META-INF/manifest.mf, incluyendo referencia al script:
    <manifest:file-entry manifest:media-type="" manifest:full-path="Scripts/python/mostrarversion.py"/>
  4. Volver a comprimir el documento
  • Empaquetado
Se creará una estructura de archivos:
  /description.xml
  /Scripts/python/holamundo.py
  /META-INF/manifest.mf
Donde description.xml sirve para dar información sobre el paquete (ver 2_simplemacropkg), y manifest.mf referencia la ruta base de los scripts del siguiente modo:
<manifest:manifest>
 <manifest:file-entry manifest:media-type="application/vnd.sun.star.framework-script" manifest:full-path="Scripts"/>
</manifest:manifest>

Transformando código Java a Python: diferencias

Una buena forma de aprender sobre UNO es mediante los ejemplos que hay disponibles. Lamentablemente la mayoría de código es Java o C++.

  • La primera diferencia es obvia: python no es estáticamente tipado
  • Para obtener y usar un servicio, no es necesario instanciar el servicio y luego hacer un UnoRuntime.queryInterface para obtener el interface deseado del tipo correcto. Basta con instanciar el servicio o componente, y usarlo directamente. Ej:
  // doc es un objeto documento
  XSpreadsheetDocument xSpreadsheetDocument = (XSpreadsheetDocument)
	UnoRuntime.queryInterface(XSpreadsheetDocument.class, doc);
 
  XSpreadsheets xSpreadsheets = xSpreadsheetDocument.getSheets();
  xSpreadsheets.insertNewByName("MySheet", (short)0);

Esto se traduce a:

  xSpreadsheets = doc.getSheets()
  xSpreadsheets.insertNewByName("MySheet", 0)
  • Los arrays y listas se transforman de y hacia python como tuplas, NO como listas!.
  com.sun.star.beans.PropertyValue[] conditions = new com.sun.star.beans.PropertyValue[1];
  conditions[0] = condition1
  conditions[1] = condition2
  obj.metodoquerecibeprops(conditions)
Lo anterior en python sería:
  conditions = (condition1, condition2)
  obj.metodoquerecibeprops(conditions)


Calc: Api

Icon casestudy.gif

Ejemplo

Ejemplos del api de calc

Leer y ejecutar paso a paso la macro del ejemplo 3_calc_api.




Componentes y extensiones en PyUNO