Difference between revisions of "FR/Documentation/L'automation d'OpenOffice.org avec un binaire exécutable"

From Apache OpenOffice Wiki
Jump to: navigation, search
m (Introduction au Bootstrapping)
m (Introduction au Bootstrapping)
Line 106: Line 106:
  
 
{{Documentation/Caution|Comme tous les schémas, sa compréhension nécessite de comprendre toutes les conventions qu'il utilise. Je pense changer de conventions dans le futur en m'inspirant du nouvel inspecteur d'objet Java disponible maintenant}}
 
{{Documentation/Caution|Comme tous les schémas, sa compréhension nécessite de comprendre toutes les conventions qu'il utilise. Je pense changer de conventions dans le futur en m'inspirant du nouvel inspecteur d'objet Java disponible maintenant}}
If you are interested in, have a look simultaneously to the code and to the drawing to see the schematic conventions I have used to carry out the Figure above. For instance both XInterface are connected because we use the same variable in fact. The gray filled rectangles are for parameters... and so on.
 
  
We want now the desktop and load a OooCalc component.  
+
Si vous êtes intéressé, regardez simultanément le code et le dessin pour comprendre les conventions pour réaliser la figure ci-dessus. Par exemple, les deux interfaces XInterface sont connectées parcequ'on utilise la même variable en fait. Les rectangles rempli en gris sont réservés aux paramètres... etc...
  
The '''first step''' is to obtain desktop. You then add this code :
+
On veut maintenant le desktop et charger un composant tableur OooCalc.
 +
 
 +
La '''première étape''' est d'obtenir le desktop. Vous ajouter ensuite ce code :
  
 
<source lang="cpp">
 
<source lang="cpp">
Line 118: Line 119:
 
   OUString::createFromAscii( "com.sun.star.frame.Desktop" ));
 
   OUString::createFromAscii( "com.sun.star.frame.Desktop" ));
 
</source>
 
</source>
Your desktop object is xDesktop.
+
Votre objet desktop est la variable xDesktop.
  
'''Second step''' : query for the XComponentLoader interface
+
'''Deuxième étape''' : demande de l'interface XComponentLoader
  
 
<source lang="cpp">
 
<source lang="cpp">
Line 132: Line 133:
 
     }
 
     }
 
</source>
 
</source>
Before to see the problems with this code, we give again a schematic representation :
+
Avant d'examiner les problèmes avec ce code, nous en donnons une représentation schématique :
  
 
[[Image:ch4fig2Componentloader.png|none|thumb|600px|Component Loader]]
 
[[Image:ch4fig2Componentloader.png|none|thumb|600px|Component Loader]]
  
The code above gives error messages :  
+
Le code ci-dessus produit malheureusement les messages d'erreur suivant :  
 
<pre>
 
<pre>
 
error 'XcomponentLoader' undeclared (First use this function) ....
 
error 'XcomponentLoader' undeclared (First use this function) ....
 
</pre>
 
</pre>
It shows us there is a problem with XComponentLoader : this indicates we have probably to add a hpp header file in the program's include statements. The file's name is probably XComponentLoader.hpp but we have to find where it lies. One way is to go in the [http://api.openoffice.org/docs/common/ref/index-files/index-1.html general index] and to look for XComponentLoader. We find : “::com::sun::star::frame” which indicates
+
Cela nous montre l'existance d'un problème avec XComponentLoader : cela indique que vous avez probablement à ajouter une inclusion d'un fichier hpp dans votre programme à l'aide des "include". Le nom du fichier concerné est probablement XComponentLoader.hpp mais nous avons à trouver son chemin complet. Une façon est d'utiliser l' [http://api.openoffice.org/docs/common/ref/index-files/index-1.html index général] et d'y chercher XComponentLoader. On trouve alors : “::com::sun::star::frame” qui nous permet de déduire que
 
<source lang="cpp">
 
<source lang="cpp">
 
#include <com/sun/star/frame/XComponentLoader.hpp>
 
#include <com/sun/star/frame/XComponentLoader.hpp>
 
</source>
 
</source>
is required. We can try and see it is not enough, we obtain always the same error message and one new before :
+
est requis. Un essai nous permet de constater que ce n'est pas suffisant puisque le même message d'erreur que précédemment est obtenu :
 +
<pre>
 
com/sun/star/frame/XComponentLoader.hpp: No such file or directory  
 
com/sun/star/frame/XComponentLoader.hpp: No such file or directory  
I have already discussed this fact : the SDK doesn't provide any hpp file, they have to be constructed from IDL files. An other task is then  : open and change the makefile. Only add the correspondant line :
+
</pre>
 +
J'ai déjà discuté ce fait : le SDK ne fournit pas les fichiers hpp mais seulement les moyens de les construire à partir des fichiers IDL. Il vous faudra donc ouvrir et changer le fichier "makefile". Regardez comme cela est réalisé ci-dessous avec l'ajout d'une ligne :
 
<pre>
 
<pre>
 
#added com.sun.star.frame.XComponentLoader
 
#added com.sun.star.frame.XComponentLoader
Line 166: Line 169:
 
     com.sun.star.container.XHierarchicalNameAccess
 
     com.sun.star.container.XHierarchicalNameAccess
 
</pre>
 
</pre>
Making the project gives again the same error message. What is still lacking now ?  
+
Construisant le projet donne toujours le même message d'erreur. Qu'est-ce qui manque maintenant ?
Only a namespace statement in the source file :
+
Seulement une instruction de nommage qui nous donne le résultat final :
 
<source lang="cpp">
 
<source lang="cpp">
 
// C++
 
// C++
 
using namespace com::sun::star::frame;
 
using namespace com::sun::star::frame;
 
</source>
 
</source>
(To go further with the two steps above see [[IDL_Files_and_Cpp#Getting_an_interface_in_C.2B.2B|Getting an Interface in C++]])
+
(Pour aller plus loin avec ces deux étapes voir [[IDL_Files_and_Cpp#Getting_an_interface_in_C.2B.2B|Getting an Interface in C++]])
  
'''Step 3''' : get an instance of the spreadsheet
+
'''étape 3''' : obtenir une instance du tableur
 
    
 
    
 
<source lang="cpp">
 
<source lang="cpp">
// Listing 4 Loading a new OOoCalc document
+
// Listing 4 Créer un nouveau document OOoCalc
 
// C++
 
// C++
 
Reference< XComponent > xcomponent = rComponentLoader->loadComponentFromURL(
 
Reference< XComponent > xcomponent = rComponentLoader->loadComponentFromURL(
Line 185: Line 188:
 
         Sequence < ::com::sun::star::beans::PropertyValue >());
 
         Sequence < ::com::sun::star::beans::PropertyValue >());
 
</source>
 
</source>
and it works : you have a new OOoCalc document.
+
et cela fonctionne : vous avez un nouveau document OOoCalc vierge.
  
This [[IDL_Files_and_Cpp#Getting_an_interface_in_C.2B.2B|hyperlink]] will takkle again the header file construction problem.
+
Ce [[IDL_Files_and_Cpp#Getting_an_interface_in_C.2B.2B|hyperlien (en anglais)]] abordera de nouveau le problème de la construction des fichiers d'inclusion.
  
An other thing to note is : when constructing variables with Reference template like :  
+
Une autre chose à noter est : quand vous construisez des variables avec le modèle Reference comme cela est fait dans l'extrait de code ci-dessous :  
 
<pre>
 
<pre>
 
Reference<...>varName  
 
Reference<...>varName  
 
</pre>
 
</pre>
you can check with
+
vous disposez en contrepartie de la possibilité de tester la réussite de la construction avec la fonction :
 
<pre>
 
<pre>
 
varName.is()  
 
varName.is()  
 
</pre>
 
</pre>
function. The problem of what to do if this variable is not created (varName.is() is false) is complex and not deeply tackled in this document. It refers to exceptions.
+
Le problème de choisir quoi faire en cas d'échec de la création de la variable (varName.is() est faux) est complexe est pas abordé complètement dans ce document. Il réfère aux exceptions.
  
 +
== Utiliser l'objet desktop ==
  
 
On veut maintenant l'objet desktop pour charger un document tableur OOoCalc.  
 
On veut maintenant l'objet desktop pour charger un document tableur OOoCalc.  

Revision as of 13:55, 4 July 2008

Nous voulons maintenant nous attaquer a un programme entier en UNO/OpenOffice.org. Ce programme effectuera quelques taches sur des documents OpenOffice.org , chargements de fichiers, modifications de fichiers, sauvegardes de fichiers....

Introduction à partir d'un exemple du SDK

Danny Brewer a écrit dans le forum sur Openoffice :ici. Pour faire quelque chose d'utile avec OOo à travers l'API, dans la plupart des cas, cela nécessite soit de créer, soit d'ouvrir un nouveau document. Ensuite vous aimeriez manipuler le contenu du document, en extraire de l'information, l'imprimer, le convertir en un autre format, travailler avec des données d'un formulaire ou encore réaliser d'autres tâches sur les documents. Pour cela la première chose à apprendre est comment ouvrir ou créer des documents. Les objets ServiceManager et Desktop

Pour pouvoir travailler avec OOo avec l'API, vous devez obtenir deux objets absolument essentiels 1. le ServiceManager (gestionnaire de service) 2. le Desktop (le bureau)

Une fois le ServiceManager obtenu,un appel à sa méthoded createInstance() permet d'obtenir l'objet Desktop. Une fois obtenu cet objet Desktop, vous pouvez l'utiliser pour créer ou ouvrir des nouveaux documents.

Obtenir le gestionnaire de services

pour chaque différent langage, il y a un mécanisme permettant d' acquérir le “Service Manager.” Le moyen d'obtenir le service manager est donné dans l'exemple SDK  : <OpenOffice.org1.1_SDK>/examples/DevelopersGuide/ProfUNO/CppBinding Nous regardons le premier exemple en premier (sous Linux) : Template:Documentation/Linux

qui écrit seulement : "Connected successfully to the office". Mais c'est déjà pas mal ? Non ?

Sous windows, cela donnerait : Template:Documentation/Windows

Nous commencerons notre travail à partir de cet exemple. Tout les listings que nous donnerons sont à ajouter à cet exemple. Où ça? Ceci montré maintenant :

//Listing 14 
//C++  *** extract from office_connect.cxx
int main( )
{
	// create the initial component context
	Reference< XComponentContext > rComponentContext =
		defaultBootstrap_InitialComponentContext();
	// retrieve the servicemanager from the context
	Reference< XMultiComponentFactory > rServiceManager =
		rComponentContext->getServiceManager();
	// instantiate a sample service with the servicemanager.
	Reference< XInterface > rInstance =
		rServiceManager->createInstanceWithContext(
			OUString::createFromAscii("com.sun.star.bridge.UnoUrlResolver" ),
			rComponentContext );
	// Query for the XUnoUrlResolver interface
	Reference< XUnoUrlResolver > rResolver( rInstance, UNO_QUERY );
	if( ! rResolver.is() )
	{
		printf( "Error: Couldn't instantiate com.sun.star.bridge.UnoUrlResolver service\n" );
		return 1;
	}
	try
	{
		// resolve the uno-url
		rInstance = rResolver->resolve( OUString::createFromAscii( 
			"uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager" ) );
		if( ! rInstance.is() )
		{
			printf( "StarOffice.ServiceManager is not exported from remote counterpart\n" );
			return 1;
		}
		// query for the simpler XMultiServiceFactory interface, sufficient for scripting
		Reference< XMultiServiceFactory > rOfficeServiceManager (rInstance, UNO_QUERY);
		if( ! rInstance.is() )
        {
            printf( "XMultiServiceFactory interface is not exported for StarOffice.ServiceManager\n" );
            return 1;
        }
 
        printf( "Connected sucessfully to the office\n" );
//  ***** mettez votre code ici 
	}
	catch( Exception &e )
	{
		OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
		printf( "Error: %s\n", o.pData->buffer );
		return 1;
	}
	return 0;
}

Je ne peux pas expliquer complètement toutes les lignes de ce fichier source. Je peux juste dire que c'est un moyen parmi d'autres d'obtenir le “ Service Manager”. Une autre façon de le faire est donnée dans <OpenOffice.org1.1_SDK>/examples/cpp/DocumentLoader's example.

Introduction au Bootstrapping

Le Bootstrap (désolé je garde la terminologie anglaise) est dicuté plus en détail plus tard (référence anglaise!!!). Nous nous contenterons donc d'une introduction maintenant.

Mémoriser le code de la section précédente est difficile et probablement inutile. Cependant, nous en donnons une représentation graphique pour en montrer les principales étapes.

Bootstrapping
Documentation caution.png Comme tous les schémas, sa compréhension nécessite de comprendre toutes les conventions qu'il utilise. Je pense changer de conventions dans le futur en m'inspirant du nouvel inspecteur d'objet Java disponible maintenant

Si vous êtes intéressé, regardez simultanément le code et le dessin pour comprendre les conventions pour réaliser la figure ci-dessus. Par exemple, les deux interfaces XInterface sont connectées parcequ'on utilise la même variable en fait. Les rectangles rempli en gris sont réservés aux paramètres... etc...

On veut maintenant le desktop et charger un composant tableur OooCalc.

La première étape est d'obtenir le desktop. Vous ajouter ensuite ce code :

// Listing 2 Obtaining a desktop interface
// C++
Reference< XInterface  > xDesktop = rOfficeServiceManager->createInstance(
   	OUString::createFromAscii( "com.sun.star.frame.Desktop" ));

Votre objet desktop est la variable xDesktop.

Deuxième étape : demande de l'interface XComponentLoader

// Listing 3  Query a XcomponentLoader Interface
// C++
// query a XcomponentLoader Interface 
Reference< XComponentLoader > rComponentLoader (xDesktop, UNO_QUERY);
if( rComponentLoader.is() )
    	{
        	printf( "XComonentloader succesfully instanciated\n" );
    	}

Avant d'examiner les problèmes avec ce code, nous en donnons une représentation schématique :

Component Loader

Le code ci-dessus produit malheureusement les messages d'erreur suivant :

error 'XcomponentLoader' undeclared (First use this function) ....

Cela nous montre l'existance d'un problème avec XComponentLoader : cela indique que vous avez probablement à ajouter une inclusion d'un fichier hpp dans votre programme à l'aide des "include". Le nom du fichier concerné est probablement XComponentLoader.hpp mais nous avons à trouver son chemin complet. Une façon est d'utiliser l' index général et d'y chercher XComponentLoader. On trouve alors : “::com::sun::star::frame” qui nous permet de déduire que

#include <com/sun/star/frame/XComponentLoader.hpp>

est requis. Un essai nous permet de constater que ce n'est pas suffisant puisque le même message d'erreur que précédemment est obtenu :

com/sun/star/frame/XComponentLoader.hpp: No such file or directory 

J'ai déjà discuté ce fait : le SDK ne fournit pas les fichiers hpp mais seulement les moyens de les construire à partir des fichiers IDL. Il vous faudra donc ouvrir et changer le fichier "makefile". Regardez comme cela est réalisé ci-dessous avec l'ajout d'une ligne :

#added com.sun.star.frame.XComponentLoader
TYPES := \
	com.sun.star.uno.XNamingService \
	com.sun.star.uno.XComponentContext \
	com.sun.star.uno.XWeak \
	com.sun.star.uno.XAggregation \
	com.sun.star.frame.XComponentLoader \
	com.sun.star.lang.XMain \ 
        com.sun.star.lang.XMultiServiceFactory \
	com.sun.star.lang.XSingleComponentFactory \
	com.sun.star.lang.XTypeProvider \
	com.sun.star.lang.XComponent \
	com.sun.star.registry.XSimpleRegistry \
	com.sun.star.registry.XImplementationRegistration \
	com.sun.star.bridge.XBridgeFactory \
	com.sun.star.bridge.XUnoUrlResolver \
    com.sun.star.container.XHierarchicalNameAccess

Construisant le projet donne toujours le même message d'erreur. Qu'est-ce qui manque maintenant ? Seulement une instruction de nommage qui nous donne le résultat final :

// C++
using namespace com::sun::star::frame;

(Pour aller plus loin avec ces deux étapes voir Getting an Interface in C++)

étape 3 : obtenir une instance du tableur

// Listing 4 Créer un nouveau document OOoCalc
// C++
Reference< XComponent > xcomponent = rComponentLoader->loadComponentFromURL(
	OUString::createFromAscii("private:factory/scalc"),
        OUString::createFromAscii("_blank"),
        0,
        Sequence < ::com::sun::star::beans::PropertyValue >());

et cela fonctionne : vous avez un nouveau document OOoCalc vierge.

Ce hyperlien (en anglais) abordera de nouveau le problème de la construction des fichiers d'inclusion.

Une autre chose à noter est : quand vous construisez des variables avec le modèle Reference comme cela est fait dans l'extrait de code ci-dessous :

	Reference<...>varName 

vous disposez en contrepartie de la possibilité de tester la réussite de la construction avec la fonction :

	varName.is() 

Le problème de choisir quoi faire en cas d'échec de la création de la variable (varName.is() est faux) est complexe est pas abordé complètement dans ce document. Il réfère aux exceptions.

Utiliser l'objet desktop

On veut maintenant l'objet desktop pour charger un document tableur OOoCalc. La première étape est d'obtenir le desktop. Ensuite vous ajouté ce code:

//Listing 15 
// C++
Reference< XInterface  > xDesktop = rOfficeServiceManager->createInstance(
   	OUString::createFromAscii( "com.sun.star.frame.Desktop" ));

Votre objet desktop est dans notre variable xDesktop. Deuxième étape : demander une interface XComponentLoader

//Listing 16 
// C++
// query a XcomponentLoader Interface 
Reference< XComponentLoader > rComponentLoader (xDesktop, UNO_QUERY);
if( rComponentLoader.is() )
    	{
        	printf( "XComonentloader succesfully instanciated\n" );
    	}

Le code ci dessus donne des messages d'erreurs : error 'XComponentLoader' undeclared (First use this function) .... Cela nous montre qu'il y a un problème avec XComponentLoader : Cela indique que nous devons probablement ajouter un fichier hpp dans les directives habituelles d'inclusion. Le nom du fichier est sûrement XComponentLoader.hpp mais nous devons trouver où il se situe. Un moyen simple consiste a aller sur : http://api.openoffice.org/docs/common/ref/index-files/index-1.html et regarder pour XComponentLoader. Nous trouvons: “::com::sun::star::frame” ce qui indique qu'une directive :

//Listing 17 
// C++
#include <com/sun/star/frame/XComponentLoader.hpp>

est requise. Nous pouvons essayer de l'ajouter, tout cela pour s'apercevoir que ce n'est pas suffisant. On obtient toujours le même message d'erreur aussi qu'un autre en bonus : com/sun/star/frame/XComponentLoader.hpp: No such file or directory Je discuterais ce fait beaucoup plus en détail dans le chapitre XX : le SDK ne fournit pas les fichiers hpp , ils doivent être construit à partir de fichiers IDL . Pour cela il nous faut ouvrir et changer le makefile comme indiqué ci-dessous (repérez bien la ligne correspondante).

#added com.sun.star.frame.XComponentLoader
TYPES := \
	com.sun.star.uno.XNamingService \
	com.sun.star.uno.XComponentContext \
	com.sun.star.uno.XWeak \
	com.sun.star.uno.XAggregation \
	com.sun.star.frame.XComponentLoader \
	com.sun.star.lang.XMain \ 
    com.sun.star.lang.XMultiServiceFactory \
	com.sun.star.lang.XSingleComponentFactory \
	com.sun.star.lang.XTypeProvider \
	com.sun.star.lang.XComponent \
	com.sun.star.registry.XSimpleRegistry \
	com.sun.star.registry.XImplementationRegistration \
	com.sun.star.bridge.XBridgeFactory \
	com.sun.star.bridge.XUnoUrlResolver \
    com.sun.star.container.XHierarchicalNameAccess

On obtient cette fois encore le même message d'erreur dans le projet. Mais que manque-t-il donc encore pour éviter ce message ? Il manque juste une assertion de nommage dans le fichier source :

//Listing 18 
// C++
using namespace com::sun::star::frame;

Troisième étape : obtenir une instance du tableur

//Listing 19 
// C++
Reference< XComponent > xcomponent = rComponentLoader->loadComponentFromURL(
	OUString::createFromAscii("private:factory/scalc"),
        OUString::createFromAscii("_blank"),
        0,
        Sequence < ::com::sun::star::beans::PropertyValue >());

Avec toutes ces modifications vous venez de créer visuellement un document tableur vierge sans nom.

La chaîne de compilation

Il est très important de connaître la chaîne de compilation si vous voulez modifier un makefile. Si vous n'en n'avez pas l'intention passer au chapitre 4.3 Pour résumer, nous donnons le flot de conception (voir Figure 3) d'un exemple vu précédemment.

<OpenOffice.org1.1_SDK>/examples/DevelopersGuide/ProfUNO/CppBinding
Personal tools