Difference between revisions of "FR/Documentation/OpenOffice Calc"

From Apache OpenOffice Wiki
Jump to: navigation, search
m (Zone de cellules)
m (Rechercher l'adresse d'une zone de cellules)
Line 590: Line 590:
 
}; }; }; };
 
}; }; }; };
 
</source>
 
</source>
(voir aussi <idl>com.sun.star.table.CellRangeAddress</idl>) et une interface XCellRangeAdressable. En partant d'une zone de cellules, nous ajoutons :
+
(voir aussi <idl>com.sun.star.table.CellRangeAddress</idl>) et une interface <idl>com.sun.star.sheet.XCellAddressable</idl>. En partant d'une zone de cellules, nous ajoutons :
 
<source lang="cpp">
 
<source lang="cpp">
 
//Listing 23  
 
//Listing 23  

Revision as of 16:43, 2 March 2009

Pour éviter de chercher dans le code précédent ou l'on va inserer le nouveau listing, nous redonnons le code (juste le main() sans les directives d'inclusiones et autres) :

//Listing 1
// C++ 
int main( ) {
//retrieve an instance of the remote service manager
    Reference< XMultiServiceFactory > rOfficeServiceManager;
    rOfficeServiceManager = ooConnect();
    if( rOfficeServiceManager.is() ){
        printf( "Connected sucessfully to the office\n" );
    }
 
//get the desktop service using createInstance returns an XInterface type
    Reference< XInterface  > Desktop = rOfficeServiceManager->createInstance(
    OUString::createFromAscii( "com.sun.star.frame.Desktop" ));
 
//query for the 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 >());
// ajouter du code ici
    return 0;
}

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 interressante 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.

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 condidère la numération des feuilles à partir de 0 et donc le numéro un 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 XModel, et demander ensuite avec getCurrentSelection l'interface XInterface pour obtenir enfin l'interface XCellRange.

//Listing 26 Cell Range under Focus
// 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 voulez aller encore plus loin, le guide du développeur est un bon début. Le seul problème est que les exemples sont en majorité écrits en langage Java. Vous devez alors apprendre comment le traduire en C++. A première vue vous pourrez trouver cette traduction assez compliquée mais je l'ai expérimenté en tant que 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);

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);

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. Avec de la chance on peut distinguer deux types de constantes :

  • celles avec un nom spécifique : GeneralFunction_AVERAGE au lieu de AVERAGE en Java,
  • 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”.

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

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.

//Listing 31
// C++ à tester et corriger
// Ne pas oublier la directive : #include <com/sun/star/sheet/XCellRangeData.hpp>
// Ne pas oublier d'ajouter "com.sun.star.sheet.XCellRangeData \" in the makefile
 
// query the XCellRangeData Interface
// rCellRange with previous example, but xCellRange here with Developpers Guide convantion
	Reference< XCellRangeData> xData(xCellRange, UNO_QUERY); 
 
	Any aValues[3][2] = { {new Double(1.1), new Integer(10)}, 
				{new Double(2.2), new String("")},
			 	{new Double(3.3), new String("Text")} }; 
	xData -> setDataArray(aValues);

Le code :

//Listing 32
// C++
Reference< XCellRangeData> xData(rCellRange, UNO_QUERY);
	Sequence< Sequence< Any> > aValues; // or aValues(1)(2); ?????
	aValues[0][0] <<=  1.1; aValues[0][1] <<= OUString::createFromAscii("Text");
	xData -> setDataArray(aValues);

peut être compilé mais ne fonctionne pas. Voir aussi com.sun.star.sheet.XCellRangeData.

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++

Retour à la page d'accueil

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

Voir aussi

Personal tools