Difference between revisions of "Extensions development vfp"

From Apache OpenOffice Wiki
Jump to: navigation, search
(How to drive openOffice from within Visual Foxpro)
Line 1: Line 1:
 +
[[User:FOXIL|FOXIL]]
 
10:02, 30 November 2007 (CET)
 
10:02, 30 November 2007 (CET)
 
==Présentation générale==
 
==Présentation générale==
  
'''Visual Foxpro''' est une base de donnée de Microsoft. En plus de cette fonction, c'est aussi un bon langage de programmtion. On peut travailler soit en procédural soit en orienté objet (et on peut mixer les deux).
+
'''Visual Foxpro''' est une base de donnée de Microsoft. En plus de cette fonction, c'est aussi un bon langage de programmation. On peut travailler soit en procédural soit en orienté objet (et on peut mixer les deux).
  
 
Une des forces de VFP (outre la puissance de sa base) est son intégration dans le Microsoft Office. On peut se servir de Word et d'Excel pour créer des états  complexes ou plus jolis (agréables à lire) que le simple gestionnaire d'état. Mais cela devient de plus en plus compliqué et ... on peut faire la même chose avec Open Office 2.3 ....
 
Une des forces de VFP (outre la puissance de sa base) est son intégration dans le Microsoft Office. On peut se servir de Word et d'Excel pour créer des états  complexes ou plus jolis (agréables à lire) que le simple gestionnaire d'état. Mais cela devient de plus en plus compliqué et ... on peut faire la même chose avec Open Office 2.3 ....
Line 8: Line 9:
 
Le premier listing ci-dessous contient des classes qui vont faciliter l'interface entre VFP et 00. On démarre avec la classe VFP_OO qui contient les propriétés et méthodes de base : ouverture d'un document, enregistrement, impression, etc ... Cette classe est sous-classée en  
 
Le premier listing ci-dessous contient des classes qui vont faciliter l'interface entre VFP et 00. On démarre avec la classe VFP_OO qui contient les propriétés et méthodes de base : ouverture d'un document, enregistrement, impression, etc ... Cette classe est sous-classée en  
  
<nowiki> - vfp_oo_writer : qui contient des propriétés et des méthodes propre à Writer : insertion de texte, gestion des polices, des paragraphes ...
+
<nowiki>   - vfp_oo_writer : qui contient des propriétés et des méthodes propre à Writer : insertion de texte, gestion des polices, des paragraphes ...</nowiki>
</nowiki>
+
  
<nowiki> - vfp_oo_calc  : qui contient des propriétés et des méthodes propre à Calc : création de feuille, sélection de cellule, ....
+
<nowiki>   - vfp_oo_calc  : qui contient des propriétés et des méthodes propre à Calc : création de feuille, sélection de cellule, ....</nowiki>
</nowiki>
+
  
 
Quelques petites classes utilitaires sont aussi présentes comme oo_police pour la gestion des polices de caractère et oo_paragraphe pour la gestion des marges.
 
Quelques petites classes utilitaires sont aussi présentes comme oo_police pour la gestion des polices de caractère et oo_paragraphe pour la gestion des marges.
Line 22: Line 21:
 
Je voudrais détailler un point technique : si on a une propriété 'toto', la méthode 'toto_assign' de la même classe sera AUTOMATIQUEMENT lancée chaque fois que l'on tentera de modifier la valeur de toto (inversement on a une méthode toto_access qui est lancée chaque fois que l'on tente de lire la propriété). Cette façon de faire est utilisée pour simplifier les modifications simples d'une seul paramètres. Par exemple on pourra écrire :
 
Je voudrais détailler un point technique : si on a une propriété 'toto', la méthode 'toto_assign' de la même classe sera AUTOMATIQUEMENT lancée chaque fois que l'on tentera de modifier la valeur de toto (inversement on a une méthode toto_access qui est lancée chaque fois que l'on tente de lire la propriété). Cette façon de faire est utilisée pour simplifier les modifications simples d'une seul paramètres. Par exemple on pourra écrire :
  
<nowiki>  oo.paragraphe.marge_gauche = 1000
+
<nowiki>  oo.paragraphe.marge_gauche = 1000</nowiki>
</nowiki>
+
  
<nowiki>  oo.paragraphe.marge_droite = 2000
+
<nowiki>  oo.paragraphe.marge_droite = 2000</nowiki>
</nowiki>
+
  
<nowiki>  oo.paragraphe.retrait_ligne1 = 1000
+
<nowiki>  oo.paragraphe.retrait_ligne1 = 1000</nowiki>
</nowiki>
+
  
<nowiki>  oo.paragraphe.faire()
+
<nowiki>  oo.paragraphe.faire()</nowiki>
</nowiki>mais si on a que la marge gauche à modifier, on n'écrira qu'une seule ligne :
+
  
<nowiki>  oo.paragraphe.a_marge_gauche = 1500
+
mais si on a que la marge gauche à modifier, on n'écrira qu'une seule ligne :
</nowiki>
+
 
 +
<nowiki>  oo.paragraphe.a_marge_gauche = 1500</nowiki>
  
 
et la méthode _assign correspondante mettra à jour la propriété marge_gauche et lancera la méthode faire.
 
et la méthode _assign correspondante mettra à jour la propriété marge_gauche et lancera la méthode faire.
Line 136: Line 132:
 
  *    1408 .date_dans_cellule
 
  *    1408 .date_dans_cellule
 
  *    1442 .lire_une_cellule
 
  *    1442 .lire_une_cellule
===défibition des constantes===
+
===définition des constantes===
 
  *OO_automation/sdk/docs/common/ref/com/sun/star/text/ControlCharacter.html
 
  *OO_automation/sdk/docs/common/ref/com/sun/star/text/ControlCharacter.html
 
  #DEFINE PARAGRAPH_BREAK  0 && nouveau paragraphe
 
  #DEFINE PARAGRAPH_BREAK  0 && nouveau paragraphe
Line 144: Line 140:
 
  #DEFINE HARD_SPACE        4 && espace insécable
 
  #DEFINE HARD_SPACE        4 && espace insécable
 
  #DEFINE APPEND_PARAGRAPH  5 && ajoute un nouveau paragraphe
 
  #DEFINE APPEND_PARAGRAPH  5 && ajoute un nouveau paragraphe
 
+
 
  #DEFINE COLOR_WHITE        16777215
 
  #DEFINE COLOR_WHITE        16777215
 
  #DEFINE COLOR_BLACK              0
 
  #DEFINE COLOR_BLACK              0
 
+
 
  * OO_automation/sdk/idl/com/sun/star/awt/FontWeight.idl  : graisse des caractères
 
  * OO_automation/sdk/idl/com/sun/star/awt/FontWeight.idl  : graisse des caractères
 
  #DEFINE GRAISSE_DONTKNOW    0.000000    && graisse par défaut
 
  #DEFINE GRAISSE_DONTKNOW    0.000000    && graisse par défaut
Line 159: Line 155:
 
  #DEFINE GRAISSE_ULTRABOLD 175.000000    && très gras  
 
  #DEFINE GRAISSE_ULTRABOLD 175.000000    && très gras  
 
  #DEFINE GRAISSE_BLACK    200.000000    && ultra gras
 
  #DEFINE GRAISSE_BLACK    200.000000    && ultra gras
 
+
 
  * OO_automation/sdk/idl/com/sun/star/awt/FontUnderline.idl  : soulignement
 
  * OO_automation/sdk/idl/com/sun/star/awt/FontUnderline.idl  : soulignement
 
  #DEFINE SOULIGN_NONE            0 && pas de soulignement
 
  #DEFINE SOULIGN_NONE            0 && pas de soulignement
Line 180: Line 176:
 
  #DEFINE SOULIGN_BOLDDASHDOTDOT 17 && tiret point point en gras
 
  #DEFINE SOULIGN_BOLDDASHDOTDOT 17 && tiret point point en gras
 
  #DEFINE SOULIGN_BOLDWAVE      18 && vague grasse
 
  #DEFINE SOULIGN_BOLDWAVE      18 && vague grasse
 
+
 
  * OO_automation/sdk/idl/com/sun/star/awt/FontWidth.idl
 
  * OO_automation/sdk/idl/com/sun/star/awt/FontWidth.idl
 
  #DEFINE LARGEUR_DONTKNOW        0.000000  && largeur inconnue (par défaut ?)
 
  #DEFINE LARGEUR_DONTKNOW        0.000000  && largeur inconnue (par défaut ?)
Line 202: Line 198:
 
  #DEFINE ITALIC_INVERSE          5 && italique inverse (penchée à gauche si la police
 
  #DEFINE ITALIC_INVERSE          5 && italique inverse (penchée à gauche si la police
 
                                   && l'accepte (non utilisé ici
 
                                   && l'accepte (non utilisé ici
 
+
 
  * OO_automation/sdk/idl/com/sun/star/style/ParagraphAdjust.idl
 
  * OO_automation/sdk/idl/com/sun/star/style/ParagraphAdjust.idl
 
  #DEFINE ALIGNEMENT_GAUCHE        0  && paragraphe cadré à gauche
 
  #DEFINE ALIGNEMENT_GAUCHE        0  && paragraphe cadré à gauche
Line 254: Line 250:
 
      
 
      
 
   * il n'y a pas de méthode DESTROY dans cette classe
 
   * il n'y a pas de méthode DESTROY dans cette classe
 
+
 
 
   PROCEDURE init && jme 26/11/2007
 
   PROCEDURE init && jme 26/11/2007
 
     LPARAMETERS pocurseur
 
     LPARAMETERS pocurseur
 
     This.curseur_ecriture = m.pocurseur
 
     This.curseur_ecriture = m.pocurseur
 
   ENDPROC
 
   ENDPROC
 
+
 
 
   PROCEDURE faire( )
 
   PROCEDURE faire( )
 
     * This.curseur_ecriture : curseur d'écriture sur lequel on doit paramétrer
 
     * This.curseur_ecriture : curseur d'écriture sur lequel on doit paramétrer
Line 292: Line 288:
 
     ENDIF && ISNULL(This.curseur_ecriture)
 
     ENDIF && ISNULL(This.curseur_ecriture)
 
   ENDPROC && faire
 
   ENDPROC && faire
 
+
 
 
   HIDDEN PROCEDURE a_nom_assign
 
   HIDDEN PROCEDURE a_nom_assign
 
     * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
 
     * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
Line 306: Line 302:
 
     ENDIF
 
     ENDIF
 
   ENDPROC && procedure a_nom_assign
 
   ENDPROC && procedure a_nom_assign
 
+
 
 
   HIDDEN PROCEDURE a_taille_assign
 
   HIDDEN PROCEDURE a_taille_assign
 
     * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
 
     * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
Line 317: Line 313:
 
     ENDIF
 
     ENDIF
 
   ENDPROC && procedure a_taille_assign
 
   ENDPROC && procedure a_taille_assign
 
+
 
 
   HIDDEN PROCEDURE a_gras_assign
 
   HIDDEN PROCEDURE a_gras_assign
 
     * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
 
     * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
Line 331: Line 327:
 
     ENDIF
 
     ENDIF
 
   ENDPROC && procedure a_gras_assign
 
   ENDPROC && procedure a_gras_assign
 
+
 
 
   HIDDEN PROCEDURE a_italique_assign
 
   HIDDEN PROCEDURE a_italique_assign
 
     * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
 
     * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
Line 342: Line 338:
 
     ENDIF
 
     ENDIF
 
   ENDPROC && procedure a_italique_assign
 
   ENDPROC && procedure a_italique_assign
 
+
 
 
   HIDDEN PROCEDURE a_souligne_assign
 
   HIDDEN PROCEDURE a_souligne_assign
 
     * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
 
     * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
Line 363: Line 359:
 
   * paramètres d'un paragraphe. Toutes les valeurs sont en 1/100mm
 
   * paramètres d'un paragraphe. Toutes les valeurs sont en 1/100mm
 
   * (centième de millimètre)
 
   * (centième de millimètre)
 
+
 
 
   marge_gauche = 0  && 1000 = 1cm
 
   marge_gauche = 0  && 1000 = 1cm
 
   retrait_ligne1 = 0
 
   retrait_ligne1 = 0
Line 377: Line 373:
 
    
 
    
 
   * il n'y a pas de méthode DESTROY dans cette classe
 
   * il n'y a pas de méthode DESTROY dans cette classe
 +
 
   PROCEDURE init
 
   PROCEDURE init
 
     LPARAMETERS pocurseur
 
     LPARAMETERS pocurseur
 
     This.curseur_ecriture = m.pocurseur
 
     This.curseur_ecriture = m.pocurseur
 
   ENDPROC
 
   ENDPROC
 
+
 
 
   PROCEDURE alignement( pcalign AS String)
 
   PROCEDURE alignement( pcalign AS String)
    * NOTE test : cette méthode a le même nom qu'une des propriétés !
 
 
     IF "CENTR" $ UPPER(m.pcalign)
 
     IF "CENTR" $ UPPER(m.pcalign)
 
       This.gdcj = ALIGNEMENT_CENTRE
 
       This.gdcj = ALIGNEMENT_CENTRE
Line 452: Line 448:
 
     ENDIF
 
     ENDIF
 
   ENDPROC && procedure a_marge_gauche_assign
 
   ENDPROC && procedure a_marge_gauche_assign
 
+
 
 
   HIDDEN PROCEDURE a_marge_droite_assign
 
   HIDDEN PROCEDURE a_marge_droite_assign
 
     * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
 
     * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
Line 463: Line 459:
 
     ENDIF
 
     ENDIF
 
   ENDPROC && procedure a_marge_droite_assign
 
   ENDPROC && procedure a_marge_droite_assign
 
+
 
 
   HIDDEN PROCEDURE a_retrait_ligne1_assign
 
   HIDDEN PROCEDURE a_retrait_ligne1_assign
 
     * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
 
     * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
Line 476: Line 472:
 
    
 
    
 
ENDDEFINE && oo_paragraphe
 
ENDDEFINE && oo_paragraphe
 +
 
===classe parametres_imprimante===
 
===classe parametres_imprimante===
 
'''DEFINE CLASS parametres_imprimante''' AS Custom
 
'''DEFINE CLASS parametres_imprimante''' AS Custom
Line 486: Line 483:
 
ENDDEFINE && parametres_imprimante AS Custom
 
ENDDEFINE && parametres_imprimante AS Custom
  
 +
===classe parametres_page===
 
'''DEFINE CLASS parametres_page''' AS Custom
 
'''DEFINE CLASS parametres_page''' AS Custom
 
   * définition des paramètres de la page
 
   * définition des paramètres de la page
Line 499: Line 497:
 
   sf = NULL            && pointeur sur la famille de styles
 
   sf = NULL            && pointeur sur la famille de styles
 
   standard = NULL      && pointeur sur le style standard
 
   standard = NULL      && pointeur sur le style standard
 
+
 
 
   PROCEDURE init
 
   PROCEDURE init
 
     LPARAMETERS pocurseur
 
     LPARAMETERS pocurseur
Line 505: Line 503:
 
     This.faire()
 
     This.faire()
 
   ENDPROC
 
   ENDPROC
 
+
 
 
   PROCEDURE faire( )
 
   PROCEDURE faire( )
 
     * This.page : objet que l'on doit paramétrer
 
     * This.page : objet que l'on doit paramétrer
Line 548: Line 546:
 
    
 
    
 
ENDDEFINE && parametres_page AS Custom
 
ENDDEFINE && parametres_page AS Custom
 +
 
===classe parametres_impression===
 
===classe parametres_impression===
 
'''DEFINE CLASS parametres_impression''' AS custom
 
'''DEFINE CLASS parametres_impression''' AS custom
Line 633: Line 632:
 
     ENDIF && This.erreur = 1
 
     ENDIF && This.erreur = 1
 
   ENDPROC && init
 
   ENDPROC && init
 
+
 
 
   PROTECTED PROCEDURE destroy
 
   PROTECTED PROCEDURE destroy
 
     * une méthode PROTECTED est accessible par toutes les méthodes de la classe où
 
     * une méthode PROTECTED est accessible par toutes les méthodes de la classe où
Line 648: Line 647:
 
     This.gestionnaire_de_services = NULL
 
     This.gestionnaire_de_services = NULL
 
   ENDPROC
 
   ENDPROC
 
+
 
 
   PROCEDURE nouveau_document( pctypdoc AS String)
 
   PROCEDURE nouveau_document( pctypdoc AS String)
 
     * on crée un nouveau document dont le type est contenu dans pctypdoc
 
     * on crée un nouveau document dont le type est contenu dans pctypdoc
Line 682: Line 681:
 
     ENDIF && This.erreur =2
 
     ENDIF && This.erreur =2
 
   ENDPROC
 
   ENDPROC
 
+
 
 
   PROCEDURE ouvrir_document( pcfichier AS String)
 
   PROCEDURE ouvrir_document( pcfichier AS String)
 
     * pcfichier est un nom de fichier 00 au format Windows ("c:\toto\tata\tutu.odt")
 
     * pcfichier est un nom de fichier 00 au format Windows ("c:\toto\tata\tutu.odt")
Line 748: Line 747:
 
     This.doc.storeAsURL( m.lcurl, @ lcparam)
 
     This.doc.storeAsURL( m.lcurl, @ lcparam)
 
   ENDPROC && enregistrer_document
 
   ENDPROC && enregistrer_document
 
+
 
 
   PROCEDURE enregistrer_copie_document( pcnomfichier AS String)
 
   PROCEDURE enregistrer_copie_document( pcnomfichier AS String)
 
     * on veut créer une copie du document courant (on crée un fichier
 
     * on veut créer une copie du document courant (on crée un fichier
Line 773: Line 772:
 
     ENDIF && PCOUNT() = 1 AND ! EMPTY(m.pcnomfichier)
 
     ENDIF && PCOUNT() = 1 AND ! EMPTY(m.pcnomfichier)
 
   ENDPROC && enregistrer_document
 
   ENDPROC && enregistrer_document
 
+
 
 
   PROCEDURE fermer_document
 
   PROCEDURE fermer_document
 
     LOCAL llok
 
     LOCAL llok
Line 797: Line 796:
 
     ENDIF && m.llok = .T.
 
     ENDIF && m.llok = .T.
 
   ENDPROC && fermer_document()
 
   ENDPROC && fermer_document()
 
+
 
 
   PROCEDURE imprimer_document
 
   PROCEDURE imprimer_document
 
     * ATTENTION : il faut normalement 5 paramètres pour piloter l'impression. Ces
 
     * ATTENTION : il faut normalement 5 paramètres pour piloter l'impression. Ces
Line 852: Line 851:
 
     This.doc.Print( @loparam)
 
     This.doc.Print( @loparam)
 
   ENDPROC && imprimer_document
 
   ENDPROC && imprimer_document
 
+
 
 
   PROCEDURE informations_document
 
   PROCEDURE informations_document
 
     LOCAL lcfichier, loinfos, lodate
 
     LOCAL lcfichier, loinfos, lodate
Line 880: Line 879:
 
     *  private:factory/scalc  pour un nouveau classeur de feuilles de calcul
 
     *  private:factory/scalc  pour un nouveau classeur de feuilles de calcul
 
     *  private:factory/simpress && pour un nouveau document de présentation
 
     *  private:factory/simpress && pour un nouveau document de présentation
 
+
   
 
  *!*        *  LOCAL oPropertyValue
 
  *!*        *  LOCAL oPropertyValue
 
  *!*        *  oPropertyValue = OOoCreateStruct( "com.sun.star.beans.PropertyValue" )
 
  *!*        *  oPropertyValue = OOoCreateStruct( "com.sun.star.beans.PropertyValue" )
Line 902: Line 901:
 
     COMARRAY( This.doc, 10 )
 
     COMARRAY( This.doc, 10 )
 
   ENDPROC
 
   ENDPROC
 
+
 
 
   FUNCTION OOoPropertyValue( cName, uValue, nHandle, nState )
 
   FUNCTION OOoPropertyValue( cName, uValue, nHandle, nState )
 
     * Create a com.sun.star.beans.PropertyValue struct and return it.
 
     * Create a com.sun.star.beans.PropertyValue struct and return it.
Line 979: Line 978:
 
     ENDIF && This.erreur = 2
 
     ENDIF && This.erreur = 2
 
   ENDPROC && init
 
   ENDPROC && init
 
+
 
 
   PROTECTED PROCEDURE destroy
 
   PROTECTED PROCEDURE destroy
 
     IF !ISNULL(This.doc) AND This.abandon_document=.F. AND This.doc.isModified
 
     IF !ISNULL(This.doc) AND This.abandon_document=.F. AND This.doc.isModified
Line 991: Line 990:
 
     DODEFAULT()
 
     DODEFAULT()
 
   ENDPROC
 
   ENDPROC
 
+
 
 
   PROCEDURE nouveau_document_texte
 
   PROCEDURE nouveau_document_texte
 
     * on crée un nouveau document texte
 
     * on crée un nouveau document texte
Line 1,030: Line 1,029:
 
     ENDIF && This.erreur =2
 
     ENDIF && This.erreur =2
 
   ENDPROC
 
   ENDPROC
 
+
 
 
   PROCEDURE ouvrir_document_texte( pcfichier AS String)
 
   PROCEDURE ouvrir_document_texte( pcfichier AS String)
 
     * pcfichier est un nom de fichier document text au format Windows
 
     * pcfichier est un nom de fichier document text au format Windows
Line 1,082: Line 1,081:
 
     ENDIF && EMPTY(pcfichier)
 
     ENDIF && EMPTY(pcfichier)
 
   ENDPROC && ouvrir_texte
 
   ENDPROC && ouvrir_texte
 
+
 
 
   PROTECTED PROCEDURE objets_doc
 
   PROTECTED PROCEDURE objets_doc
 
     * met à jour les pointeurs et les paramètres utilisés pour manipuler le texte
 
     * met à jour les pointeurs et les paramètres utilisés pour manipuler le texte
Line 1,093: Line 1,092:
 
     This.page = NEWOBJECT("parametres_page", "", "", This.doc)
 
     This.page = NEWOBJECT("parametres_page", "", "", This.doc)
 
     * This.page sert à gérer les valeurs de marge haute, marge basse, gauche et
 
     * This.page sert à gérer les valeurs de marge haute, marge basse, gauche et
     * droite de la page.
+
     * droite de la page.
   
+
 
   ENDPROC && objets_doc
 
   ENDPROC && objets_doc
  
Line 1,121: Line 1,119:
 
     ENDIF && PCOUNT() = 1 AND ! EMPTY(m.pcnomfichier)
 
     ENDIF && PCOUNT() = 1 AND ! EMPTY(m.pcnomfichier)
 
   ENDPROC && enregistrer_document
 
   ENDPROC && enregistrer_document
 
+
 
 
   PROCEDURE informations_document
 
   PROCEDURE informations_document
 
     LOCAL lcfichier, loinfos, lodate
 
     LOCAL lcfichier, loinfos, lodate
Line 1,135: Line 1,133:
 
     ENDIF && !ISNULL(This.doc)
 
     ENDIF && !ISNULL(This.doc)
 
   ENDPROC && informations_document
 
   ENDPROC && informations_document
 
+
 
 
   PROCEDURE debut_texte
 
   PROCEDURE debut_texte
 
     This.cuecr.gotoStart(.F.)
 
     This.cuecr.gotoStart(.F.)
 
   ENDPROC
 
   ENDPROC
 
+
 
 
   PROCEDURE ajouter_texte( pctexte AS String)
 
   PROCEDURE ajouter_texte( pctexte AS String)
 
     This.texte.insertString( This.cuecr, m.pctexte, .F.)
 
     This.texte.insertString( This.cuecr, m.pctexte, .F.)
 
   ENDPROC && ajouter_texte
 
   ENDPROC && ajouter_texte
 
+
 
 
   PROCEDURE nouveau_paragraphe && insertion d'un nouveau paragraphe
 
   PROCEDURE nouveau_paragraphe && insertion d'un nouveau paragraphe
 
     * à l'endroit du curseur d'écriture
 
     * à l'endroit du curseur d'écriture
Line 1,149: Line 1,147:
 
     This.texte.insertControlCharacter(This.cuecr, PARAGRAPH_BREAK, .F.)
 
     This.texte.insertControlCharacter(This.cuecr, PARAGRAPH_BREAK, .F.)
 
   ENDPROC && nouveau_paragraphe
 
   ENDPROC && nouveau_paragraphe
 
+
 
 
   PROCEDURE appliquer_police && applique la police définie dans la
 
   PROCEDURE appliquer_police && applique la police définie dans la
 
     * classe police
 
     * classe police
Line 1,155: Line 1,153:
 
     This.font.faire()
 
     This.font.faire()
 
   ENDPROC && appliquer_police
 
   ENDPROC && appliquer_police
 
+
 
 
   PROCEDURE police( pcnompolice AS String, ;
 
   PROCEDURE police( pcnompolice AS String, ;
 
   pntaille AS Number, plgras AS Logical, plsouligne AS Logical)
 
   pntaille AS Number, plgras AS Logical, plsouligne AS Logical)
Line 1,207: Line 1,205:
 
     ENDIF && This.erreur = 2
 
     ENDIF && This.erreur = 2
 
   ENDPROC && init
 
   ENDPROC && init
 
+
 
 
   PROTECTED PROCEDURE destroy
 
   PROTECTED PROCEDURE destroy
 
     IF !ISNULL(This.doc) AND This.doc.isModified AND This.abandon_document=.F.
 
     IF !ISNULL(This.doc) AND This.doc.isModified AND This.abandon_document=.F.
Line 1,219: Line 1,217:
 
     DODEFAULT()
 
     DODEFAULT()
 
   ENDPROC
 
   ENDPROC
 
+
 
 
   PROCEDURE nouveau_tableur
 
   PROCEDURE nouveau_tableur
 
     * on crée un nouveau document de calcul
 
     * on crée un nouveau document de calcul
Line 1,240: Line 1,238:
 
     ENDIF && This.erreur =2
 
     ENDIF && This.erreur =2
 
   ENDPROC
 
   ENDPROC
 
+
 
 
   PROCEDURE ouvrir_tableur( pcfichier AS String)
 
   PROCEDURE ouvrir_tableur( pcfichier AS String)
 
     * pcfichier est un nom de fichier document Calc (au format Windows)
 
     * pcfichier est un nom de fichier document Calc (au format Windows)
Line 1,277: Line 1,275:
 
     ENDIF && EMPTY(pcfichier)
 
     ENDIF && EMPTY(pcfichier)
 
   ENDPROC && ouvrir_texte
 
   ENDPROC && ouvrir_texte
 
+
 
 
   PROTECTED PROCEDURE maj_infos_tableur
 
   PROTECTED PROCEDURE maj_infos_tableur
 
     * met à jour les propriétés nombre_feuilles, et feuilles avec
 
     * met à jour les propriétés nombre_feuilles, et feuilles avec
 
     * le nombre de feuilles leurs nom, position et ordre
 
     * le nombre de feuilles leurs nom, position et ordre
 
     LOCAL lnaccu, lni, lnmax, lo1feuille
 
     LOCAL lnaccu, lni, lnmax, lo1feuille
 
+
   
 
     STORE This.doc.Sheets.Count TO This.nombre_feuilles, lnaccu
 
     STORE This.doc.Sheets.Count TO This.nombre_feuilles, lnaccu
 
     DIMENSION This.feuilles(m.lnaccu,3)
 
     DIMENSION This.feuilles(m.lnaccu,3)
Line 1,324: Line 1,322:
 
     ENDIF && PCOUNT() = 1 AND ! EMPTY(m.pcnomfichier)
 
     ENDIF && PCOUNT() = 1 AND ! EMPTY(m.pcnomfichier)
 
   ENDPROC && enregistrer_document
 
   ENDPROC && enregistrer_document
 
+
 
 
   PROCEDURE informations_document
 
   PROCEDURE informations_document
 
     LOCAL lcfichier, loinfos, lodate
 
     LOCAL lcfichier, loinfos, lodate
Line 1,345: Line 1,343:
 
     *  oSheet = oDoc.getSheets().getByIndex( 0 ) ' get the zero'th sheet
 
     *  oSheet = oDoc.getSheets().getByIndex( 0 ) ' get the zero'th sheet
 
     *  oSheet = oDoc.getSheets().getByName( "Sheet3" ) ' get by name
 
     *  oSheet = oDoc.getSheets().getByName( "Sheet3" ) ' get by name
 
+
   
 
     IF PCOUNT() > 0
 
     IF PCOUNT() > 0
 
       IF VARTYPE(m.luparametre)=="C" AND !EMPTY(m.luparametre)
 
       IF VARTYPE(m.luparametre)=="C" AND !EMPTY(m.luparametre)
Line 1,397: Line 1,395:
 
     ENDIF && PCOUNT() > 0
 
     ENDIF && PCOUNT() > 0
 
   ENDPROC && selection_feuille
 
   ENDPROC && selection_feuille
 
+
 
 
   PROCEDURE ajouter_feuille( lnposition AS Number, lcnom AS String)
 
   PROCEDURE ajouter_feuille( lnposition AS Number, lcnom AS String)
 
     * On ajoute la feuille de nom lcnom à la position lnposition.
 
     * On ajoute la feuille de nom lcnom à la position lnposition.
Line 1,430: Line 1,428:
 
     ENDIF && PCOUNT()=2 AND BETWEEN(m.lnposition, 1, This.nombre_feuilles+1) AND
 
     ENDIF && PCOUNT()=2 AND BETWEEN(m.lnposition, 1, This.nombre_feuilles+1) AND
 
   ENDPROC && ajouter_feuille
 
   ENDPROC && ajouter_feuille
 
+
 
 
   PROCEDURE cellule_coord_alpha_vers_num( m.lccoord AS String)
 
   PROCEDURE cellule_coord_alpha_vers_num( m.lccoord AS String)
 
     * dans OO.Calc, une cellule peut être accédée par deux types de coordonnées équivalentes :
 
     * dans OO.Calc, une cellule peut être accédée par deux types de coordonnées équivalentes :
Line 1,457: Line 1,455:
 
     This.coord_cellule(2)= m.lncolonne - 1
 
     This.coord_cellule(2)= m.lncolonne - 1
 
   ENDPROC && cellule_coord_alpha_vers_num
 
   ENDPROC && cellule_coord_alpha_vers_num
 
+
 
 
   PROCEDURE cellule_coord_num_vers_alpha( lnligne AS Number, lncol AS Number)
 
   PROCEDURE cellule_coord_num_vers_alpha( lnligne AS Number, lncol AS Number)
 
     * lnligne et lncol commence à 0 (et non 1)
 
     * lnligne et lncol commence à 0 (et non 1)
Line 1,491: Line 1,489:
 
     This.coord_cellule_alpha = m.lcresult+ ALLTRIM(STR(This.coord_cellule(1)+1,6))
 
     This.coord_cellule_alpha = m.lcresult+ ALLTRIM(STR(This.coord_cellule(1)+1,6))
 
   ENDPROC && cellule_coord_num_vers_alpha
 
   ENDPROC && cellule_coord_num_vers_alpha
 
+
 
 
   PROCEDURE texte_dans_cellule( pctext AS String, pnligne AS Number, pncol AS Number)
 
   PROCEDURE texte_dans_cellule( pctext AS String, pnligne AS Number, pncol AS Number)
 
     * si on ne transmet qu'un seul paramètre, on travaille sur la cellule courante
 
     * si on ne transmet qu'un seul paramètre, on travaille sur la cellule courante
Line 1,504: Line 1,502:
 
     This.une_cellule.setString( m.pctext )
 
     This.une_cellule.setString( m.pctext )
 
   ENDPROC && texte_dans_cellule
 
   ENDPROC && texte_dans_cellule
 
+
 
 
   PROCEDURE valeur_dans_cellule( pnvaleur AS Number, pnligne AS Number, pncol AS Number)
 
   PROCEDURE valeur_dans_cellule( pnvaleur AS Number, pnligne AS Number, pncol AS Number)
 
     * si on ne transmet qu'un seul paramètre, on travaille sur la cellule courante
 
     * si on ne transmet qu'un seul paramètre, on travaille sur la cellule courante
Line 1,517: Line 1,515:
 
     This.une_cellule.setValue( m.pnvaleur )
 
     This.une_cellule.setValue( m.pnvaleur )
 
   ENDPROC && valeur_dans_cellule
 
   ENDPROC && valeur_dans_cellule
 
+
 
 
   PROCEDURE formule_dans_cellule( pctext AS String, pnligne AS Number, pncol AS Number)
 
   PROCEDURE formule_dans_cellule( pctext AS String, pnligne AS Number, pncol AS Number)
 
     * si on ne transmet qu'un seul paramètre, on travaille sur la cellule courante
 
     * si on ne transmet qu'un seul paramètre, on travaille sur la cellule courante
Line 1,530: Line 1,528:
 
     This.une_cellule.setFormula( m.pctext )
 
     This.une_cellule.setFormula( m.pctext )
 
   ENDPROC && texte_dans_cellule
 
   ENDPROC && texte_dans_cellule
 
+
 
 
   PROCEDURE date_dans_cellule( pudate,  pnligne AS Number, pncol AS Number)
 
   PROCEDURE date_dans_cellule( pudate,  pnligne AS Number, pncol AS Number)
 
     * si on ne transmet qu'un seul paramètre, on travaille sur la cellule courante
 
     * si on ne transmet qu'un seul paramètre, on travaille sur la cellule courante
Line 1,564: Line 1,562:
 
     This.une_cellule.NumberFormat = m.lnformatdate
 
     This.une_cellule.NumberFormat = m.lnformatdate
 
   ENDPROC && date_dans_cellule
 
   ENDPROC && date_dans_cellule
 
+
 
 
   PROCEDURE lire_une_cellule( pnligne AS Number, pncol AS Number)
 
   PROCEDURE lire_une_cellule( pnligne AS Number, pncol AS Number)
 
     * lit le contenu d'une cellule
 
     * lit le contenu d'une cellule
Line 1,575: Line 1,573:
 
       This.une_cellule = This.feuille_active.getCellByPosition( This.coord_cellule(2), This.coord_cellule(1))
 
       This.une_cellule = This.feuille_active.getCellByPosition( This.coord_cellule(2), This.coord_cellule(1))
 
     ENDIF && PCOUNT()=3
 
     ENDIF && PCOUNT()=3
 
+
   
 
     This.une_cellule_valeur = This.une_cellule.value && valeur numérique de la cellule
 
     This.une_cellule_valeur = This.une_cellule.value && valeur numérique de la cellule
 
     This.une_cellule_texte = This.une_cellule.string && texte contenu dans la cellule
 
     This.une_cellule_texte = This.une_cellule.string && texte contenu dans la cellule
Line 1,588: Line 1,586:
 
===test_oo.prg===
 
===test_oo.prg===
 
TEST_OO.PRG :
 
TEST_OO.PRG :
 
+
 
  * J. MAURICE jsm.maurice@wanadoo.fr
 
  * J. MAURICE jsm.maurice@wanadoo.fr
 
  * programme permettant de tester la librairie lib_automation_vfp_oo.prg
 
  * programme permettant de tester la librairie lib_automation_vfp_oo.prg
Line 1,594: Line 1,592:
 
  PUBLIC looo
 
  PUBLIC looo
 
  LOCAL lcaccu
 
  LOCAL lcaccu
 
+
 
  WAIT WINDOW "début" NOWAIT NOCLEAR
 
  WAIT WINDOW "début" NOWAIT NOCLEAR
 
  looo = NEWOBJECT("vfp_oo_writer", "lib_automation_vfp_oo.prg")
 
  looo = NEWOBJECT("vfp_oo_writer", "lib_automation_vfp_oo.prg")
Line 1,683: Line 1,681:
 
   looo.paragraphe.retrait_ligne1 = 1000 && 1 cm
 
   looo.paragraphe.retrait_ligne1 = 1000 && 1 cm
 
   looo.paragraphe.alignement("justifié")
 
   looo.paragraphe.alignement("justifié")
 
+
 
 
   looo.abandon_document=.T.
 
   looo.abandon_document=.T.
 
   WAIT WINDOW "impression du document" NOWAIT
 
   WAIT WINDOW "impression du document" NOWAIT
Line 1,734: Line 1,732:
 
   looo = NULL
 
   looo = NULL
 
  ENDIF && m.looo.erreur>1
 
  ENDIF && m.looo.erreur>1
 +
 
==fin du document==
 
==fin du document==
 
Tous les programmes ci-dessus sont librement utilisables.
 
Tous les programmes ci-dessus sont librement utilisables.

Revision as of 09:38, 30 November 2007

FOXIL 10:02, 30 November 2007 (CET)

Présentation générale

Visual Foxpro est une base de donnée de Microsoft. En plus de cette fonction, c'est aussi un bon langage de programmation. On peut travailler soit en procédural soit en orienté objet (et on peut mixer les deux).

Une des forces de VFP (outre la puissance de sa base) est son intégration dans le Microsoft Office. On peut se servir de Word et d'Excel pour créer des états complexes ou plus jolis (agréables à lire) que le simple gestionnaire d'état. Mais cela devient de plus en plus compliqué et ... on peut faire la même chose avec Open Office 2.3 ....

Le premier listing ci-dessous contient des classes qui vont faciliter l'interface entre VFP et 00. On démarre avec la classe VFP_OO qui contient les propriétés et méthodes de base : ouverture d'un document, enregistrement, impression, etc ... Cette classe est sous-classée en

- vfp_oo_writer : qui contient des propriétés et des méthodes propre à Writer : insertion de texte, gestion des polices, des paragraphes ...

- vfp_oo_calc : qui contient des propriétés et des méthodes propre à Calc : création de feuille, sélection de cellule, ....

Quelques petites classes utilitaires sont aussi présentes comme oo_police pour la gestion des polices de caractère et oo_paragraphe pour la gestion des marges.

Ensuite vous verrez deux petits programmes de test pour vous montrer comment utiliser les classes.

Ces sources peuvent être téléchargées librement à partir du site www.atoutfox.org dans la zone 'contributions' : piloter oo à partir de VFP (URL de la page : http://www.atoutfox.org/articles.asp?ACTION=FCONSULTER&ID=0000000490). Le fichier lib_automation_vfp_oo.prg contient les classes; test_oo et test_oo_calc sont les deux programmes de test (un .prg est un fichier texte, il peut donc s'ouvrir avec oo.writer).

Je voudrais détailler un point technique : si on a une propriété 'toto', la méthode 'toto_assign' de la même classe sera AUTOMATIQUEMENT lancée chaque fois que l'on tentera de modifier la valeur de toto (inversement on a une méthode toto_access qui est lancée chaque fois que l'on tente de lire la propriété). Cette façon de faire est utilisée pour simplifier les modifications simples d'une seul paramètres. Par exemple on pourra écrire :

oo.paragraphe.marge_gauche = 1000

oo.paragraphe.marge_droite = 2000

oo.paragraphe.retrait_ligne1 = 1000

oo.paragraphe.faire()

mais si on a que la marge gauche à modifier, on n'écrira qu'une seule ligne :

oo.paragraphe.a_marge_gauche = 1500

et la méthode _assign correspondante mettra à jour la propriété marge_gauche et lancera la méthode faire.


LIBRAIRIE DE CLASSES :

présentation

* J. MAURICE jsm.maurice@wanadoo.fr  www.atoutfox.org
* (et aussi www.aedtf.org !!)
* librairie de classes pour l'automation d'OpenOffice 2.0
* à partir de VFP (Visual FoxPro). Version du  jme 26/11/2007
* Ces classes sont issues de nombreuses contributions en particulier
* celles de Ted ROCHE. 
* Le livre Programmation OpenOffice.org 2 macros et API aux éditions
* Eyrolles auteurs : Bernard MARCILLY et Laurent GODARD m'a été d'un
* très grand secours.
* un remerciement spécial à
*   Bernard MARCILLY, un des auteurs du livre qui m'a défriché le terrain
*   Laurent Godard, l'autre auteur du livre qui m'a aidé à créer la rubrique
*                   dans wiki.services.openoffice.org
*   Cesar CHALOM pour ses liens
*   Olivier HAMOU
*   ...
* les sites suivants sont aussi dignes d'intéret :
*  http://www.oooforum.org/forum/viewtopic.phtml?p=28389#28389
*
* dans tout ce qui suit OO veut dire OpenOffice 2 
* Ce document comprend d'abord quelques définitions, puis une série de petites
* classes correspondant plus à une structure C qu'à une vraie classe (mais elles
* peuvent avoir quelques méthodes) et enfin les classes utilisables par le programmeur.
* Ces classes respectent un peu la hierarchie d'OO : une classe de base contient
* les propriétés et les méthodes communes à chaque document OO (c'est vfp_oo); elle
* est sous classée en vfp_oo_writer pour manipuler le traitement de texte; puis
* en vfp_oo_calc pour manipuler le tableur, ...
* Liste des classes et de leurs méthodes
* Classe: OO_POLICE   basée sur Custom
*      226 .init
*      231 .faire
*      264 .a_nom_assign
*      278 .a_taille_assign
*      289 .a_gras_assign
*      303 .a_italique_assign
*      314 .a_souligne_assign
*
* Classe: OO_PARAGRAPHE   basée sur Custom
*      344 .init
*      349 .alignement
*      367 .faire
*
* Classe: PARAMETRES_IMPRIMANTE   basée sur Custom
*
* Classe: PARAMETRES_IMPRESSION   basée sur custom
*
* Classe: VFP_OO   basée sur custom
*      460 .init
*      502 .destroy
*      517 .nouveau_document
*      551 .ouvrir_document
*      591 .enregistrer_document
*      617 .enregistrer_copie_document
*      644 .fermer_document
*      668 .imprimer_document
*      723 .informations_document
*      747 .OOoOpenURL
*      777 .OOoPropertyValue
*      797 .OOoCreateStruct
*      822 .OOoConvertToURL
*
* Classe: VFP_OO_WRITER   basée sur vfp_oo
*      845 .init
*      857 .destroy
*      869 .nouveau_document_texte
*      908 .ouvrir_document_texte
*      960 .objets_doc
*      970 .enregistrer_copie_document
*      995 .informations_document
*     1009 .debut_texte
*     1013 .ajouter_texte
*     1017 .nouveau_paragraphe
*     1023 .appliquer_police
*     1030 .police
*
* Classe: VFP_OO_CALC   basée sur vfp_oo
*     1072 .init
*     1081 .destroy
*     1093 .nouveau_tableur
*     1114 .ouvrir_tableur
*     1151 .maj_infos_tableur
*     1173 .enregistrer_copie_document
*     1198 .informations_document
*     1212 .selection_feuille
*     1271 .ajouter_feuille
*     1308 .cellule_coord_alpha_vers_num
*     1335 .cellule_coord_num_vers_alpha
*     1369 .texte_dans_cellule
*     1382 .valeur_dans_cellule
*     1395 .formule_dans_cellule
*     1408 .date_dans_cellule
*     1442 .lire_une_cellule

définition des constantes

*OO_automation/sdk/docs/common/ref/com/sun/star/text/ControlCharacter.html
#DEFINE PARAGRAPH_BREAK   0 && nouveau paragraphe
#DEFINE LINE_BREAK        1 && nouvelle ligne dans un paragraphe
#DEFINE HARD_HYPHEN       2 && tiret insécable
#DEFINE SOFT_HYPHEN       3 && tiret conditionnel
#DEFINE HARD_SPACE        4 && espace insécable
#DEFINE APPEND_PARAGRAPH  5 && ajoute un nouveau paragraphe

#DEFINE COLOR_WHITE        16777215
#DEFINE COLOR_BLACK               0

* OO_automation/sdk/idl/com/sun/star/awt/FontWeight.idl  : graisse des caractères
#DEFINE GRAISSE_DONTKNOW    0.000000    && graisse par défaut
#DEFINE GRAISSE_THIN       50.000000    && caractères fin (moitié de la graisse normale)
#DEFINE GRAISSE_ULTRALIGHT 60.000000    && caractères ultra fins (60% de la graisse normale) 
#DEFINE GRAISSE_LIGHT      75.000000    && caractères fins (3/4 de la graisse normale) 
#DEFINE GRAISSE_SEMILIGHT  90.000000    && 90% de la graisse normale 
#DEFINE GRAISSE_NORMAL    100.000000    && graisse normale 
#DEFINE GRAISSE_SEMIBOLD  110.000000    && demi gras (110% de la graisse normale)
#DEFINE GRAISSE_BOLD      150.000000    && gras 
#DEFINE GRAISSE_ULTRABOLD 175.000000    && très gras 
#DEFINE GRAISSE_BLACK     200.000000    && ultra gras

* OO_automation/sdk/idl/com/sun/star/awt/FontUnderline.idl  : soulignement
#DEFINE SOULIGN_NONE            0 && pas de soulignement
#DEFINE SOULIGN_SINGLE          1 && ligne simple
#DEFINE SOULIGN_DOUBLE          2 && ligne double
#DEFINE SOULIGN_DOTTED          3 && pointillé
#DEFINE SOULIGN_DONTKNOW        4 && inconnu (??!!??)
#DEFINE SOULIGN_DASH            5 && tirets
#DEFINE SOULIGN_LONGDASH        6 && tirets longs
#DEFINE SOULIGN_DASHDOT         7 && tiret point
#DEFINE SOULIGN_DASHDOTDOT      8 && tiret point point
#DEFINE SOULIGN_SMALLWAVE       9 && petite vague
#DEFINE SOULIGN_WAVE           10 && vague
#DEFINE SOULIGN_DOUBLEWAVE     11 && double vague
#DEFINE SOULIGN_BOLD           12 && ligne grasse
#DEFINE SOULIGN_BOLDDOTTED     13 && points gras
#DEFINE SOULIGN_BOLDDASH       14 && tirets gras
#DEFINE SOULIGN_BOLDLONGDASH   15 && long tirets gras
#DEFINE SOULIGN_BOLDDASHDOT    16 && tiret point gras
#DEFINE SOULIGN_BOLDDASHDOTDOT 17 && tiret point point en gras
#DEFINE SOULIGN_BOLDWAVE       18 && vague grasse

* OO_automation/sdk/idl/com/sun/star/awt/FontWidth.idl
#DEFINE LARGEUR_DONTKNOW         0.000000  && largeur inconnue (par défaut ?)
#DEFINE LARGEUR_ULTRACONDENSED  50.000000  && condensé (50%)
#DEFINE LARGEUR_EXTRACONDENSED  60.000000  && condensé (60%)
#DEFINE LARGEUR_CONDENSED       75.000000  && condensé (75%)
#DEFINE LARGEUR_SEMICONDENSED   90.000000  && semi-condensé (90%)
#DEFINE LARGEUR_NORMAL         100.000000  && normal
#DEFINE LARGEUR_SEMIEXPANDED   110.000000  && semi-expansé (110%)
#DEFINE LARGEUR_EXPANDED       150.000000  && expansé (150%)
#DEFINE LARGEUR_EXTRAEXPANDED  175.000000  && extraexpansé (175%)
#DEFINE LARGEUR_ULTRAEXPANDED  200.000000  && ultra-expansé (200%)

* OO_automation/sdk/idl/com/sun/star/awt/Fontslant.idl
#DEFINE ITALIC_DROIT            0 && pas d'italique
#DEFINE ITALIC_OBLIQUE          1 && italique si la police ne l'accepte pas (non utilisé ici)
#DEFINE ITALIC_ITALIC           2 && italique (à condition que la police l'accepte)
#DEFINE ITALIC_INCONNU          3 && comme son nom l'indique !! (non utilisé ici)
#DEFINE ITALIC_OBLIQUE_INVERSE  4 && italique inverse (penchée à gauche) si la police
                                  && ne l'accepte pas (non utilisé ici)
#DEFINE ITALIC_INVERSE          5 && italique inverse (penchée à gauche si la police
                                  && l'accepte (non utilisé ici

* OO_automation/sdk/idl/com/sun/star/style/ParagraphAdjust.idl
#DEFINE ALIGNEMENT_GAUCHE        0  && paragraphe cadré à gauche
#DEFINE ALIGNEMENT_DROIT         1  && paragraphe cadré à droite
#DEFINE ALIGNEMENT_JUSTIFIE_BEAU 2  && paragraphe justifié sauf la dernière
                                    && ligne qui reste à gauche
#DEFINE ALIGNEMENT_CENTRE        3  && paragraphe centré
#DEFINE ALIGNEMENT_JUSTIFIE      4  && paragraphe justifié y compris la dernière ligne


#DEFINE avec_ww .T.   && si cette constante est définie, on affiche des messages
 * d'erreur avec WAIT WINDOW. Si vous mettez la ligne en commentaire et que vous
 * recompilez, aucun message n'est affiché en cas d'erreur
* ATTENTION : NE METTRE AUCUN CODE EXECUTABLE APRES UN DEFINE CLASS

classe oo_police

DEFINE CLASS oo_police AS Custom

 * paramètres d'une police de caractères
 * je suis obligé de renommer les constantes car dans OO on peut avoir deux constantes
 * de même nom dans deux fichiers de déclaration différents mais pas dans VFP
 * notes à propos des propriétés a_nom, a_taille, a_gras, a_italique et a_souligne (dans
 * lesquelles le a_ veut dire 'automatique' : il y a une méthode assign sur chacune
 * de ces propriétés et donc, si on a un seul paramètre à modifier, la simple mise à jour
 * de la propriété va bien être reportée sur le texte. Pour les autres propriétés, il 
 * faut mettre à jour les propriétés puis lancer la méthode faire().
 
 nom = "Courier New"  && cette police a des caractères de taille fixe; il est donc
 *  très facile de faire des documents avec des colonnes (facture, ...) alors que si
 *  on utilise une police proportionnelle cela devient un cauchemar.
 taille = 12
 gras = .F.
 italique = .F.
 souligne = .F.
 couleur_texte = color_black
 couleur_fond =  color_white
 * une autre possibilité pour paramétrer la police est d'utiliser les propriétés
 * a_nom, a_taille, a_gras, a_italique, a_souligne ci-dessous. Sur chacune de
 * ces propriétés il y a une méthode _assign qui lance la méthode This.faire; donc
 * lorsqu'on a beaucoup de paramètres à changer, on peut mettre à jour les
 * propriétés nom, taille, ... puis lancer la méthode This.faire(); mais si
 * on ne veut changer qu'une seule valeur, il est plus simple de faire une
 * simple assignation sur les propriétés a_nom, ...
 a_nom = "Courier New"
 a_taille = 12
 a_gras = .F.
 a_italique = .F.
 a_souligne = .F.
 curseur_ecriture = NULL   && pointeur sur le curseur d'écriture. 
 * c'est sur ce curseur que vont être appliqué la police et ses caractéristiques.
   
 * il n'y a pas de méthode DESTROY dans cette classe
 PROCEDURE init && jme 26/11/2007
   LPARAMETERS pocurseur
   This.curseur_ecriture = m.pocurseur
 ENDPROC
 PROCEDURE faire( )
   * This.curseur_ecriture : curseur d'écriture sur lequel on doit paramétrer
   * la police. On commence par mettre à jour les propriétés de cette classe puis
   * on appelle cette méthode pour les appliquer au curseur pointé par
   * This.curseur_ecriture.
   * pour l'instant, je ne sais pas vérifier si l'objet passé est
   * correct. S'il y a un problème, on ne fait rien (sauf faire
   * un wait window si la compilation se fait avec avec_ww = .T.
   
   IF ISNULL(This.curseur_ecriture)
     #IFDEF avec_ww
     WAIT WINDOW "paramétrage de la police OO impossible:"+ CHR(13)+ ;
       "curseur d'écriture NULL" NOWAIT
     #ENDIF
   ELSE
     TRY
       WITH This.curseur_ecriture
         .CharFontName = This.nom
         .CharHeight = This.taille
         .CharColor = This.couleur_texte
         .CharBackColor = This.couleur_fond
         .CharWeight = IIF( This.gras, GRAISSE_BOLD, GRAISSE_NORMAL)
         .CharPosture = IIF( This.italique, ITALIC_ITALIC, ITALIC_DROIT)
         .CharUnderline = IIF( This.souligne, SOULIGN_SINGLE, SOULIGN_NONE)
       ENDWITH  && This.curseur_ecriture
     CATCH
       #IFDEF avec_ww
       WAIT WINDOW "problème lors du paramétrage de la police OO" NOWAIT
       #ENDIF
     ENDTRY
   ENDIF && ISNULL(This.curseur_ecriture)
 ENDPROC && faire
 HIDDEN PROCEDURE a_nom_assign
   * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
   * que l'on modifie la valeur de This.a_nom
   * une méthode HIDDEN n'est pas accessible par les heritiers de cette classe ni
   * du public (elle n'est seulement accessible que de l'intérieur de la classe
   * où elle est définie)
   LPARAMETERS pcnouval
   
   IF This.nom <> m.pcnouval
     STORE m.pcnouval TO This.a_nom, This.nom
     This.faire()
   ENDIF
 ENDPROC && procedure a_nom_assign
 HIDDEN PROCEDURE a_taille_assign
   * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
   * que l'on modifie la valeur de This.a_taille
   LPARAMETERS pnnouval
   
   IF This.taille <> m.pnnouval
     STORE m.pnnouval TO This.a_taille, This.taille
     This.faire()
   ENDIF
 ENDPROC && procedure a_taille_assign
 HIDDEN PROCEDURE a_gras_assign
   * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
   * que l'on modifie la valeur de This.a_gras
   * une méthode HIDDEN n'est pas accessible par les heritiers de cette classe ni
   * du public (elle n'est seulement accessible que de l'intérieur de la classe
   * où elle est définie)
   LPARAMETERS plnouval
   
   IF This.gras <> m.plnouval
     STORE m.plnouval TO This.gras, This.a_gras
     This.faire()
   ENDIF
 ENDPROC && procedure a_gras_assign
 HIDDEN PROCEDURE a_italique_assign
   * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
   * que l'on modifie la valeur de This.a_italique
   LPARAMETERS plnouval
   
   IF This.italique <> m.plnouval
     STORE m.plnouval TO This.italique, This.a_italique
     This.faire()
   ENDIF
 ENDPROC && procedure a_italique_assign
 HIDDEN PROCEDURE a_souligne_assign
   * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
   * que l'on modifie la valeur de This.a_souligne
   * une méthode HIDDEN n'est pas accessible par les heritiers de cette classe ni
   * du public (elle n'est seulement accessible que de l'intérieur de la classe
   * où elle est définie)
   LPARAMETERS plnouval
   
   IF This.souligne <> m.plnouval
     STORE m.plnouval TO This.souligne, This.a_souligne
     This.faire()
   ENDIF
 ENDPROC && procedure a_souligne_assign
 

ENDDEFINE && oo_police

classe oo_paragraphe

DEFINE CLASS oo_paragraphe AS Custom && jme 04/11/2007

 * paramètres d'un paragraphe. Toutes les valeurs sont en 1/100mm
 * (centième de millimètre)
 
 marge_gauche = 0  && 1000 = 1cm
 retrait_ligne1 = 0
 marge_droite = 0
 hauteur_avant = 0
 hauteur_apres = 0
 gdcj = ALIGNEMENT_GAUCHE  && alignement par défaut du paragraphe
 curseur_ecriture = NULL   && pointeur sur le curseur d'écriture. 
 * c'est sur ce curseur que vont être appliqué les paramètres du paragraphe
 a_marge_gauche = 0  && il y aune méthode _assign
 a_retrait_ligne1 = 0
 a_marge_droite = 0
 
 * il n'y a pas de méthode DESTROY dans cette classe
 PROCEDURE init
   LPARAMETERS pocurseur
   This.curseur_ecriture = m.pocurseur
 ENDPROC
 PROCEDURE alignement( pcalign AS String)
   IF "CENTR" $ UPPER(m.pcalign)
     This.gdcj = ALIGNEMENT_CENTRE
   ELSE
     IF "DROIT" $ UPPER(pcalign)
       This.gdcj = ALIGNEMENT_DROIT
     ELSE
       IF "JUSTI" $ UPPER(m.pcalign)
         This.gdcj = ALIGNEMENT_JUSTIFIE_BEAU
       ELSE
         This.gdcj = ALIGNEMENT_GAUCHE
       ENDIF && "JUSTI" $ UPPER(m.pcalign)
     ENDIF && "DROIT" $ UPPER(pcalign)
   ENDIF && "CENTR" $ UPPER(m.pcalign)
   This.faire()
 ENDPROC && alignement
 PROCEDURE faire( )
   * This.curseur_ecriture : curseur d'écriture sur lequel on doit paramétrer
   * le paragraphe. On commence par mettre à jour les propriétés de cette classe puis
   * on appelle cette méthode pour les appliquer au curseur pointé par
   * This.curseur_ecriture.
   * pour l'instant, je ne sais pas vérifier si l'objet passé est
   * correct. S'il y a un problème, on ne fait rien (sauf faire
   * un wait window si la compilation se fait avec avec_ww = .T.
   
   IF ISNULL(This.curseur_ecriture)
     #IFDEF avec_ww
     WAIT WINDOW "paramétrage du paragraphe OO impossible:"+ CHR(13)+ ;
       "curseur d'écriture NULL" NOWAIT
     #ENDIF
   ELSE
     TRY
       WITH This.curseur_ecriture
         .ParaLeftMargin = This.marge_gauche
         .ParaFirstLineIndent = This.retrait_ligne1
         .ParaRightMargin = This.marge_droite
         .ParaTopMargin = This.hauteur_avant
         .ParaBottomMargin = This.hauteur_apres
         .ParaAdjust = This.gdcj
         IF INLIST(This.gdcj, ALIGNEMENT_JUSTIFIE, ALIGNEMENT_JUSTIFIE_BEAU)
           IF This.gdcj = ALIGNEMENT_JUSTIFIE_BEAU
             .ParaLastLineAdjust = ALIGNEMENT_GAUCHE
           ELSE
             .ParaLastLineAdjust = ALIGNEMENT_JUSTIFIE
           ENDIF && This.alignement = ALIGNEMENT_JUSTIFIE_BEAU
         ENDIF && INLIST(This.gdcj, ALIGNEMENT_JUSTIFIE, ALIGNEMENT_JUSTIFIE_BEAU)
       ENDWITH  && This.curseur_ecriture
     CATCH
       #IFDEF avec_ww
       WAIT WINDOW "problème lors du paramétrage du paragraphe OO" NOWAIT
       #ENDIF
     ENDTRY
   ENDIF && ISNULL(This.curseur_ecriture)
 ENDPROC && faire
 HIDDEN PROCEDURE a_marge_gauche_assign
   * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
   * que l'on modifie la valeur de This.a_marge_gauche
   * quand on a qu'une seule valeur à changer il est plus facile de
   * mettre à jour a_marge_gauche qui aura un effet immédiat que d'écrire
   * deux lignes de programme
   LPARAMETERS plnouval
   
   IF This.marge_gauche <> m.plnouval
     STORE m.plnouval TO This.marge_gauche, This.a_marge_gauche
     This.faire()
   ENDIF
 ENDPROC && procedure a_marge_gauche_assign
 HIDDEN PROCEDURE a_marge_droite_assign
   * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
   * que l'on modifie la valeur de This.a_marge_droite
   LPARAMETERS plnouval
   
   IF This.marge_droite <> m.plnouval
     STORE m.plnouval TO This.marge_droite, This.a_marge_droite
     This.faire()
   ENDIF
 ENDPROC && procedure a_marge_droite_assign
 HIDDEN PROCEDURE a_retrait_ligne1_assign
   * cette méthode est lancée automatiquement (suffixe _assign) chaque fois
   * que l'on modifie la valeur de This.a_retrait_ligne1
   LPARAMETERS plnouval
   
   IF This.retrait_ligne1 <> m.plnouval
     STORE m.plnouval TO This.retrait_ligne1, This.a_retrait_ligne1
     This.faire()
   ENDIF
 ENDPROC && procedure a_retrait_ligne1_assign
 

ENDDEFINE && oo_paragraphe

classe parametres_imprimante

DEFINE CLASS parametres_imprimante AS Custom

 marge_haute = 1
 marge_basse = 1
 marge_gauche = 1
 marge_droite = 1
 nom_imprimante = ""
 orientation = 1       && 1 portrait, 2 paysage

ENDDEFINE && parametres_imprimante AS Custom

classe parametres_page

DEFINE CLASS parametres_page AS Custom

 * définition des paramètres de la page
 * les valeurs sont en centièmes de millimètre
 * les paramètres modifiés sont ceux du style standard
 
 marge_haute = 1000
 marge_basse = 1000
 marge_gauche = 1000
 marge_droite = 1000
 orientation = 1       && 1 portrait, 2 paysage
 page = NULL           && pointeur sur le document
 sf = NULL             && pointeur sur la famille de styles
 standard = NULL       && pointeur sur le style standard
 PROCEDURE init
   LPARAMETERS pocurseur
   This.page = m.pocurseur
   This.faire()
 ENDPROC
 PROCEDURE faire( )
   * This.page : objet que l'on doit paramétrer
   * On commence par mettre à jour les propriétés de cette classe puis
   * on appelle cette méthode pour les appliquer au document pointé par
   * This.page.
   * pour l'instant, je ne sais pas vérifier si l'objet passé est
   * correct. S'il y a un problème, on ne fait rien (sauf faire
   * un wait window si la compilation se fait avec avec_ww = .T.
   * les valeurs sont en centièmes de millimètres
   
   IF ISNULL(This.page)
     #IFDEF avec_ww
     WAIT WINDOW "paramétrage de la page OO impossible:"+ CHR(13)+ ;
       "document NULL" NOWAIT
     #ENDIF
   ELSE
     TRY
       This.sf = This.page.StyleFamilies.getByName("PageStyles")
       This.standard = This.sf.getByName("Standard")
       IF ISNULL( This.standard)
         #IFDEF avec_ww
         WAIT WINDOW "paramétrage de la page OO impossible:"+ CHR(13)+ ;
           "style standard NULL" NOWAIT
         #ENDIF
       ELSE
         WITH This.standard
           .LeftMargin = This.marge_gauche
           .RightMargin = This.marge_droite
           .TopMargin = This.marge_haute
           .BottomMargin = This.marge_basse
           .IsLandscape = IIF(This.orientation=2, .T., .F.)
         ENDWITH  && This.standard
       ENDIF && ISNULL( This.standard)
     CATCH
       #IFDEF avec_ww
       WAIT WINDOW "problème lors du paramétrage de la page OO" NOWAIT
       #ENDIF
     ENDTRY
   ENDIF && ISNULL(This.page)
 ENDPROC && faire
 

ENDDEFINE && parametres_page AS Custom

classe parametres_impression

DEFINE CLASS parametres_impression AS custom

 * cette classe ne contient que des propriétés. A priori elle ne peut
 * être utilisée que par la classe VFP_OO et ses descendantes
 nombre_copie = 1
 impression_dans_un_fichier = .F.
 fichier_impression = ""   && par exemple SYS(5)+CURDIR()+ "essai.prn"
 previsualisation = .F.    && non encore utilisé
 ordre_des_pages = .T.     && si plusieurs exemplaires : .T. on imprime d'abord
   * le document n° 1, puis le document n° 2 etc ...  .F. : on imprime toutes les
   * pages 1, puis toutes les pages 2, etc ...
 attente_fin = .T.         && par défaut on attend que l'impression soit mise dans
   * la file d'attente (le spool) avant de continuer
 pages = ""                && liste des pages à imprimer. Vide si on imprime tout
   * sinon quelque chose comme "3;5;7-11" : impression des pages 3, 5 et de toutes celles
   * comprises entre 7 et 11

ENDDEFINE && parametres_impression AS custom

classe de base : vfp_oo

DEFINE CLASS vfp_oo AS custom

 * cette classe contient les propriétés et les méthodes communes à tous les
 * types de document OpenOffice. Elle va être, éventuellement, sous-classée
 * pour construire les classes correspondant au Writer (traitement de texte),
 * à Calc (feuille de calcul), à Draw (dessin) et à Impress (présentation)
 
 oo_est_installe = .F.               && .T. si OpenOffice est installé
 gestionnaire_de_services = NULL     && pointeur sur le ServiceManager d'OO
 doc = NULL                          && pointeur sur le document OO
 bureau = NULL                       && pointeur sur le 'bureau' d'OO (oo desktop
 fichier_courant = ""                && nom complet du fichier en cours de traitement
 imprimante = NULL                   && pointeur sur la classe parametres_imprimante
 impression = NULL                   && pointeur sur la classe parametres_impression
 cst_paragraph = NULL && essai
   
 abandon_document = .F. && pour les tests : si .T. on ne sauvegarde pas le document dans le destroy
 
 erreur = -1                         && -1 non encore initialisé
 *  -2 OO n'est pas installable  -3 échec du createobject,  -4 impossible de créer le bureau
 *  -10  structure UNO impossible à créer, -11 paramètre invalide
 *  -13  impossible de fermer le document
 *  -20  impossible de créer le docuemnt,  -21  impossible de lire le document
 *  -30 et -31 Impossible de créer le pointeur sur le texte
 *  -32  Impossible de créer le curseur d'insertion texte
 PROTECTED PROCEDURE init
   * à l'init on vérifie si openoffice est installé
   * une méthode PROTECTED est accessible par toutes les méthodes de la classe où
   * elle est définie mais aussi des méthodes des sous-classes mais pas du public
   This.imprimante = NEWOBJECT("parametres_imprimante")
   This.impression = NEWOBJECT("parametres_impression")
   TRY
     This.gestionnaire_de_services = CREATEOBJECT( "com.sun.star.ServiceManager" )
     IF ISNULL(This.gestionnaire_de_services)
       #IFDEF avec_ww
       WAIT WINDOW "erreur instanciation OO" NOWAIT
       #ENDIF
       This.erreur = -3
     ELSE
       This.erreur = 1
     ENDIF && ISNULL(This.gestionnaire_de_services)
   CATCH
     #IFDEF avec_ww
     WAIT WINDOW "Impossible d'instancier OO" NOWAIT
     #ENDIF
     This.erreur = -2
   ENDTRY
   * on va maintenant ouvrir le bureau d'OO
   * note je ne sais pas si on doit avoir un bureau par document
   * ou un bureau par instance d'OO (donc a priori un seul). pour
   * tester je vais en créer qu'un seul donc ici dans l'init
   IF This.erreur = 1
     TRY
       This.bureau = ;
        This.gestionnaire_de_services.createInstance( "com.sun.star.frame.Desktop" )
       COMARRAY( This.bureau, 10 ) &&The array is a zero-based array and is passed by reference
       This.erreur = 2 && ok
     CATCH
       #IFDEF avec_ww
       WAIT WINDOW "impossible d'instancier le bureau OO" NOWAIT
       #ENDIF
       This.bureau = NULL
       This.erreur = -4
     ENDTRY
   ENDIF && This.erreur = 1
 ENDPROC && init
 PROTECTED PROCEDURE destroy
   * une méthode PROTECTED est accessible par toutes les méthodes de la classe où
   * elle est définie mais aussi des méthodes des sous-classes mais pas du public
   IF !ISNULL(This.doc) AND This.doc.isModified AND This.abandon_document=.F.
     * si on n'a pas de nom de fichier quand on sort, on en créer un automatiquement
     IF EMPTY(This.fichier_courant)
       This.fichier_courant = "OOO_OO_"+ SYS(2015)
     ENDIF && EMPTY(This.fichier_courant)
     This.enregistrer_document()
   ENDIF && This.doc.isModified
   This.doc = NULL
   This.bureau = NULL
   This.gestionnaire_de_services = NULL
 ENDPROC
 PROCEDURE nouveau_document( pctypdoc AS String)
   * on crée un nouveau document dont le type est contenu dans pctypdoc
   * nouveau texte : pctypdoc = "private:factory/swriter"
   * nouveau tableur : pctypdoc = "private:factory/scalc"
   * nouveau dessin :  pctypdoc = "private:factory/sdraw"
   * nouvelle présentation :  pctypdoc = "private:factory/simpress"
   * nouvelles formules mathématiques :  pctypdoc = "private:factory/smath"
   
   IF This.erreur >=0 AND !EMPTY(m.pctypdoc)
     * on ne crée pas de nouveau document s'il y en a déjà un actif
     IF ISNULL(This.doc)
       This.erreur = 0
       This.OOoOpenURL( m.pctypdoc )
       IF ISNULL(This.doc)
         This.erreur = -20
         #IFDEF avec_ww
         WAIT WINDOW "Impossible de créer un nouveau document" NOWAIT
         #ENDIF
       ELSE
         This.erreur = 2 && document ok
         This.abandon_document=.F. && on met .T. quand on ne veut pas que le
         * document soit enregistrer dans le destroy event; il faut donc
         * bien penser à la remettre à faux lors de la création d'un nouveau
         * document
       ENDIF && ISNULL(This.doc)
     ELSE
       #IFDEF avec_ww
       WAIT WINDOW "Création nouveau document impossible" + CHR(13)+ ;
        "un autre existe déjà" NOWAIT
       #ENDIF
     ENDIF && ISNULL(This.doc)
   ENDIF && This.erreur =2
 ENDPROC
 PROCEDURE ouvrir_document( pcfichier AS String)
   * pcfichier est un nom de fichier 00 au format Windows ("c:\toto\tata\tutu.odt")
   LOCAL ARRAY lttab(1)
   LOCAL lcurl
   
   IF This.erreur<2 OR EMPTY(m.pcfichier)
     This.erreur = -11 && paramètre invalide
     #IFDEF avec_ww
     WAIT WINDOW "Il faut indiquer le nom du fichier à ouvrir" NOWAIT
     #ENDIF
   ELSE
     * on demande à VFP de vérifier que le fichier existe bien avant de l'ouvrir
     IF ADIR(lttab, m.pcfichier) > 0
       This.erreur = 0 && on raz l'erreur éventuelle
       This.doc = NULL
       lcurl = This.OOoConvertToURL( m.pcfichier )
       This.OOoOpenURL( m.lcurl )
       IF ISNULL( This.doc)
         This.erreur = -21
         #IFDEF avec_ww
         WAIT WINDOW "Impossible d'ouvrir le fichier" + CHR(13)+ ;
          m.pcfichier NOWAIT
         #ENDIF
       ELSE
         This.erreur = 2 && document ok
         This.abandon_document=.F. && on met .T. quand on ne veut pas que le
         * document soit enregistrer dans le destroy event; il faut donc
         * bien penser à la remettre à faux lors de l'ouverture d'un nouveau
         * document
       ENDIF && ISNULL( This.doc)
     ELSE
       This.erreur = -20
       #IFDEF avec_ww
       WAIT WINDOW "Le fichier" + CHR(13)+ m.pcfichier+ CHR(13)+ ;
        "n'existe pas"NOWAIT
       #ENDIF
     ENDIF && ADIR(lttab, m.pcfichier) > 0
   ENDIF && EMPTY(pcfichier)
 ENDPROC && ouvrir_texte
 PROCEDURE enregistrer_document( pcnomfichier AS String)  && vfp_oo
   * attention, si vous travaillez sur un document TOTO et que vous
   * l'enregistrez sous le nom TATA, vous travaillerez dorénavant sur TATA
   * pcnomfichier contient un nom de fichier (avec éventuellement un chemin)
   * au format Windows
   * on ne peut pas exporter en PDF avec storeasurl()
   IF PCOUNT() = 1 AND ! EMPTY(m.pcnomfichier)
     This.fichier_courant = m.pcnomfichier
   ENDIF && PCOUNT() = 1 AND ! EMPTY(m.pcnomfichier)
   * on pourrait tester si le document a été modifié avec la propriété 
   *  This.doc.isModified (cette propriété est en lecture/écriture)
   IF EMPTY( JUSTPATH(This.fichier_courant))
     * on ne peut pas sauvegarder un document SANS lui donner le chemin complet !
     This.fichier_courant = SYS(5)+ CURDIR()+ This.fichier_courant
   ENDIF && EMPTY( JUSTPATH(This.fichier_courant))
   LOCAL lcurl, lcext
   LOCAL ARRAY lcparam(1)
   lcext = JUSTEXT(This.fichier_courant)
   * on veut prévenir l'opérateur s'il écrase une version précédente du document
   * (même si c'est le même fichier; si c'est trop perturbant on peut supprimer
   *  cette option ou effacer le fichier destinataire avant de faire l'enregistrement)
   lcparam(1) = This.OOoPropertyValue( "Overwrite", .F. )
   lcurl = This.OOoConvertToURL( This.fichier_courant)
   This.doc.storeAsURL( m.lcurl, @ lcparam)
 ENDPROC && enregistrer_document
 PROCEDURE enregistrer_copie_document( pcnomfichier AS String)
   * on veut créer une copie du document courant (on crée un fichier
   * sur le disque mais on continue de travailler sur le document courant)
   * pcnomfichier contient un nom de fichier (avec éventuellement un chemin)
   * au format Windows
   * attention la méthode storeToURL est différente de storeAsURL
   * avec cette méthode on pourrait exporter en PDF, mais, comme les paramètres
   * dépendent du type de document, on va faire une méthode héritée dans
   * vfp_oo_writer pour un document texte et dans vfp_oo_calc pour une feuille de calcul.
   IF PCOUNT() = 1 AND ! EMPTY(m.pcnomfichier)
     IF EMPTY( JUSTPATH(m.pcnomfichier))
       * on ne peut pas sauvegarder un document SANS lui donner le chemin complet !
       pcnomfichier = SYS(5)+ CURDIR()+ m.pcnomfichier
     ENDIF && EMPTY( JUSTPATH(m.pcnomfichier))
     LOCAL lcurl
     LOCAL ARRAY lcparam(1)
     * on veut prévenir l'opérateur s'il écrase une version précédente du document
     * (même si c'est le même fichier; si c'est trop perturbant on peut supprimer
     *  cette option)
     lcparam(1) = This.OOoPropertyValue( "Overwrite", .T. )
     lcurl = This.OOoConvertToURL( m.pcnomfichier )
     This.doc.storeToURL( m.lcurl, @ lcparam)
   ENDIF && PCOUNT() = 1 AND ! EMPTY(m.pcnomfichier)
 ENDPROC && enregistrer_document
 PROCEDURE fermer_document
   LOCAL llok
   
   llok = .T.
   IF This.doc.isModified
     llok = IIF( INLIST( MESSAGEBOX("Le document" + CHR(13)+ This.fichier_courant + ;
      CHR(13)+ "n'a pas été enregistré." + CHR(13)+ "Voulez-vous l'enregistrer ?", ;
       4+32, "ATTENTION", 60000), -1,6), .T., .F.)
   ENDIF && This.doc.isModified
   IF m.llok = .T.
     TRY
       This.doc.close(.T.)
       This.abandon_document=.T. && on ne veut pas enregistrer dans le destroy
       This.doc = NULL
       This.erreur = 1
     CATCH
       This.erreur = -13 && impossible de fermer le document
       #IFDEF avec_ww
       WAIT WINDOW "Impossible de fermer le document" NOWAIT
       #ENDIF
     ENDTRY
   ENDIF && m.llok = .T.
 ENDPROC && fermer_document()
 PROCEDURE imprimer_document
   * ATTENTION : il faut normalement 5 paramètres pour piloter l'impression. Ces
   * 5 paramètres sont mémorisés dans l'instance de parametres_impression pointée
   * par This.impression. Lorsqu'un paramètre est vide (comme filename si on
   * imprime sur l'imprimante ou pages si on veut tout imprimer), il ne doit PAS
   * être transmis. La dimension du tableau transmis à OO est donc variable et
   * dépend du nombre de paramètres utiles.
   
*!*      ci dessous un bout de code pour imprimer les propriétés de printer et leur valeur    
*!*      loprinter = This.doc.printer
*!*      lnaccu = ALEN(loprinter)
*!*      SET TEXTMERGE TO essai_printer.txt ADDITIVE NOSHOW
*!*      SET TEXTMERGE ON
*!*      \<<DATE()>> <<TIME()>>
*!*      lcaccu = ""
*!*      FOR m.lni = 1 TO m.lnaccu
*!*         *lcaccu = m.lcaccu+loprinter(m.lni).name+ CHR(13)
*!*         IF VARTYPE(loprinter(m.lni).value) <> "O"
*!*           \  <<loprinter(m.lni).name>> : <<loprinter(m.lni).value>>
*!*         ELSE
*!*           \  <<loprinter(m.lni).name>> : objet
*!*         ENDIF && VARTYPE(loprinter(m.lni).value) <> "O"
*!*      ENDFOR &&* m.lni = 1 TO m.lnaccu
*!*      SET TEXTMERGE OFF
*!*      SET TEXTMERGE TO
   
   WITH This.impression
     DO CASE
     CASE .impression_dans_un_fichier AND EMPTY(.pages)
       * impression de tout le document dans un fichier
       LOCAL ARRAY loparam(4)
       loparam(4) = This.OOoPropertyValue( "FileName", .fichier_impression)
     CASE .impression_dans_un_fichier AND !EMPTY(.pages)
       * impression d'une liste de pages du document dans un fichier
       LOCAL ARRAY loparam(5)
       loparam(5) = This.OOoPropertyValue( "FileName", .fichier_impression)
       loparam(4) = This.OOoPropertyValue( "Pages", .pages)
     CASE !.impression_dans_un_fichier AND EMPTY(.pages)
       * impression de tout le document sur l'imprimante
       LOCAL ARRAY loparam(3)
     CASE !.impression_dans_un_fichier AND !EMPTY(.pages)
       * impression d'une liste de pages du document sur l'imprimante
       LOCAL ARRAY loparam(4)
       loparam(4) = This.OOoPropertyValue( "Pages", .pages)
     ENDCASE
     loparam(1) = This.OOoPropertyValue( "CopyCount", .nombre_copie) && faut expliquer ?
     * Collate : si plusieurs exemplaires : .T. on imprime d'abord le document n° 1, 
     * puis le document n° 2 etc ...  .F. : on imprime toutes les pages 1, puis toutes 
     * les pages 2, etc ...
     loparam(2) = This.OOoPropertyValue( "Collate", .ordre_des_pages)
     loparam(3) = This.OOoPropertyValue( "Wait", .attente_fin)
   ENDWITH  && This.impression
   This.doc.Print( @loparam)
 ENDPROC && imprimer_document
 PROCEDURE informations_document
   LOCAL lcfichier, loinfos, lodate
   IF !ISNULL(This.doc)
     lcfichier = This.doc.location
     loinfos = This.doc.documentInfo
     lodate = loinfos.CreationDate
     = MESSAGEBOX("document :"+ m.lcfichier+ CHR(13)+ ;
      "auteur: "+ m.loinfos.Author+ CHR(13)+ ;
      "création: "+ STR(m.lodate.Day,2)+"/"+ TRANSFORM(m.lodate.Month, "@L 99")+ ;
       "/"+ STR(m.lodate.Year,4)+ CHR(13), 0, "informations")
   ENDIF && !ISNULL(This.doc)
 ENDPROC && informations_document
 
*********************************************************  
* ci-dessous : toutes les méthodes OO utilisées ci-dessus
*********************************************************
* HIDDEN : la méthode ne peut être appelée que depuis cette classe. Même
*          les sous-classes de vfp_oo ne peuvent pas y accéder.
 PROTECTED PROCEDURE OOoOpenURL( pcURL )
   * Ouvre ou crée un document à partir de son URL.
   * Pour créer un nouveau document, l'URL est :
   *  private:factory/sdraw  pour un nouveau document de dessin
   *  private:factory/swriter pour un nouveau document texte
   *  private:factory/scalc  pour un nouveau classeur de feuilles de calcul
   *  private:factory/simpress && pour un nouveau document de présentation
   
*!*        *  LOCAL oPropertyValue
*!*        *  oPropertyValue = OOoCreateStruct( "com.sun.star.beans.PropertyValue" )
*!*        *  LOCAL ARRAY aNoArgs[1]
*!*        *  aNoArgs[1] = oPropertyValue
*!*        *  aNoArgs[1].Name = "ReadOnly"
*!*        *  aNoArgs[1].Value = .F.
*!*        * These two lines replace the alternate version above,
*!*        *  which are left commented for the insight they provide.
   LOCAL ARRAY aNoArgs[1]
   * grossièrement : on crée une structure contenant la propriété 'hidden'
   *  initialisée à .F. et dont l'adresse est dans le premier élément de anoargs
   aNoArgs[1] = This.OOoPropertyValue( "Hidden", .F. )
   This.doc = This.bureau.LoadComponentFromUrl( m.pcURL, "_blank", 0, @aNoargs )
   * Make sure that arrays passed to this document are passed zero based and through
   * reference
   * COMARRAY indique à VFP que tous les tableaux passés à this.doc doivent être
   * basés sur 0 (le premier élément a pour indice 0 et non 1) et être passés par
   * référence. Toutefois, malgré cette instruction (bug ?) les tableaux doivent être
   * précédés par @ si on veut que VFP les passe par référence.
   COMARRAY( This.doc, 10 )
 ENDPROC
 FUNCTION OOoPropertyValue( cName, uValue, nHandle, nState )
   * Create a com.sun.star.beans.PropertyValue struct and return it.
   * créer une structure du type com.sun.star.beans.PropertyValue et
   * retourne un pointeur
   * la structure utilisée par OO ne peut pas être créée directement en VFP
   * on va donc demander à OO de la créer pour nous
   LOCAL oPropertyValue
   oPropertyValue = This.OOoCreateStruct( "com.sun.star.beans.PropertyValue" )
   oPropertyValue.Name = m.cName
   oPropertyValue.Value = m.uValue
   * si on a des paramètres supplémentaires, on les traite
   IF TYPE([nHandle])="N"
     oPropertyValue.Handle = m.nHandle
   ENDIF
   IF TYPE([nState])="N"
     oPropertyValue.State = m.nState
   ENDIF
   RETURN m.oPropertyValue
 ENDFUNC
 FUNCTION OOoCreateStruct( cTypeName AS String)
   * fonction pour créer n'importe quel type de structure UNO
   * on l'a fait créer par OO
   LOCAL oStruct
   oStruct = .NULL.
   TRY
     oStruct = This.gestionnaire_de_services.Bridge_GetStruct( m.cTypeName )
   CATCH
     WAIT WINDOW "impossible de créer la structure" TIMEOUT 2
     oStruct = NULL
     This.erreur = -10 && structure UNO impossible à créer
   ENDTRY
   * dans les exemples lus, il semble qu'il pouvait y avoir un problème si certaines
   * variables globales étaient déjà mises à jour. Pour l'instant, je supprime
   * cette partie
*!*      IF ISNULL( m.oStruct )
*!*        * on n'a pas réussi à créer la structure, on essaie de corriger un problème
*!*        * et de recommencer
*!*        =__OOoReleaseCachedVars()
*!*        oServiceManager = OOoGetServiceManager()
*!*        oStruct = oServiceManager.Bridge_GetStruct( cTypeName )
*!*      ENDIF && ISNULL( m.oStruct )
   RETURN m.oStruct
 ENDFUNC && OOoCreateStruct( cTypeName )
 FUNCTION OOoConvertToURL( cFilename AS String)
   * convertit un nom de fichier Windows en un nom OO
   * le nom doit commencer par "/" et il faut changer les \ en /
   RETURN "file://" + IIF(ASC(m.cFilename)=47, "", "/")+ ;
    CHRTRAN( m.cFilename, "\", "/" )
 ENDFUNC
 

ENDDEFINE && vfp_oo

sous-classe de vfp_oo : vfp_oo_writer

DEFINE CLASS vfp_oo_writer AS vfp_oo && jme 04/11/2007

 * cette classe contient les propriétés et les méthodes propres au
 * document Writer (traitement de texte) d'openOffice
 
 texte = NULL                        && pointeur sur le texte du document
 cuecr = NULL                        && curseur écriture
 cureel = NULL                       && curseur visible (le clignotant)
 font = NULL                         && pointeur sur la classe police
 paragraphe = NULL                   && pointeur sur la classe paragraphe
 page = NULL                         && pointeur sur la classe parametres_page
 *  erreur = -1                      && -1 non encore initialisé
 *  -30 et -31 Impossible de créer le pointeur sur le texte
 *  -32  Impossible de créer le curseur d'insertion texte
 PROTECTED PROCEDURE init
   * à l'init on vérifie si openoffice est installé
   DODEFAULT()
   IF This.erreur = 2
     * initialisation propre au Writer
   ENDIF && This.erreur = 2
 ENDPROC && init
 PROTECTED PROCEDURE destroy
   IF !ISNULL(This.doc) AND This.abandon_document=.F. AND This.doc.isModified
     * si on n'a pas de nom de fichier quand on sort, on en créer un automatiquement
     IF EMPTY(This.fichier_courant)
       This.fichier_courant = "OOO_WRITER_"+ SYS(2015)
     ENDIF && EMPTY(This.fichier_courant)
     This.enregistrer_document()
   ENDIF && This.doc.isModified
   This.doc = NULL
   DODEFAULT()
 ENDPROC
 PROCEDURE nouveau_document_texte
   * on crée un nouveau document texte
   IF This.erreur =2
     * on ne crée pas de nouveau document s'il y en a déjà un actif
     IF ISNULL(This.doc)
       This.nouveau_document( "private:factory/swriter" )
       IF ISNULL(This.doc)
         * il n'y a rien à faire ici, l'erreur a déjà été donnée
       ELSE
         This.texte = This.doc.Text && pointeur sur le texte du document
         * note le texte est le contenu du document. D'autres pointeurs 
         * existent pour l'en-tête, le pied de page, etc ....
         IF ISNULL(This.texte)
           This.erreur = -30
           #IFDEF avec_ww
           WAIT WINDOW "Impossible de créer le pointeur sur le texte" NOWAIT
           #ENDIF
         ELSE
           This.cuecr = This.texte.createTextCursor()
           IF ISNULL(This.cuecr)
             This.erreur = -32
             #IFDEF avec_ww
             WAIT WINDOW "Impossible de créer le curseur d'insertion texte" NOWAIT
             #ENDIF
           ELSE
             This.erreur = 2 && tout va bien
             This.objets_doc()
           ENDIF && ISNULL(This.cuecr)
         ENDIF && ISNULL(This.texte)
       ENDIF && ISNULL(This.doc)
     ELSE
       #IFDEF avec_ww
       WAIT WINDOW "Création nouveau document impossible" + CHR(13)+ ;
        "un autre existe déjà" NOWAIT
       #ENDIF
     ENDIF && ISNULL(This.doc)
   ENDIF && This.erreur =2
 ENDPROC
 PROCEDURE ouvrir_document_texte( pcfichier AS String)
   * pcfichier est un nom de fichier document text au format Windows
   LOCAL ARRAY lttab(1)
   LOCAL lcurl
   
   IF EMPTY(m.pcfichier)
     This.erreur = -11 && paramètre invalide
     WAIT WINDOW "Il faut indiquer le nom du fichier à ouvrir" NOWAIT
   ELSE
     IF ADIR(lttab, m.pcfichier) > 0
       This.erreur = 0 && on raz l'erreur éventuelle
       This.doc = NULL
       lcurl = This.OOoConvertToURL( m.pcfichier )
       This.OOoOpenURL( m.lcurl )
       IF ISNULL( This.doc)
         This.erreur = -21
         #IFDEF avec_ww
         WAIT WINDOW "Impossible d'ouvrir le fichier" + CHR(13)+ ;
          m.pcfichier NOWAIT
         #ENDIF
       ELSE
         This.texte = This.doc.Text && pointeur sur le texte du document
         * note le texte est le contenu du document. D'autres pointeurs 
         * existent pour l'en-tête, le pied de page, etc ....
         IF ISNULL(This.texte)
           This.erreur = -31
           #IFDEF avec_ww
           WAIT WINDOW "Impossible de créer le pointeur sur le texte" NOWAIT
           #ENDIF
         ELSE
           This.cuecr = This.texte.createTextCursor()
           IF ISNULL(This.cuecr)
             This.erreur = -32
             #IFDEF avec_ww
             WAIT WINDOW "Impossible de créer le curseur d'insertion texte" NOWAIT
             #ENDIF
           ELSE
             This.erreur = 2 && tout va bien
             This.objets_doc()
           ENDIF && ISNULL(This.cuecr)
         ENDIF && ISNULL(This.texte)
       ENDIF && ISNULL( This.doc)
     ELSE
       This.erreur = -20
       #IFDEF avec_ww
       WAIT WINDOW "Le fichier" + CHR(13)+ m.pcfichier+ CHR(13)+ ;
        "n'existe pas"NOWAIT
       #ENDIF
     ENDIF && ADIR(lttab, m.pcfichier) > 0
   ENDIF && EMPTY(pcfichier)
 ENDPROC && ouvrir_texte
 PROTECTED PROCEDURE objets_doc
   * met à jour les pointeurs et les paramètres utilisés pour manipuler le texte
   This.font = NEWOBJECT("oo_police", "", "", This.cuecr) && quand on ne met pas de module,
   *  VFP cherche dans les classes de base (mais oo_police n'y est pas) puis
   *  dans le programme courant
   This.paragraphe = NEWOBJECT("oo_paragraphe", "", "", This.cuecr) && idem
   * This.font sert pour la gestion des polices de caractères
   * This.paragraphe sert pour la gestion des paragraphes
   This.page = NEWOBJECT("parametres_page", "", "", This.doc)
   * This.page sert à gérer les valeurs de marge haute, marge basse, gauche et
   * droite de la page.  
 ENDPROC && objets_doc
 PROCEDURE enregistrer_copie_document( pcnomfichier AS String)  && vfp_oo_writer
   * on veut créer une copie du document texte courant (on crée un fichier
   * sur le disque mais on continue de travailler sur le document courant)
   * pcnomfichier contient un nom de fichier (avec éventuellement un chemin)
   * au format Windows
   * on va créer systématiquement un export  PDF
   IF PCOUNT() = 1 AND ! EMPTY(m.pcnomfichier)
     IF EMPTY( JUSTPATH(m.pcnomfichier))
       * on ne peut pas sauvegarder un document SANS lui donner le chemin complet !
       pcnomfichier = SYS(5)+ CURDIR()+ m.pcnomfichier
     ENDIF && EMPTY( JUSTPATH(m.pcnomfichier))
     DODEFAULT( m.pcnomfichier)
     LOCAL lcurl
     LOCAL ARRAY lcparam(2)
     * on veut prévenir l'opérateur s'il écrase une version précédente du document
     * (même si c'est le même fichier; si c'est trop perturbant on peut supprimer
     *  cette option ou supprimer le PDF avant de lancer cette méthode)
     lcparam(2) = This.OOoPropertyValue( "Overwrite", .T. )
     lcparam(1) = This.OOoPropertyValue( "FilterName", "writer_pdf_Export")
     * il faut enlever l'éventuelle extension du nom du fichier pour la remplacer par .pdf
     lcurl = This.OOoConvertToURL( JUSTPATH(m.pcnomfichier)+ "\"+ JUSTSTEM(m.pcnomfichier)+ ".pdf")
     This.doc.storeToURL( m.lcurl, @ lcparam)
   ENDIF && PCOUNT() = 1 AND ! EMPTY(m.pcnomfichier)
 ENDPROC && enregistrer_document
 PROCEDURE informations_document
   LOCAL lcfichier, loinfos, lodate
   IF !ISNULL(This.doc)
     lcfichier = This.doc.location
     loinfos = This.doc.documentInfo
     lodate = loinfos.CreationDate
     = MESSAGEBOX("document :"+ m.lcfichier+ CHR(13)+ ;
      "auteur: "+ m.loinfos.Author+ CHR(13)+ ;
      "création: "+ STR(m.lodate.Day,2)+"/"+ TRANSFORM(m.lodate.Month, "@L 99")+ ;
       "/"+ STR(m.lodate.Year,4)+ CHR(13)+ ;
      "nombre de mots: "+ ALLTRIM(STR(This.doc.WordCount,6)), 0, "informations")
   ENDIF && !ISNULL(This.doc)
 ENDPROC && informations_document
 PROCEDURE debut_texte
   This.cuecr.gotoStart(.F.)
 ENDPROC
 PROCEDURE ajouter_texte( pctexte AS String)
   This.texte.insertString( This.cuecr, m.pctexte, .F.)
 ENDPROC && ajouter_texte
 PROCEDURE nouveau_paragraphe && insertion d'un nouveau paragraphe
   * à l'endroit du curseur d'écriture
   * "com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK"
   This.texte.insertControlCharacter(This.cuecr, PARAGRAPH_BREAK, .F.)
 ENDPROC && nouveau_paragraphe
 PROCEDURE appliquer_police && applique la police définie dans la
   * classe police
   This.font.curseur_ecriture = This.cuecr
   This.font.faire()
 ENDPROC && appliquer_police
 PROCEDURE police( pcnompolice AS String, ;
  pntaille AS Number, plgras AS Logical, plsouligne AS Logical)
   IF PCOUNT()>0 AND !ISNULL(m.pcnompolice) AND !EMPTY(m.pcnompolice)
     This.font.nom = m.pcnompolice
   ENDIF
   IF PCOUNT()>1 AND !ISNULL(m.pntaille) AND BETWEEN(m.pntaille, 2, 99)
     This.font.taille = m.pntaille
   ENDIF
   IF PCOUNT()>2 AND !ISNULL(m.plgras)
     This.font.gras = m.plgras
   ENDIF
   IF PCOUNT()>3 AND !ISNULL(m.plsouligne)
     This.font.souligne = m.plsouligne
   ENDIF
   This.font.curseur_ecriture = This.cuecr
   This.font.faire()
 ENDPROC && police

ENDDEFINE && vfp_oo_writer

sous-classe de vfp_oo : vfp_oo_calc

DEFINE CLASS vfp_oo_calc AS vfp_oo && jme 07/11/2007

 * cette classe contient les propriétés et les méthodes propres au
 * document Writer (traitement de texte) d'openOffice
 
 nombre_feuilles = 0       && nombre de feuilles
 DIMENSION feuilles(1,3)   && tableau contenant les noms des feuilles (col 1),
   * leur ordre de création (colonne 2) et leur position (colonne 3) (les valeurs
   * pour l'ordre et la position commencent à 0 et non 1)
   * la 2éme feuille créée peut bien être déplacée à la 5éme position par exemple.
 feuille_active = 0        && ordre de la feuille active
 coord_cellule_alpha = ""  && coordonées d'une cellule au format "A5" ou "BA15"
 DIMENSION coord_cellule(2)  && 1: numéro de la ligne où est la cellule ( à partir de 0);
   * 2: numéro de la colonne où est la cellule ( à partir de 0)
 une_cellule = NULL        && pointeur sur une structure représentant une cellule
 une_cellule_valeur = 0    && valeur numérique d'une cellule
 une_cellule_texte = ""    && texte contenu dans une cellule
 une_cellule_formule = ""  && formule contenue dans une cellule
 une_cellule_date = {}     && date contenue dans une cellule
 coord_region_alpha = ""   && coordonnées d'une région au format "A5:Z10"
 DIMENSION coord_region(4)  && 1: ligne du coin en haut à gauche, 2 colonne de ce coin;
   * 3 ligne du coin en bas à droite, 4 colonne de ce coin
 
 PROTECTED PROCEDURE init
   * à l'init on vérifie si openoffice est installé
   DODEFAULT()
   IF This.erreur = 2
     * initialisation propre à Calc
     STORE 0 TO This.coord_cellule, This.coord_region
   ENDIF && This.erreur = 2
 ENDPROC && init
 PROTECTED PROCEDURE destroy
   IF !ISNULL(This.doc) AND This.doc.isModified AND This.abandon_document=.F.
     * si on n'a pas de nom de fichier quand on sort, on en créer un automatiquement
     IF EMPTY(This.fichier_courant)
       This.fichier_courant = "OOO_CALC_"+ SYS(2015)
     ENDIF && EMPTY(This.fichier_courant)
     This.enregistrer_document()
   ENDIF && This.doc.isModified
   This.doc = NULL
   DODEFAULT()
 ENDPROC
 PROCEDURE nouveau_tableur
   * on crée un nouveau document de calcul
   IF This.erreur =2
     * on ne crée pas de nouveau document s'il y en a déjà un actif
     IF ISNULL(This.doc)
       This.nouveau_document( "private:factory/scalc" )
       IF ISNULL(This.doc)
         * il n'y a rien à faire ici, l'erreur a déjà été donnée
       ELSE
         This.maj_infos_tableur()
         This.erreur = 2 && ok
       ENDIF && ISNULL(This.doc)
     ELSE
       #IFDEF avec_ww
       WAIT WINDOW "Création nouveau document impossible" + CHR(13)+ ;
        "un autre existe déjà" NOWAIT
       #ENDIF
     ENDIF && ISNULL(This.doc)
   ENDIF && This.erreur =2
 ENDPROC
 PROCEDURE ouvrir_tableur( pcfichier AS String)
   * pcfichier est un nom de fichier document Calc (au format Windows)
   LOCAL ARRAY lttab(1)
   LOCAL lcurl
   
   IF EMPTY(m.pcfichier)
     This.erreur = -11 && paramètre invalide
     WAIT WINDOW "Il faut indiquer le nom du fichier à ouvrir" NOWAIT
   ELSE
     * on demande à VFP de vérifier l'existence du fichier (c'est pour faciliter
     * la gestion de l'erreur, je ne sais pas ce que fait OO si le fichier 
     * n'existe pas)
     IF ADIR(lttab, m.pcfichier) > 0
       This.erreur = 0 && on raz l'erreur éventuelle
       This.doc = NULL
       lcurl = This.OOoConvertToURL( m.pcfichier )
       This.OOoOpenURL( m.lcurl )
       IF ISNULL( This.doc)
         This.erreur = -21
         #IFDEF avec_ww
         WAIT WINDOW "Impossible d'ouvrir le fichier" + CHR(13)+ ;
          m.pcfichier NOWAIT
         #ENDIF
       ELSE
         This.maj_infos_tableur()
         This.erreur = 2 && ok
       ENDIF && ISNULL( This.doc)
     ELSE
       This.erreur = -20
       #IFDEF avec_ww
       WAIT WINDOW "Le fichier" + CHR(13)+ m.pcfichier+ CHR(13)+ ;
        "n'existe pas"NOWAIT
       #ENDIF
     ENDIF && ADIR(lttab, m.pcfichier) > 0
   ENDIF && EMPTY(pcfichier)
 ENDPROC && ouvrir_texte
 PROTECTED PROCEDURE maj_infos_tableur
   * met à jour les propriétés nombre_feuilles, et feuilles avec
   * le nombre de feuilles leurs nom, position et ordre
   LOCAL lnaccu, lni, lnmax, lo1feuille
   
   STORE This.doc.Sheets.Count TO This.nombre_feuilles, lnaccu
   DIMENSION This.feuilles(m.lnaccu,3)
   lnmax = m.lnaccu -1
   FOR m.lni = 0 TO m.lnmax
     lnaccu = m.lni + 1
     * lo1feuille = This.doc.Sheets( m.lni)
     lo1feuille = This.doc.getSheets().getByIndex( m.lni )
     This.feuilles( m.lnaccu, 1) = lo1feuille.Name && nom de la feuille
     This.feuilles( m.lnaccu, 2) = m.lnaccu
     * la troisième feuille créée a pu être déplacée à la 1ère position par
     * l'opérateur; la 3éme colonne du tableau contient donc la position de 
     * la feuille et non son ordre de création.
     This.feuilles( m.lnaccu, 3) = lo1feuille.getRangeAddress().Sheet
   ENDFOR &&* m.lni = 0 TO m.lnmax
   This.feuille_active = This.doc.currentController.activeSheet
 ENDPROC && maj_infos_tableur
 PROCEDURE enregistrer_copie_document( pcnomfichier AS String)  && vfp_oo_calc
   * on veut créer une copie du tableur courant (on crée un fichier
   * sur le disque mais on continue de travailler sur le document courant)
   * pcnomfichier contient un nom de fichier (avec éventuellement un chemin)
   * au format Windows
   * on va créer systématiquement un export PDF
   IF PCOUNT() = 1 AND ! EMPTY(m.pcnomfichier)
     IF EMPTY( JUSTPATH(m.pcnomfichier))
       * on ne peut pas sauvegarder un document SANS lui donner le chemin complet !
       pcnomfichier = SYS(5)+ CURDIR()+ m.pcnomfichier
     ENDIF && EMPTY( JUSTPATH(m.pcnomfichier))
     DODEFAULT( m.pcnomfichier)
     LOCAL lcurl
     LOCAL ARRAY lcparam(2)
     * on veut prévenir l'opérateur s'il écrase une version précédente du document
     * (même si c'est le même fichier; si c'est trop perturbant on peut supprimer
     *  cette option ou supprimer le PDF avant de lancer cette méthode)
     lcparam(2) = This.OOoPropertyValue( "Overwrite", .T. )
     lcparam(1) = This.OOoPropertyValue( "FilterName", "calc_pdf_Export")
     * il faut enlever l'éventuelle extension du nom du fichier pour la remplacer par .pdf
     lcurl = This.OOoConvertToURL( JUSTPATH(m.pcnomfichier)+ "\"+ JUSTSTEM(m.pcnomfichier)+ ".pdf")
     This.doc.storeToURL( m.lcurl, @ lcparam)
   ENDIF && PCOUNT() = 1 AND ! EMPTY(m.pcnomfichier)
 ENDPROC && enregistrer_document
 PROCEDURE informations_document
   LOCAL lcfichier, loinfos, lodate
   IF !ISNULL(This.doc)
     lcfichier = This.doc.location
     loinfos = This.doc.documentInfo
     lodate = loinfos.CreationDate
     = MESSAGEBOX("document :"+ m.lcfichier+ CHR(13)+ ;
      "auteur: "+ m.loinfos.Author+ CHR(13)+ ;
      "création: "+ STR(m.lodate.Day,2)+"/"+ TRANSFORM(m.lodate.Month, "@L 99")+ ;
       "/"+ STR(m.lodate.Year,4)+ CHR(13)+ ;
      "nombre de feuilles: "+ ALLTRIM(STR(This.nombre_feuilles,6)), 0, "informations")
   ENDIF && !ISNULL(This.doc)
 ENDPROC && informations_document
 PROCEDURE selection_feuille(luparametre)
   * si luparametre est une chaîne de caractères, on recherche la feuille qui porte
   * ce nom. Si c'est une valeur numérique, on cherche la feuille de ce rang (ordre
   * visible commençant à 1 et non ordre de création)
   *  oSheet = oDoc.getSheets().getByIndex( 0 ) ' get the zero'th sheet
   *  oSheet = oDoc.getSheets().getByName( "Sheet3" ) ' get by name
   
   IF PCOUNT() > 0
     IF VARTYPE(m.luparametre)=="C" AND !EMPTY(m.luparametre)
       * on cherche le feuille qui porte le nom passé en paramètre
       IF This.doc.getSheets().hasByName( m.luparametre)
         This.feuille_active = NULL
         This.feuille_active = This.doc.getSheets().getByName( m.luparametre )
         IF ISNULL(This.feuille_active)
           #IFDEF avec_ww
           WAIT WINDOW "La feuille" + CHR(13)+ m.luparametre+ CHR(13)+ ;
            "est impossible à atteindre" NOWAIT
           #ENDIF
         ELSE
           This.doc.currentController.activeSheet = This.feuille_active
         ENDIF && ISNULL(This.feuille_active)
       ELSE
         #IFDEF avec_ww
         WAIT WINDOW "La feuille" + CHR(13)+ m.luparametre+ CHR(13)+ ;
          "n'existe pas" NOWAIT
         #ENDIF
       ENDIF && This.doc.getSheets().hasByName( "Sheet3" )
     ELSE
       IF VARTYPE(m.luparametre)=="N" OR VARTYPE(m.luparametre)=="I"
         IF BETWEEN(m.luparametre, 1, This.nombre_feuilles)
           This.feuille_active = NULL
           This.feuille_active = This.doc.getSheets().getByIndex( m.luparametre -1)
           IF ISNULL(This.feuille_active)
             #IFDEF avec_ww
             WAIT WINDOW "La feuille n° " + STR(m.luparametre)+ CHR(13)+ ;
              "est impossible à atteindre" NOWAIT
             #ENDIF
           ELSE
             This.doc.currentController.activeSheet = This.feuille_active
           ENDIF && ISNULL(This.feuille_active)
         ELSE
           #IFDEF avec_ww
           WAIT WINDOW "numéro de feuille hors limites" NOWAIT
           #ENDIF
         ENDIF && BETWEEN(m.luparametre, 1, This.nombre_feuilles)
       ELSE
         #IFDEF avec_ww
         WAIT WINDOW "paramètre incorrect" NOWAIT
         #ENDIF
       ENDIF && VARTYPE(m.luparametre)=="N"
     ENDIF && VARTYPE(m.luparametre)=="C"
   ELSE
     #IFDEF avec_ww
     WAIT WINDOW "Il me faut le nom de la feuille" + CHR(13)+ ;
      "ou son numéro d'ordre" NOWAIT
     #ENDIF
   ENDIF && PCOUNT() > 0
 ENDPROC && selection_feuille
 PROCEDURE ajouter_feuille( lnposition AS Number, lcnom AS String)
   * On ajoute la feuille de nom lcnom à la position lnposition.
   * lnposition compris entre 1 (et non 0) et This.nombre_feuilles + 1
   * NOTE : je met beaucoup de tests mais c'est pour faciliter le déboguage
   IF PCOUNT()=2 AND BETWEEN(m.lnposition, 1, This.nombre_feuilles+1) AND ;
    !EMPTY(m.lcnom)
     IF This.doc.getSheets().hasByName( m.lcnom)
       * une feuille porte déjà ce nom
       #IFDEF avec_ww
       WAIT WINDOW "Une feuille porte déjà le nom" + CHR(13)+ m.lcnom NOWAIT
       #ENDIF
     ELSE
       LOCAL lofeuille
       lofeuille = This.feuille_active
       This.feuille_active = NULL
       This.doc.getSheets().insertNewByName(m.lcnom, m.lnposition-1)
       IF This.doc.getSheets().hasByName( m.lcnom)
         This.feuille_active = This.doc.getSheets().getByName( m.lcnom)
         IF ISNULL( This.feuille_active)
           This.feuille_active = m.lofeuille
         ENDIF && ISNULL( This.feuille_active)
       ELSE
         This.feuille_active = m.lofeuille
       ENDIF && This.doc.getSheets().hasByName( m.lcnom)
       This.doc.currentController.activeSheet = This.feuille_active
     ENDIF && This.doc.getSheets().hasByName( m.lcnom)
   ELSE
     #IFDEF avec_ww
     WAIT WINDOW "Au moins un paramètre incorrect" NOWAIT
     #ENDIF
   ENDIF && PCOUNT()=2 AND BETWEEN(m.lnposition, 1, This.nombre_feuilles+1) AND
 ENDPROC && ajouter_feuille
 PROCEDURE cellule_coord_alpha_vers_num( m.lccoord AS String)
   * dans OO.Calc, une cellule peut être accédée par deux types de coordonnées équivalentes :
   * le texte "A1" ou "AA5" ou par ses numéros de ligne/ numéros de colonne.
   * "A1" équivaut à 0,0
   IF PCOUNT()=1 AND !EMPTY(m.lccoord)
     This.coord_cellule_alpha = ALLTRIM(m.lccoord)
   ENDIF && PCOUNT()=1 AND !EMPTY(m.lccoord)
   LOCAL lnligne, lnaccu, lncolonne, lccar, lnlong
   STORE 0 TO lncolonne, lnligne
   lnaccu = 1
   lnlong = LEN(This.coord_cellule_alpha)
   lccar = LEFT(This.coord_cellule_alpha,1)
   DO WHILE ISALPHA(m.lccar)
     lncolonne = m.lncolonne * 26 + (ASC(m.lccar)-64)
     lnaccu = m.lnaccu + 1
     lccar = IIF(m.lnaccu<=m.lnlong, SUBSTR( This.coord_cellule_alpha, m.lnaccu,1), "")
   ENDDO && ISALPHA(SUBSTR( This.coord_cellule_alpha, m.lnaccu,1))
   * normalement, lccar contient le premier chiffre
   DO WHILE ISDIGIT(m.lccar)
     lnligne = m.lnligne * 10 + (ASC(m.lccar)-48)
     lnaccu = m.lnaccu + 1
     lccar = IIF(m.lnaccu<=m.lnlong, SUBSTR( This.coord_cellule_alpha, m.lnaccu,1), "")
   ENDDO && ISALPHA(SUBSTR( This.coord_cellule_alpha, m.lnaccu,1))
   This.coord_cellule(1)= m.lnligne - 1
   This.coord_cellule(2)= m.lncolonne - 1
 ENDPROC && cellule_coord_alpha_vers_num
 PROCEDURE cellule_coord_num_vers_alpha( lnligne AS Number, lncol AS Number)
   * lnligne et lncol commence à 0 (et non 1)
   * dans OO.Calc, une cellule peut être accédée par deux types de coordonnées équivalentes :
   * le texte "A1" ou "AA5" ou par ses numéros de ligne/ numéros de colonne.
   * "A1" équivaut à 0,0
   IF PCOUNT()=2
     This.coord_cellule(1)= m.lnligne
     This.coord_cellule(2)= m.lncol
   ENDIF && PCOUNT()=2
   LOCAL lnli, lnco, lnaccu, lcresult
   lcresult = ""
   lnco = This.coord_cellule(2)
   DO CASE
   CASE m.lnco >= 702
     * le résultat a 3 lettres
     lnaccu = INT(m.lnco / 702)
     lcresult = m.lcresult + CHR(64+ m.lnaccu)
     lnco = m.lnco - m.lnaccu*702
     lnaccu = INT(m.lnco / 26)
     lcresult = m.lcresult + CHR(65+ m.lnaccu)
     lnco = m.lnco - m.lnaccu*26
     lcresult = m.lcresult + CHR(65+m.lnco)
   CASE m.lnco >= 26
     lnaccu = INT(m.lnco / 26)
     lcresult = m.lcresult + CHR(64+ m.lnaccu)
     lnco = m.lnco - m.lnaccu*26
     lcresult = m.lcresult + CHR(65+m.lnco)
   CASE m.lnco >= 0
     lcresult = m.lcresult + CHR(65+m.lnco)
   ENDCASE
   * maintenant que l'on a les lettres, on fait les chiffres, c'est plus simple
   This.coord_cellule_alpha = m.lcresult+ ALLTRIM(STR(This.coord_cellule(1)+1,6))
 ENDPROC && cellule_coord_num_vers_alpha
 PROCEDURE texte_dans_cellule( pctext AS String, pnligne AS Number, pncol AS Number)
   * si on ne transmet qu'un seul paramètre, on travaille sur la cellule courante
   IF PCOUNT()=3
     This.coord_cellule(1)= m.pnligne
     This.coord_cellule(2)= m.pncol
   ENDIF && PCOUNT()=3
   This.une_cellule_texte = m.pctext
   * attention, dans getCellPosition le 1ere paramètre est la colonne, le 2éme la ligne
   *This.feuille_active.getCellByPosition( This.coord_cellule(2), This.coord_cellule(1)).setString( m.pctext )
   This.une_cellule = This.feuille_active.getCellByPosition( This.coord_cellule(2), This.coord_cellule(1))
   This.une_cellule.setString( m.pctext )
 ENDPROC && texte_dans_cellule
 PROCEDURE valeur_dans_cellule( pnvaleur AS Number, pnligne AS Number, pncol AS Number)
   * si on ne transmet qu'un seul paramètre, on travaille sur la cellule courante
   IF PCOUNT()=3
     This.coord_cellule(1)= m.pnligne
     This.coord_cellule(2)= m.pncol
   ENDIF && PCOUNT()=3
   This.une_cellule_valeur = m.pnvaleur
   * attention, dans getCellPosition le 1ere paramètre est la colonne, le 2éme la ligne
   *This.feuille_active.getCellByPosition( This.coord_cellule(2), This.coord_cellule(1)).setValue( m.pnvaleur )
   This.une_cellule = This.feuille_active.getCellByPosition( This.coord_cellule(2), This.coord_cellule(1))
   This.une_cellule.setValue( m.pnvaleur )
 ENDPROC && valeur_dans_cellule
 PROCEDURE formule_dans_cellule( pctext AS String, pnligne AS Number, pncol AS Number)
   * si on ne transmet qu'un seul paramètre, on travaille sur la cellule courante
   IF PCOUNT()=3
     This.coord_cellule(1)= m.pnligne
     This.coord_cellule(2)= m.pncol
   ENDIF && PCOUNT()=3
   * attention, dans getCellPosition le 1ere paramètre est la colonne, le 2éme la ligne
   This.une_cellule_formule = m.pctext
   *This.feuille_active.getCellByPosition( This.coord_cellule(2), This.coord_cellule(1)).setFormula( m.pctext )
   This.une_cellule = This.feuille_active.getCellByPosition( This.coord_cellule(2), This.coord_cellule(1))
   This.une_cellule.setFormula( m.pctext )
 ENDPROC && texte_dans_cellule
 PROCEDURE date_dans_cellule( pudate,  pnligne AS Number, pncol AS Number)
   * si on ne transmet qu'un seul paramètre, on travaille sur la cellule courante
   IF PCOUNT()=3
     This.coord_cellule(1)= m.pnligne
     This.coord_cellule(2)= m.pncol
   ENDIF && PCOUNT()=3
   * attention, dans getCellPosition le 1ere paramètre est la colonne, le 2éme la ligne
   LOCAL lddate, lcaccu, loformat, lolocal, lnformatdate
   lcaccu = VARTYPE(m.pudate)
   IF m.lcaccu=="T"
     lddate = TTOD(m.pudate)
   ELSE
     IF m.lcaccu=="D"
       lddate = m.pudate
     ELSE
       lddate = DATE()
     ENDIF && m.lcaccu=="D"
   ENDIF && VARTYPE(m.pudate)=="T"
   This.une_cellule_date = m.lddate
   * on détaille les calculs pour faciliter le set step on
   * DTOC ne convient pas car OO veut une date à l'américaine ...
   *lcaccu = DTOC(m.lddate)
   lcaccu = TRANSFORM( MONTH(m.lddate), "@L 99")+"/"+ ;
    TRANSFORM( DAY(m.lddate), "@L 99")+"/"+ STR(YEAR(m.lddate),4)
   This.une_cellule = This.feuille_active.getCellByPosition( This.coord_cellule(2), This.coord_cellule(1))
   This.une_cellule.setFormula( m.lcaccu)
   * dans les quelques lignes ci-dessous, je recopie bêtement l'exemple; j'ai pas tout compris.
   loformat = This.doc.getNumberFormats()
   lolocal = This.OOoCreateStruct( "com.sun.star.lang.Locale" )
   * com.sun.star.util.NumberFormat.DATE = 2
   lnformatdate = loformat.getStandardFormat( 2, lolocal) && 2 = date
   This.une_cellule.NumberFormat = m.lnformatdate
 ENDPROC && date_dans_cellule
 PROCEDURE lire_une_cellule( pnligne AS Number, pncol AS Number)
   * lit le contenu d'une cellule
   * mais comment savoir le type de donnée ? 
   *  si c'est une valeur numérique, string et formula contiennent le STR(valeur)!
   * si on ne transmet pas de paramètre, on travaille sur la cellule courante
   IF PCOUNT()=2
     This.coord_cellule(1)= m.pnligne
     This.coord_cellule(2)= m.pncol
     This.une_cellule = This.feuille_active.getCellByPosition( This.coord_cellule(2), This.coord_cellule(1))
   ENDIF && PCOUNT()=3
   
   This.une_cellule_valeur = This.une_cellule.value && valeur numérique de la cellule
   This.une_cellule_texte = This.une_cellule.string && texte contenu dans la cellule
   This.une_cellule_formule = This.une_cellule.formula && formule contenue dans la cellule
   LOCAL lnaccu
   lnaccu = 0 && pour le set step on
 ENDPROC && lire_une_cellule

ENDDEFINE && vfp_oo_calc

programmes de test

test_oo.prg

TEST_OO.PRG :

* J. MAURICE jsm.maurice@wanadoo.fr
* programme permettant de tester la librairie lib_automation_vfp_oo.prg
* version du  26/11/2007
PUBLIC looo
LOCAL lcaccu

WAIT WINDOW "début" NOWAIT NOCLEAR
looo = NEWOBJECT("vfp_oo_writer", "lib_automation_vfp_oo.prg")
WAIT WINDOW "nouveau document" NOWAIT NOCLEAR
looo.nouveau_document_texte()
IF m.looo.erreur>1
  WAIT WINDOW "insertion texte" NOWAIT NOCLEAR
  looo.abandon_document=.T.
  looo.debut_texte()
  looo.ajouter_texte("première ligne créée automatiquement depuis VFP"+CHR(10))
  looo.nouveau_paragraphe()
  looo.ajouter_texte("deuxième ligne "+ DTOS(DATE())+ " "+ TIME())
*!*    looo.informations_document()
  looo.nouveau_paragraphe()
  looo.font.taille = 16
  looo.font.gras = .T.
  looo.appliquer_police()
  looo.ajouter_texte("ceci devrait être dans une taille 16"+ CHR(10))
  looo.nouveau_paragraphe()
  looo.font.gras = .F.
  looo.font.taille = 8
  looo.font.souligne = .T.
  looo.font.nom = "Impact"
  looo.appliquer_police()
  looo.ajouter_texte("police Impact, taille 8 non gras, souligné")
  looo.nouveau_paragraphe()
  looo.ajouter_texte("nouveau")
  looo.police("Courier New", 10, .F., .F.)
  looo.ajouter_texte(" texte avec ")
  looo.police("Courier New", 16, .F., .F.)
  looo.ajouter_texte("changement de ")
  looo.police("", 9, .F., .T.)
  looo.ajouter_texte("police")
  looo.ajouter_texte(".")
  looo.nouveau_paragraphe()
  looo.police("Times New Roman", 12, .F., .F.)
  looo.ajouter_texte("et retour à la normale")
  looo.nouveau_paragraphe()
  FOR m.i = 8 TO 24 STEP 2
    looo.police("Times New Roman", m.i, .F., .F.)
    looo.ajouter_texte("Times "+ STR(m.i,3)+", ")
  ENDFOR &&* m.i = 1 TO 10
  looo.nouveau_paragraphe()
  FOR m.i = 8 TO 24 STEP 2
    looo.police("Courier New", m.i, .F., .F.)
    looo.ajouter_texte("Courier "+ STR(m.i,3)+", ")
  ENDFOR &&* m.i = 1 TO 10
  * lorsque l'on veut changer qu'un seul parametre, il est plus
  * facile d'utiliser les propriétés a_nom, a_taille, a_gras
  * a_souligne, a_italique qui possèdent des méthodes _assign
  * ex: si on ne change que la taille :
  looo.nouveau_paragraphe()
  looo.police("Courier New", 12, .F., .F.)
  looo.ajouter_texte("Courier : avec les assign")
  looo.nouveau_paragraphe()
  FOR m.i = 8 TO 24 STEP 2
     looo.font.a_taille = m.i
     looo.ajouter_texte("Courier assign"+ STR(m.i,3))
     looo.nouveau_paragraphe()
  ENDFOR &&* m.i = 8 TO 24 STEP 2
  looo.nouveau_paragraphe()
  looo.police("Courier New", 12, .F., .F.)
  looo.ajouter_texte("gestion des paragraphes")
  looo.nouveau_paragraphe()
  FOR m.i = 0 TO 3000 STEP 500
     looo.paragraphe.marge_gauche = m.i
     looo.paragraphe.faire()
     looo.ajouter_texte("marge gauche"+ STR(m.i,6))
     looo.nouveau_paragraphe()
  ENDFOR
  looo.nouveau_paragraphe()
  looo.paragraphe.marge_gauche = 0
  looo.ajouter_texte("ceci est un paragraphe aligné à gauche")
  looo.paragraphe.alignement("gauche")
  looo.nouveau_paragraphe()
  looo.font.a_italique = .T.
  looo.ajouter_texte("ceci est un paragraphe aligné à droite")
  looo.paragraphe.alignement("droite")
  looo.nouveau_paragraphe()
  looo.font.a_italique = .F.
  looo.ajouter_texte("ceci est un paragraphe centré")
  looo.paragraphe.alignement("centré")
  looo.nouveau_paragraphe()
 
  lcaccu = "ceci est un paragraphe que l'on va tenté de justifier. "
  looo.ajouter_texte(m.lcaccu+" Remarquez son retrait de première ligne !."+m.lcaccu)
  looo.ajouter_texte(m.lcaccu+m.lcaccu+m.lcaccu+"1234")
  looo.paragraphe.retrait_ligne1 = 1000 && 1 cm
  looo.paragraphe.alignement("justifié")
 
  looo.abandon_document=.T.
  WAIT WINDOW "impression du document" NOWAIT
  * ATTENTION : on imprime dans un fichier mais il faut tout de même qu'une
  * imprimante soit connectée. je regarde le problème.
  looo.impression.pages = ""
  looo.impression.fichier_impression = SYS(5)+CURDIR()+"essai_oo.prn"
  looo.impression.impression_dans_un_fichier = .T.
  looo.imprimer_document()
  WAIT WINDOW "enregistrement du document" NOWAIT NOCLEAR
  lcaccu = SYS(5)+CURDIR()+"essai_"+DTOS(DATE())+"_"+ CHRTRAN(TIME(), ":", "")+".swx"
  looo.enregistrer_document(m.lcaccu)
  lcaccu = SYS(5)+CURDIR()+"copie_"+DTOS(DATE())+"_"+ CHRTRAN(TIME(), ":", "")+".swx"
  looo.enregistrer_copie_document(m.lcaccu)
  looo.fermer_document()
  WAIT WINDOW "document fermé" NOWAIT && TIMEOUT 2
  WAIT CLEAR
ELSE
  looo = NULL
ENDIF && m.looo.erreur>1


test_oo_calc.prg

TEST_OO_CALC.PRG :

PUBLIC looo
SET DATE FRENCH
WAIT WINDOW "début" NOWAIT NOCLEAR
looo = NEWOBJECT("vfp_oo_calc", "lib_automation_vfp_oo.prg")
WAIT WINDOW "ouvrir document" NOWAIT NOCLEAR
looo.ouvrir_tableur("d:\mau\profess9\open_office\test\test_calc.ods")
IF m.looo.erreur>1
  WAIT WINDOW "tableur ouvert" NOWAIT NOCLEAR
  looo.abandon_document=.T.
*  looo.informations_document()
  looo.selection_feuille(2)
  looo.selection_feuille("SYBIC")
*!*    WAIT WINDOW "enregistrement du document" NOWAIT NOCLEAR
*!*    lcaccu = SYS(5)+CURDIR()+"essai_"+DTOS(DATE())+"_"+ CHRTRAN(TIME(), ":", "")+".swx"
*!*    looo.enregistrer_document(m.lcaccu)
  looo.ajouter_feuille( 1, "PAPOUCHE")
  looo.texte_dans_cellule("chatte", 0,2)
  looo.valeur_dans_cellule(123, 0,3)
  looo.date_dans_cellule( DATE(),0,4)
  looo.lire_une_cellule(0,3)
*  looo.fermer_document()
*  WAIT WINDOW "document fermé" TIMEOUT 2
  WAIT CLEAR
ELSE
  looo = NULL
ENDIF && m.looo.erreur>1

fin du document

Tous les programmes ci-dessus sont librement utilisables.

Personal tools