explota el potencial de openoffice con pyuno
TRANSCRIPT
-
7/31/2019 Explota el Potencial de OpenOffice con PyUno
1/5
Esta es la gran cuestin no resuelta
de la informtica pero, aunque no
hayamos encontrado una solucin
fiable, s se disponen de tcnicas que
aumentan la probabilidad de que, al
menos, se cree algn software til.
Una de estas tcnicas consiste en
emplear un sistema de componentes
como base para el desarrollo. Un com-ponente es una cantidad de software
que ofrece un servicio bien definido y
que es reutilizable. Adems debe ser
posible reutilizarlo de verdad: desde
cualquier lenguaje y cualquier sitio.
Cualquiera que tenga conocimiento
sobre cmo funcionan los lenguajes de
programacin a bajo nivel sabr que
esto es muy muy complicado. Por ello
se han desarrollado infraestructuras
que nos permiten interactuar con los
componentes de manera indirecta. A
este software se le suele llamar mid-
dleware (algo as como software deen medio).
Ejemplos famosos de Middleware son
J2EE, que muchos conocern, y
CORBA, que a muchos les gustara no
conocer. Ambos son sistemas enormes
y costosos que relegan al programador
a mera herramienta en manos de inge-
nieros denominados arquitectos que
conocen su compleja infraestructura.
Pero los sistemas de componentes
tambin se emplean en software libre y
han dado buenos resultados. Quizs el
ms desconocido es UNO, de Universal
Network Objects, el sistema que
emplea OpenOffice, ver Listado [1], y
que SUN desarroll para su precursor:
StarOffice.
PyUNOUn sistema de componentes con el que
slo se pueda programar en un
lenguaje no tiene mucha utilidad. Poreso en OpenOffice se han asegurado de
fomentar la creacin de interfaces a
distintos lenguajes de programacin.
Podemos acceder a UNO usando
Javascript, Java, Ruby, Perl o Python
(ver Recurso [2]).
PyUNO es el nombre de la interfaz y
podremos encontrarlo sin problemas en
nuestra distribucin de Linux. Eviden-
temente, necesitamos tambin tener
instalado OpenOffice. En este artculo
hemos realizado los programas usando
OpenOffice 2.0, que cambi la interfaz
respecto a la versin 1.0, y la versinde PyUNO 0.7.0.
Un ejemplo rpidoVamos a crear el famoso Hola mundo
con PyUNO. Para ello primero debemos
arrancar OpenOffice con el siguiente
comando desde el directorio donde est
instalado:
$> ./sofficeU
"-accept=socket,U
host=localhost,U
port=2002;urp;"
No es ni ser la ltima vez que
desde esta seccin recordemos
que la idea original de Stallman
era la de que cada programa libre estu-
viese construido sobre libreras de fun-
ciones, de manera que su cdigo fuesereutilizable por cualquier otro pro-
grama.
Quizs en un programa pequeo no
sea muy til este tipo de diseo, pero
qu pasa con esos monstruos consumi-
dores de memoria que rondan por nues-
tros discos duros? Nos referimos a pro-
gramas o entornos del calibre de
Gnome, KDE, Mozilla u OpenOffice.
Todo el mundo se queja de su tamao
excesivo, su alto consumo de recursos y
su inexplicable complejidad.
Quizs con este artculo desmintamos
este mito y hagamos que el lector mirecon nuevos ojos a estos maravillosos
programas.
Grandes sistemas decomponentesEl diseo de un gran programa puede
llevar aos y cientos o miles de progra-
madores. Organizar tal cantidad de per-
sonas supone ya una locura slo por el
hecho de asegurarse que todos cobren.
Pero vayamos a nuestro mundillo
cmo podemos organizarles para que
el desarrollo no acabe en un fiasco?
DESARROLLO Python
50 Nmero 17 WWW.LINUX - M A G A Z I N E . E S
PyUNO: Explota todo el potencial de OpenOffice
PYTHON NO HAYMS QUE UNOHas visto alguna vez a los brokers de bolsa? Recuerdas sus sofisticados y caros pro-
gramas para ver las cotizaciones de las empresas en bolsa en tiempo real? Nosotros
haremos lo mismo con 70 lineas de cdigo Python, OpenOffice y la tecnologa UNO de
OpenOffice. POR JOS MARA RUIZ
050-053 Python xx 05.04.2006 16:29 Uhr Pgina 50
-
7/31/2019 Explota el Potencial de OpenOffice con PyUno
2/5
Al arrancar OpenOffice se arranca su
sistema de componentes. Podemos pen-
sar en este proceso como en el arranque
de un servidor, slo cuando est funcio-
nando podrn los clientes trabajar con
l.
Las opciones que pasamos son para
que se cree un socket y se escuche en
localhost en el puerto 2002. Por defecto
OpenOffice no abre el socket, de ma-
nera que no podrn controlar nuestro
OpenOffice sin nuestro consentimiento.
OpenOffice incorpora de serie varios
intrpretes de lenguajes, entre ellos unode Python que ya viene preconfigurado
para poder hacer uso de la librera UNO.
Est junto al resto de ejecutables de
OpenOffice, as que lo ejecutaremos
desde all. El programa que usaremos se
encuentra en el Listado [2].
El proceso es el siguiente:
Obtenemos un contexto local (un
sitio donde guardar los datos de la
conexin)
Arrancamos el componente UnoUrl-
Resolver que nos sirve para acceder
a otro OpenOffice en otro equipo
(en nuestro caso accederemos anuestro propio equipo)
Emplearemos el objeto resolverpara
acceder al OpenOffice remoto
Arrancamos un Desktop (escrito-
rio) de OpenOffice (esto es una
instancia de OpenOffice vaca)
Arrancamos un SWriter (es decir, el
procesador de textos) en el escrito-
rio
Obtenemos un cursor, con el que
podremos posicionarnos dentro del
texto
e insertamos texto en el cursor
El resultado, no muy espectacular,
podemos verlo en la Figura [1]. Ya te-
nemos nuestro hola mundo insertado
en SWriter.
Demasiado cdigo? Piensa por un
momento lo que estamos haciendo.
Hemos levantado dos componentes y
hecho acceso remoto a otro OpenOffice.
Este segundo OpenOffice puede estar en
una mquina al otro lado del mundo. Es
algo bastante impresionante, pero por el
momento poco til. Veamos un poco
ms sobre UNO antes de realizar un
programa ms til.
Arquitectura de UNOOpenOffice est implementado en
C++. UNO se usa internamente para
realizar cualquier cosa. Bsicamente
OpenOffice no es ms que una gran
cantidad de componentes que interac-
tan entre s. Todo dentro de OpenOf-
fice es un componente, as que
podemos acceder a cualquier parte de la
aplicacin, incluso reconstruir Open-
Office en Python!
Los sistemas de componentes usan
un registro de componentes al que se lepuede pedir que arranque compo-
nentes. El registro localiza el compo-
nente en disco y lo carga en memoria,
de manera que puede ser usado. Las lla-
madas a las funciones no se realizan
directamente, sino que se suele emplear
algn sistema no dependiente de
lenguaje o plataforma, como puede ser
XML o un formato ASCII.
El registro tambin debe ser capaz de
gestionar los recursos que consume el
componente, descargndolo de memo-
ria cuando ya no sea necesario.
Los componentes pueden ser progra-
mados en cualquier lenguaje con el
que se tenga interfaz. Un componente
es un conjunto de ficheros que propor-
cionan un servicio. Se acompaan deun fichero XML que describe su fun-
cionalidad. Lo mejor es que podemos
vincular ese servicio a algn compo-
nente grfico, como por ejemplo un
botn o men.
Comenzaremos por realizar un pro-
grama que funcionar de manera
externa a OpenOffice y despus creare-
mos un componente con l y lo inte-
graremos en OpenOffice.
Nuestro programa deStocksComencemos con la parte til, ver Lis-
tado [2]. Vamos a crear un sistema que
nos permita controlar las acciones de
una serie de empresas que estn en
bolsa dentro de un ndice tecnolgico,
el Nasdaq (para algo estamos en una
revista de informtica), usando la hoja
de clculo SCalc y un programa
Python. Nuestro programa acceder
usando Internet a un sitio web donde
podr recoger los datos en CSV (Val-
ores Separados por Comas), los proce-
sar y los introducir en SCalc.
Comenzaremos por crear una fun-cin que recoja el fichero CSV y lo pro-
cese. Lo que hacemos es conectarnos
con la pgina web finance.yahoo.com .
Yahoo tiene un sitio web bastante
avanzado sobre cotizaciones de bolsa,
y uno de sus servicios nos permite
recoger los datos de cotizacin de una
empresa en tiempo real en formato
CSV. Sin embargo, Yahoo no nos per-
mitir acceder a los datos demasiado a
menudo, ya que dispone de un servi-
cio de pago para ello, as que puede
cortarnos el grifo en cualquier
momento si hacemos demasiadas con-sultas por minuto. Por eso recogere-
mos los datos cada 10 segundos. La
funcin getSimbolo() se encargar de
ello.
Ahora ya tenemos los datos, te-
nemos que mandarlos a SCalc. Hemos
creado un objeto llamado Calc para
gestionar el acceso. Hemos metido en
el mtodo constructor (__init__) el
cdigo que conecta con el OpenOffice,
puesto que slo lo haremos una vez.
Una hoja de clculo posee varias
hojas, as que tendremos que solici-
Python DESARROLLO
51Nmero 17WWW.LINUX- M A G A Z I N E . E S
01 import uno0203 localContext =
uno.getComponentContext()0405 resolver =
localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver",
06localContext )
07 ctx = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
0809 desktop =
ctx.ServiceManager.createInstanceWithContext(
"com.sun.star.frame.Desktop",ctx)1011 doc =
desktop.loadComponentFromURL("private:factory/swriter","_blank",0,())
1213 cursor =
doc.Text.createTextCursor()1415 doc.Text.insertString( cursor,
"Hola Mundo", 0 )1617 ctx.ServiceManager
Listado 1: programa Hola Mundo
050-053 Python xx 05.04.2006 16:29 Uhr Pgina 51
-
7/31/2019 Explota el Potencial de OpenOffice con PyUno
3/5
primera hoja, que es la que se ve
cuando arrancamos SCalc.
El mtodo actualiza() admite una
lista con los datos de cotizacin y
nmero que representa la fila donde
aparecer en SCalc. Una hoja de clculo
se compone de celdas y stas tienen un
tipo. La funcin getCellByPosition() nos
permite acceder a una celda pasndole
la columna y la fila (al revs de lo nor-
mal, as que cuidado).
Una vez localizada la celda tenemos
varias funciones para poder asignar un
valor:
setString(): para poner una cadena setValue(): para poner un nmero
setFormula(): para poner una fr-
mula
El dato cotizacin es la lista de
parmetro de cotizacin, pero vienen
dados como cadenas de caracteres. Las
posiciones 0, 2 y 3 son realmente cade-
nas, pero el resto son nmeros. Por eso
tenemos que convertir ciertos valores
al tipo float() mediante la funcin
float().
El resultado se puede ver en la Figura
[2], veremos cmo se abre una ventana
tar una usando el mtodo getSheets(),
que nos devuelve una lista con las dis-
tintas hojas. Dentro de esta lista usare-
mos getByIndex() para seleccionar la
DESARROLLO Python
52 Nmero 17 WWW.LINUX - M A G A Z I N E . E S
01 import uno
02 import random
03 import time04 import httplib
05 import csv
06
07 class Calc:
08 def __init__(self):
09 self.conecta()
10
11 def conecta (self):
12 self.local =
uno.getComponentContext()
13 self.resolver =
self.local.ServiceManager.crea
teInstanceWithContext("com.sun
.star.bridge.UnoUrlResolver",
self.local)
14
15 self.context =
self.resolver.resolve("uno:soc
ket,host=localhost,port=2002;u
rp;StarOffice.ComponentContext
")
16
17 self.desktop =
self.context.ServiceManager.cr
eateInstanceWithContext("com.s
un.star.frame.Desktop",
18self.context)
19
20 #self.doc =
self.desktop.getCurrentCompone
nt()21 self.doc =
self.desktop.loadComponentFrom
URL("private:factory/scalc","_
blank",0,())
22
23 self.hojas =
self.doc.getSheets()
24 self.s1 =
self.hojas.getByIndex(0)
25
26 def actualiza(self,
cotizacion, fila):
27
28 i = 0
29 for entrada in
cotizacion:
30 if (i == 0) or (i
== 2) or (i ==3):
31
self.s1.getCellByPosition(i,fi
la).setString(entrada)
32 else:
33
self.s1.getCellByPosition(i,fi
la).setValue(float(entrada))
34
35 i = i + 136
37 def getSimbolo(simbolo):
38 c =
httplib.HTTPConnection("finance.yahoo.com")
39
c.request("GET","/d/quotes.csv
?s="+simbolo+"&f=sl1d1t1c1ohgv
&e=.csv")
40 r = c.getresponse()
41 cad = r.read()
42 reader = csv.reader([cad])
43 resultado = []
44 for row in reader:
45 resultado = row
46 return resultado
47
48 if __name__ == '__main__':
49
50 simbolos =
["GOOG","MSFT","RHAT"]
51
52 c = Calc()
53
54 while(1):
55 i = 0;
56 for s in simbolos:
57
c.actualiza(getSimbolo(s),i)
58 i = i + 1
5960 time.sleep(10)
Listado 2: OfficeBroker
Figura 1: Un documento de Write de OpenOffice con el ineludible Hello World generado a par-
tir de PyUNO.
050-053 Python xx 05.04.2006 16:29 Uhr Pgina 52
-
7/31/2019 Explota el Potencial de OpenOffice con PyUno
4/5
de SCalc y se rellena con los valores de
las contizaciones, adems de cmo se
actualizan cada 10 segundos. Si
creamos un grfico que use esos va-
lores se actualizar con ellos.
Pero este es un programa externo
estara bien que pudisemos hacer eso
pulsando un botn
Creamos un componenteUNOLos componentes UNO no son ms que
cdigo debidamente empaquetado. Los
paquetes que OpenOffice admite tienen
una estructura fija. Son ficheros ZIP
que contienen los ficheros con el
cdigo fuente, recursos (como im-
genes) y un fichero de configuracin
XML.
Los ficheros deben tener nombres
especiales. El fichero de configuracin
debe llamarse Addons.xcu y permite
asignar el cdigo fuente del paquete con
el widget que deseemos, un botn, una
entrada de un men Ver Listado [3].
La sintaxis del fichero parece bastante
complicada, cuando en realidad no esmuy difcil de entender. Bsicamente
decimos que queremos que nuestro com-
ponente se asocie con una entrada en el
men Addons que est en Tools o Her-
ramientas en castellano. Nuestro compo-
nente tiene una ruta que especificaremos
despus y que es:
org.openoffice.comp.pyuno.U
linuxmagazine.Stock
Esta ruta la hemos creado nosotros y
tenemos que tener cuidado de que sea
nica, por eso hemos incorporado li-
nuxmagazine en ella ;). Definimos un
ttulo, que puede estar en varios
idiomas, y una imagen, que hemos
escogido de entre las que proporcionaOpenOffice.
El fichero con el cdigo fuente Python en
s se puede ver en el Listado 4. Tenemos un
objeto llamado StockJob que ser el que se
invocar en caso de pulsar la entrada en el
men. Ese objeto se vincula a la ruta que
vimos antes. Cada vez que se pulse sobre la
entrada del men se ejecutar el mtodo
trigger, que descargar de Internet las coti-
zaciones y las mostrar en la hoja de cl-
culo. Es posible hacer que slo se muestre
el men cuando arrancamos la hoja de cl-
culo SCalc, pero por motivos de espacio no
hemos puesto la restriccin. An as si noestamos en una hoja de clculo no suce-
der nada, simplemente no funcionar.
Manejo de paquetes enOpenOfficeAhora tenemos que generar nuestro
paquete UNO. Para ello necesitaremos el
programa ZIP, gzip no nos vale, y crear un
fichero:
$> zip stock.zipU
stock_comp.py Addons.xcu
updating: ...../Addons.xcuU
Python DESARROLLO
53Nmero 17WWW.LINUX- M A G A Z I N E . E S
01
02
05
06
07
08
09
10
service:org.openoffice.
comp.pyuno.linuxmagazine.Stock
?insert
11
12
13
14 Stock
Market
15 Cotizacin enBolsa
16
17 18
_self
19
20
21
private:image/3216
22
23
24
25
26
27
Listado 3: Addons.xcu
Figura 2: Nuestro programa examina los valores de la bolsa NASDAQ disponibles en Yahoo a
intervalos regulares y los inserta en una hoja de clculo de OpenOffice.
050-053 Python xx 05.04.2006 16:29 Uhr Pgina 53
-
7/31/2019 Explota el Potencial de OpenOffice con PyUno
5/5
Con esto concluye la instalacin del
paqueteno ha sido tan difcil!
Cuando arranquemos de nuevo
OpenOffice podremos seleccionar la
hoja de clculo SCalc y en el men
Tools/Herramientas veremos cmo ha
aparecido al final un nuevo submen:
Complementos (add-ons). Dentro
del mismo aparecer una nueva
entrada llamada Cotizacin de
Bolsa. Si lo pulsamos aparecen los
datos de 3 compaas (Google,
Microsoft y Redhat) del Nasdaq ennuestra hoja de clculo.
ConclusinPython nos permite
un uso nuevo de
algo tan trillado
como puede
ser un
paquete
ofimtico.
OpenOffice
entero es
accesible
desde Python; no es difcil imaginarse
programas que podran facilitarnos
mucho la vida y no son tan difciles de
crear gracias a PyUNO. No hemos
explorado la posibilidad de actuar
sobre un OpenOffice remoto por falta
de espacio, pero es una nueva posibili-
dad que abre un camino para aplica-
ciones muy interesantes, como puede
ser la edicin distribuida de documen-
tos o un uso ms creativo de la hoja de
clculo.
Todo un mundo de posibilidades seabre ante nosotros gracias a Python. I
(deflated 59%)
updating: ...../stock_comp.pyU
(deflated 57%)
>
Este fichero debe ser integrado en Open-
Office, iremos al directorio donde est
instalado y ejecutaremos como root:
$> sudo ./unopkg addU
stock.zip
>
DESARROLLO Python
[1] El sitio de OpenOffice: http://www.
openoffice.org
[2] El puente entre Python y OpenOf-
fice: http://udk.openoffice.org/python/
python-bridge.html
[3] Los listados de este arculo: http://
www.linux-magazine.es/Magazine/
Downloads/17
RECURSOS
Listado 4: stock_comp.py
01 import uno
02 import unohelper
0304 import random
05 import time
06 import httplib
07 import csv
08
09 from com.sun.star.task import
XJobExecutor
10
11 def getSimbolo(simbolo):
12 c =
httplib.HTTPConnection("financ
e.yahoo.com")
13
c.request("GET","/d/quotes.csv?s="+simbolo+"&f=sl1d1t1c1ohgv
&e=.csv")
14 r = c.getresponse()
15 cad = r.read()
16 reader = csv.reader([cad])
17 resultado = []
18 for row in reader:
19 resultado = row
20 return resultado
21
22 class StockJob(
unohelper.Base, XJobExecutor
):
23 def __init__( self, ctx ):
24
25 self.ctx = ctx26
27 def trigger( self, args ):
28 desktop =
self.ctx.ServiceManager.create
InstanceWithContext(
29
"com.sun.star.frame.Desktop",
self.ctx )
30
31 model =
desktop.getCurrentComponent()
32
33 self.hojas =
model.getSheets()34
35 self.s1 =
self.hojas.getByIndex(0)
36
37 simbolos =
["GOOG","MSFT","RHAT"]
38 i = 0;
39
40 for s in simbolos:
41
self.actualiza(getSimbolo(s),i
)
42 i = i + 1
43
44 def actualiza(self,
cotizacion, fila):45 i = 0
46 for entrada in
cotizacion:
47 if (i == 0) or (i
== 2) or (i ==3):
48
self.s1.getCellByPosition(i,fi
la).setString(entrada)
49 else:
50
self.s1.getCellByPosition(i,fi
la).setValue(float(entrada))
51
52 i = i + 153
54 g_ImplementationHelper =
unohelper.ImplementationHelper
()
55
56
g_ImplementationHelper.addImpl
ementation( StockJob,
57
"org.openoffice.comp.pyuno.lin
uxmagazine.Stock",
58
("com.sun.star.task.Job",),)
54 Nmero 17 WWW.LINUX - M A G A Z I N E . E S
050-053 Python xx 05.04.2006 16:29 Uhr Pgina 54