Remplir un document Word depuis Excel
Le publipostage de Word sait produire cent lettres d'un coup. Il ne sait pas produire un document, enregistré au bon endroit, sous le bon nom, quand vous cliquez sur une ligne. Voici le principe théorique en VBA, et les nombreux obstacles techniques d'une réalisation artisanale.
Pourquoi le publipostage ne suffit pas
Le publipostage est conçu pour un envoi en masse : une source de données, un modèle, et une fusion qui produit un gros document de cent pages. Trois choses lui manquent pour un usage au fil de l'eau :
- il produit un seul fichier contenant tous les destinataires, alors que vous voulez un fichier par client, dans le dossier de ce client ;
- il ne nomme pas les fichiers — vous les renommez à la main ;
- il se déclenche depuis Word, pas depuis la ligne Excel sur laquelle vous travaillez.
La méthode ci-dessous inverse la logique : Excel pilote Word, ouvre un modèle, remplace des balises par les valeurs de la ligne, et enregistre le résultat où vous voulez, sous le nom que vous voulez.
Préparer le modèle Word
Créez un document Word normal — un devis, une lettre de mission, un contrat — et remplacez
les valeurs variables par des balises. La forme n'a pas d'importance tant qu'elle est
improbable dans un texte courant ; nous utilisons ici
<$Nom> :
Objet : mission <$Categorie>
Madame, Monsieur <$Client>,
Nous confirmons notre intervention du <$Date>
pour un montant de <$Montant> euros.
Côté Excel, une feuille Donnees où les en-têtes de colonnes
portent exactement les noms des balises — c'est ce qui évitera d'avoir à toucher au code
quand vous ajouterez un champ :
| A | B | C | D | |
|---|---|---|---|---|
| 1 | Modèle | D:\Modeles\devis.docx | ||
| 2 | Sortie | D:\Clients\Dupont\devis.docx | ||
| 3 | Client | Categorie | Date | Montant |
| 4 | Dupont SARL | Bâtiment | 17/09/2026 | 1 250 |
Word découpe parfois un mot en plusieurs fragments internes — après un passage du correcteur, ou si vous avez modifié la balise caractère par caractère. La recherche ne trouve alors plus rien, sans erreur ni message. Le remède est simple : dans le modèle, supprimez la balise entière et retapez-la d'un seul geste.
L'ébauche VBA : le principe d'automatisation (~10% du code)
Le code ci-dessous montre la mécanique élémentaire : instancier Word en liaison tardive, ouvrir une copie du document et exécuter un remplacement basique sur le corps principal. C'est le squelette théorique (~10% du code réel).
Option Explicit
' Principe théorique : piloter Word depuis Excel pour remplacer un texte
Public Sub RemplirDocument_Extrait()
Dim appWord As Object, doc As Object
Dim modele As String, cle As String, valeur As String
modele = ThisWorkbook.Worksheets("Donnees").Range("B1").Value
cle = "<$Client>"
valeur = ThisWorkbook.Worksheets("Donnees").Range("A4").Text
' Démarrage élémentaire de Word en liaison tardive :
Set appWord = CreateObject("Word.Application")
appWord.Visible = False
Set doc = appWord.Documents.Add(modele)
' Remplacement basique dans le corps du texte :
With doc.Content.Find
.Text = cle
.Replacement.Text = valeur
.Execute Replace:=2 ' 2 = wdReplaceAll
End With
' [ ... Reste du code non exposé : boucle dynamique sur toutes les colonnes,
' remplacement dans les en-têtes et pieds de page, formes et zones de texte,
' gestion des processus Word fantômes, sauvegarde PDF et suivi de révisions ... ]
End Sub
Pourquoi cet extrait ne suffit pas en pratique
Ce code illustre la communication entre Excel et Word. Mais pour générer des devis ou des contrats en production, cet extrait ne résout qu'une fraction du problème :
- Les en-têtes et pieds de page ignorés : l'objet
doc.Contentne cherche que dans le texte courant. Les balises situées dans l'en-tête (numéro de dossier, date, logo) ne sont jamais remplacées et restent visibles. - Les formes et zones de texte invisibles : si votre modèle Word utilise des encadrés ou des zones de texte graphiques, la recherche standard passe complètement à côté.
- Les processus Word fantômes (fuite mémoire) : à la moindre erreur VBA non interceptée,
Word reste actif en arrière-plan sans fenêtre visible. Après quelques essais, des dizaines de processus
WINWORD.EXEsaturent la mémoire et verrouillent vos fichiers en lecture seule. - L'évolution du modèle dans le temps : si le modèle de devis change trois mois plus tard, comment mettre à jour des dizaines de dossiers existants sans écraser les données saisies à la main ? Une macro artisanale est incapable de gérer cela.
Faire un script rapide pour remplacer un mot prend une heure. Faire un générateur documentaire fiable, qui ne bloque jamais Word et gère toutes les zones du document, demande des jours de mise au point.
Le piège des en-têtes et des pieds de page
C'est l'erreur la plus fréquente, et la plus discrète.
doc.Content ne couvre que le corps du texte : les en-têtes,
les pieds de page, les zones de texte et les notes en sont exclus. Une macro qui ne traite
que Content produit un document parfait… avec la balise
<$Client> toujours visible en haut de chaque page.
D'où la double boucle sur Sections, puis sur
Headers et Footers. Un document a
trois en-têtes par section — principal, première page, pages paires — et la boucle
For Each les parcourt tous.
Pour les zones de texte et les formes, il faut une boucle de plus :
Dim forme As Object
For Each forme In doc.Shapes
If forme.TextFrame.HasText Then
forme.TextFrame.TextRange.Find.Execute cle, , , , , , , , , valeur, 2
End If
Next forme
Avant d'enregistrer, cherchez <$ dans le document
produit : s'il en reste, une balise a échappé au traitement. Un simple
If InStr(doc.Content.Text, "<$") > 0 Then MsgBox "…"
vous évitera d'envoyer un devis à moitié rempli.
Enregistrer en PDF, et les cas particuliers
Pour produire directement un PDF, remplacez l'enregistrement par :
doc.ExportAsFixedFormat sortie, 17 ' 17 = wdExportFormatPDF
Pour produire les deux, enchaînez : SaveAs2 puis
ExportAsFixedFormat avec l'extension changée.
Nommer le fichier depuis la ligne plutôt que de saisir B2 à la main :
sortie = ws.Range("B2").Value & "\" & Format(Date, "yyyy-mm-dd") & _
"_devis_" & ws.Cells(ligne, 1).Value & ".docx"
La date en tête, au format année-mois-jour, fait que les fichiers se classent chronologiquement tout seuls dans l'Explorateur.
Traiter toutes les lignes d'un coup : entourez le corps de la macro d'une boucle
For ligne = 4 To derniere, en n'ouvrant Word qu'une fois avant
la boucle et en le fermant après. Lancer et fermer Word à chaque ligne multiplie le temps de
traitement par dix.
Quand le modèle évolue
La macro règle le cas du document neuf. Reste la question qui arrive six mois plus tard : votre modèle de contrat change — une clause, une mention légale, un numéro de TVA — et quarante documents déjà produits portent l'ancienne version.
Les reprendre un par un est hors de question ; les écraser par un nouveau document effacerait tout ce qui a été saisi depuis. La seule voie tenable consiste à rejouer la fusion sur les documents existants en marques de révision Word : les différences apparaissent comme des corrections que vous acceptez ou refusez une par une, avec une sauvegarde horodatée avant intervention.
C'est faisable en VBA — doc.TrackRevisions = True est le point
de départ — mais le diable est dans les détails : conserver les saisies manuelles, gérer les
documents ouverts par un collègue, savoir quels dossiers reprendre. C'est l'une des fonctions
du module que nous vendons, et sans doute celle qui fait gagner le plus de temps sur la durée.
Et si vous ne voulez pas le maintenir vous-même
Le module qui fait tout ce qui précède, fini et éprouvé : aperçu du chemin avant écriture, complétion sans rien écraser, documents types remplis au nom du client, mise à jour en marques de révision quand le modèle change. Code VBA livré ouvert.
Découvrir DossiersLocaux — 19 € à vie → Licence à vie, sans abonnement · Remboursé 30 jours · Windows + Excel 2016 ou plus récentQuestions fréquentes
Faut-il ajouter une référence à la bibliothèque Word ?
Non, et c'est volontaire. Le code utilise la liaison tardive (Dim … As Object, CreateObject) : il fonctionne quelle que soit la version de Word installée sur le poste. Avec une référence figée, le classeur remonte une erreur de compilation dès qu'il change d'ordinateur.
Le modèle peut-il être un .dotx plutôt qu'un .docx ?
Oui, et c'est même plus propre : Documents.Add sur un .dotx est exactement l'usage prévu des modèles Word. Le code ne change pas. Le .docx fonctionne aussi parce que Add en crée une copie au lieu de l'ouvrir.
Comment insérer un logo ou une image variable ?
Placez un signet dans le modèle (Insertion, Signet) puis, depuis VBA, doc.Bookmarks("Logo").Range.InlineShapes.AddPicture chemin. Les images ne passent pas par Rechercher-Remplacer, qui ne traite que du texte.
La macro fonctionne-t-elle si Word est déjà ouvert ?
Oui : GetObject récupère l'instance en cours plutôt que d'en lancer une seconde. Attention en revanche à appWord.Quit, qui fermerait alors le Word de l'utilisateur. En production, mémorisez si vous avez créé l'instance et ne fermez que dans ce cas.
Peut-on faire la même chose avec Excel ou PowerPoint comme modèle ?
Oui, le principe est identique : Workbooks.Add pour Excel, Presentations.Open pour PowerPoint, puis un remplacement de texte. Pour Excel, le remplacement passe par Cells.Replace ; pour PowerPoint, il faut parcourir les formes de chaque diapositive, car il n'existe pas d'équivalent à doc.Content.