Programmer OpenOffice.org avec Visual Basic

Version 0.2, du 19/08/2004
La dernière version de ce document est à http://www.kalitech.fr/clients/doc/VB_APIOOo_en.html

Public Documentation License Notice

The contents of this Documentation are subject to the Public Documentation License
Version 1.0 (the "License"); you may only use this Documentation if you comply with
the terms of this License. A copy of the License is available at
http://www.openoffice.org/licenses/PDL.html.
The Original Documentation is "Programmer OpenOffice.org avec Visual Basic. The 
Initial Writer of the Original Documentation is Didier ALAIN Copyright (C)2004.
All Rights Reserved. (Initial Writer contact(s): didier.alain@kalitech.fr).

Contributor(s): ______________________________________.

Portions created by ______ are Copyright (C)_________[Insert year(s)]. All Rights 
Reserved. (Contributor contact(s):________________[Insert hyperlink/alias]).
Avertissement
Document en cours de rédaction : il y a sûrement encore nombre d'imprécisions, de flous, voire d'erreurs !

Marques de révision

Pour aller vite

  1. Installer OpenOffice (version la plus récente conseillée)
  2. Dans un module Visual Basic ou Visual Basic pour Application, copier cette procédure :
    Sub DebutOOo()
    
    Dim oSM, oDesk, oDoc As Object 'Les objets de base pour travailler avec OOo
    Dim arg()                      'Les paramètres d'ouverture du fichier, ici aucun !
        
        'Instancie OOo : ces deux lignes sont obligatoires avec VB dans tout code !
        Set oSM = CreateObject("com.sun.star.ServiceManager")
        Set oDesk = oSM.createInstance("com.sun.star.frame.Desktop")
        
        'Crée un nouveau document
        Set oDoc = oDesk.loadComponentFromURL("private:factory/swriter", "_blank", 0, arg())
        'Ferme le document
        oDoc.Close (True)
        Set oDoc = Nothing
        
        'Ouvre un document existant (notez la syntaxe pour le chemin du fichier)
        Set oDoc = oDesk.loadComponentFromURL("file:///c:/dev/ooo/test.doc", "_blank", 0, arg())
        'Enregistre le document
        Call oDoc.storeToURL("file:///c:/dev/ooo/test2.doc", arg())
        'Ferme le document
        oDoc.Close (True)
        Set oDoc = Nothing
        
    End Sub
    
  3. Exécuter la procédure en pas à pas (c'est mieux, sinon, vous ne verrez pas grand chose !)

De l'API au langage de programmation

L'API de OOo peut être programmée avec différents langages : C++, java, python, StarBasic, ECMAScript, ou au travers des composants COM de m$windows : *.NET (en cours de développement), Visual C++, Visual Basic, VBScript, grâce au pont UNO-Automation. L'API de OOo est abstraite et neutre vis-à-vis des langages de programmation. Il faut donc la lire et la traduire dans le langage utilisé, c'est la principale difficulté.

De l'API à Visual Basic

  1. On crée un objet OOo avec une commande Visual Basic CreateObject
  2. On programme avec les commandes de l'API à partir de cet objet
Concrètement :

set oObjetDeBaseOOo = CreateObject(...)
                      ^commande VB


set oObjetOOo = oObjetDeBaseOOo.createInstance(...)
                                ^méthode de l'API OOo : tout ce qui suit ce point est dans l'API OOo.

Trucs pour la "traduction"

Les termes employés dans la doc de l'API sont souvent déroutants quand on vient du monde VB...

Description et structure de l'API

L'API de OOo est orientée objet, donc très différente des composants m$office:

L'API dispose de ses propres types de données :

Constantes pré-définies (en cours de correction, merci à Bernard Marcelly !)
Il existe des constantes pré-définies, comme dans l'API m$office. Attention, elles sont sensibles à la casse, ex. :

com.sun.star.text.ControlCharacter.LINE_BREAK

ControlCharacter.LINE_BREAK est le nom de la constante prédéfinie.

Les principales difficultés

Le pont UNO-Automation à ce jour connait certaines limitations qui compliquent sincèrement la vie sur certains points.

Le problème de l'accès aux propriétés d'objets OOo en VB

les propriétés des objets dans l'API de OOo sont du type de données structure.Le problème est que le pont UNO-Automation ne convertit pas automatiquement les structures OOo en structures VB. A partir de VB, il faut donc utiliser une interface particulière de l'API pour accéder aux structures (cf http://api.openoffice.org/docs/DevelopersGuide/ProfUNO/ProfUNO.htm#1+4+4+5+3+Usage+of+Types) .

Paramétrer les propriétés d'un objet de l'API OOo en VB (merci Bernard Marcelly !)

Certaines propriétés d'objet de l'API OOo sont du type structure. Pour des raisons liées à l'implémentation du pont UNO-Automation (cf http://api.openoffice.org/docs/DevelopersGuide/ProfUNO/ProfUNO.htm#1+4+4+5+3+Usage+of+Types), on ne peut passer directement une structure VB en argument d'une fonction de l'API OOo. A partir de VB, il faut donc utiliser une fonction particulière de l'API (Bridge_GetStruct) pour accéder aux structures et pouvoir ensuite passer cette structure à la fonction OOo.
Voici ci-dessous une petite fonction VB qui permet de résoudre ce problème :
Function setOOoProp(cName, uValue) As Object
    
  Dim oPropertyValue As Object
  Dim oSM As Object
	
  Set oSM = CreateObject("com.sun.star.ServiceManager")    
  Set oPropertyValue = oSM.Bridge_GetStruct("com.sun.star.beans.PropertyValue")
  oPropertyValue.Name = cName
  oPropertyValue.Value = uValue
      
  Set setOOoProp = oPropertyValue

End Function
Pour accéder à une structure de l'API, on n'aura plus qu'à appeler cette fonction, par exemple dans le cas des paramètres d'ouverture d'un fichier : Donc, quand une fonction de l'API OOo attend une structure comme argument (cas d'un des paramètres de la fonction loadComponentFromURL, par exemple), on appelle d'abord cette fonction, et on passe son résultat dans l'argument de la fonction OOo. Ex. :
Sub OuvreOOoDoc()
Rem
Rem Charger un document Writer, avec des paramètres d'ouverture (OpenPar)
Rem
  Dim oSM, ODesk as Object 'Les objets de base de OOo
  Dim OpenPar(2) As Object 'Un tableau VB

'Instancie OOo : ces deux lignes sont obligatoires avec VB dans tout code !
  Set oSM = CreateObject("com.sun.star.ServiceManager")
  Set oDesk = oSM.createInstance("com.sun.star.frame.Desktop")

'On appelle la fonction setOOoProp définie précédemment pour récupérer la structure
  Set OpenPar(0) = setOOoProp("ReadOnly", True)
  Set OpenPar(1) = setOOoProp("Password", "secret")
  Set OpenPar(2) = setOOoProp("Hidden", False)

'On appelle la fonction OOo loadComponentFromURL, en lui passant en
'dernier paramètre le résultat de la fonction setOOoProp    
  Set r_doc = oDesk.loadComponentFromURL("file:///c|test.sxw", "_blank", 0, OpenPar)

End Sub

Conflits des noms de méthodes avec les méthodes intégrées de VB

Si vous tapez :
Call oDoc.Print
La méthode Print de VB prendra le pas sur la méthode Print de l'API d'OOo. C'est d'ailleurs facile à vérifier car l'IDE de VB remet systématiquement la méthode Print en majuscule (et il supprime le Call), ce qui indique bien qu'il va chercher la méthode dans une bibliothèque intégrée à Windows.
Il faut donc dans ce cas écrire :
CallByName oDoc, "print", vbMethod, arg 'arg est un tableau d'arguments (cf setOOoProp)

La gestion des évènements

Reste encore à écrire, je n'ai presque rien compris !

Installation

Rien en vaut la doc d'origine !

(http://api.openoffice.org/docs/DevelopersGuide/ProfUNO/ProfUNO.htm#1+4+4+Automation+Bridge)

"Requirements

The Automation technology can only be used with OpenOffice.org on a Windows platform (Windows 95, 98, NT4, ME, 2000, XP). There are COM implementations on Macintosh OS and UNIX, but there has been no effort to support Automation on these platforms.

Using Automation involves creating objects in a COM-like fashion, that is, using functions like CreateObject() in VB or CoCreateInstance() in C. This requires the OpenOffice.org automation objects to be registered with the Windows system registry. This registration is carried out whenever an office is installed on the system. If the registration did not take place, for example because the binaries were just copied to a certain location, then Automation clients will not work correctly or not at all. Refer to 3.4.4 Professional UNO - UNO Language Bindings - Automation Bridge - The Service Manager Component for additional information."

POO ! (Programmation Orientée Objet)

Ce qui est spécifique au monde orienté objet, c'est bien la couche (modules)-services||interfaces-méthodes.

Les interfaces peuvent être identiques quelque soit les services auxquelles elles donnent accès.Ce qui fonde une interface, c'est qu'elle expose toujours les mêmes méthodes, quelque soit l'objet (module, composant ou service) auquel elle donne accès. Attention ! Bien entendu, les méthodes peuvent être surchargées selon les objets auxquelles elles s'adressent, càd que les paramètres de la méthode peuvent changer en fonction de l'objet auquel elle s'adresse.

On ne peut faire quoi que ce soit qu'au travers des interfaces. Ces interfaces ne sont accessibles qu'au travers des services. Donc :

  1. On accède au service
  2. On accède aux interfaces (étape masquée en fait en BASIC)
  3. On accèdes aux méthodes, propriétés ou collections (au travers des interfaces, sauf en BASIC).

De m$office à OOo

Les premières versions de StarOffice, historiquement, présentaient la suite bureautique dans un bureau (les environnements KDE et gnome, n'étaient pas au niveau d'un bureau correct !). On lançait donc StarOffice, on arrivait sur un bureau, et ensuite on accédait aux applications de la suite bureautique, et ce, y compris sous m$windows (très lourd...). L'intégration de StarOffice dans les environnements graphiques hôtes a évolué, mais cet objet desktop est toujours très présent dans l'API, et il expose en lui-même déjà un grand nombre de services, donc en dehors des différentes applications OOo.

Par conséquent, on a des services non dépendants du contexte, liés uniquement au service global desktop, et des services accessibles uniquement dans un contexte donné.