Compléter les paramètres d'un document type (.docx) quelconque à l'aide d'un formulaire Access

Les techniques suivantes seront abordées :

- récupérer dans un fichier .docx toutes les chaînes de caractères comprises entre deux balises (ex. : |*un symbole*|) et les loger dans une table Access.
Nous examinerons deux méthodes : l'une en recourant aux expressions régulières (regex), l'autre en exploitant la fonction Split() ;

- à l'aide d'un formulaire Access, associer une valeur à chacun des symboles d'un document type et déclencher la confection d'un nouveau document Word dans lequel les symboles sont remplacés par leur valeur.

Si vous voulez réagir au contenu de cet article, un espace de discussion est ouvert sur le forum. 6 commentaires Donner une note à l'article (5).

Article lu   fois.

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. L'idée

On confectionne d'abord un document type dans lequel les portions variables à personnaliser sont représentées par des symboles précédés de « |* » et suivi de « *| », comme ceci :

Image non disponible

D'autre part, on a le formulaire fParametres qui permet de rechercher ce document type :

Image non disponible

Quand l'utilisateur a choisi, le formulaire se présente ainsi :

Image non disponible

L'utilisateur complète chaque champ orange avec la valeur correspondant au symbole, par exemple :

Image non disponible

et un clic sur le bouton Image non disponible ouvre ce document :

Image non disponible

L'utilisateur reçoit alors la main sur Word pour apporter les retouches éventuelles.

II. Une fonction pour trouver les symboles contenus dans un fichier Word (utilisation des expressions régulières)

Image non disponible

Ces fonctions ont été écrites par Arkham46.

Note d'Arkham46

J'ai tout mis en late binding (Object et createObject au lieu de typer les variables et d'ajouter les références), ça évite bien des soucis lors de l'exécution sur d'autres PC.

II-A. getTagInContent() - une fonction pour trouver les tags dans un contenu texte quelconque

Recherche de tags dans un contenu texte
Sélectionnez
1.
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.
Public Function getTagInContent(pContent As String)
  Dim oReg As Object ' VBScript_RegExp_55.RegExp
  Dim oResult As Object ' IMatchCollection
  Dim oTag As Object
  Dim sTag As String
  Dim lRetColl As Collection
  Set lRetColl = New Collection
  Set oReg = CreateObject("VBScript.RegExp")
  oReg.Pattern = "\|\*(.+?)\*\|"
  oReg.MultiLine = True
  oReg.Global = True
  If oReg.Test(pContent) Then 
      Set oResult = oReg.Execute(pContent)
      For Each oTag In oResult
        sTag = oTag.subMatches(0)
        On Error Resume Next
        lRetColl.Add sTag, sTag
        On Error GoTo 0
      Next oTag
    Else
      MsgBox "Il n'y a pas de correspondance dans le document"
  End If
  Set oReg = Nothing
  ' Et on retourne la collection
  Set getTagInContent = lRetColl
End Function

N° d'instruction

Commentaires du code

9

Nous recherchons les chaînes de caractères de la forme |*Quelque chose*| qui se trouvent dans tout le texte.
Le pipe (« ») et l'astérisque (« * ») sont des caractères réservés, il faut les précéder d'un antislash (« \ » pour exprimer leur valeur littérale :

Image non disponible

« Quelque chose », dans les faits, c'est n'importe quel caractère en groupe de n'importe quelle longueur.
La syntaxe pour exprimer cela est :

  • un point (« . »), pour dire « n'importe quel caractère » ;
  • le signe plus (« + »), pour dire « répété une ou plusieurs fois ».
Image non disponible

Exprimé ainsi, nous allons récupérer tout le texte compris entre le premier « |* » et le dernier « *| ». Pour dire :  arrêtez-vous chaque fois au premier « *| » rencontré, ou en d'autres mots, pour dire « relevez les plus petites correspondances », la syntaxe est d'ajouter un point d'interrogation (« ? »). Finalement :

Image non disponible

10

Pour activer la recherche sur plusieurs lignes à la fois.

11

Pour préciser que la recherche porte sur toutes les occurrences.

12

On vérifie qu'il existe des correspondances.

13

Si oui, on déclenche la recherche.
oResult va contenir toutes les correspondances rencontrées.

14-19

On parcourt les résultats de la recherche.
Après l'exécution de l'instruction 12, oResult contient toutes les correspondances (balises « |* » et « *| » incluses), chacune dans un objet (ici oTag).
subMatches(0) est le premier bloc entre parenthèses du pattern => notre symbole.
On lance une boucle pour explorer chaque correspondance et loger celle-ci dans une collection (lRetColl).
Il se peut que le document type contienne plusieurs fois le même symbole donc plusieurs oTag.subMatches(0) identiques. Ce cas provoquerait une erreur à l'instruction 16, car dans une collection, les clés doivent être uniques. Les instructions 15 et 17 neutraliseront cette erreur éventuelle.

21

Message pour signaler qu'il n'y a pas de correspondance.

25

On affecte la collection des symboles à la fonction.

Si vous voulez presque tout savoir au sujet de l'utilisation des expressions régulières (regex) avec Access, voyez le tutoriel de cafeine : Les Expressions Rationnelles appliquées en VBA Access.

II-B. Une fonction pour appeler getTagInContent() avec un document Word

 
Sélectionnez
Public Function getTagInWord(poDoc As Object) ' Word.Document
  Set getTagInWord = getTagInContent(poDoc.Content)
End Function

II-C. Un exemple d'utilisation

 
Sélectionnez
Public Function Test()
  Dim oWord As Object ' Word.Application
  Dim oDoc As Object ' Word.Document
  Dim oTagColl As Collection
  Dim vTag As Variant
  Set oWord = CreateObject("Word.Application")
  oWord.Visible = True
  Set oDoc = oWord.Documents.Open(CurrentProject.Path & "\doc1.docx", , True) ' doc1.docx est ici logé dans le même répertoire que l'appli 
  Set oTagColl = getTagInWord(oDoc)
  oWord.Quit False
  Set oDoc = Nothing
  Set oWord = Nothing
  For Each vTag In oTagColl
    Debug.Print vTag
  Next vTag
End Function

III. fParamètres, le formulaire qui permet de piloter la manœuvre

À l'ouverture, il se présente comme ceci :

Image non disponible

car il n'a pas de source et sa section Détail est invisible.

Image non disponible

Quand l'utilisateur clique sur le bouton Image non disponible, le code suivant se déclenche :

 
Sélectionnez
1.
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.
Private Sub BtChoisir_Click()
  Dim oWord As Object ' Word.Application
  Dim oDoc As Object ' Word.Document
  Dim oTagColl As Collection
  Dim vTag As Variant
  Set oWord = CreateObject("Word.Application")
  Me.txtCheminType = ChoisirUnFichier(Me.hwnd, "Parcourir", 1, "Word", "docx")
  Me.txtCheminPerso = Left(Me.txtCheminType, Len(Me.txtCheminType) - 5) & "_PERSO.docx"
  Set oWord = CreateObject("Word.Application")
    With oWord
      .Visible = True
  Set oDoc = .Documents.Open("""" & Me.txtCheminType & """", , True)
  Set oTagColl = getTagInWord(oDoc)
      .Quit
    End With
  Set oDoc = Nothing
  Set oWord = Nothing
  'Vidanger et repeupler la table
  DoCmd.SetWarnings False
  DoCmd.RunSQL "Delete * from tParametres;"
  For Each vTag In oTagColl
    DoCmd.RunSQL "INSERT INTO tParametres ( Symbole ) SELECT """ & vTag & """ AS Expr1;"
  Next
  DoCmd.SetWarnings True
  Me.RecordSource = "tParametres"
  Me.Section("Détail").Visible = True
  Me.txtCheminPerso.Visible = True
  Me.etqCheminPerso.Visible = True
  Me.txtNbreSymboles.Visible = True
End Sub

N° d'instruction

Commentaires du code

7

On déclenche l'ouverture d'une fenêtre de sélection de fichier et on loge le chemin dans le champ txtCheminType.

8

On construit le chemin qui sera affecté au document personnalisé (l'utilisateur pourra éventuellement le modifier).

9-12

Ouverture du .docx choisi à l'instruction 7.

13

Collecte des symboles contenus dans le document.

14-17

Fermeture de la session Word.

19-20

On vidange le contenu (éventuel) de la table tParametres.

21-24

On lance une boucle pour peupler la table tParametres : un enregistrement pour chaque tag trouvé dans le document.

25

On affecte tParametres comme source du formulaire.

26-29

On rend visibles les contrôles cachés à l'origine dans le formulaire.

Image non disponible

Ce qui donne ceci pour notre exemple :

Au fur et à mesure que l'utilisateur saisira la valeur du symbole, le champ txtValeur passera au vert (mise en forme conditionnelle) :

Image non disponible

Notez qu'il est possible d'encoder une valeur sur plusieurs lignes : il suffit de saisir <CTRL + ENTER> pour passer à la ligne :

Image non disponible

Quand tout est complet, un clic sur le bouton Image non disponible déclenche ce code :

 
Sélectionnez
1.
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.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
Private Sub btCreerDoc_Click()
  Dim oWord As Object ' Word.Application
  Dim sNomDoc As String
  Dim rs As DAO.Recordset
  On Error GoTo GestionErreurs
  Me.Refresh
  FileCopy Me.txtCheminType, Me.txtCheminPerso
  'Créer un RecordSet avec tParametres
  Set rs = CurrentDb.OpenRecordset("tParametres")
  rs.MoveFirst
  'Démarrer Word
  Set oWord = CreateObject("Word.Application")
    With oWord
      .Visible = True
  'Ouvrir le document à personnaliser
      .Documents.Open """" & Me.txtCheminPerso & """"
  'Remplacer le symbole par sa valeur
  Do While Not rs.EOF
      .Selection.Find.Execute FindText:="|*" & rs("Symbole") & "*|", _
            ReplaceWith:=" " & rs("Valeur"), Replace:=2 '=wdReplaceAll
    rs.MoveNext
  Loop
  'Sauvegarder
      .ActiveDocument.Save
  'Fermer et libérer les objets
      .Quit
    End With
  Set oWord = Nothing
  rs.Close
  Set rs = Nothing
  ' Ouvrir le doc perso
  Call Ouvrir_fichier(Me.txtCheminPerso)
GestionErreurs:
  Select Case err.Number
    Case 0 ' pas d'erreur
    Case Else
      MsgBox "Erreur dans Sub btCreerDoc_Click" & Chr(13) & Chr(10) _
              & " " & err.Number & " " & err.Description & "."
      Set oWord = Nothing
      rs.Close
      Set rs = Nothing
  End Select
End Sub

N° d'instruction

Commentaires du code

6

Pour s'assurer que la dernière intervention est enregistrée.

7

On prend une copie du document type original.

9-10

On crée un recordset de la table tParametres pour accéder à chacun des enregistrements.

12-16

On crée une session Word et on ouvre le document à personnaliser.

18-22

On lance une boucle pour lire chaque enregistrement du recordset et remplacer le symbole par sa valeur.
Remarquez l'espace inséré devant le symbole :
Image non disponible
sinon les valeurs multilignes seront mal alignées (décalage d'une position vers la droite à partir de la deuxième ligne).

24-28

On sauvegarde le document personnalisé et on clôt la session Word.

29-30

On referme le recorset.

32

On affiche le document personnalisé.
La fonction Ouvrir_fichier(Chemin As String) permet d'ouvrir n'importe quel fichier avec le programme que l'utilisateur a associé à l'extension. Elle est proposée par Loufab dans cette discussion.

IV. Une variante pour la recherche des symboles : Split() au lieu des regex

Le code associé au clic de Image non disponible devient :

 
Sélectionnez
1.
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.
33.
34.
35.
36.
37.
38.
39.
40.
41.
Private Sub BtChoisir_Click()
  Dim oWord As Object ' Word.Application
  Dim oDoc As Object ' Word.Document
  Dim sDocType As String
  Dim sTab() As String
  Dim i As Integer
  Dim iPos As Integer
  Dim sTexteType As String
  'Choisir le fichier type
  sDocType = ChoisirUnFichier(Application.hWndAccessApp, "Parcourir", 1, "Fichier Word", "docx")
  'Afficher dans le formulaire
  Me.txtCheminType = sDocType
  'Proposer un chemin pour le fichier personnalisé
  Me.txtCheminPerso = Left(Me.txtCheminType, Len(Me.txtCheminType) - 5) & "_PERSO.docx"
  'Ouvrir Word pour lire le document type
  Set oWord = CreateObject("Word.Application")
  oWord.Visible = True
  Set oDoc = oWord.Documents.Open(sDocType, , True)
  sTexteType = oDoc.content
  'Refermer Word
  oWord.Quit False
  Set oDoc = Nothing
  Set oWord = Nothing
  'Isoler les parties du texte qui commencent par la balise de début |*
  sTab = Split(sTexteType, "|*")
  'Vidanger la table tParametres
  DoCmd.SetWarnings False
  DoCmd.RunSQL "Delete * from tParametres;"
  'Repeupler la table tParametres
  For i = 1 To UBound(sTab)
    iPos = InStr(sTab(i), "*|")
    DoCmd.RunSQL "INSERT INTO tParametres ( Symbole ) SELECT """ & Left(sTab(i), iPos - 1) & """ AS Expr1;"
  Next i
  DoCmd.SetWarnings True
  'Afficher le formulaire en entier
  Me.RecordSource = "tParametres"
  Me.Section("Détail").Visible = True
  Me.txtCheminPerso.Visible = True
  Me.etqCheminPerso.Visible = True
  Me.txtNbreSymboles.Visible = True
End Sub

N° d'instruction

Commentaires du code

1-18

Ces instructions sont semblables à celles décrites au chapitre III.

19

On loge le contenu du .docx dans la variable sTexteType.

21-23

On ferme la session Word.

25

On applique la fonction Split() à sTexteType avec comme délimiteur la balise début « |* » du symbole.
À ce stade, le tableau sTab contient :
- dans sa première colonne [sTab(o)] : tout ce qui précède le 1er « |* » ;
- toutes les autres colonnes commenceront par un symbole suivi de « *| » et du texte.
Donc ce qui nous intéresse, nos symboles, c'est, à partir de la deuxième colonne de sTab, le début du contenu : ce qui précède « *| ».

30-33

On lance une boucle pour lire à partir de la deuxième colonne [stab(1)] jusqu'à la dernière.
En 32, on crée un enregistrement dans tParametres pour chaque symbole.
N.B. Les doublons éventuels seront éliminés puisque Symbole est la clé :

Image non disponible

34-Fin

Ces instructions sont semblables à celles décrites au chapitre III.

V. Téléchargement

Deux bases (version regex et version Split) peuvent être téléchargées ici.

N.B. Le code a été adapté pour le rendre compatible avec les versions 64 bits. Voyez le tutoriel d'Arkham46 à ce sujet : Développer avec Office 64 bits.

VI. Remerciements

Merci à Arkham46, chrtophe, Loufab et User pour leur contribution à la réalisation de cet article.

Merci à jacques_jean pour la relecture orthographique.

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

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2017 Claude Leloup. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.