TL;DR — Pour Word, un document est un long fil de caractères, et un
RangeWord n'est qu'une position de début et une position de fin dans ce fil. Vous ne parcourez pas des cellules ; vous décrivez un passage de texte et vous agissez dessus. Le motif qui marche depuis Excel : garder la mise en page dans un modèle Word avec des balises comme{{Client}}, en ouvrir une copie, remplacer les balises par les valeurs de la feuille, enregistrer, fermer, quitter. Trois choses cassent ce motif :Dim r As Rangedans Excel désigne le Range d'Excel, si bien queSet r = doc.Contentéchoue sur une Type mismatch (« Incompatibilité de type ») ; unActiveDocumentou unSelectionnon qualifié crée un lien caché vers Word qui échoue avec l'erreur 462 à la deuxième exécution ; et Rechercher et remplacer refuse un texte de remplacement de plus de 255 caractères. Qualifiez chaque objet Word par vos propres variables, et les trois problèmes disparaissent.
Sub QuickLetter()
Dim wd As Object, doc As Object
Set wd = CreateObject("Word.Application") ' un nouveau Word, invisible
Set doc = wd.Documents.Add(ThisWorkbook.Path & "\Letter.dotx")
doc.Content.Find.Execute FindText:="{{Client}}", _
ReplaceWith:=Range("B2").Value, Replace:=2 ' 2 = wdReplaceAll
doc.SaveAs2 ThisWorkbook.Path & "\Letter_out.docx"
doc.Close
wd.Quit
End Sub
Voici le deuxième article d'une série de trois consacrée au pilotage des autres applications Office depuis
Excel. Le guide PowerPoint traite de la présentation, faite de formes sur des
diapositives. Ici, Word : un flux de texte. Le guide References explique comment
VBA apprend le vocabulaire de l'autre programme, et c'est précisément de là que vient le conflit Range
décrit plus bas. La règle, pour les trois : chaque objet appartient à une application, alors dites
laquelle.
Ce que vous allez apprendre
- Le modèle mental : un document est un fil de texte, et un Range une paire de positions
- Comment démarrer Word, ouvrir un modèle et tout refermer proprement
- Comment remplacer des balises, y compris par un texte de plus de 255 caractères
- Le conflit
Rangeentre Excel et Word, et comment l'éviter - Pourquoi un
ActiveDocumentnon qualifié provoque l'erreur 462 et laisse traîner un WINWORD.EXE - Comment coller un tableau Excel, enregistrer en DOCX et exporter en PDF
Le modèle mental : un fil de texte, pas une grille
Excel désigne une valeur par sa ligne et sa colonne. Word n'a ni lignes ni colonnes, sauf dans les tableaux.
Un document Word est une suite de caractères, marques de paragraphe comprises, et presque tout y est un
Range : une position de début et une position de fin dans cette suite.
| Vous voulez | Expression Word |
|---|---|
| tout le corps du texte | doc.Content |
| un paragraphe | doc.Paragraphs(3).Range |
| un emplacement repéré dans un modèle | doc.Bookmarks("Total").Range |
| la fin du document | doc.Content réduit à sa fin |
Vous agissez sur un range en définissant son .Text, en mettant en forme son .Font ou en le fouillant
avec .Find. Quand vous changez le texte, les positions qui suivent se décalent : voilà pourquoi le code qui
retient des numéros de caractères casse, et pourquoi celui qui cherche des repères tient bon.
Le partage du travail est donc le même qu'avec PowerPoint : Excel détient les données, Word détient la mise en page. Concevez la lettre, le contrat ou le rapport dans Word, sous forme de modèle que les métiers peuvent modifier, et laissez la macro y déposer les valeurs.
Démarrer Word et terminer proprement
Contrairement à PowerPoint, Word démarre un nouvel exemplaire invisible pour CreateObject, comme le
décrit le guide CreateObject. Cet exemplaire vous appartient, le quitter est donc
sans risque. Le danger est inverse : si la macro s'arrête sur une erreur avant wd.Quit, le Word invisible
continue de tourner, et à la prochaine ouverture du modèle Word se plaint qu'il est verrouillé. Placez le
nettoyage là où une erreur l'atteint encore :
Sub MakeLetter()
Const wdExportFormatPDF As Long = 17
Dim wd As Object, doc As Object
On Error GoTo CleanUp
Set wd = CreateObject("Word.Application")
Set doc = wd.Documents.Add(Template:=ThisWorkbook.Path & "\Letter.dotx")
ReplaceTag doc, "{{Client}}", Range("B2").Value
ReplaceTag doc, "{{Amount}}", Format(Range("B3").Value, "#,##0.00")
ReplaceTag doc, "{{Terms}}", Range("B4").Value ' peut etre un long paragraphe
doc.SaveAs2 ThisWorkbook.Path & "\Letter_" & Range("B2").Value & ".docx"
doc.ExportAsFixedFormat OutputFileName:=ThisWorkbook.Path & "\Letter.pdf", _
ExportFormat:=wdExportFormatPDF
CleanUp:
If Not doc Is Nothing Then doc.Close SaveChanges:=False
If Not wd Is Nothing Then wd.Quit
Set doc = Nothing
Set wd = Nothing
If Err.Number <> 0 Then MsgBox "Letter failed: " & Err.Description
End Sub
Documents.Add avec le chemin d'un modèle crée un nouveau document sans titre fondé sur le .dotx : le
modèle lui-même n'est jamais modifié. Le guide On Error explique le saut vers
CleanUp. Si vous voulez voir Word pendant le développement, ajoutez wd.Visible = True juste après l'avoir
créé.
Remplacer les balises, et le mur des 255 caractères
Find.Execute avec Replace:=2 (wdReplaceAll) est la façon rapide de remplacer une balise, et pour des
noms, des dates et des montants, cela suffit. Mais confiez-lui un paragraphe de conditions contractuelles et
il s'arrête sur l'erreur 5854, String parameter too long (paramètre chaîne trop long) : le texte de
remplacement est limité à 255 caractères.
La version robuste trouve chaque balise et écrit le texte directement dans le range trouvé, ce qui n'a aucune limite de longueur :
Sub ReplaceTag(doc As Object, ByVal tag As String, ByVal newText As String)
Const wdFindStop As Long = 0
Const wdCollapseEnd As Long = 0
Dim r As Object ' un range Word, PAS le Range d'Excel
Set r = doc.Content
With r.Find
.ClearFormatting
.Text = tag
.MatchCase = True
.Wrap = wdFindStop
Do While .Execute
r.Text = newText ' r est maintenant la balise trouvee
r.Collapse wdCollapseEnd ' reprendre apres ce que l'on a ecrit
Loop
End With
End Sub
Quand Execute réussit, le range r se déplace sur le texte trouvé : définir r.Text remplace donc
exactement la balise. Le réduire à sa fin permet à la boucle de repartir de là, si bien qu'une valeur qui
contiendrait elle-même la balise n'est pas remplacée une seconde fois. Les balises entre accolades sautent
aux yeux de l'auteur du modèle et ne se confondent jamais avec du vrai texte. Les contrôles de contenu et
les signets de Word fonctionnent aussi, mais les balises simples sont celles que des non-développeurs savent
entretenir.
Le conflit Range : le Range d'Excel n'est pas celui de Word
Les deux programmes ont un objet nommé Range, ainsi que Shape, Font, Border et Selection. Dans le
VBA d'Excel, un Range non qualifié désigne toujours celui d'Excel, parce que la bibliothèque d'Excel passe
avant celle de Word dans l'ordre de priorité. Ceci échoue donc, même avec une référence à Word en place :
Dim r As Range ' Excel.Range
Set r = doc.Content ' Run-time error 13: Type mismatch
La solution consiste à dire de quelle application vous parlez : Dim r As Word.Range avec une référence, ou
Dim r As Object sans référence, comme dans ReplaceTag plus haut. Le guide References
montre l'ordre de priorité qui décide de ce que signifie un nom non qualifié. L'habitude est simple : dans du
code Excel, toute variable qui contient un objet Word est soit Word.Quelquechose, soit Object, jamais un
nom nu.
Erreur 462 : le lien caché d'un ActiveDocument non qualifié
Le second conflit est plus sournois. Avec une référence à la bibliothèque Word en place, Excel vous laisse écrire les noms globaux de Word sans aucun préfixe :
Set wd = New Word.Application
wd.Documents.Add
ActiveDocument.Content.Text = "Hello" ' non qualifie - marche la premiere fois
wd.Quit
La première exécution fonctionne. La deuxième s'arrête sur l'erreur d'exécution 462, The remote server
machine does not exist or is unavailable (le serveur distant n'existe pas ou n'est pas disponible), ou bien
le Gestionnaire des tâches affiche un WINWORD.EXE qui ne disparaît jamais. L'ActiveDocument non qualifié
n'est pas passé par votre variable wd ; VBA a ouvert pour lui sa propre connexion cachée vers Word.
wd.Quit a fermé Word, mais la connexion cachée pointe toujours vers l'exemplaire fermé, et elle n'est
effacée qu'à la réinitialisation du projet VBA.
La règle : atteignez chaque objet Word par une variable que vous avez créée. Écrivez wd.ActiveDocument,
ou mieux, gardez le document dans doc et n'utilisez jamais ni ActiveDocument ni Selection. Le late
binding aide ici : sans référence, un ActiveDocument non qualifié n'est qu'une variable non déclarée, et
Option Explicit l'arrête dès la compilation.
Coller un tableau Excel dans le document
Un tableau déjà mis en forme dans Excel peut entrer dans Word comme un vrai tableau Word, à l'emplacement d'un signet posé par l'auteur du modèle :
Sub PasteTable(doc As Object)
Dim target As Object
ThisWorkbook.Worksheets("Summary").Range("A1:D12").Copy
Set target = doc.Bookmarks("SalesTable").Range
target.PasteExcelTable LinkedToExcel:=False, WordFormatting:=False, RTF:=False
Application.CutCopyMode = False
End Sub
LinkedToExcel:=False produit une simple copie, ce qui convient à une lettre ou un rapport destiné à être
envoyé. Un tableau lié casse dès que le document quitte votre PC. WordFormatting:=False conserve l'aspect
Excel ; passez-le à True pour adopter plutôt le style de tableau du document. Pour une plage qui doit
ressembler exactement à la feuille et ne jamais être modifiée, l'alternative est CopyPicture suivi d'un
collage en image, comme dans le guide PowerPoint.
Dans Word lui-même : le même modèle objet
Si vous avez cherché « VBA Word » parce que vous voulez une macro à l'intérieur de Word, tout ce qui précède
s'applique encore, le pont en moins. Dans l'éditeur VBA de Word, ActiveDocument, Range et Selection
désignent les objets de Word, et il n'y a pas de variable wd par laquelle qualifier. Le modèle du fil de
texte, la boucle Find et la limite des 255 caractères sont identiques. Ce qui change, c'est le sens : vu de
Word, c'est Excel qui devient le programme étranger, et les mêmes règles s'appliquent au Range d'Excel.
Le parti pris : Word pour la mise en page, Excel pour la boucle
Pour une lettre, l'un ou l'autre programme fait l'affaire. Pour deux cents, la décision de conception
compte. Ma règle : la boucle et les données restent dans Excel, la mise en page reste dans un modèle Word,
et la macro ne met jamais en forme un texte qu'elle aurait pu laisser au modèle. Démarrez Word une seule
fois, créez un document par ligne à partir du même .dotx, fermez chacun après l'avoir enregistré, et
quittez à la fin. C'est un publipostage que vous maîtrisez, avec les noms de fichiers, la sortie PDF et la
gestion d'erreurs de votre choix. Le publipostage intégré de Word convient pour imprimer un long document
fusionné ; dès qu'il vous faut un fichier par ligne, la macro l'emporte.
Comment ExcelMaster aide
Les bugs d'automatisation de Word se cachent dans l'espace entre les deux programmes : une incompatibilité de type sur une ligne qui a l'air juste, un WINWORD.EXE qui ne quitte jamais, une clause de contrat trop longue pour être remplacée.
ExcelMaster vous laisse décrire le résultat, par exemple « une lettre par client à partir de mon modèle, enregistrée en PDF au nom du client ». Il écrit la macro avec chaque objet Word qualifié, une boucle de remplacement des balises sans limite de longueur, et un nettoyage qui s'exécute même quand une ligne échoue.
Questions fréquentes
Comment ouvrir un document Word depuis Excel en VBA ?
Créez Word avec CreateObject("Word.Application"), puis appelez wd.Documents.Open avec le chemin du
fichier, ou wd.Documents.Add avec le chemin d'un modèle pour obtenir un nouveau document fondé sur
celui-ci. Gardez le résultat dans une variable et travaillez uniquement par cette variable.
Pourquoi ai-je l'erreur 462 en automatisant Word depuis Excel ?
Votre code a utilisé un objet Word sans le qualifier, le plus souvent ActiveDocument ou Selection, si
bien que VBA a ouvert une connexion cachée vers Word. Après Quit, cette connexion pointe vers un programme
fermé. Atteignez chaque objet Word par votre propre variable wd ou doc.
Pourquoi Dim r As Range donne-t-il une incompatibilité de type avec Word ?
Dans le VBA d'Excel, Range désigne le Range d'Excel. Un range Word est un autre type, donc lui affecter
doc.Content échoue. Déclarez-le en Word.Range avec une référence à Word, ou en Object sans référence.
Comment remplacer un texte de plus de 255 caractères dans Word en VBA ?
Trouvez la balise avec Range.Find.Execute, puis définissez le .Text du range trouvé avec la valeur
longue. La limite de 255 caractères ne s'applique qu'à l'argument ReplaceWith de Rechercher et remplacer,
pas à Range.Text.
Comment enregistrer un document Word en PDF depuis Excel en VBA ?
Appelez doc.ExportAsFixedFormat avec un nom de fichier de sortie et ExportFormat:=17, c'est-à-dire
wdExportFormatPDF. Le document reste ouvert : fermez-le, puis quittez Word.
Testé dans
Testé dans : Excel 365 et Word 365 (Windows 11), VBA 7.1 — vérifié le 02/10/2026.
Guides connexes : VBA PowerPoint · VBA References · VBA CreateObject · VBA Outlook · VBA On Error · VBA Option Explicit · VBA Replace · VBA Enregistrer en PDF
