1. Introduction

Lorsque l'on souhaite faire une recherche dans le contenu d'un document Word, la première idée qui nous traverse l'esprit est de faire une boucle sur tous les objets du document pour trouver celui qui correspond à nos critères. Cette façon de faire n'est à utiliser qu'en dernier recours. Elle est très lente et très gourmande en ressource.
Word possède une fonction de recherche et remplacement intégrée très performante qui peut vous faire gagner du temps, c'est cette fonction que nous allons aborder dans ce tutoriel.

Que vous l'utilisiez pour effectuer une recherche ou un remplacement, c'est toujours la même fonction, seuls les arguments diffèrent.

Elle correspond à la boîte de dialogue Rechercher Remplacer de l'interface graphique. Vous pouvez trouver un tutoriel détaillé sur cette fonction ici : Rechercher Remplacer

Elle peut être utilisée indifféremment sur un objet Selection ou sur objet Range. Dans les exemples, je n'utiliserai cette fonction que sur des objets Selection qui englobent la majorité des besoins.

Un objet Range représente une portion du document qui peut être l'intégralité du document tandis qu'un objet Selection représente le texte que l'on peut sélectionner à l'aide de la souris.

Pour les exemples, j'ai simplement utilisé un EasterEgg afin de remplir mes pages de textes. Si vous n'en avez jamais utilisé, c'est très simple, vous saisissez au clavier : =lorem(10,10) suivi de Entrée, votre page sera remplie par 10 paragraphes et de 10 phrases par paragraphe contenant Lorem ipsum...

2. Rechercher - Remplacer

L'objet Find peut être utilisé avec un objet Range ou un objet Selection, il permet de faire une recherche et d'effectuer le cas échéant un remplacement.

Sur une sélection (Selection)
Sélectionnez

Selection.Find.Execute FindText:="moi"
Sur une plage (Range)
Sélectionnez

Dim myR As Range

Set myR = ActiveDocument.StoryRanges(wdMainTextStory)
myR.Find.Execute FindText:="moi"

Que ce soit sur une plage ou sur une sélection, l'utilisation reste la même. Cependant, l'utilisation sur une plage ne permet pas de manipuler le résultat de la recherche, si vous souhaitez manipuler le résultat de la recherche, vous devez l'utiliser sur un objet Selection.

Cette fonction de recherche n'est pas la meilleure solution pour atteindre un point précis de votre document. Pour atteindre un point précis, je préfère utiliser la fonction GoTo ou encore les signets ("Bookmarks") qui sont plus facile à manipuler.

Nous allons l'aborder sous deux utilisations différentes, l'une en ligne et l'autre en bloc. Les résultats obtenus sont identiques, seules les possibilités d'utilisation et l'écriture du code diffèrent.

2-A. En Ligne

Pour l'utilisation en ligne, les arguments sont utilisés sur la même ligne que la fonction.

En ligne
Sélectionnez

Selection.Find.Execute FindText:="moi", Forward:=True

2-B. En Bloc

Pour l'utilisation en bloc, il est plus facile de faire appel à l'instruction With, qui permet l'application d'une série d'instructions à un objet.

En bloc
Sélectionnez

With Selection.Find
    .Text = "moi"
    .Forward = True
End With

Cette écriture est équivalente à :

 
Sélectionnez

Selection.Find.Text = "moi"
Selection.Find.Forward = True

Il est plus facile d'écrire et de lire le code lorsque l'on utilise l'instruction "With [...] End With".

2-C. Propriétés

Les propriétés détaillées dans ce tutoriel ne sont pas exhaustives. Seules les plus courantes sont détaillées.

Certaines options sont incompatibles entre elles, par exemple, rechercher en tenant compte de la casse est incompatible avec une recherche sur toutes les formes d'un mot.

Certaines propriétés sont persistantes entre deux utilisations, c'est le cas de la recherche pour toutes les formes d'un mot, si vous passez cette propriété à True, elle le restera pour toutes les autres utilisations. Vous devrez pour ne pas fausser le résultat, modifier la valeur de cette propriété. C'est le cas pour la recherche sur toutes les formes d'un mot.

2-C-1. Font

Permet de spécifier la police de caractères à rechercher. Comme c'est l'objet Font qui est utilisé, toutes les propriétés de cette police peuvent être utilisées.

Font
Sélectionnez
Selection.HomeKey unit:=wdStory

    With Selection.Find
        .ClearFormatting
        With .Font
            .Bold = True
            .Name = "Arial"
        End With
        .Forward = True
        .Text = "auctor"
        .Execute
        Debug.Print .Found
    End With

Dans ce code, nous recherchons le mot "auctor" qui est écrit en gras et en Arial. Le Debug.Print devant la propriété .Found permet d'afficher le résultat de la recherche dans la fenêtre d'exécution.

Le Debug.Print inséré devant la méthode .Execute aurait eu le même résultat. La seule différence est que .Found peut être utilisé un grand nombre de fois, alors que .Execute lancera la recherche chaque fois qu'elle sera appelée.

2-C-2. Format

Cette propriété spécifie si le format du texte doit être pris en compte pour exécuter la recherche. Si l'on prend l'exemple précédent, cette propriété doit être placée après le .Font, placée avant, elle n'aura aucun effet.

Si elle est utilisée avec une valeur False, le format ne sera pas pris en compte.

Format
Sélectionnez
Selection.HomeKey unit:=wdStory

    With Selection.Find
        .ClearFormatting
        With .Font
            .Bold = True
            .Name = "Arial"
        End With
        .Format = True
        .Forward = True
        .Text = "auctor"
        .Execute
        Debug.Print .Found
    End With

Elle est surtout intéressante si vous souhaitez dialoguer avec l'utilisateur pour prendre ses choix en compte.

2-C-3. Forward

Cette propriété indique à la fonction si la recherche doit se faire du début à la fin du document ou inversement. La valeur par défaut est True.

Forward
Sélectionnez
With Selection.Find
    .Forward = True
    .Text = "auctor"
    .Execute
End With

Si vous souhaitez commencer la recherche par le début du document, vous devrez insérer :
Selection.HomeKey Unit:=wdStory

2-C-4. Found

Cette propriété est très importante si vous souhaitez utiliser le résultat de votre recherche. C'est le cas si vous effectuez une boucle basée sur ce résultat.

Found
Sélectionnez
    With Selection.Find
        .ClearFormatting
        .Forward = True
        .Text = "auctor"
        .Execute
        Debug.Print .Found
    End With

Si la recherche est fructueuse, vous aurez l'affichage True dans la fenêtre d'exécution (Debug.Print .Found).

2-C-5. Highlight

Permet de rechercher un texte surligné lors qu'elle est à True.

Highlight
Sélectionnez
    With Selection.Find
        .ClearFormatting
        .Highlight = True 'Recherche d'un texte surligné
        .Forward = True
        .Text = "auctor"
        .Execute
        Debug.Print .Found
    End With

Image non disponible

Dans l'exemple ci-dessus, c'est ce mot surligné en rouge qui sera trouvé par la recherche.

2-C-6. IgnorePunct

Cette propriété lorsqu'elle est True permet d'ignorer la ponctuation dans une recherche. Si le texte recherché se trouve dans le document mais séparé par un signe de ponctuation, il sera trouvé.

IgnorePunct
Sélectionnez
    With Selection.Find
        .ClearFormatting
        .IgnorePunct = True
        .Forward = True
        .Text = "sapien auctor"
        .Execute
        Debug.Print .Found
    End With

Dans l'exemple ci-dessus, les textes suivants seront trouvés par la recherche : "sapien auctor" ainsi que "sapien. auctor", bien que ces deux mots soient séparés dans le second cas par un signe de ponctuation.

2-C-7. IgnoreSpace

Cette propriété permet de rechercher des expressions dans un document, même si elles contiennent un ou plusieurs espaces consécutifs.

IgnorePunct
Sélectionnez
    With Selection.Find
        .ClearFormatting
        .IgnoreSpace = True
        .Forward = True
        .Text = "sapienauctor"
        .Execute
        Debug.Print .Found
    End With

Dans l'exemple ci-dessus, le texte suivant sera trouvé par la recherche : "sapien auctor".

2-C-8. LanguageID

Permet de limiter la recherche à une langue. Cette propriété prend comme argument une constante wdLanguageId.

IgnorePunct
Sélectionnez
    With Selection.Find
        .ClearFormatting
        .LanguageId = wdBelgianDutch
        .Forward = True
        .Text = "sapienauctor"
        .Execute
        Debug.Print .Found
    End With

Pour certaines langues, il est important d'identifier clairement la langue d'édition. Pour la Belgique, nous avons wdBelgianDutch et wdBelgianFrench qui sont tous deux différents de wdDutch et wdFrench.

2-C-9. MatchAllWordForms

Propriété très intéressante. Elle permet de trouver toutes les formes d'un même mot. Prenons l'exemple de cheval qui au pluriel devient chevaux. Si cette propriété est utilisée, lors de la recherche de "cheval", "chevaux" sera également trouvé.

MatchAllWordForms
Sélectionnez
    With Selection.Find
        .ClearFormatting
        .MatchAllWordForms = True
        .Forward = True
        .Text = "cheval"
        .Execute
        Debug.Print .Found
    End With

C'est valable pour les pluriels, les formes conjuguées d'un verbe, si vous recherchez "être", vous trouverez toutes ses formes conjuguées : "suis", "es"…

Dans l'interface graphique il est précisé que cette option ne fonctionne que pour la langue anglaise, mais il n'en est rien, elle fonctionne aussi en français, mais pas efficacement.

Alors que cette propriété fonctionne très bien pour l'anglais, ses résultats sont très mitigés pour la langue française.

2-C-10. MatchCase

Cette propriété permet la distinction entre les majuscules et les minuscules.

MatchCase
Sélectionnez
    With Selection.Find
        .ClearFormatting
        .MatchCase = True
        .Forward = True
        .Text = "Cheval"
        .Execute
        Debug.Print .Found
    End With

Dans cet exemple, seul Cheval écrit avec une majuscule sera trouvé.

2-C-11. MatchPhrase

Cette propriété permet de retrouver une phrase en omettant les signes de ponctuation, les espaces...

MatchPhrase
Sélectionnez
    With Selection.Find
        .ClearFormatting
        .MatchPhrase = True
        .Forward = True
        .Text = "un animal qui appartient"
        .Execute
        Debug.Print .Found
    End With

Dans l'exemple ci-dessus, votre recherche aboutira aussi pour "un animal, qui appartient".

2-C-12. MatchSoundsLike

La traduction de cette propriété est "sonne comme", ce qui signifie que l'on va retrouver les homophones du texte.

MatchSoundsLike
Sélectionnez
    With Selection.Find
        .ClearFormatting
        .MatchSoundsLike = True
        .Forward = True
        .Text = "home"
        .Execute
        Debug.Print .Found
    End With

Dans la phrase "Cet homme habite ce home", seront trouvés "homme" et "home".

Dans l'interface graphique il est précisé que cette option ne fonctionne que pour la langue anglaise, mais il n'en est rien, elle fonctionne aussi en français, mais les résultats sont assez décevant pour le français.

2-C-13. MatchWholeWord

Cette option va limiter la recherche au mot entier, les portions de mots seront ignorées.

MatchSoundsLike
Sélectionnez
    With Selection.Find
        .ClearFormatting
        .MatchWholeWord = True
        .Forward = True
        .Text = "hom"
        .Execute
        Debug.Print .Found
    End With

Dans la phrase "Cet homme habite ce home", la recherche sera infructueuse.

2-C-14. MatchWildcards

Si vous souhaitez utiliser des caractères génériques dans vos recherches, cette propriété doit être True.

Le plus connu de ces caractères génériques est l'étoile "*". Ce caractère représente, lorsqu'il est utilisé, un ou plusieurs caractères.

Si vous utilisez pour votre recherche "i*m", vous obtiendrez comme résultat : ipsum; icies, purus lectus m… En fait, toutes les combinaisons possibles dans votre document commençant par un "i" et se terminant par un "m", que ces lettres soient ou non dans un même mot. Au point que si vous prenez la première et la dernière lettre de votre texte, vous aurez un résultat contenant tout votre texte.

MacthWildcards
Sélectionnez
    With Selection.Find
        .Text = "i*m"
        .Forward = True
        .MatchWildcards = True
        .Execute
    End With

Si cette propriété n'est pas True, pour la même recherche, les seuls résultats qui seront fructueux seront les mots de trois lettres suivants : "i*m".

2-C-15. NoProofing

Cette propriété, lorsqu'elle est True, ignore dans la recherche les mots trouvés fautifs par le vérificateur d'orthographe ou de grammaire.

NoProofing
Sélectionnez
    With Selection.Find
        .Text = "i*m"
        .Forward = True
        .NoProofing = True
        .Execute
    End With

2-C-16. ParagraphFormat

Permet de faire une recherche sur des propriétés précises d'un paragraphe comme son niveau, son espacement…

ParagraphFormat
Sélectionnez
    With Selection.Find
        .Forward = True
        .ParagraphFormat.OutlineLevel = wdOutlineLevel3    'Recherche sur un niveau 3
        .Execute
    End With

Si vous exécutez une recherche sur un format de paragraphe, la propriété .Text peut être omise.

2-C-17. Replacement

Cette propriété permet, lorsqu'elle est utilisée, de remplacer le mot recherché par celui qui lui est passé en argument. Cette propriété peut en recevoir d'autres en argument.

Si vous souhaitez que la police du mot trouvé change, c'est en argument que vous devez le spécifier.

Replacement
Sélectionnez
    With Selection.Find
        .Text = "Mon texte à chercher"
        .Replacment.Text = "Mon texte de remplacement"
        .ClearFormating
        .Execute
    End With

Si dans votre remplacement, vous souhaitez modifier le format du texte, le surligner en rouge, c'est avec cette propriété que vous devez le faire.

2-C-18. Style

Style permet de faire une recherche sur une portion de texte avec un style précis.

Style
Sélectionnez
    With Selection.Find
        .Text = "auctor"
        .Style = "Normal"
        .Forward = True
        .NoProofing = True
        .Execute
    End With

2-C-19. Text

Cette propriété reçoit comme argument le texte qui sera recherché.

Text
Sélectionnez
    With Selection.Find
        .Text = "auctor"
        .Forward = True
        .NoProofing = True
        .Execute
    End With

2-C-20. Wrap

Cette propriété permet de définir si la recherche n'a pas commencé au début du document, si elle doit reprendre dès le début quand la fin du texte est atteinte.

Wrap
Sélectionnez
.Wrap = wdFindStop

Cette propriété peut prendre trois valeurs en argument wdFindStop, wdFindAsk et wdFindcontinue qui auront comme résultat l'arrêt à la fin du document, une demande à l'utilisateur ou continuer depuis le début.

2-D. Méthodes

Comme pour les propriétés, la liste des méthodes n'est pas exhaustive, seules deux méthodes sont abordées.

Si vous souhaitez lancer la recherche par le début du document, vous devez déplacer la sélection vers le début de votre document avec :
Selection.HomeKey Unit:=wdStory

2-D-1. ClearFormatting

Cette méthode est utilisée pour supprimer le formatage du texte de la recherche ou du remplacement.

ClearFormatting
Sélectionnez
Selection.HomeKey unit:=wdStory

    With Selection.Find
        .ClearFormatting
        With .Font
            .Bold = True
            .Name = "Arial"
        End With
        .Forward = True
        .Text = "auctor"
        .Execute
        Debug.Print .Found
    End With

Dans l'exemple ci-dessus, nous cherchons un texte qui serait écrit avec la police de caractère Arial.

Si nous lançons une seconde recherche :

ClearForamtting
Sélectionnez
Selection.HomeKey unit:=wdStory

    With Selection.Find
        .ClearFormatting
        With .Font
            .Italic = True
        End With
        .Forward = True
        .Text = "auctor"
        .Execute
        Debug.Print .Found
    End With

La recherche ne sera fructueuse que pour le mot "auctor" qui sera écrit en Arial gras et italique. Les paramètres de formatage de la recherche précédente restent en "mémoire" et faussent le résultat. En utilisant .ClearFormatting, vous "videz la mémoire".

Cette méthode doit être utilisée tant pour la recherche que pour le remplacement.

ClearFormatting
Sélectionnez
With Selection.Find
    .ClearFormatting
    .Replacement.ClearFormatting
End With
….
….
….

2-D-2. Execute

Cette méthode est la plus importante. Sous Word 2010 et 2007 on retrouve une méthode Execute2007 qui est semblable à la méthode Execute.

Elle va exécuter la recherche demandée. Cette méthode renvoie True si la recherche est couronnée de succès. Avec cette méthode, vous pouvez passer directement les arguments à la fonction.

Find.Execute
Sélectionnez
Sub RechercherUnMot()
    MsgBox Selection.Find.Execute (FindText:="Olivier")
End Sub

Si votre texte contient le mot "Olivier", vous aurez une boîte de message avec comme texte "True".

Elle peut prendre un argument qui est important dans le cas d'un remplacement.

Argument de la focntion Execute
Sélectionnez
With Selection.Find
    .Text = "Moi"
    .Replacement.Text = "Toi"
    .Execute Replace:=wdReplaceAll
End With

En argument, si vous souhaitez faire un remplacement, vous devrez utiliser : Replace. Elle peut recevoir trois valeurs, qui sont des constantes : wdReplaceAll; wdReplaceOne et wdReplaceNone.

3. En pratique

Nous allons simplement couvrir quelques possibilités concernant l'utilisation de la méthode de recherche.

3-A. Recherche et remplacement d'une liste de mots

La recherche d'une liste de mots va se faire sur la base d'une boucle et sur le résultat renvoyé par la recherche.

Dans cet exemple, la liste des mots sera contenue dans un tableau Word composé de deux colonnes, la première contenant les mots à rechercher et la seconde contenant les mots de remplacement.

La fonction située ci-dessous sert à supprimer les deux caractères présents lorsque l'on extrait du texte d'une cellule.

Fonction de nettoyage
Sélectionnez
Function NetText(stTemp As String) As String
'-------------------------------------------------
'Fonction de nettoyage
'Supprime les deux caractères de fin de cellule
'-------------------------------------------------
NetText = Left(stTemp, Len(stTemp) - 2)

End Function

Nous l'utiliserons dans notre procédure pour obtenir les mots recherchés et les mots de remplacement.

3-A-1. La procédure de recherche et remplacement.

Dans un premier temps, nous allons ouvrir les deux documents, le premier contenant la liste des mots à rechercher (tableau à deux colonnes) et le second étant celui dans lequel nous souhaitons faire les remplacements.

Pour ouvrir les documents, au lieu de les mettre en "dur" dans le code, nous allons utiliser un objet "FileDialog". Cet objet permet de sélectionner un répertoire ou un fichier. Dans notre exemple, nous allons l'utiliser pour les fichiers. Ce choix s'obtient par l'argument passé lors de l'affectation.

FileDialog
Sélectionnez
Set oDlg = Application.FileDialog(msoFileDialogFilePicker)

Pour afficher cette boîte de dialogue, nous allons utiliser sa méthode ".Show".

Comme il s'agit d'un échange avec l'utilisateur, nous avons la possibilité de choisir un titre pour la boîte de dialogue et nous n'avons besoin que d'un seul fichier.

FileDialog
Sélectionnez
With oDlg
    'Pour un seul fichier la valeur sera False
    .AllowMultiSelect = False
    .Title = "Document contenant le tableau"
    .Show
End With

Cet objet va renvoyer le nom du fichier choisi par l'utilisateur. Comme il n'y a qu'un seul fichier, nous récupérons le premier élément.

Choix du fichier
Sélectionnez
oDlg.SelectedItems(1)

Il n'est pas nécessaire de passer par une variable, nous pouvons directement utiliser le résultat en argument.

Que ce soit pour le document source ou le document cible, la méthode d'ouverture du document est toujours la même.

Ouverture des documents
Sélectionnez
Set oDocSource = Documents.Open(oDlg.SelectedItems(1))

Il ne nous reste que la boucle sur les éléments du tableau qui seront utilisés pour la recherche et le remplacement. On affecte le premier tableau du document source à la variable tableau pour ensuite faire une boucle sur les lignes du tableau. Dans notre cas, c'est assez simple, la première colonne contient le mot à rechercher et la seconde, le mot de remplacement.

Boucle sur le tableau
Sélectionnez
Set oTbl = oDocSource.Tables(1)
'Boucle sur les cellules de la table
For Each oRow In oTbl.Rows
        'Sélection du document cible
        oDocCible.Select
            Selection.HomeKey unit:=wdStory
            With Selection.Find
                .ClearFormatting
                .Forward = True
                .Text = NetText(oRow.Cells(1).Range.Text)   'utilisation de notre fonction
                .Replacement.Text = NetText(oRow.Cells(2).Range.Text)   'utilisation de notre fonction
                .Replacement.ClearFormatting
                .Execute Replace:=wdReplaceAll
            End With
    
Next oRow

Dans cette boucle, nous utilisons directement le résultat dans notre fonction de recherche et remplacement.

Recherche et remplacement
Sélectionnez
            With Selection.Find
                .ClearFormatting
                .Forward = True
                .Text = NetText(oRow.Cells(1).Range.Text)   'utilisation de la fonction de nettoyage
                .Replacement.Text = NetText(oRow.Cells(2).Range.Text)   'utilisation de la fonction de nettoyage
                .Replacement.ClearFormatting
                .Execute Replace:=wdReplaceAll
            End With

Voici le code complet :

Procédure de remplacement
Sélectionnez
Sub RemplacerListeDeMots()
'-------------------------------------------------
'Cette macro a pour rôle de remplacer les mots d'un
' document par une liste de
'mots se trouvant dans une table à deux colonnes
'-------------------------------------------------
'Déclaration des variables
'Le document oDocSource , contient la
'liste des mots et le document oDocCible les mots
'à remplacer
Dim oDocSource As Document, oDocCible As Document
'Déclaration des variables table
Dim oTbl As Table
Dim oRow As Row
'Une boîte de dialogue pour choisir les documents
Dim oDlg As FileDialog

'Ouverture du premier document
'Affectation de l'objet oDlg
Set oDlg = Application.FileDialog(msoFileDialogFilePicker)
'Ouverture de la boîte de dialogue
With oDlg
    .AllowMultiSelect = False
    .Title = "Document contenant le tableau"
    .Show
End With
'La propriété SelectedItems contient
Set oDocSource = Documents.Open(oDlg.SelectedItems(1))
'Il faut répéter l'opération une seconde fois pour le
'document cible
With oDlg
    .AllowMultiSelect = False
    .Title = "Document avec remplacement"
    .Show
End With
'ouverture du second document
Set oDocCible = Documents.Open(oDlg.SelectedItems(1))
'Affectation de la table
Set oTbl = oDocSource.Tables(1)
'Boucle sur les cellules de la table
For Each oRow In oTbl.Rows
        'Sélection du document cible
        oDocCible.Select
            Selection.HomeKey unit:=wdStory
            With Selection.Find
                .ClearFormatting
                .Forward = True
                .Text = NetText(oRow.Cells(1).Range.Text)   'utilisation de notre fonction
                .Replacement.Text = NetText(oRow.Cells(2).Range.Text)   'utilisation de notre fonction
                .Replacement.ClearFormatting
                .Execute Replace:=wdReplaceAll
            End With
    
Next oRow
'Libération des objets
Set oDlg = Nothing
Set oTbl = Nothing
oDocSource.Close savechanges:=wdDoNotSaveChanges
Set oDocSource = Nothing


End Sub

Ces deux codes sont à placer dans le Normal.Dotm pour qu'ils soient disponibles pour toutes vos recherches. La fonction de nettoyage des caractères de fin de cellule peut être réutilisée dans d'autres codes.

3-B. Recherche dans plusieurs documents situés dans un répertoire

Le travail sur des documents contenus dans un répertoire n'est pas plus compliqué.

Pour intervenir sur les fichiers et les répertoires, j'utilise la bibliothèque Microsoft Scripting Runtime. Si vous souhaitez en apprendre un peu plus sur cette bibliothèque, je vous conseille de lire ce tutoriel : Manipulation des fichiers en VBA.

Ce que nous allons faire est une pseudo d'indexation d'un mot dans les fichiers d'un répertoire.

La première étape est l'ajout de la bibliothèque Microsoft Scripting Runtime qui permet de travailler sur les fichiers et les répertoires. Nous pourrons alors faire une boucle sur les fichiers d'un répertoire.

Image non disponible

Image non disponible

Image non disponible

Cette étape peut être ignorée si l'on utilise le LateBinding. L'utilisation de l'EarlyBinding permet de profiter de l'intellisense. L'intellisense est une fonctionnalité de l'éditeur VBE qui affiche pour chaque objet une liste déroulante contenant les propriétés ou méthodes disponibles. Elle nous permet d'éliminer ou de diminuer les erreurs dans la saisie du code. Tous les exemples sont basés sur le EarlyBinding.

Les mots que nous allons rechercher dans les documents d'un répertoire sont stockés dans une table qui ne contient qu'une colonne. Chaque mot étant dans une cellule.

Table contenant les mots à rechercher
Sélectionnez
Set oDocSource = Documents.Open(FileName:="C:\Users\Oliver\Documents\Word\Forum\Tuto\listemots.docm")

...

'Affectation de la table qui contient les mots à rechercher.
Set oTbl1 = oDocSource.Tables(1)

Il est plus facile de travailler avec un objet table qu'avec un document. Cet objet table sera affecté à la variable oTbl1 et le résultat de la recherche sera stocké dans une table créée dans un nouveau document.

Ajout d'un nouveau document contenant une table
Sélectionnez
'Affectation du document qui recevra le résultat de la recherche
Set oDocCible = Documents.Add

'Affectation de la table qui recevra les résultats
Set oTbl2 = oDocCible.Tables.Add(Range:=Selection.Range, numrows:=1, numcolumns:=3)
'Titres des colonnes de la table
With oTbl2.Rows(1)
    .Cells(1).Range.Text = "Mots"
    .Cells(2).Range.Text = "Page"
    .Cells(3).Range.Text = "Fichier"
End With

Le code ci-dessus permet d'ajouter un "titre" aux colonnes.

Nous allons faire la recherche sur tous les fichiers d'un répertoire, nous avons besoin de récupérer le chemin de ce répertoire. Pour y parvenir, nous utiliserons un objet FileDialog.

Récupération du répertoire
Sélectionnez
Set oDlg = Application.FileDialog(msoFileDialogFolderPicker)
'Affichage de la boîte de dialogue
oDlg.Show

...

'Affectation du répertoire
Set oFol = oFso.GetFolder(oDlg.SelectedItems(1))

Le résultat de l'objet FileDialog est utilisé pour affecter un répertoire à l'objet File System Object.

Nous utiliserons deux objets de cette "bibliothèque", le premier est l'objet Folder et le second l'objet File, qui sont respectivement les objets Répertoire et Fichier

Nous allons faire une boucle sur les fichiers d'un répertoire choisi par l'utilisateur. Pour ce choix, nous allons utiliser un objet FileDialog, mais contrairement à l'exemple précédent, nous n'allons pas récupérer le nom d'un fichier mais celui d'un répertoire.

Boucle sur les fichiers d'un répertoire
Sélectionnez
For Each oFil In oFol.Files

'Traitement de nos fichiers

Next oFil

Dans cette boucle, nous allons traiter un par un les fichiers. Comme nous ne traitons que les fichiers Word, nous allons tester les extensions des fichiers pour n'utiliser que les "doc", "docx" et "docm". Les autres fichiers seront simplement ignorés.

Tri sur les documents
Sélectionnez
If Right(oFil.Name, 4) = "docm" Or Right(oFil.Name, 4) = "docx" Or Right(oFil.Name, 3) = "doc" Then
…
End If

Si nous sommes en présence d'un document, nous allons le traiter, la première opération sera l'ouverture du document.

Après ouverture du document, nous allons lancer la recherche pour chaque mot contenu dans la table. Nous allons faire une boucle pour chaque élément de la table et pour chaque élément récupéré, une boucle de recherche.

Boucle sur la table contenant les mots
Sélectionnez
'Première boucle sur les éléments de la table
        For Each oRw In oTbl1.Rows
            'Pour chaque mot, retour au début du document
            Selection.HomeKey unit:=wdStory
            'seconde boucle sur la recherche
            Do
            'Recherche
            With Selection.Find
                'Récupération du mot de la liste
                .Text = NetText(oRw.Cells(1).Range.Text)
                .Execute
                'Affectation du résultat de la recherche à une variable
                boofound = .Found
            End With
                'si la recherche est fructueuse
                If boofound Then
                    Debug.Print oFil.Path & " - " & NetText(oRw.Cells(1).Range.Text) & " - " & Selection.Information(wdActiveEndPageNumber)
                    'Ajout d'une ligne à la table
                    oTbl2.Rows.Add
                    'Utilisation du range de la nouvelle ligne de la table
                    With oTbl2.Rows(oTbl2.Rows.Count)
                        'Remplissage de la table
                        .Cells(1).Range.Text = NetText(oRw.Cells(1).Range.Text)
                        .Cells(2).Range.Text = Selection.Information(wdActiveEndPageNumber)
                        .Cells(3).Range.Text = oFil.Path
                    End With
                End If
        
            'test de sortie de boucle
            Loop While boofound
        
        Next oRw

Pour chaque mot, nous devons repositionner la Selection au début du document avec Selection.HomeKey unit:=wdStory. La récupération des mots contenus dans la table passe par un nettoyage de la chaîne de caractères. Chaque cellule d'une table Word contient deux caractères supplémentaires qu'il faut éliminer. Pour ce nettoyage, j'ai une petite fonction NetText qui élimine ces deux derniers caractères.

Ensuite, c'est une recherche normale dans le document. Comme nous souhaitons récupérer le résultat de la recherche, nous allons faire une boucle et tant que la recherche est fructueuse, nous l'exécutons.

Boucle de recherche
Sélectionnez
            Do
….
            'test de sortie de boucle
            Loop While boofound

Le résultat est testé en fin de boucle. Si le mot n'est pas trouvé, la recherche s'arrête pour passer au mot suivant.

Recherche fructueuse
Sélectionnez
                'si la recherche est fructueuse
                If boofound Then
                    'Ajout d'une ligne à la table
                    oTbl2.Rows.Add
                    'Utilisation du range de la nouvelle ligne de la table
                    With oTbl2.Rows(oTbl2.Rows.Count)
                        'Remplissage de la table
                        .Cells(1).Range.Text = NetText(oRw.Cells(1).Range.Text)
                        .Cells(2).Range.Text = Selection.Information(wdActiveEndPageNumber)
                        .Cells(3).Range.Text = oFil.Path
                    End With
                End If

Si le mot a été trouvé, nous ajoutons une ligne à notre table et insérons dans cette ligne le résultat : mot, page et nom du document. Avant d'ajouter une ligne, nous vérifions le résultat de la recherche. Ce test est nécessaire pour une raison simple : sans test, quelque soit le résultat, la boucle sera exécutée et la ligne ajoutée "If boofound Then".

Voilà le code complet avec la fonction de nettoyage :

Recherche dans les fichiers d'un répertoire
Sélectionnez
Sub BoucleSurRepertoire()
'Déclaration des variables
Dim oFso As FileSystemObject
Dim oFol As Folder
Dim oFil As File
Dim oDlg As FileDialog
Dim stFolder As String
'Deux document, un qui recevra le résultat et un dans lequel
'la recherche sera exécutée
'La liste des mots à trouver sera dans le doc cible sous
'la forme d'une table
Dim oDocSource As Document, oDocCible As Document, oDocTrv As Document
Dim oTbl1 As Table, oTbl2 As Table
Dim oRw As Row
Dim boofound As Boolean

'Affectation des variables
Set oFso = New FileSystemObject
Set oDlg = Application.FileDialog(msoFileDialogFolderPicker)
'Affichage de la boîte de dialogue
oDlg.Show

'Affectation du document contenant la liste
Set oDocSource = Documents.Open(FileName:="C:\Users\Oliver\Documents\Word\Forum\Tuto\listemots.docm")

'Affectation du document qui recevra le résultat de la recherche
Set oDocCible = Documents.Add

'Affectation de la table qui recevra les résultats
Set oTbl2 = oDocCible.Tables.Add(Range:=Selection.Range, numrows:=1, numcolumns:=3)
'Titres des colonnes de la table
With oTbl2.Rows(1)
    .Cells(1).Range.Text = "Mots"
    .Cells(2).Range.Text = "Page"
    .Cells(3).Range.Text = "Fichier"
End With

'Affectation de la table qui contient les mots à rechercher.
Set oTbl1 = oDocSource.Tables(1)

'Affectation du répertoire
Set oFol = oFso.GetFolder(oDlg.SelectedItems(1))


For Each oFil In oFol.Files

    'Test pour ne traiter que les documents et ignorer les autres fichiers
    If Right(oFil.Name, 4) = "docm" Or Right(oFil.Name, 4) = "docx" Or Right(oFil.Name, 3) = "doc" Then
        'ouverture des fichiers
        Set oDocTrv = Documents.Open(oFil.Path)
        'selection du fichier
        oDocTrv.Select
        'boucle sur la table contenant les mots
        For Each oRw In oTbl1.Rows
            'Pour chaque mot, retour au début du document
            Selection.HomeKey unit:=wdStory
            'boucle sur la recherche
            Do
            'Recherche
            With Selection.Find
                'Récupération du mot de la liste
                .Text = NetText(oRw.Cells(1).Range.Text)
                .Execute
                'Affectation du résultat de la recherche à une variable
                boofound = .Found
            End With
                'si la recherche est fructueuse
                If boofound Then
                    Debug.Print oFil.Path & " - " & NetText(oRw.Cells(1).Range.Text) & " - " & Selection.Information(wdActiveEndPageNumber)
                    'Ajout d'une ligne à la table
                    oTbl2.Rows.Add
                    'Utilisation du range de la nouvelle ligne de la table
                    With oTbl2.Rows(oTbl2.Rows.Count)
                        'Remplissage de la table
                        .Cells(1).Range.Text = NetText(oRw.Cells(1).Range.Text)
                        .Cells(2).Range.Text = Selection.Information(wdActiveEndPageNumber)
                        .Cells(3).Range.Text = oFil.Path
                    End With
                End If
        
            'test de sortie de boucle
            Loop While boofound
        
        Next oRw
        'Fermeture du document dans lequel nous effectuons la recherche
        oDocTrv.Close
    End If
Next oFil


Set oTbl1 = Nothing
Set oTbl2 = Nothing
oDocSource.Close
Set oDocSource = Nothing



Set oDlg = Nothing
Set oFol = Nothing
Set oFso = Nothing



End Sub

Function NetText(stTemp As String) As String
'Fonction de nettoyage
'Supprime les deux derniers caractères de la cellule
NetText = Left(stTemp, Len(stTemp) - 2)

End Function

4. Remerciements

Un grand merci à l'équipe Office et aux relecteurs orthographiques et plus particulièrement Jacques Thery.