Difference between revisions of "FR/Documentation/OpenOffice Calc"
SergeMoutou (talk | contribs) |
SergeMoutou (talk | contribs) |
||
Line 618: | Line 618: | ||
</source> | </source> | ||
Ce code affiche “Hello !!!” dans le haut à gauche de la zone de cellules sélectionnée. | Ce code affiche “Hello !!!” dans le haut à gauche de la zone de cellules sélectionnée. | ||
+ | |||
+ | Voir aussi <idl>com.sun.star.table.XCellRange</idl>. | ||
==Montrer une zone de cellules comme “sélectionnée”== | ==Montrer une zone de cellules comme “sélectionnée”== |
Revision as of 19:06, 11 July 2008
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 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 code dans les prochaines parties.
Si vous connaissez seulement l'index de la feuille, vous pourrez la récupérer en utilisant un moyen un peu plus compliqué :
//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 XIndexAccess. Cela signifie comme d'habitude ajouter deux lignes dans le code et une dans le makefile.
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 :
//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 :
//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 :
//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 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
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 (XTextCursor interface). 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 CellContentType.idl :
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 XCalculateTable :calculate() et calculateAll() Vous pouvez obtenir cette interface depuis un document XSreadsheet.
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);
Annotations des cellules
L'exemple suivant va insérer une annotation et la rendra visible de manière permanente.
//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”.
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 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 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 XCellRangeAdressable. 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”.
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.
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.
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"); }
};
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);
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
- Classeurs
- Spreadsheet Documents in Developer's Guide
- C++ and UNO tutorial
- Writing a Program to Control OpenOffice.org, by Franco Pingiori — Part 1 and Part 2, Linux Journal
- OOCalc with COM (en français)