I. Présentation▲
4D S.A. propose deux plug-ins dits de productivité :
- un traitement de texte : 4D Write ;
- un tableur : 4D View.
Comment utiliser les possibilités de 4D View afin de générer des tableaux utilisables dans 4D Write ?
Et si je rajoute que j’aimerais pouvoir éditer le document composite dans Word, vous allez me dire non ?
Hé bien si, c’est possible. Cette note technique va vous le montrer.
La réflexion à l’origine de cette note technique provient d’un double constat :
- 4D Write ne gère pas de vrais tableaux comme son grand frère Word. Les « tableaux » à la mode 4D Write ne sont en réalité que des mises en forme à l’aide de tabulations. De plus, l’assistant de tableaux ne permet pas de revenir sur une mise en forme. Autrement dit, si à l’issue de votre parcours dans l’assistant, vous n’êtes pas satisfaits, il ne vous reste plus qu’à tout reprendre ;
- il est également regretté le manque d’interaction entre les différents plug-ins de productivité de 4D, en particulier le Write et le View. Aucune commande ne permet d’insérer le résultat produit par l’un dans l’autre.
Nous allons tenter de proposer une solution répondant à ces deux remarques.
Pour la partie mise en forme de la zone 4D View nous réutiliserons en partie le composant 4D View Helper présenté dans la Note technique 4D-200211-35-FR.
II. Méthode n° 1 : faire bonne image▲
La partie traitement de texte▲
Nous nous contentons d’afficher une zone 4D Write dans une zone externe en laissant l’accès libre à toutes les fonctionnalités par défaut.
La partie tableur▲
Nous construisons un tableau à partir d’une sélection des enregistrements contenus dans la table [CD]. La méthode CD_PV_LigneColonne prépare le tableau. Puis CD_PV_Remplir remplit le tableau en utilisant la commande PV CHAMP VERS CELLULES.
Des contrôles (liste déroulante, case à cocher…) situés sur la droite du tableau permettent de fixer les propriétés d’enrichissement des lignes du tableau :
Insérer une image du tableau dans le Write▲
Une fois le texte saisi et mis en forme dans la partie traitement texte, il est possible d’insérer le tableau 4D View à l’emplacement du point d’insertion dans la zone Write. Pour cela, il suffit de cliquer sur le bouton 'Insérer tableau'. Nous obtenons le résultat suivant :
Comment ça marche ?▲
La première technique que nous utilisons exploite la capacité de 4D View à construire l’image d’une zone grâce à la commande PV_CreerImage.
Extrait de la documentation :
« La commande PV Creer image retourne une image de la plage de cellules désignée par les paramètres gauche, haut, droite et bas. »
Précisons que le format de l’image obtenue est vectoriel ce qui lui assure une bonne qualité d’impression.
Une fois cette image construite, il est très simple de l’insérer dans la zone Write par la commande WR INSERER IMAGE. Extrait de la documentation : « La commande WR INSERER IMAGE insère une image dans la zone à la position déterminée par destination, posHoriz et posVert ».
Nous disposons ainsi du meilleur des deux mondes :
- nous définissons notre mise en page dans 4D Write ;
- nous définissons notre tableau dans 4D View, lorsque celui-ci nous convient nous l’insérons sous forme d’image dans la zone Write à l’emplacement du point d’insertion :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
C_IMAGE
(
$_vI_Pict
)
$_vI_Pict
:=
PV_CreerImage (
$_vl_PV_Zone
)
`--- Insertion ds le Write
`comptons les images
merge_ve_RefPict:=
WR Compter (
$_vl_WR_Zone
;
wr nb images dans texte )+
1
WR INSERER IMAGE (
$_vl_WR_Zone
;
$_vI_Pict
)
WR SELECTIONNER (
$_vl_WR_Zone
;
4
;
merge_ve_RefPict)
`Sélectionnons-la
Nous prenons simplement la précaution de noter dans la variable merge_ve_RefPict le n° de l’image insérée afin de pouvoir la retrouver plus tard. Nous verrons un peu plus loin pourquoi. Précisons qu’il s’agit du seul moyen d’identifier une image dans une zone Write.
Problème sur Windows si vous reprenez ce code en 4D 2003 :
La commande $_vI_Pict
:=
PV_CreerImage (
$_vl_PV_Zone
)
ne fonctionne pas correctement sur Windows. L’image retournée s’affiche comme un rectangle noir.
Ce problème est corrigé en 4D 2004.
S’assurer de bons offices▲
Vous connaissez les développeurs, ce sont d’éternels insatisfaits en quête d’un Graal mythique… À peine notre solution présentée, des demandes supplémentaires s’expriment : « Oui d’accord, mais moi je veux éditer des documents dans MS Word ».
Ouvrir le document dans Word▲
Qu’à cela ne tienne. Réfléchissons au problème.
4D Write permet d’enregistrer un document sous plusieurs formats : texte, write, RTF, Word 2000, HTML.
Enregistrons donc notre document au format RTF et ouvrons-le dans Word ! C’est ce que vous obtenez en cliquant sur le bouton 'vers Word simple' :
Pour cela, nous enregistrons une copie temporaire du document Write au format RTF dans le dossier temporaire :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
C_TEXTE
(
$_vt_PathFinal
)
$_vt_PathFinal
:=
Dossier temporaire
+
"temp.doc"
C_HEURE
(
$_vh_Ref
)
$_vh_Ref
:=
Creer document
(
$_vt_PathFinal
)
FERMER DOCUMENT
(
$_vh_Ref
)
WR SAUVER DOCUMENT (
wr_vl_zone;
$_vt_PathFinal
;
"RTF "
)
DOC_Ouvre_Word (
$_vt_PathFinal
)
La méthode DOC_Ouvre_Word ouvre un document disque dans Word en appelant la commande AP ShellExecute du plug-in 4D Pack, qui elle-même transfère la demande au système. Pour être surs que cette commande lance Word, nous fixons le type et le créateur sur Mac et l’extension sous Windows :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
C_TEXTE
(
$1
)
C_TEXTE
(
$_vt_PathDoc
)
$_vt_PathDoc
:=
$1
Si
(
ENV_si_Windows )
CHANGER TYPE DOCUMENT(
$_vt_PathDoc
;
"DOC"
)
Sinon
CHANGER TYPE DOCUMENT(
$_vt_PathDoc
;
"DOC"
)
CHANGER CREATEUR DOCUMENT(
$_vt_PathDoc
;
"MSWD"
)
Fin de si
`Déclenche l’ouverture du doc suivant son type et créateur
C_ENTIER(
$_ve_Error
)
$_ve_Error
:=
AP ShellExecute (
$_vt_PathDoc
)
La commande AP ShellExecute présente l’intérêt de s’affranchir de la connaissance de l’emplacement exact de l’application Word sur le disque de l’utilisateur, c’est le système qui se débrouille, aussi bien sur Mac que sur PC.
Cependant, notre développeur perfectionniste n’est pas encore comblé :
« Oui, mais comme le tableau est exporté comme image, il n’est pas éditable dans Word ! ».
C’est vrai la critique est recevable. Comment répondre à cette demande ?
En passant par le HTML avec mes sabots▲
La solution que nous avons retenue peut surprendre puisque nous allons utiliser un format intermédiaire en HTML !
Write, tout comme View, permet d’enregistrer le contenu de la zone en HTML. Word permet d’ouvrir un document HTML et de l’afficher sans que l’utilisateur puisse déceler le format d’origine du fichier.
Conversion Write->HTML->Word▲
Nous avons testé la conversion Write vers Word au travers des différents formats proposés et la conversion utilisant le HTML comme format pivot a présenté de bons résultats.
Cependant, un problème existe avec Word sur Mac qui ne reconnaît pas les images dans les pages HTML et ne les affiche pas dans le document converti au format Word. Cela que le document HTML provienne de 4D Write ou de n’importe quelle autre application. Sur Word Windows, cela fonctionne parfaitement.
De la métamorphose▲
Nous disposons donc de toutes les briques nécessaires à la mise en œuvre de notre métamorphose. Voici le processus :
- enregistrement de la zone Write en HTML ;
- enregistrement de la zone View en HTML ;
- récupération de la partie utile, le BODY, de l’export HTML Write ;
- récupération de la partie utile, le BODY, de l’export HTML View ;
- concaténation des deux extraits HTML dans un nouveau document HTML ;
- rajout d’un entête et d’un pied HTML ;
- ouverture du document résultant dans Word.
À l’issue de processus alchimique, miracle, nous disposons bien d’un document Word présentant notre tableau issu de 4D View, lequel tableau est parfaitement reconnu comme un tableau Word et par conséquent complètement éditable.
La preuve en image :
Quelques briques utiles▲
Nous stockons dans le champ [INTERFACE]HTML_debut du code HTML qui servira à l’initialisation de notre document HTML final :
<!
DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd"
>
<html lang
=
"fr"
>
<head>
<meta http-equiv
=
"content-type"
content
=
"text/html; charset=macintosh"
>
<title>Test</title>
</head>
<body>
Remarque :Une optimisation consisterait à remplacer le texte statique « Test » par une balise propriétaire contenant le titre réel du document.
Le code HTML se trouvant à la suite de la balise <body> du résultat de la conversion en HTML de la zone Write sera inséré après cet entête. Ce sera la tâche de la méthode DOC_Merge_HTML. Cette méthode sera de nouveau appelée pour ajouter le code HTML du <body> de la conversion en HTML de la zone View.
Il ne restera plus qu’à terminer notre document HTML correctement en refermant les balises ouvertes. Cette fin de document HTML est stockée dans le champ [INTERFACE]HTML_fin :
</body>
</html>
La méthode DOC_AjouterPaquet_Fin se charge d’ajouter ce texte à la fin du document existant :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
`Relecture du document cible dans un BLOB
C_BLOB
(
$_vx_Blob
)
DOCUMENT VERS BLOB
(
$_vt_PathCible
;
$_vx_Blob
)
`ajout à la fin
`il suffit de convertir le texte en BLOB et de l’ajouter à la fin
C_ENTIER(
$_ve_Offset
)
$_ve_Offset
:=
Taille BLOB
(
$_vx_Blob
)
TEXTE VERS BLOB
(
$_Vt_temp
;
$_vx_Blob
;
Texte sans longueur ;
$_ve_Offset
)
Différence de comportement entre Write et View sur Windows▲
Petite subtilité sur Windows :
- la commande de 4D Write
WR SAUVER DOCUMENT(
$_vl_WR_Zone
;
$_vt_Path_DocHTML_temp
;
"HTML"
)
donne l’extension « .html » au document généré ; - tandis que la commande correspondante de 4D View
PV ENREGISTRER DOCUMENT(
$_vl_PV_Zone
;
$_vt_Path_DocHTML_temp
;
0
;
1
;
pv html)
donne l’extension « .htm ».
Notre code devra en tenir compte.
Perfectionnisme▲
Ah, notre développeur mécontent s’exprime de nouveau :
« Oui, mais je voudrais insérer mon tableau View où je veux dans mon document Write, pas simplement à la fin ! ».
Encore une fois la demande est pertinente et nous devons réfléchir au moyen d’y donner satisfaction.
Repérer la balise
La solution que nous avons retenue consiste à utiliser une balise propriétaire que nous définissons dans une variable interprocess lors de la méthode Sur ouverture :
2.
3.
C_TEXTE
(<>
merge_vt_Ancre)
<>
merge_vt_Ancre:=
"<--!PV_Zone1-->"
Lorsque nous insérons l’image de la zone View dans le document Write, nous précédons de manière invisible l’image par cette balise :
WR INSERER EXPRESSION HTML (
$_vl_WR_Zone
;<>
merge_vt_Ancre)
Lorsque nous enregistrons la zone Write en HTML, nous supprimons préalablement l’image après avoir pris soin de sauvegarder l’état initial du document dans un BLOB pour pouvoir le réafficher correctement en fin de traitement. Souvenez-vous, nous avions pris soin de noter sa référence dans la variable merge_ve_RefPict :
2.
3.
4.
5.
6.
7.
`--- sauvegarde du document
merge_vx_BLOBWrite_priv:=
WR Zone vers blob (
$_vl_WR_Zone
;
1
)
`---une image de la zone PV a été insérée : je la supprime
WR SELECTIONNER (
$_vl_WR_Zone
;
4
;
merge_ve_RefPict)
WR SUPPRIMER SELECTION
(
$_vl_WR_Zone
)
Ensuite, nous recherchons notre balise dans le code HTML généré et la remplaçons par le code HTML provenant de la conversion de la zone View. Le code HTML pouvant dépasser 32 000 caractères, nous devons effectuer la recherche non pas dans une variable texte, mais dans un BLOB. Nous utilisons pour cela la routine ZBLOB_FindString présentée dans la note technique 4D-200312-36-FR « B. A. BA des BLOBS ».
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
`--- Trouver la position de l’ancre ds le BLOB cible
C_BLOB
(
DOC_AjouterPaquet_Blob_Priv)
DOC_AjouterPaquet_Blob_Priv:=
$_vx_Blob
C_ENTIER(
$_ve_Pos
)
$_ve_Pos
:=
ZBLOB_FindString (->
DOC_AjouterPaquet_Blob_Priv;
$_vt_Anchor
;
0
)
C_ENTIER(
$_ve_Offset
)
Si
(
$_ve_Pos
=
0
)
`Pas d’ancre trouvée, on ajoute à la fin
$_ve_Offset
:=
Taille BLOB
(
$_vx_Blob
)
TEXTE VERS BLOB
(
$_Vt_temp
;
$_vx_Blob
;
Texte sans longueur ;
$_ve_Offset
)
Sinon
`l’ancre a été trouvée
`on copie le BLOB avt l’ancre
FIXER TAILLE BLOB
(
$_vx_Blob
;
0
)
COPIER BLOB
(
DOC_AjouterPaquet_Blob_Priv;
$_vx_Blob
;
0
;
0
;
$_ve_Pos
)
`le BLOB à insérer à la place
$_ve_Offset
:=
Taille BLOB
(
$_vx_Blob
)
TEXTE VERS BLOB
(
$_Vt_temp
;
$_vx_Blob
;
Texte sans longueur ;
$_ve_Offset
)
`on ajoute la suite du BLOB
$_ve_Offset
:=
Taille BLOB
(
$_vx_Blob
)
COPIER BLOB
(
DOC_AjouterPaquet_Blob_Priv;
$_vx_Blob
;
$_ve_Pos
+
Longueur
(
$_vt_Anchor
);
$_ve_Offset
;
Taille BLOB
(
DOC_AjouterPaquet_Blob_Priv)-
$_ve_Pos
-
Longueur
(
$_vt_Anchor
))
Fin de si
`on enregistre le document final
BLOB VERS DOCUMENT
(
$_vt_PathCible
;
$_vx_Blob
)
EFFACER VARIABLE
(
DOC_AjouterPaquet_Blob_Priv)
À conserver en tête▲
Dans un souci de finition, nous devons présenter la méthode PV_ParamPrinting. Celle-ci se charge de recopier les entêtes des colonnes dans une nouvelle ligne insérée dans le tableau 4D View afin de disposer d’un tableau complet dans l’export HTML :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
`--- insérer les libellés en 1re ligne
`insérer une ligne vierge
PV INSERER LIGNES (
$_vl_RefZone
;
1
;
1
)
C_ENTIER(
$_ve_NbreCol
)
$_ve_NbreCol
:=
PV Lire propriete document (
$_vl_RefZone
;
pv nombre colonnes )
`relire les libellés
C_TEXTE
(
$_vt_Titre
)
C_ENTIER(
$_ve_Tri
)
C_ENTIER(
$i
)
Boucle
(
$i
;
1
;
$_ve_NbreCol
)
PV LIRE ENTETE COLONNE (
$_vl_RefZone
;
$i
;
$_vt_Titre
)
`;$_ve_Tri)
PV FIXER VALEUR CELL TEXTE (
$_vl_RefZone
;
$i
;
1
;
$_vt_Titre
)
PV FIXER PROPRIETE CELLULE (
$_vl_RefZone
;
$i
;
1
;
pv style texte gras ;
pv valeur vrai )
Fin de boucle
Là encore, nous sauvegardons notre zone PV initiale pour la réafficher correctement après ce traitement préparatoire à l’export :
2.
3.
C_BLOB
(
$_vx_BLOBView
)
$_vx_BLOBView
:=
PV Zone vers blob (
$_vl_PV_Zone
)
III. Deux exports pour le prix d’un▲
Comme notre document est au format intermédiaire HTML, il peut bien évidemment s’ouvrir également dans un navigateur. Un clic sur le bouton « Vers Word » en maintenant la touche Majuscule enfoncée illustre ce gain « collatéral » :
Pratique pour réaliser un client léger !
IV. Conclusion en hommage à Palace▲
Cette fois notre développeur perfectionniste ne peut que s’incliner et repartir en marmonnant :
« Un jour, je l’aurai, oui je l’aurai… ».
Cette note illustre les possibilités qu’offrent les formats de fichiers ouverts, en texte, comme le RTF ou le HTML, par rapport aux formats binaires. Dans le même esprit, on ne peut que se réjouir de l’adoption généralisée de XML comme format d’enregistrement des données, par exemple dans Microsoft Office 2003. Cette évolution prélude à des interactions facilitées entre les différents acteurs des systèmes d’information, dont 4D…
V. Base exemple▲
Téléchargez la base exemple :
base exemple
PlugIns