🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA Word dans Excel — remplir un modèle, éviter le conflit Range et l'erreur 462

|

VBA Word dans Excel — remplir un modèle, éviter le conflit Range et l'erreur 462

TL;DR — Pour Word, un document est un long fil de caractères, et un Range Word 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 Range dans Excel désigne le Range d'Excel, si bien que Set r = doc.Content échoue sur une Type mismatch (« Incompatibilité de type ») ; un ActiveDocument ou un Selection non 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 Range entre Excel et Word, et comment l'éviter
  • Pourquoi un ActiveDocument non 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