4D & Word 2004 OSX

Contrairement à son homologue sur Windows, la dernière version d'Office sur OSX n'offre que peu de solutions de collaborations avec 4D. Cette note technique aborde le pilotage d'une application Office par AppleScript depuis 4D, le support du langage de scripts d'Apple ayant été notablement amélioré depuis la version 2004 d'Office.

Article lu   fois.

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Contrairement à son homologue sur Windows, la dernière version d'Office sur OSX n'offre que peu de solutions de collaborations avec 4D. Trois axes principaux sont envisageables :

  • L'utilisation de plugins comme 4D Office, mais déboguage et pérennité peuvent inquiéter et le coût des licences peut rebuter ;
  • Pilotage d'une application Office par AppleScript depuis 4D, le support du langage de scripts d'Apple ayant été notablement amélioré depuis la version 2004 d'Office
  • Export de données depuis 4D et utilisation des possibilités de liaisons de données.



Nous allons explorer le deuxième axe afin de construire un document dynamique Word en liaison avec des données 4D.

Nous mettrons encore une fois en œuvre la nouvelle commande magique de 4D 2004 : LANCER PROCESS EXTERNE

Nous reprenons le même exemple que dans la Note technique « 4D, XML & Word 2003 Windows ». Le cahier des charges, la structure de données sont identiques, ainsi que le formulaire où nous retrouvons le bouton 'Courrier' qui provoque la génération du document Word.

II. Technologie employée

Nous utilisons un document Word de référence, ici « modelesWord/sampleMac.doc ». Ce modèle, très simple dans notre exemple, contient des champs qui afficheront les données provenant de 4D comme dans la note technique décrivant la liaison sur PC. Cependant, le type des champs diffère, nous utilisons ici des champs DOCVARIABLE :

Pictures 0586x0114
Figure 1 – les codes des champs d'affichage des données




Ces champs permettent d'afficher le contenu de variables de documents. Nous procédons en trois étapes :

  • Définir les variables de document dans le document de référence

  • Afficher des valeurs de ces variables grâce à des champs

  • Modifier la valeur de ces variables d'après les valeurs de l'enregistrement courant dans 4D.

Définir les variables de documents

Un peu de code VBA (Visual Basic for Application) est nécessaire, voici une fonction qui initialise les variables nécessaires à notre exemple en leur donnant des valeurs par défaut :

 
Sélectionnez
   Sub initDocVars()
    
      CK_NewVariable "assurePrenom", "Emile"
      CK_NewVariable "assureNom", "Zola"
      CK_NewVariable "assureAdresse", "1, rue j'accuse"
      CK_NewVariable "assureCPVille", "Ile du Diable"
    
   End Sub



Le code de la fonction CK_NewVariable, qui vérifie avant d'ajouter une variable qu'elle n'est pas déjà présente :

 
Sélectionnez
   Sub CK_NewVariable(varName As String, varValue As String)

      For Each aVar In ActiveDocument.Variables
         If aVar.Name = varName Then num = aVar.Index
      Next aVar
      If num = 0 Then
         ActiveDocument.Variables.Add Name:=varName, Value:=varValue
      Else
         ActiveDocument.Variables(num).Value = varValue
      End If
    
   End Sub

Afficher dans des champs

Les techniques d'ajout de champs sont les mêmes que pour les champs INCLUDETEXT décrits dans la note technique précédente. Par exemple la commande "Insertion/champ..." provoque l'affichage du dialogue suivant :

Pictures 0637x0362




Il y a cependant moins d'option à renseigner que pour les champs INCLUDETEXT puisqu'il suffit que le mot-clé DOCVARIABLE soit suivi du nom de la variable à afficher, mis entre guillemets double. La seule option disponible consiste à conserver ou non la mise en forme à chaque mise à jour, option cochée par défaut.

Attention cependant à respecter l'ordre présenté ici : il n'est pas possible de définir un champ sans avoir défini au préalable la variable de document et son contenu !

Modification des valeurs

Notez que jusqu'ici rien n'est spécifique à la plate forme Mac : cette solution fonctionne également pour Windows.

Nous retrouvons à cette étape le cœur du problème : comment piloter Word depuis 4D ? Réponse en utilisant les possibilités d'AppleScript sur OSX, de VBScript sur Windows.

Exemple d'interface d'ajout de champs

Avant d'aborder la phase de scripting, précisons qu'il est tout à fait possible au moyen des USerForms de VBA de fournir une interface graphique permettant à l'utilisateur d'insérer les champs au bon endroit du document :

Pictures 0182x0240
Version Windows



Pictures 0155x0203
Version OSX




La sélection d'une ligne dans la drop-down list insère un nouveau champ à l'emplacement du point d'insertion dans le document.

Un autre type d'interface pourrait permettre aux utilisateurs finaux de rajouter des champs au moment de l'édition de leur document. Il suffit que l'ensemble des variables correspondantes aient été définies dans le document avant son ouverture.

Ici, cependant, nous devons mentionner une différence de fonctionnement entre le Mac et le PC : sur Mac ce genre de dialogue est malheureusement toujours modal, ce qui oblige à le refermer après chaque choix de l'utilisateur.

III. Piloter Word par AppleScript

Savoir ouvrir un dictionnaire

Le support d'AppleScript dans MS Office a été très nettement amélioré en version 2004. Vous trouverez plus d'information sur la partie du site Microsoft dédié à Office sur MacOS : Mactopia.

http://www.microsoft.com/mac/

Si le langage AppleScript ne présente guère de difficulté en lui-même, il ne tire sa puissance que par les modèles objets (classes, propriétés, méthodes) exposés par les applications scriptables. En effet, une application peut se contenter de respecter la « required suite » minimale préconisée par Apple. Le modèle exposé par l'application scriptable se nomme le dictionnaire et se consulte (menu Fichier/Ouvrir un dictionnaire...) depuis l'éditeur de scripts fourni par Apple « Script Editor ».

Voici par exemple le dictionnaire de 4D Server :

Pictures 0556x0132
Figure 2 – dictionnaire de 4D Server




Et un extrait de celui de Word 2004 qui nous concerne particulièrement puisqu'il décrit la classe Field :

Pictures 0685x0353
Figure 3 – extrait du dictionnaire de MS Word




Malheureusement, Word n'est pas « enregistrable » au sens Applescript, c'est-à-dire qu'au contraire des macros, il n'est pas possible de déclencher la génération automatique d'un script par l'enregistrement d'une séquence d'actions.

Nous devons donc étudier le dictionnaire et programmer !

Script de pilotage de Word

Voici le résultat de cette phase de recours à la matière grise, le script suivant met à jour deux variables de document assurePrenom et assureNom puis rafraîchit les champs liés aux variables :

tell application "Microsoft Word"

set myDoc to
         "Proxima:Users:ckeromen:Altair:CKTI_Informatique:4D_NT_CK:NT_Word4D:demoMac
         _WordScripting:modeleWord:sample2.doc"
open myDoc

-- maj des valeurs des variables dynamiques
set variable value of variable "assurePrenom" of active document to "Victor"
set variable value of variable "assureNom" of active document to "Hugo"

-- provoquer le raffraichissement de l'affichage des champs lies aux variables
set fieldsNumber to count of fields of active document
repeat with i from 1 to fieldsNumber
set uField to update field field i of active document
end repeat

-- enregistrement du doc sous un autre nom
save as document myDoc file name
         "Proxima:Users:ckeromen:Altair:CKTI_Informatique:4D_NT_CK:NT_Word4D:demoMac
         _WordScripting:modeleWord:sample2-B.doc"

end tell

Rendre le script dynamique

Cependant, ce script est statique, il ne présente pour l'instant aucun lien avec 4D. Pour cela nous allons recourir aux balises proposées par 4D depuis la version 6.5 pour rendre dynamiques les pages HTML. Voici le résultat, toutes les infos statiques du script précédent ont été remplacées par des balises faisant référence à des variables process 4D :

tell application "Microsoft Word"

-- ouverture du modèle
set myDoc to "<!--#4DVAR DEMO_vt_docWord_path-->"
open myDoc

-- maj des valeurs des variables dynamiques
set variable value of variable "assurePrenom" of active document to "<!--#4DVAR demo_vt_assurePrenom-->"
set variable value of variable "assureNom" of active document to "<!--#4DVAR demo_vt_assureNom-->"
set variable value of variable "assureAdresse" of active document to "<!--#4DVAR demo_vt_assureAdresse-->"
set variable value of variable "assureCPVille" of active document to "<!--#4DVAR demo_vt_assureCPVille-->"
set variable value of variable "assureNoDossier" of active document to "<!--#4DVAR demo_vt_assureNoDossier-->"

-- provoquer le raffraichissement de l'affichage des champs liés aux variables
set fieldsNumber to count of fields of active document
repeat with i from 1 to fieldsNumber
set uField to update field field i of active document
end repeat

-- enregistrement du doc sous un autre nom
save as document myDoc file name "<!--#4DVAR demo_vt_pathNewDocWord-->"

end tell


Une seule commande permettra de traiter ce modèle de script pour remplacer les balises par les valeurs en mémoire dans 4D : TRAITER BALISES HTML.

IV. Les méthodes utilisées côté 4D

Méthode principale : demo

C_ENTIER LONG(<>demo_vl_process)

Au cas ou

       : (Nombre de parametres=0)
Si (<>demo_vl_process>0)
PASSER AU PREMIER PLAN(<>demo_vl_process)
Sinon
             <>demo_vl_process:=Nouveau process("demo";64*1024;"Démo";"liaison Word";*)
Fin de si

Sinon

TOUT SELECTIONNER([PATIENT])
TRIER([PATIENT])

FORMULAIRE ENTREE([PATIENT];"Entrée")
FORMULAIRE SORTIE([PATIENT];"Liste")

MODIFIER SELECTION([PATIENT];*)

          <>demo_vl_process:=0

Fin de cas



Le script du bouton 'Courrier' dans le format [PATIENT];"Entrée" est le suivant :

Si (Numero dans selection([ACTE])#0)

CHARGER ENREGISTREMENT([ACTE])
CHERCHER([MEDECIN_TRAITANT];[MEDECIN_TRAITANT]PK_Medecin=[ACTE]FK_medecin_traitant)
CHERCHER([CHIRURGIEN];[CHIRURGIEN]PK_chirurgien=[ACTE]FK_chirurgien)

demo_liaisonWord

Sinon
ALERTE("Veuillez sélectionner un acte au préalable")

Fin de si

Méthode demo_LiaisonWord

C_BOOLEEN($_vb_siOk)

    $_vb_siOk:=Vrai

` charger les données de la base ds les variables de fusion
demo_getData

C_TEXTE(DEMO_vt_docWord_path)   `var process reprise ds le modèle de script
    DEMO_vt_docWord_path:=<>DEMO_vt_docWord_path

    demo_vt_pathNewDocWord:=Remplacer chaine(DEMO_vt_docWord_path;".doc";"-B.doc")
Si (Tester chemin acces(demo_vt_pathNewDocWord)=Est un document )
SUPPRIMER DOCUMENT(demo_vt_pathNewDocWord)
Fin de si

C_TEXTE($_vt_pathNewScript)
    $_vt_pathNewScript:=Remplacer chaine(<>DEMO_vt_script_path;".applescript";"-new.applescript")
Si (Tester chemin acces($_vt_pathNewScript)=Est un document )
SUPPRIMER DOCUMENT($_vt_pathNewScript)
Fin de si

` traite un document disque contenant des balises 4D
    $_vb_siOk:=ZDOC_TraiterBalises (<>DEMO_vt_script_path;$_vt_pathNewScript)

Si ($_vb_siOk)   `appliquer le script
C_TEXTE($error)
       $error:=LPE_appleScript_Exec ($_vt_pathNewScript)   ` exécute un appleScript $1 par LANCER
` PROCESS EXTERNE

Si (ok=1)
`le document est ouvert et présente les champs de fusion à jour
Sinon
ECRIRE TEXTE DANS PRESSE PAPIERS($error)
ALERTE("Echec de la commande "+$error)
Fin de si

Fin de si

Méthode ZDOC_TraiterBalises

C_BOOLEEN($0)

C_TEXTE($1;$_vt_pathScript)
    $_vt_pathScript:=$1

C_TEXTE($2;$_vt_NewScript)
Si (Nombre de parametres=1)   `on écrase le fichier de départ
       $_vt_NewScript:=$1
Sinon   `on enregistre ds un nouveau fichier
       $_vt_NewScript:=$2
Fin de si

C_BLOB($_vx_BLOB)
DOCUMENT VERS BLOB($_vt_pathScript;$_vx_BLOB)

    $0:=(ok=1)

Si ($0)
TRAITER BALISES HTML($_vx_BLOB;$_vx_BLOB)
`pbme remplace les caractères accentués par des entités HTML
       $0:=(ok=1)

Si (Faux)
ECRIRE TEXTE DANS PRESSE PAPIERS(BLOB vers texte($_vx_BLOB;Texte sans longueur ))
Fin de si

Fin de si

Méthode LPE_appleScript_Exec

C_TEXTE($0)

C_TEXTE($1;$_vt_pathScript)
    $_vt_pathScript:=$1

C_TEXTE($in;$out;$error)
    $in:=""
    $out:=""
    $error:=""

    ok:=1
LANCER PROCESS EXTERNE("osascript \""+ZDOC_pathClassicTopathOSX ($_vt_pathScript)+"\"";$in;$out;$error)

    $0:=$error

V. Commande shell osascript

Dans cette méthode, nous appelons la commande SHELL osascript, cette commande attend un chemin d'accès au format UNIX. La fonction ZDOC_pathClassicTopathOSX transforme un chemin d'accès MacOS « Classic », tel que 4D les gère sous MacOS, en chemin d'accès UNIX.

Méthode ZDOC_pathClassicTopathOSX

C_TEXTE($1;$_vt_Racine)

    $_vt_Racine:=$1

C_TEXTE($0;$_vt_PathUnix)

    $_vt_PathUnix:=Remplacer chaine($_vt_Racine;zdoc_get_separateur ;"/")   `les : par /
    $_vt_PathUnix:=Remplacer chaine($_vt_PathUnix;" ";"\\ ")   `pour échapper les espaces

`puis on rajoute "/Volumes"
    $_vt_PathUnix:="/Volumes/"+$_vt_PathUnix

    $0:=$_vt_PathUnix

Description d’osascript

osascript exécute le fichier de script indiqué ou l'input standard si aucun fichier n'est indiqué. Les scripts peuvent être en texte ou compilés.


Pour plus d'information, consulter l'aide via le Terminal. Voici un extrait de ce que l'on obtient en tapant man osascript dans le terminal :

OSASCRIPT(1)            BSD General Commands Manual            OSASCRIPT(1)

NAME
      osascript - execute AppleScripts and other OSA language scripts

SYNOPSIS
      osascript [-l language] [-e command] [-s flags] [programfile]

VI. Conclusion

Au travers de ces deux notes techniques, nous avons présenté des moyens de rendre des documents Word dynamiques, rafraîchissant les données présentées dans des champs avant d'afficher le résultat à l'utilisateur.

Nous avons étudié plus particulièrement dans cette deuxième note une technique aux 2/3 multi plate forme, seule la partie scripting différant : recours à VBScript sur Windows et Applescript sur OSX.

VII. Base exemple

Téléchargez la base exemple :

base exemple

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.