FR/Documentation/OpenOffice Calc

From Apache OpenOffice Wiki
Jump to: navigation, search

Pour éviter de chercher dans le code examiné au précédent chapitre, on va insérer de nouveau les listings importants pour débuter ce chapitre :

  • Nous donnons pour commencer la fonction ooConnect() :
// Listing 0
// C++
#include <stdio.h>
#include <cppuhelper/bootstrap.hxx>
#include <com/sun/star/bridge/XUnoUrlResolver.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
// on ajoute la ligne ci-apres
#include <com/sun/star/frame/XComponentLoader.hpp>
 
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::bridge;
// ajouté aussi :
using namespace com::sun::star::frame;
 
using namespace rtl;
using namespace cppu;
 
// appel de la fonction de démarrage
Reference< XMultiServiceFactory > ooConnect(){
   // create the initial component context
   Reference< XComponentContext > rComponentContext = 
				defaultBootstrap_InitialComponentContext();
 
   // obtention du servicemanager à partir du 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 NULL;
   }
   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 NULL;
      }
 
      // query for the simpler XMultiServiceFactory interface, sufficient for scripting
      Reference< XMultiServiceFactory > rOfficeServiceManager (rInstance, UNO_QUERY);
 
      if( ! rOfficeServiceManager.is() ){
            printf( "XMultiServiceFactory interface is not exported for StarOffice.ServiceManager\n" );
            return NULL;
        }       
        return rOfficeServiceManager;
   }
   catch( Exception &e ){
      OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
      printf( "Error: %s\n", o.pData->buffer );
      return NULL;
   }
   return NULL;
}

Note : vous devez éventuellement changer le port de "port=8100" avec "port=2083" pour les SDK récents (après 2.X).

Il serait bon de regarder aussi :

  1. les interfaces com.sun.star.uno.XComponentContext, com.sun.star.lang.XMultiComponentFactory, com.sun.star.uno.XInterface, com.sun.star.bridge.XUnoUrlResolver et com.sun.star.lang.XMultiServiceFactory,
  2. et aussi le service com.sun.star.bridge.UnoUrlResolver.
  • Nous donnons maintenant le programme principal à modifier (le "main()") :
// code C++
//Listing 0b Notre programme principal
int main( ) {
//retrouve une instance service manager distant avec notre ooConnect()
    Reference< XMultiServiceFactory > rOfficeServiceManager;
    rOfficeServiceManager = ooConnect();
    if( rOfficeServiceManager.is() ){
        printf( "Connecté avec succès à OpenOffice\n" );
    }
 
//get the desktop service using createInstance returns an XInterface type
    Reference< XInterface  > Desktop = rOfficeServiceManager->createInstance(
    OUString::createFromAscii( "com.sun.star.frame.Desktop" ));
 
//demande de l'interface XComponentLoader interface
    Reference< XComponentLoader > rComponentLoader (Desktop, UNO_QUERY);
    if( rComponentLoader.is() ){
        	printf( "XComponentloader successfully instanciated\n" );
    	}
 
//get an instance of the spreadsheet
    Reference< XComponent > xcomponent = rComponentLoader->loadComponentFromURL(
	OUString::createFromAscii("private:factory/scalc"),
        OUString::createFromAscii("_blank"),
        0,
        Sequence < ::com::sun::star::beans::PropertyValue >());
//*********************************
// c'est ici que l'on rajoute le code présenté dans ce chapitre;
//*********************************
    return 0;
}

Ce code est appelé un programme d'amorce ou de démarrage et utilise :

  1. les interfaces com.sun.star.lang.XMultiServiceFactory, com.sun.star.uno.XInterface, com.sun.star.frame.XComponentLoader et com.sun.star.lang.XComponent interfaces
  2. le service com.sun.star.frame.Desktop,
  3. la structure UNO com.sun.star.beans.PropertyValue.

Rappelez-vous que chaque fois que vous demandez une interface vous devez ajouter des lignes de code si elles n'existent pas dans le code source ainsi que dans le makefile. Je vais en général ajouter des commentaires pour éviter les omissions.

Documentation note.png Note importante : Le point le plus important dans la chaîne de compilation des exemples ci-après est que l'utilitaire cppumaker construira chacun des fichiers d'inclusion hpp et hdl que votre application utilisera. Le SDK ne fournit pas les fichiers hpp, mais vous devez les construire à partir des fichiers IDL qui eux sont fournis avec le SDK.
Documentation note.png Il est possible de construire tous les fichiers d'inclusion hpp lors de l'installation du SDK comme j'ai eu l'occasion de le mentionner pour l'installation sous Windows. C'est naturellement possible aussi avec les autres systèmes d'exploitation. En procédant ainsi il ne vous faudra plus modifier votre MakeFile (sauf peut-être le chemin pour atteindre ces fichiers).

Souvenez vous que chaque fois que vous demandez pour une interface, vous devez ajouter quelques lignes de code (si elles n'existent pas) dans le code source et une ligne dans le makefile.

Trouver une feuille

L'interface la plus l'intéressante dans ce chapitre est com.sun.star.sheet.XSpreadsheetDocument. Cette interface propose la méthode getSheets(). Cette interface est héritée de l'interface de base Xinterface qui propose quant à elle le mécanisme d'obtention d'une nouvelle interface : c'est un peu technique et pas très utile à comprendre complètement pour le moment.

Avant de travailler sur des cellules, vous devez préciser dans quel document elles se trouvent, et dans quelle feuille.

Une feuille existante

Chaque feuille de Calc comporte un onglet. Le nom des onglets est par défaut, dans la version localisée française, Feuille1, Feuille2, etc.

Si vous connaissez le nom de la feuille, utilisez la méthode “getByName” :

//Listing 2 
//C++
// Ne pas oublier d'ajouter : using namespace com::sun::star::sheet;
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSpreadsheetDocument \" dans le makefile
//demande de l'interface XSpreadsheetDocument
	Reference< XSpreadsheetDocument > rSheetDoc (xcomponent, UNO_QUERY); 
 
//Utilisation pour obtenir l'interface XSpreadsheets
	Reference< XSpreadsheets > rSheets = rSheetDoc->getSheets(); 
 
//utilisation de getByName pour obtenir une feuille (type Any) 
	Any rSheet = rSheets->getByName( OUString::createFromAscii("Feuille2"));

Si on jette un coup d'oeil à la méthode getByName, nous pouvons voir qu'elle peut gérer un exception « no such element ». Une bonne programmation C++ nécessiterait donc que le code précédent soit dans une structure de contrôle try et catch.

//Listing 3 
//C++
// Ne pas oublier d'ajouter : using namespace com::sun::star::sheet;
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSpreadsheetDocument \" dans le makefile
//demande de l'interface XSpreadsheetDocument
	Reference< XSpreadsheetDocument > rSheetDoc (xcomponent, UNO_QUERY); 
 
//utilisation pour l'obtention de l'interface XSpreadsheets 
	Reference< XSpreadsheets > rSheets = rSheetDoc->getSheets(); 
 
//utilisation de getByName pour obtenir la feuille (type Any)
	try { 
		Any rSheet = rSheets->getByName( OUString::createFromAscii("Sheet2")); 
	}
	catch( Exception &e ){
      OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
      printf( "Error: No such element ;%s\n", o.pData->buffer );
   }

Pour simplifier nous n'utiliserons plus ce genre de code dans les prochaines parties, autrement dit nous ne gérerons pas les exceptions.

Si vous connaissez seulement l'index de la feuille, vous pourrez la récupérer en utilisant un moyen un peu plus compliqué (voir com.sun.star.frame.XIndexAccess) :

//Listing 4 
//C++
// Ne pas oublier d'ajouter : using namespace com::sun::star::sheet;
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSpreadsheetDocument \" dans le makefile
// Ne pas oublier d'ajouter : using namespace com::sun::star::container;
// Ne pas oublier la directive : #include <com/sun/star/container/XIndexAccess.hpp>
// Ne pas oublier d'ajouter "com.sun.star.frame.XIndexAccess \" dans le makefile
//query for a XSpreadsheetDocument interface 
	Reference< XSpreadsheetDocument > rSheetDoc (xcomponent, UNO_QUERY); 
 
//use it to get the XSpreadsheets interface 
	Reference< XSpreadsheets > rSheets = rSheetDoc->getSheets();
 
// query for the ::com::sun::star::container::XIndexAccess service
    Reference< XIndexAccess > rSheetsByIndex (rSheets, UNO_QUERY);  
 
//use getByName to get a reference (type Any) 
	Any rSheet = rSheetsByIndex->getByIndex( (short)1 );

Comme vous le constatez vous devez demander une nouvelle interface com.sun.star.frame.XIndexAccess. Cela signifie comme d'habitude ajouter deux lignes dans le code et une dans le makefile.

Documentation caution.png Prenez garde : UNO considère la numérotation des feuilles à partir de 0 et donc le numéro un de la dernière ligne du programme ci-dessus correspond à la deuxième feuille.


Creer, renommer, copier et supprimer une feuille

Pour créer une feuille on utilise la méthode du “insertNewByName”. La méthode insertNewByName insère une nouvelle feuille vierge à une position donnée parmi les feuilles du document, et lui donne un nom :

//C++
// Ne pas oublier d'ajouter : using namespace com::sun::star::sheet;
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSpreadsheetDocument \" dans le makefile
//query for a XSpreadsheetDocument interface 
	Reference< XSpreadsheetDocument > rSheetDoc (xcomponent, UNO_QUERY); 
 
//use it to get the XSpreadsheets interface 
	Reference< XSpreadsheets > rSheets = rSheetDoc->getSheets(); 
 
//use it to create a new sheet called MySheet 
	rSheets->insertNewByName(OUString::createFromAscii("MySheet"), (short)0);

(short)0 est l'index de position de la nouvelle feuille insérée. Ici, dans cet exemple « MySheet » sera notre première feuille puisqu'elle porte le numéro 0.

Comment déplacer une feuille connue par son nom :

//Listing 5 
//C++
// Ne pas oublier d'ajouter : using namespace com::sun::star::sheet;
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSpreadsheetDocument \" dans le makefile
//demande de l'interface XSpreadsheetDocument
	Reference< XSpreadsheetDocument > rSheetDoc (xcomponent, UNO_QUERY); 
 
//puis utilisation pour obtebir l'interface XSpreadsheets 
	Reference< XSpreadsheets > rSheets = rSheetDoc->getSheets(); 
 
//enfin utilisation pour déplacer la feuille MySheet en troisième position  
	rSheets->moveByName(OUString::createFromAscii("MySheet"), (short)2);

Comment copier une feuille :

//Listing 6 
//C++
// Don't forget to add : using namespace com::sun::star::sheet;
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
// Don't forget to add "com.sun.star.sheet.XSpreadsheetDocument \" in the makefile
//query for a XSpreadsheetDocument interface 
	Reference< XSpreadsheetDocument > rSheetDoc (xcomponent, UNO_QUERY); 
 
//use it to get the XSpreadsheets interface 
	Reference< XSpreadsheets > rSheets = rSheetDoc->getSheets(); 
 
//use it to copy a sheet called MySheet in second position with the name "MySheet2" 
	rSheets->copyByName(OUString::createFromAscii("MySheet"),
                                 OUString::createFromAscii("MySheet2"), (short)1);

MySheet2 est une copie exacte de MySheet inserée comme seconde feuille. Comment renommer une feuille (voir com.sun.star.sheet.XNamed):

//C++ 
// Ne pas oublier d'ajouter : using namespace com::sun::star::sheet;
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSpreadsheetDocument \" dans le makefile
// Ne pas oublier d'ajouter : using namespace com::sun::star::container;
// Ne pas oublier la directive : #include <com/sun/star/sheet/XNamed.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XNamed \" dans le makefile
 
//query for a XSpreadsheetDocument interface 
	Reference< XSpreadsheetDocument > rSheetDoc (xcomponent, UNO_QUERY); 
 
//use it to get the XSpreadsheets interface 
	Reference< XSpreadsheets > rSheets = rSheetDoc->getSheets(); 
 
//use getByName to get a reference (type Any) 
	Any rSheet = rSheets->getByName( OUString::createFromAscii("Feuille2")); 
 
// query for XNamed Interface
	Reference< XNamed > rname (rSheet, UNO_QUERY);
 
// rename
	rname->setName(OUString::createFromAscii("MySheet"));

Rechercher ou changer une feuille actuellement sélectionnée

Nous disposons d'une feuille connue par son nom et désirons la rendre sélectionnée (voir com.sun.star.frame.XModel, com.sun.star.sheet.XSpreadsheetView et com.sun.star.sheet.XSpreadsheet) :

//Listing 7 
//C++ 
// Ne pas oublier d'ajouter : using namespace com::sun::star::sheet;
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSpreadsheetDocument \" dans le fichier makefile
// Ne pas oublier d'ajouter : using namespace com::sun::star::frame;
// Ne pas oublier la directive : #include <com/sun/star/frame/XModel.hpp>
// Ne pas oublier d'ajouter "com.sun.star.frame.XModel \" dans le makefile
 
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheetView.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSpreadsheetView \" dans le makefile
 
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheet.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSpreadsheet \" dans le makefile
 
//demande de l'interface XSpreadsheetDocument 
	Reference< XSpreadsheetDocument > rSheetDoc (xcomponent, UNO_QUERY); 
	Reference< XSpreadsheets > rSheets = rSheetDoc->getSheets(); 
 
//utilisation de getByName pour obtenir la feuille (type Any) 
	Any rSheet = rSheets->getByName( OUString::createFromAscii("Feuille2")); 
// we want to make our new sheet the current sheet, so we need to ask the model 
// for the controller: first query the XModel interface from our spreadsheet component 
 
//query for the XSpreadsheet interface
	Reference< XSpreadsheet > rSpSheet (rSheet, UNO_QUERY);
 
	Reference< XModel > rSpreadsheetModel (rSheetDoc, UNO_QUERY); 
 
// then get the current controller from the model 
	Reference< XController > rSpreadsheetController = rSpreadsheetModel->getCurrentController(); 
 
// get the XSpreadsheetView interface from the controller, we want to call its method 
// setActiveSheet 
	Reference< XSpreadsheetView > rSpreadsheetView (rSpreadsheetController, UNO_QUERY); 
 
// make our newly inserted sheet the active sheet using setActiveSheet 
	rSpreadsheetView->setActiveSheet(rSpSheet);

Maintenant, nous voulons réaliser un peu le contraire, à savoir, comment récupérer la feuille actuellement sélectionnée :

//Listing 8 Obtenier la feuille sélectionnée
//C++
// Pas si simple qu'en OooBasic : Ne fonctionne pas !!!!!!!!!!!!!!!!!
//query for a XSpreadsheetDocument interface 
	Reference< XSpreadsheetDocument > rSheetDoc (xcomponent, UNO_QUERY); 
	// get the focus
	Any rSheet = rSheetDoc.CurrentController.ActiveSheet();
	printf("Sheet %s under the focus\n",rSheet.getName());

Comment obtenir une cellule

Quand vous avez votre feuille, il est facile d'obtenir une cellule particulière (voir com.sun.star.sheet.XSpreadsheetDocument, com.sun.star.sheet.XSpreadsheet et com.sun.star.table.XCell) :

//Listing 9 
//C++
// N'oubliez pas d'ajouter : using namespace com::sun::star::sheet;
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
// N'oubliez pas d'ajouter "com.sun.star.sheet.XSpreadsheetDocument \" dans le makefile
// N'oubliez pas d'ajouter : using namespace com::sun::star::table; (for XCell)
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheet.hpp>
// N'oubliez pas d'ajouter "com.sun.star.sheet.XSpreadsheet \" dans le makefile
//Demande de l'interface XSpreadsheetDocument
	Reference< XSpreadsheetDocument > rSheetDoc (xcomponent, UNO_QUERY);
 
//et utilisation pour obtenir l'interface XSpreadsheets
	Reference< XSpreadsheets > rSheets = rSheetDoc->getSheets();
 
//utilisation de getByName pour obtenir une feuille (type Any)
	Any rSheet = rSheets->getByName( OUString::createFromAscii("Feuille1"));
 
//demande de l'interface XSpreadsheet 
	Reference< XSpreadsheet > rSpSheet (rSheet, UNO_QUERY);
 
	Reference< XCell > rCell = rSpSheet->getCellByPosition(0, 0);

Le premier paramètre est le numéro de la colonne, et le second est le numéro de la ligne, les deux numérotations commençant par zéro. Voir les exemples donnés ci-dessus où l'on accède à la cellule en haut à gauche appelée A1.

Que peut-on faire avec une cellule ?

L'interface com.sun.star.table.XCell fournit six méthodes :

  • getFormula : retourne la chaîne contenant la formule d'une cellule.
  • setFormula : positionne une formule dans la cellule
  • getValue : retourne la valeur en virgule flottante de la cellule
  • setValue : permet de mettre une valeur en virgule flottante dans une cellule
  • getType : retourne le type contenu dans la cellule
  • getError : retourne l'erreur de la cellule

Une valeur numérique dans une cellule

Mettre une valeur numérique dans une cellule est très facile :

//Listing 10 
//C++
// Ne pas oublier d'ajouter : using namespace com::sun::star::sheet;
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSpreadsheetDocument \" dans le makefile
// Ne pas oublier d'ajouter : using namespace com::sun::star::table; (for XCell)
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheet.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSpreadsheet \" dans le makefile
//query for a XSpreadsheetDocument interface
	Reference< XSpreadsheetDocument > rSheetDoc (xcomponent, UNO_QUERY);
 
//use it to get the XSpreadsheets interface
	Reference< XSpreadsheets > rSheets = rSheetDoc->getSheets();
 
//use getByName to get a reference (type Any)
	Any rSheet = rSheets->getByName( OUString::createFromAscii("Sheet1"));
 
//query the reference of type Any for the XSpreadsheet interface
	Reference< XSpreadsheet > rSpSheet (rSheet, UNO_QUERY);
 
	Reference< XCell > rCell = rSpSheet->getCellByPosition(0, 0);
 
//set the cell value then get another cell etc..
	rCell->setValue(219);
	rCell = rSpSheet->getCellByPosition(0, 1);
	rCell->setValue(25);
  Une formule dans une Cellule

Voir aussi com.sun.star.sheet.XSpreadsheetDocument et com.sun.star.sheet.XSpreadsheet

Mettre une formule dans une cellule

Pour mettre une formule dans une cellule, il suffit de remplacer setValue par setFormula. Ce qui donne :

//Listing 11 
//C++
	Reference< XCell > rCell = rSpSheet->getCellByPosition(0, 0);
	rCell->setValue(21);
	rCell = rSpSheet->getCellByPosition(0, 1);
	rCell->setValue(23);
	rCell = rSpSheet->getCellByPosition(0, 2);
	rCell->setFormula(OUString::createFromAscii("=sum(A1:A2)"));

Ce code met en fait la valeur 44 dans A3.

Chaîne de caractères dans une cellule

Nous utilisons un peu près le même principe que vu précédemment :

//Listing 12 
//C++ 
//set a string in the cell  
	rCell->setFormula(OUString::createFromAscii("Hello"));

Il est possible de changer le texte contenu dans une cellule avec un curseur (interface com.sun.star.text.XTextCursor obtenue de com.sun.star.text.XText). Le code ci-dessous nous permet de réaliser ce changement :

//Listing 13 
//C++
// Ne pas oublier d'ajouter : using namespace com::sun::star::text;
// Ne pas oublier la directive : #include <com/sun/star/text/XText.hpp>
// Ne pas oublier d'ajouter "com.sun.star.text.XText \" dans le makefile
 
// query first the XText interface
	Reference< XText > rText (rCell, UNO_QUERY); 
 
//query for the XTextCursor interface 
	//Reference< XTextCursor > rTextCurs (rText, UNO_QUERY); 
	Reference< XTextCursor > rTextCurs = rText -> createTextCursor(); 
	rTextCurs -> gotoEnd(false);
	rTextCurs -> setString(OUString::createFromAscii(" Bye"));

Ajouter ce code nous donne “Hello Bye” dans une cellule si "Hello" a été ajouté auparavant dans la même cellule (listing 12).

Quel est le type contenu dans une cellule ?

Nous utilisons tout naturellement la méthode getType de l'interface XCell. Elle retourne une des quatres possibilités : EMPTY, VALUE, TEXT or FORMULA (::com::sun::star::table) Comment voit-on les valeurs en C++ ? Nous donnons ici le contenu partiel de com.sun.star.table.CellContentType :

namespace com
{
namespace sun
{
namespace star
{
namespace table
{
 
enum CellContentType
{
    CellContentType_EMPTY = 0,
    CellContentType_VALUE = 1,
    CellContentType_TEXT = 2,
    CellContentType_FORMULA = 3,
    CellContentType_MAKE_FIXED_SIZE = SAL_MAX_ENUM
};
 
} // table
} // star
} // sun
} // com

qui nous montre qu'un “using namespace com::sun::star::table;” sera nécessaire. Il nous permet d'écrire en C++ quelque-chose comme: CellContentType_EMPTY si vous avez bien ajouté la directive d'inclusion  :

//Listing 14 
// C++
#include <com/sun/star/table/CellContentType.hpp>

Voir aussi com.sun.star.table.CellContentType

Le code ci-dessous en est un exemple :

Listing 15 
//C++
// Ne pas oublier d'ajouter : using namespace com::sun::star::sheet;
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSpreadsheetDocument \" dans le makefile
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheet.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSpreadsheet \" dans le makefile
 
// Ne pas oublier la directive #include <com/sun/star/table/CellContentType.hpp>
// Ne pas oublier d'ajouter "com.sun.star.table.CellContentType \" dans le makefile
 
//query for a XSpreadsheetDocument interface
	Reference< XSpreadsheetDocument > rSheetDoc (xcomponent, UNO_QUERY);
	Reference< XSpreadsheets > rSheets = rSheetDoc->getSheets();
 
	Any rSheet = rSheets->getByName( OUString::createFromAscii("Feuille1"));
	//query the reference of type Any for the XSpreadsheet interface
	Reference< XSpreadsheet > rSpSheet (rSheet, UNO_QUERY);
 
	Reference< XCell > rCell = rSpSheet->getCellByPosition(0, 0);
	rCell->setValue(43);
	switch (rCell->getType()){
		case CellContentType_EMPTY : printf("Empty\n");break;
		case CellContentType_VALUE : printf("Numerical Value\n");break;
		case CellContentType_TEXT : printf("Text\n");break;
		case CellContentType_FORMULA : printf("Formula\n");break;
	}

qui écrit “Numerical Value”.

Calculer une formule

Deux méthodes sont disponibles depuis l'interface com.sun.star.sheet.XCalculatable :calculate() et calculateAll() Vous pouvez obtenir cette interface depuis l'interface com.sun.star.sheet.XSpreadsheetDocument.

Formater une cellule

Le moyen le plus simple de formater une cellule est d'utiliser un style prédéfini du tableur. Les noms des styles prédéfinis doivent apparaître en anglais même s'ils apparaissent dans une autre langue dans la barre des objets. Elles sont  : Result, Result2, Default, Heading, Heading1 ...

//Listing 16 
//C++
// Ne pas oublier d'ajouter : using namespace com::sun::star::beans;
// Ne pas oublier la directive : #include <com/sun/star/beans/XPropertySet.hpp>
// Ne pas oublier d'ajouter "com.sun.star.beans.XPropertySet \" dans le makefile
 
//query for the cell property interface 
	Reference< XPropertySet > rCellProps (rCell, UNO_QUERY); 
 
//create an Any to hold our property value 
	Any mPropVal; 
	mPropVal <<= OUString::createFromAscii("Result"); 
 
//set some properties 
	rCellProps->setPropertyValue(OUString::createFromAscii("CellStyle"), mPropVal);

Voir aussi com.sun.star.beans.XPropertySet.

Annotations des cellules

L'exemple suivant va insérer une annotation et la rendra visible de manière permanente. Voir aussi com.sun.star.sheet.XSpreadsheetDocument, com.sun.star.sheet.XSpreadsheet, com.sun.star.sheet.XCellAddressable, com.sun.star.sheet.XSheetAnnotationsSupplier et com.sun.star.sheet.XSheetAnnotationAnchor.

//Listing 17 
//C++
// Ne pas oublier d'ajouter : using namespace com::sun::star::sheet;
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSpreadsheetDocument \" dans le makefile
 
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSpreadsheet.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSpreadsheet \" dans le makefile
 
// Ne pas oublier la directive : #include <com/sun/star/sheet/XCellAddressable.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XCellAddressable \" dans le makefile
 
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSheetAnnotationsSupplier.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSheetAnnotationsSupplier \" dans le makefile
 
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSheetAnnotationAnchor.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSheetAnnotationAnchor \" dans le makefile
 
//query for a XSpreadsheetDocument interface
	Reference< XSpreadsheetDocument > rSheetDoc (xcomponent, UNO_QUERY);
	Reference< XSpreadsheets > rSheets = rSheetDoc->getSheets();
 
	Any rSheet = rSheets->getByName( OUString::createFromAscii("Feuille1"));
 
//query the reference of type Any for the XSpreadsheet interface
	Reference< XSpreadsheet > rSpSheet (rSheet, UNO_QUERY);
 
//query for XCell Interface
	Reference< XCell > rCell = rSpSheet->getCellByPosition(0, 0);
 
//query for the XcellAddressable Interface
	Reference< XCellAddressable > rCellAddr (rCell, UNO_QUERY);
	CellAddress rAddress = rCellAddr -> getCellAddress();
 
//query for XSheetAnnotationsSupplier Interface 
	Reference< XSheetAnnotationsSupplier > rAnnotationSupp (rSheet, UNO_QUERY);
	Reference< XSheetAnnotations > rAnnotations = rAnnotationSupp -> getAnnotations();
	rAnnotations -> insertNew(rAddress,OUString::createFromAscii("Ceci est une annotation"));
 
// make the annotation visible
 
//query the XSheetAnnotationAnchor
	Reference< XSheetAnnotationAnchor > rAnnotAnchor (rCell, UNO_QUERY);
	Reference< XSheetAnnotation > rAnnotation = rAnnotAnchor -> getAnnotation();
	rAnnotation->setIsVisible(true);

Si vous voulez une annotation partiellement visible vous devez juste enlever les trois dernières lignes du code. Il est très intéressant de mettre une annotation dans une cellule mais comment l'obtenir si elle existe déjà ? Il suffit d'ajouter pour le test ce petit morceau de code au code du Listing 17 :

//Listing 18 
// C++
// Ne pas oublier d'ajouter : using namespace com::sun::star::text;
// Ne pas oublier la directive : #include <com/sun/star/text/XSimpleText.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSimpleText \" dans le makefile
 
// query the XSimpleTextInterface
	Reference< XSimpleText > rSimpleText (rAnnotation, UNO_QUERY);
 
	printf("Annotation : %s\n",
		OUStringToOString(rSimpleText->getString(),RTL_TEXTENCODING_ASCII_US).getStr());
// or if you want to put the text in the cell :
// 	rCell->setFormula(rSimpleText->getString());

qui affiche à l'écran la chaîne de caractères :“Annotation : Ceci est une annotation”.

Voir aussi com.sun.star.sheet.XSimpleText.

Zone de cellules

Le moyen d'obtenir une zone de cellules n'est pas aussi aisé qu'en OOoBasic. Il vous faut d'abord obtenir une interface com.sun.star.table.XCellRange pour avoir accès à sa méthode getCellRangeByName :

//Listing 19 Obtention d'une zone de cellules
//C++
// Ne pas oublier d'ajouter : using namespace com::sun::star::table;
// Ne pas oublier la directive : #include <com/sun/star/table/XCellRange.hpp>
// Ne pas oublier d'ajouter "com.sun.star.table.XCellRange \" dans le makefile
 
//query for a XSpreadsheetDocument interface 
	Reference< XSpreadsheetDocument > rSheetDoc (xcomponent, UNO_QUERY); 
	Reference< XSpreadsheets > rSheets = rSheetDoc->getSheets(); 
 
//use getByName to get a reference (type Any) 
	Any rSheet = rSheets->getByName( OUString::createFromAscii("Feuille1")); 
 
// query for the XCellRange interface
	Reference< XCellRange > rSheetCellRange (rSheet, UNO_QUERY);
 
// query the cell range
	Reference< XCellRange> rCellRange = 
		rSheetCellRange->getCellRangeByName(OUString::createFromAscii("B2:F5"));

Avec l'interface com.sun.star.table.XCellRange vous pouvez aussi accéder à la zone de cellules avec la méthode getCellRangeByPosition.

Pour obtenir une cellule de la zone de cellules vous pouvez simplement ajouter le code précédent :

//Listing 20 
//C++
	Reference< XCell > rCell = rCellRange->getCellByPosition(0, 0);
	rCell->setFormula(OUString::createFromAscii("it works"));

La position X et Y est alors relative à la zone de cellules et non plus à la feuille.

Rechercher les positions absolues X et Y d'une cellule

Ce sujet à déjà été abordé mais parmi tant d'autres. Nous avons d'abord besoin d'un type “ CellAddress “ décrit par une structure dans le fichier IDL suivant : <OpenOffice.org1.1_SDK>/idl/com/sun/star/text/CellAddress.idl. Nous reproduisons pour information ce fichier en ayant pris soin de retirer tous les commentaires inutiles.

//Listing 21 Structure CellAddress
// IDL
module com {  module sun {  module star {  module table {
struct CellAddress
{
	short Sheet;
	long Column;
	long Row;
};
}; }; }; };

Voir aussi com.sun.star.table.CellAddress.

En partant du Listing 19 précédent et en ajoutant

 
// C++
// Ne pas oublier la directive : #include <com/sun/star/sheet/XCellAddressable.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XCellAddressable \" dans le makefile
 
// Ne pas oublier la directive : #include <com/sun/star/table/CellAddress.hpp>
// Ne pas oublier d'ajouter "com.sun.star.table.CellAddress \" dans le makefile
 
//query for the XcellAddressable Interface
	Reference< XCellAddressable > rCellAddr (rCell, UNO_QUERY);
	CellAddress rAddress = rCellAddr -> getCellAddress();
	printf("sheet : %d, column : %d row: %d \n",rAddress.Sheet,rAddress.Column,rAddress.Row);

cela nous donne un programme qui nous retourne la position X et Y absolue d'une cellule.

Voir aussi com.sun.star.sheet.XCellAddressable.

Rechercher l'adresse d'une zone de cellules

Tout d'abord nous avons besoins d'une CellRange addresse type decrite dans: <OpenOffice.org1.1_SDK>/idl/com/sun/star/table/CellRangeAddress.idl :

//Listing 22 
// IDL
module com {  module sun {  module star {  module table {
 
struct CellRangeAddress
{
	short Sheet;
	long StartColumn;
	long StartRow;
	long EndColumn;
	long EndRow;
};
}; }; }; };

(voir aussi com.sun.star.table.CellRangeAddress) et une interface com.sun.star.sheet.XCellAddressable. En partant d'une zone de cellules, nous ajoutons :

//Listing 23 
// C++
// Ne pas oublier la directive : #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XCellRangeAddressable \" dans le makefile
 
// Ne pas oublier la directive : #include <com/sun/star/sheet/CellRangeAddress.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.CellRangeAddress \" dans le makefile
 
//query for the XCellRangeAddressable interface
	Reference< XCellRangeAddressable > rCellRangeAddr (rCellRange, UNO_QUERY);
	CellRangeAddress rRangeAddress = rCellRangeAddr -> getRangeAddress();
	printf("sheet : %d, start column : %d start row: %d ...\n",
		rRangeAddress.Sheet,rRangeAddress.StartColumn,rRangeAddress.StartRow);

Ce programme affiche seulement trois des quatre attributs de la zone de cellules.

Obtenir une zone de cellules à partir d'une sélection

Nous avons abordé un problème similaire dans la section ( Rechercher ou changer une feuille actuellement sélectionnée). Il nous faut partir encore de l'interface com.sun.star.frame.XModel, et demander ensuite avec getCurrentSelection l'interface XInterface pour obtenir enfin l'interface com.sun.star.table.XCellRange. Un exemple sera plus parlant :

//Listing 26 Zone de cellules selectionnée
// C++
	Reference< XInterface > rInterface = rSpreadsheetModel->getCurrentSelection();
 
// Don't forget to add : #include <com/sun/star/table/XCellRange.hpp>
// Don't forget to add "com.sun.star.table.XCellRange \" in the makefile
	Reference< XCellRange > rCellRange(rInterface,UNO_QUERY);
	rCell = rCellRange ->getCellByPosition(0, 0);
	rCell->setFormula(OUString::createFromAscii("Hello !!!"));

Ce code affiche “Hello !!!” dans le haut à gauche de la zone de cellules sélectionnée.

Voir aussi com.sun.star.table.XCellRange.

Montrer une zone de cellules comme “sélectionnée”

Le but est de sélectionner une zone par macro, et d’afficher cette sélection à l’utilisateur, mais je ne sais pas faire pour le moment.

Prêt à traduire le guide du développeur en C++

Si vous désirez aller encore plus loin, le guide du développeur est un bon point de départ. Le seul problème est que les exemples sont en majorité écrits en langage Java. Vous devez alors apprendre comment les traduire en C++. A première vue, vous pourrez trouver cette traduction assez compliquée mais je l'ai expérimenté en tant que total débutant en Java et je n'ai rencontré aucune grande difficulté.

L'exemple “Compute Function”

Commençons avec l'exemple SDK de la méthode computeFunction. Celle-ci permet d'appeler directement un nombre limité de fonctions du tableur. Ce nombre est limité car on doit éliminer toute fonction matricielle. Regardez la façon dont elle est appelée il en résulte que la fonction appelée doit retourner un type double.

//Listing 24 Code Java utilisant la méthode computeFunction
// Java
// --- Sheet operation. --- 
// Compute a function 
	com.sun.star.sheet.XSheetOperation xSheetOp = 
		(com.sun.star.sheet.XSheetOperation) UnoRuntime.queryInterface
			(com.sun.star.sheet.XSheetOperation.class, xCellRange);
	double fResult = xSheetOp.computeFunction(com.sun.star.sheet.GeneralFunction.AVERAGE);
 	System.out.println("Average value of the data table A10:C30: " + fResult); 
// Clear cell contents
	xSheetOp.clearContents( com.sun.star.sheet.CellFlags.ANNOTATION |
		 com.sun.star.sheet.CellFlags.OBJECTS);

où l'interface com.sun.star.sheet.XSheetOperation est utilisée. La traduction en C++ donne :

//Listing 25 Code C++ utilisant la méthode computeFunction
// C++
// Ne pas oublier la directive : #include <com/sun/star/sheet/XSheetOperation.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XSheetOperation \" dans le makefile
 
// Ne pas oublier la directive : #include <com/sun/star/sheet/GeneralFunction.hpp>
// and see in GeneralFunction.hdl how AVERAGE is generated : here GeneralFunction_AVERAGE
// Ne pas oublier d'ajouter "com.sun.star.sheet.GeneralFunction \" dans le makefile
 
// Ne pas oublier la directive : #include <com/sun/star/sheet/CellFlags.hpp>
// and see in CellFlags.hdl how ANNOTATION and OBJECT are generated :  here ANNOTATION, OBJECT
// in the namespace CellFlags donc :
// Ne pas oublier d'ajouter : using namespace com::sun::star::sheet::CellFlags;
// Ne pas oublier d'ajouter "com.sun.star.sheet.CellFlags \" dans le makefile
 
// --- Sheet operation. ---
// Compute a function
		// !!! rCellRange instead xCellRange in our previous code !!!
	Reference< XSheetOperation >  xSheetOp( xCellRange,UNO_QUERY);
	double fResult= xSheetOp->computeFunction(GeneralFunction_AVERAGE);
	printf("Average value of the data table B2:C4: %f", fResult);
// Clear cell contents
	 xSheetOp->clearContents( ANNOTATION | OBJECTS);

(Voir aussi com.sun.star.sheet.XSheetOperation, com.sun.star.sheet.GeneralFunction et com.sun.star.sheet.CellFlags).

Nous pouvons voir sur ces extraits de codes que les appels UNO sont plus simples en C++ qu'en Java. J'ai seulement ajouté beaucoup de commentaires pour expliquer comment les constantes sont gérées. Nous avons beaucoup de chance car on peut distinguer les deux types de constantes que l'on rencontre en programmation C++ UNO :

  • celles avec un nom spécifique : GeneralFunction_AVERAGE au lieu de AVERAGE en Java, (ce problème sur les types énumés a déjà été traité ici)
  • celles qui utilisent le même nom en IDL et en Java mais avec un espace de nommage particulier nécessitant le classique “using namespace” (ce problème sur les constantes est traité ici).

Pour trouver ces informations, il vous faut générer les fichiers hdl et hpp en partant des fichiers IDL et aller lire non pas les fichiers hpp, mais les fichiers hdl. Ce travail est laissé aux débutants, les autres pourront se contenter des fichiers IDL pour en déduire exactement le même type d'information. Regardons les deux extraits IDL correspondants. Pour commencer le fichier CellFlags.idl

//Listing 26 Le fichier CellFags.idl
// IDL
// extracted from CellFlags.idl
constants CellFlags
{
	const long VALUE = 1;
	const long DATETIME = 2;
	const long STRING = 4;
	const long ANNOTATION = 8;
	const long FORMULA = 16;
	const long HARDATTR = 32;
	const long OBJECTS = 128;
	const long EDITATTR = 256;
};

et pour finir le fichier GeneralFunction.idl

//Listing 57 Le fichier GeneralFunction.idl
// IDL
// extracted from GeneralFunction.idl
enum GeneralFunction
{
	NONE,
	AUTO,
	SUM,
	COUNT,
	AVERAGE,
	MAX,
	MIN,
	PRODUCT,
	COUNTNUMS,
	STDEV,
	STDEVP,
	VAR,
	VARP
};

Regardez dans le code C++ quelles sont les conséquences sur les utilisations de ces constantes. Vous pouvez en déduire une règle, n'est-ce-pas ?

Un deuxième exemple : ajouter un nom à une cellule (ou une zone)

Nous donnons en premier le code Java trouvé dans le SDK :

//Listing 28
// Java
// insert a named range 
	com.sun.star.beans.XPropertySet xDocProp = (com.sun.star.beans.XPropertySet)
		UnoRuntime.queryInterface(com.sun.star.beans.XPropertySet.class, xDocument);
	Object aRangesObj = xDocProp.getPropertyValue("NamedRanges");
	com.sun.star.sheet.XNamedRanges xNamedRanges = (com.sun.star.sheet.XNamedRanges) 
			UnoRuntime.queryInterface(com.sun.star.sheet.XNamedRanges.class, aRangesObj);
	com.sun.star.table.CellAddress aRefPos = new com.sun.star.table.CellAddress();
        aRefPos.Sheet = 0; 
	aRefPos.Column = 6; 
	aRefPos.Row = 44; 
	xNamedRanges.addNewByName("ExampleName", "SUM(G43:G44)", aRefPos, 0);
 // use the named range in formulas 
	xSheet.getCellByPosition(6, 44).setFormula("=ExampleName"); 
	xSheet.getCellByPosition(7, 44).setFormula("=ExampleName");

Le même code en C++ :

//Listing 29
// C++
// Ne pas oublier la directive : #include <com/sun/star/beans/XPropertySet.hpp>
// Ne pas oublier d'ajouter "com.sun.star.beans.XPropertySet \" dans le makefile
 
// Ne pas oublier la directive : #include <com/sun/star/sheet/XNamedRanges.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XNamedRanges \" dans le makefile
 
// Ne pas oublier la directive : #include <com/sun/star/table/CellAddress.hpp>
// Ne pas oublier d'ajouter "com.sun.star.table.CellAddress \" dans le makefile
 
// insert a named range 
		// !!! rSheetDoc instead xDocument in our previous code !!!
 	Reference< XPropertySet > xDocProp(xDocument, UNO_QUERY); 
	Any aRangesObj = xDocProp->getPropertyValue(OUString::createFromAscii("NamedRanges"));
	Reference< XNamedRanges > xNamedRanges(aRangesObj,UNO_QUERY);
	CellAddress aRefPos;
	aRefPos.Sheet = 0;
	aRefPos.Column = 6;
	aRefPos.Row = 44;
	xNamedRanges->addNewByName(OUString::createFromAscii("ExampleName"),
			OUString::createFromAscii("SUM(G43:G44)"), aRefPos, 0);
 // use the named range in formulas
		// !!! rSpSheet instead xSheet in our previous code  !!!
	xSheet->getCellByPosition(6, 44)->setFormula(OUString::createFromAscii("=ExampleName"));
	xSheet->getCellByPosition(7, 44)->setFormula(OUString::createFromAscii("=ExampleName"));

On peut s'apercevoir qu'object est traduit par un type any et que vous devez aussi ajouter un “OUString::createFromAscii “ devant chacune des chaînes de caractères. Ce programme permet de nommer une cellule par “ExampleName” et donne une valeur associée avec ce nom : "SUM(G43:G44)". Quand vous utilisez ce nom il est remplacé par sa valeur.

Voir aussi com.sun.star.beans.XPropertySet, com.sun.star.sheet.XNamedRanges et com.sun.star.table.CellAddress.

Le dernier exemple

Voici un autre exemple :

//Listing 30
// Java
// --- Cell range data --- 
com.sun.star.sheet.XCellRangeData xData = (com.sun.star.sheet.XCellRangeData)
 	UnoRuntime.queryInterface(com.sun.star.sheet.XCellRangeData.class, xCellRange); 
Object[][] aValues = { {new Double(1.1), new Integer(10)}, 
			{new Double(2.2), new String("")},
			 {new Double(3.3), new String("Text")} }; 
xData.setDataArray(aValues);

Cet exemple très intérressant prend les valeurs d'un tableau et les met dans une zone de cellules.

Le code :

//Listing 32 Putting Cell Range Values in an Array
//C++
// Don't forget to add : using namespace com::sun::star::sheet;
// Don't forget to add : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
// Don't forget to add "com.sun.star.sheet.XSpreadsheetDocument \" in the makefile
//query for a XSpreadsheetDocument interface
	Reference< XSpreadsheetDocument > rSheetDoc (xcomponent, UNO_QUERY);
 
//use it to get the XSpreadsheets interface
//	Reference< XSpreadsheets > rSheets = rSheetDoc->getSheets();
 
// Don't forget to add : using namespace com::sun::star::frame;
// Don't forget to add : #include <com/sun/star/frame/XModel.hpp>
// Don't forget to add "com.sun.star.frame.XModel \" in the makefile
	Reference< XModel > rSpreadsheetModel (rSheetDoc, UNO_QUERY);
 
// then get the current controller from the model
	Reference< XController > rSpreadsheetController = 
							rSpreadsheetModel->getCurrentController();
 
// Don't forget to add : #include <com/sun/star/sheet/XSpreadsheetView.hpp>
// Don't forget to add "com.sun.star.sheet.XSpreadsheetView \" in the makefile
// get the XSpreadsheetView interface from the controller, we want to call its method
// setActiveSheet
	Reference< XSpreadsheetView > rSpreadsheetView (rSpreadsheetController, UNO_QUERY);
	Reference< XSpreadsheet> rSheet=rSpreadsheetView->getActiveSheet();
 
	Reference< XInterface > rInterface = rSpreadsheetModel->getCurrentSelection();
 
// Don't forget to add : #include <com/sun/star/table/XCellRange.hpp>
// Don't forget to add "com.sun.star.table.XCellRange \" in the makefile
	Reference< XCellRange > rCellRange(rInterface,UNO_QUERY);
 
// Don't forget to add : #include <com/sun/star/sheet/XCellRangeData.hpp>
// Don't forget to add "com.sun.star.sheet.XCellRangeData \" in the makefile
	Reference< XCellRangeData> xData(rCellRange, UNO_QUERY);
 
// Java translation begins here .........
	Sequence< Sequence< Any > > aValues(3); // or aValues(1)(2); ?????
	Sequence< Any > aValues2(2);
	aValues2[0] <<=  (double) 1.1; aValues2[1] <<= (sal_Int32)10;
	aValues[0] = aValues2;
	aValues2[0] <<=  (double)2.2; aValues2[1] <<= OUString::createFromAscii("");
	aValues[1] = aValues2;
	aValues2[0] <<=  (double)3.3; aValues2[1] <<= OUString::createFromAscii("Text");
	aValues[2] = aValues2;
	xData -> setDataArray(aValues);

peut être compilé et fonctionne correctement si l'on a pris soin d'ouvrir un document OOoCalc et de sélectionner une zone de cellules. Voir aussi com.sun.star.sheet.XSpreadsheetDocument, com.sun.star.frame.XModel, com.sun.star.sheet.XSpreadsheetView, com.sun.star.table.XCellRange and com.sun.star.sheet.XCellRangeData.

Un exemple du OooForum: ouvrir un document protégé par mot de passe

Kscape nous a posté : “Il y a un exemple en java pour ouvrir un document protégé par un mot de passe qui affiche une demande de mot de passe [1] mais il n'y a aucun exemple en C++, et je n'arrive pas à obtenir les bons services et me pose des questions sur le chemin à suivre. Y a-t-il une chance que quelqu'un puisse traduire ce snippet ou fournir un exemple C++ complet pour ouvrir un tel document protégé?

Merci d'avance."

Voici tout d'abord le code Java correspondant :

//Listing 33 Java starting Code
// Java
XInteractionHandler xHandler = (XInteractionHandler)UnoRuntime.queryInterface( XInteractionHandler.class, xSMGR.createInstance("com.sun.star.task.InteractionHandler"));
 
PropertyValue[] lArgs    = new PropertyValue[1];
lArgs[0] = new PropertyValue();
lArgs[0].Name  = "InteractionHandler";
lArgs[0].Value = xHandler;
 
xDoc = xDesktop.loadComponentFromURL(sURL, sTarget, nSearchFlags, lArgs);

Et voici dans la foulée le code C++ correspondant :

//Listing 34 The correspnding C++ Code
// C++ 
// Don't forget to add : #include <com/sun/star/task/XInteractionHandler.hpp> 
// Don't forget to add "com.sun.star.task.XInteractionHandler \" in the makefile 
// Don't forget to add : using namespace com::sun::star::task; 
 
	Reference <XInteractionHandler> xHandler = 
		Reference<XInteractionHandler>( rOfficeServiceManager->createInstance( 
			OUString( RTL_CONSTASCII_USTRINGPARAM( 
				"com.sun.star.task.InteractionHandler" ))), UNO_QUERY ); 
	if (xHandler.is()) printf("xHandler OK...\n"); else printf("Error xHandler ... \n"); 
 
	Sequence <PropertyValue > largs(1); 
	largs[0].Name = OUString::createFromAscii("InteractionHandler"); 
	largs[0].Value = makeAny(xHandler); 
 
//get an instance of the OOoDraw document 
	Reference< XComponent > xcomponent = rComponentLoader->loadComponentFromURL( 
		OUString::createFromAscii("private:factory/sdraw"), 
		OUString::createFromAscii("_blank"), 
		0, 
		largs);

Je n'ai pas testé ce code, mais le demandeur en a semblé ravi.

Voir aussi com.sun.star.task.XInteractionHandler.

Intercepter un événement (“Event Listener”)

Voir aussi Creating Listeners and Handlers en OOoBasic.

Premier intercepteur d'événements (Event Listener)

Les intercepteurs d'événements "Event listener" en C++ ne sont pas documentés dans le Developers Guide. Pour trouver un moyen de résoudre ce problème, j'ai commencé par lire du code Java. J'en ai déduit que pour implanter un "event listener" il nous faut construire une classe qui hérite d'une classe connue et l'installer, c'est à dire la déclarer comme écouteur. Mon premier essai a planté complètement OOo (sans message d'excuse !) Pour continuer dans ma quête, j'ai décidé de lire le code source OOo en espérant y trouver un exemple. Avec énormément de chance le deuxième fichier ouvert en contenait un. Il s'agit de  : OOo_1.1.3_src/basic/source/basmgr/basmgr.cxx Pour faire ce travail vous disposez d'un helper pour créer la classe, c'est à dire que votre classe doit hériter de cet helper :

//Listing 35 Premier Event Listener
// C++
// Ne pas oublier la directive #include<com/sun/star/view/XSelectionChangeListener.hpp>
// Ne pas oublier d'ajouter com.sun.star.view.XSelectionChangeListener \ dans le makefile
 
// Ne pas oublier la directive #include <cppuhelper/implbase1.hxx>
 
typedef ::cppu::WeakImplHelper1< ::com::sun::star::view::XSelectionChangeListener > 
                                                              SelectionChangeListenerHelper;
// Voila, c'est ici qu'on hérite :
class SelectionChangeListener : public SelectionChangeListenerHelper
{
public:
	SelectionChangeListener()
	{printf("EventListener installed\n");fflush(stdout);}
 
	~SelectionChangeListener()
	{printf("EventListener released\n");fflush(stdout);}
 
	virtual void SAL_CALL selectionChanged(const com::sun::star::lang::EventObject& aEvent)
	 throw ( RuntimeException)
	{
		printf("Selection changed \n");fflush(stdout);
	}
 
	virtual void SAL_CALL disposing ( const com::sun::star::lang::EventObject& aEventObj )
		throw(::com::sun::star::uno::RuntimeException)
	{ printf("object listened to will be disposed\n"); }
};

(Voir aussi com.sun.star.view.XSelectionChangeListener). La méthode selectionChanged sera ainsi appelée à chaque changement de sélection avec la souris (ou autre) : ici elle affiche seulement un message. Le fflush(stdout) est important si vous voulez voir le printf quand les événements se produisent (merci à Emmanuel GUYpour cela). Pour installer cet "event listener" comme écouteur :

//Listing 36 Installing an Event Listener
// C++
// event listener
// Ne pas oublier la directive #include <com/sun/star/view/XSelectionSupplier.hpp>
// Ne pas oublier d'ajouter com.sun.star.view.XSelectionSupplier \ dans le makefile
 
	Reference< XSelectionSupplier > aSelSupp(rSpreadsheetController,UNO_QUERY);
 
	SelectionChangeListener  *xListener = new SelectionChangeListener();
 
	Reference< XSelectionChangeListener > xSelChListener = 
			static_cast< XSelectionChangeListener* > ( xListener );
 
	aSelSupp->addSelectionChangeListener(xSelChListener);
 
	getchar();
	aSelSupp->removeSelectionChangeListener(xSelChListener);

(Voir aussi com.sun.star.view.XSelectionSupplier). On instancie tout d'abord notre classe avec un "new", mais il nous faut ensuite réaliser un transtypage (un static_cast) avant de l'installer avec la méthode appropriée. Pour nous la méthode est addSelectionchangeListener(). Il est important ensuite de s'arranger pour que le programme ne se termine pas sans retirer l'"event listener". Nous utilisons la fonction C getchar() pour cela (fonction bloquant le programme en fait) mais dans un programme réel il faudra trouver une autre solution (à vous d'être créatifs).

Pour tester ce code il vous faut une interface XSpreadsheetController. Un moyen est d'utiliser l'exemple précédent ici, en retirant la traduction du code Java. Vous lancez ensuite OOocalc en sélectionnant un groupe de cellules. La sélection d'un autre groupe de cellules provoquera le message dans la fenêtre shell. MichaelJ1980 dans oooforum nous indique qu'il lui a fallu écrire

// C++
SelectionChangeListener  *xListener = ::new SelectionChangeListener();

au lieu de

// C++
SelectionChangeListener  *xListener = new SelectionChangeListener();

Voir aussi com.sun.star.view.XSelectionSupplier

A second Event Listener

Emmanuel GUY a posté un autre exemple dans OOoForum : events (XEventListener, XWindowListener, ...) in C++

Graphiques

Embarquer des images (code Java attendant une traduction en C++)

Ajouter des images externes à un document calc est possible et c'est une opération différente de celle de de lier des images. Linking to images requiert à l'utilisateur d'avoir des fichiers images externes qui est toujours au même endroit par rappor au document calc, tandis qu'embarquer une image traite de l'inclusion de l'image même dans le fichier ODS lui-même.

Premièrement, il nous faut une variable xDocModel de type com.sun.star.frame.XModel, et que cette variable soit reliée au document calc. On peut obtenir du document calc la feuille courante (active) en utilisant le code ci-dessous :

XSpreadsheetDocument xDoc = (XSpreadsheetDocument)UnoRuntime.queryInterface(
	XSpreadsheetDocument.class, xDocModel);
XSpreadsheetView xsv = (XSpreadsheetView)UnoRuntime.queryInterface(
	XSpreadsheetView.class, m_xFrame.getController());
XSpreadsheet curSheet = xsv.getActiveSheet();

Voir aussi com.sun.star.sheet.XSpreadsheetDocument, com.sun.star.sheet.XSpreadsheetView, com.sun.star.sheet.XSpreadsheet et com.sun.star.frame.XFrame.

Ensuite, nous devons créer un objet com.sun.star.lang.XMultiServiceFactory pour pouvoir créer un composant dans le fichier actuel. On créera une table a BitmapTable, qui sera destinée à stocker l'image en interne ((source for Writer).

XMultiServiceFactory xmsf = (XMultiServiceFactory)UnoRuntime.queryInterface(
	XMultiServiceFactory.class, xDocModel);
XNameContainer xBitmapContainer = (XNameContainer) UnoRuntime.queryInterface(
	XNameContainer.class, xmsf.createInstance("com.sun.star.drawing.BitmapTable"));

Voir aussi com.sun.star.lang.XMultiServiceFactory, com.sun.star.container.XNameContainer et com.sun.star.drawing.BitmapTable.

Le fichier lui-même est ajouter au conteneur comme un lien, semblable aux URLs en ligne. Ainsi un chemin vers une image dans un répertoire home Linux pourrait être file:///home/username/image.png. On ajoute ce lien au conteneur, et utilisons la classe AnyConverter pour obtenir l'URL du contenaur lui-même, appelée internalURL. Cet internalURL sera utilisée comme un nouveau lien vers la nouvelle image (maintenant interne).

Documentation linux.png
String sPath = "file:///home/wojciech/Desktop/img.png"; 
xBitmapContainer.insertByName("someID", sPath);
String internalURL = AnyConverter.toString(xBitmapContainer.getByName("someID"));


L'image elle-même est stockée comme un objet com.sun.star.drawing.XShape, qui est créé ci-dessous.

Object imgTemp = xmsf.createInstance("com.sun.star.drawing.GraphicObjectShape");
XShape xImage = (XShape)UnoRuntime.queryInterface(XShape.class, imgTemp);

Voir aussi com.sun.star.drawing.GraphicObjectShape et com.sun.star.drawing.XShape.

On positionne maintenant la propriété de la forme actuelle (qui est l'image) (voir l'interface com.sun.star.beans.XPropertySet):

XPropertySet xpi = ( XPropertySet )UnoRuntime.queryInterface(XPropertySet.class, xImage );
xpi.setPropertyValue("GraphicURL", internalURL);
Size imgSize = new Size(2500, 5000);
xImage.setSize(imgSize);

Et finalement nous obtenons les interfaces pour dessiner directement dans le document calc lui-même, qui nous permettent le dessin. La dernière ligne de code retire simplement l'image du conteneur temporaire. Voir aussi l'interface com.sun.star.drawing.XDrawPageSupplier.

XDrawPageSupplier oDPS = (XDrawPageSupplier) UnoRuntime.queryInterface(
	XDrawPageSupplier.class, curSheet);
XDrawPage xDrawPage = oDPS.getDrawPage();  
xDrawPage.add(xImage);
xBitmapContainer.removeByName("someID");

Retour à la page d'accueil

Page d'accueil du développement C++ à l'aide du SDK

Voir aussi

Personal tools