Le blog: Web, Python, Django, Javascript ...

Utiliser OpenOffice avec Python

OpenOffice, la suite bureautique libre que l'on trouve installée sur de nombreux postes de travail, est livrée avec Python. Il est ainsi possible de créer des macros et outils intégrés avec des feuilles de calculs ou autres traitements de textes et présentations. Si la puissance de Python laisse imaginer de nombreuses utilisations, la mise en oeuvre se révèle (enfin dans mon cas) un peu plus complexe qu'attendue.

Connexion à OpenOffice depuis Python

Premier piège, il faut qu'au préalable OpenOffice soit lancé en mode serveur. La commande suivante permet cela:

"c:\Program Files\OpenOffice.org 3\program\soffice" -accept="socket,host=localhost,port=2002;urp;"

Si vous travaillez sous Linux la suite est simple: on ouvre une console, lance python et exécute un import uno.

Sous Windows, cette même opération génère une erreur car cette plateforme ne propose pas Python en standard. OpenOffice y est donc installé avec sa propre version de l'interprêteur que l'on retrouve dans le répertoire program.

Une possibilité est donc de se rendre dans le répertoire "C:\Program Files\OpenOffice.org 3\program" avec une ligne de commande et de lancer python. L'import uno fonctionne à présent. Inconvénient de cette approche: les librairies installées avec l'interprêteur principal ne sont plus disponibles.

Il est possible de faire fonctionner l'interprêteur principal avec OpenOffice en bidouillant un peu les variables d'environnement pour permettre à pyuno de retrouver les chemins vers l'install OpenOffice. Cette technique n'est pas très propre mais semble fonctionner sans soucis. Voici un petit script qui résume les astuces nécessaires trouvées après quelques recherches sur Google.

import os, sys
if sys.platform == 'win32':
    #This is required in order to make pyuno usable with the default python interpreter under windows
    #Some environment varaible must be modified
    
    #get the install path from registry
    import _winreg
    value = _winreg.QueryValue(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\OpenOffice.org\UNO\InstallPath')
    install_folder = '\\'.join(value.split('\\')[:-1])
    
    #modify the environment variables
    os.environ['URE_BOOTSTRAP'] = 'vnd.sun.star.pathname:{0}\\program\\fundamental.ini'.format(install_folder)
    os.environ['UNO_PATH'] = install_folder+'\\program\\'

    sys.path.append(install_folder+'\\Basis\\program')

    paths = ''
    for path in ("\\URE\\bin;", "\\Basis\\program;"):
        paths += install_folder + path
    os.environ['PATH'] =  paths+ os.environ['PATH']

import uno

Un exemple avec Calc

Python est alors capable de communiquer avec un document OpenOffice. Il est ainsi possible par exemple de lire ou écrire des valeurs dans une feuille de calcul Calc (l'équivalent OOo d'Excel si vous n'êtes pas encore famillier de ce logiciel).

Combiné avec Python, les possibilités d'OOo semblent immenses. L'ensemble du logiciel est accessible et peut permettre d'automatiser les tâches facilement à l'aide de petits scripts. Mais tout cela à un prix, celui d'une relative complexité des API d'OpenOffice qui de plus souffrent à mon goût d'un manque de documentation.

La création d'un document se rélève assez lourde, obligeant à la création de plusieurs objets. Je vous propose une petite classe pour faciliter cela:

class UnoClient:

    def __init__(self):
        localContext = uno.getComponentContext()
        resolver = localContext.ServiceManager.createInstanceWithContext(
            "com.sun.star.bridge.UnoUrlResolver", localContext)
        self.smgr = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ServiceManager")

    def create_document(self, app):
        remoteContext = self.smgr.getPropertyValue("DefaultContext")
        desktop = self.smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",remoteContext)
        url = "private:factory/{0}".format(app)
        return desktop.loadComponentFromURL(url,"_blank", 0, () )

Cette classe peut ensuite être utilisée comme dans l'exemple suivant:

calc = UnoClient().create_document('scalc') #cree un nouveau classeur
sheet = calc.getSheets().getByIndex(0) #1ere feuille du classeur
sheet.getCellByPosition(0, 0).setString("Salut") #Un texte
sheet.getCellByPosition(0, 1).setValue(3.14) #Un nombre
sheet.getCellByPosition(0, 2).setFormula("=SUM(2+2)") #Une formule
sheet.getCellByPosition(0, 2).CellBackColor = int("ff7f00", 16) #Couleur RGB de fond
sheet.getCellByPosition(0, 2).CharUnderline = 1 # Souligne
sheet.getCellByPosition(0, 2).CharHeight = 16 #Taille de la police
sheet.getCellByPosition(0, 2).CharWeight = 150 #Gras
sheet.getCellByPosition(0, 2).CharPosture = 2 #Italique

Pour aller plus loin, je vous recommande de jeter un oeil au travail impressionnant réalisé sur le module Danny.OOO. Tout n'est pas forcément réutilisable en l'état mais c'est à coup sur une source d'inspiration inégalable sur ce sujet.

Manipulation facile avec OOSheet

Je vous recommande aussi un coup d'oeil à la librairie OOSheet qui simplifie beaucoup la manipulation de feuilles de calcul. Ce module est très orienté sur l'utilisation de Calc (même si l'accès aux autres types de document semble possible).

Un exemple tiré de la doc du module: 

>>> from oosheet import OOSheet as S
>>> S('a1').value = 1
>>> S('a2').formula = '=a1+10'
>>> S('a2').value
11.0

L'accès à une cellule se fait directement depuis son nom. Différents sélecteurs, dans l'esprit jquery, permettent de manipuler les cellules beaucoup plus facilement.

Voila pour ce 1er article sur l'utilisation de Python avec OpenOffice. Ces exemples ont été testés avec OpenOffice 3 et Python 2.6 sous Vista et Ubuntu. D'après ce que j'ai lu, cela devrait aussi fonctionner avec LibreOffice, projet qui s'est créé sur la même base qu'OpenOffice mais qui, si j'ai bien compris, suit son propre chemin en raison de divergences avec la vision d'Oracle sur OOo. Je suis pour l'instant resté avec OpenOffice qui est plus largement déployé mais LibreOffice me parait une initiative séduisante.

A bientôt pour d'autres articles sur la bureautique pythonique :)


Nom: Email: URL: Commentaire: Si vous saisissez quelque chose dans ce champ, votre commentaire sera considéré comme étant indésirable: Captcha: captcha

Luc JEAN

09.65.20.15.70

ljean@apidev.fr

Luc JEAN

Suivez les nouveautés

Wikio RSS  RSS Blog Python Django selenium Rss commentaires
Paperblog : Les meilleurs actualités issues des blogs Follow luc_apidev on Twitter