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ébogage 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 et 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 :
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 :
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 :
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 :
Il y a cependant moins d'options à 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 doubles. 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 :
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.
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 objet (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 :
Et un extrait de celui de Word 2004 qui nous concerne particulièrement puisqu'il décrit la classe Field :
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 rafraichissement 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 rafraichissement 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 multiplateforme, 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