Votre Partenaire en Solutions Numériques, Formation et Assistance
Explorez les techniques VBA avancées pour une automatisation et une personnalisation poussées de Microsoft Word.
Bienvenue dans ce cours avancé de VBA pour Microsoft Word. Ce module est conçu pour les utilisateurs ayant déjà une solide compréhension des bases de VBA et souhaitant explorer des techniques plus complexes pour automatiser et personnaliser Word.
Document
, Selection
, Range
, Paragraph
, Table
).On Error Resume Next
).Ce module explore plus en profondeur le modèle objet de Word, en se concentrant sur des objets et collections moins courants mais puissants.
Application
: propriétés et méthodes globales.Find
et Replacement
: recherches et remplacements complexes.
' Exemple de recherche avancée
Sub AdvancedFind()
Dim rng As Range
Set rng = ActiveDocument.Content
With rng.Find
.ClearFormatting
.Text = "mot spécifique"
.Font.Bold = True ' Chercher uniquement le mot en gras
.Replacement.ClearFormatting
.Replacement.Text = "nouveau mot"
.Replacement.Font.Italic = True
.Execute Replace:=wdReplaceAll, Forward:=True, Wrap:=wdFindContinue
End With
End Sub
HeaderFooter
).Shape
et InlineShape
pour les graphiques et images.ContentControl
) : les manipuler par VBA.Collection
.
Sub MyCustomCollection()
Dim colNames As New Collection
Dim i As Long
colNames.Add "Alice"
colNames.Add "Bob", "Person2" ' Ajout avec une clé
colNames.Add "Charlie"
MsgBox "Nombre d'éléments : " & colNames.Count
MsgBox "Premier élément : " & colNames(1)
MsgBox "Élément avec clé 'Person2' : " & colNames("Person2")
For i = 1 To colNames.Count
Debug.Print colNames(i)
Next i
End Sub
Scripting.Dictionary
: avantages (clé unique, vérification d'existence).
Sub UseDictionary()
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
dict("ID001") = "Produit A"
dict("ID002") = "Produit B"
If dict.Exists("ID001") Then
MsgBox dict("ID001")
End If
' Parcourir un dictionnaire
Dim key As Variant
For Each key In dict.Keys
Debug.Print key & ": " & dict(key)
Next key
End Sub
Une application fiable nécessite une gestion d'erreurs efficace et des techniques de débogage pour identifier et corriger les problèmes.
On Error GoTo Label
et On Error Resume Next
.Err
: Number
, Description
, Source
.
Sub ErrorHandlingExample()
On Error GoTo ErrorHandler
Dim x As Integer
Dim y As Integer
Dim z As Integer
x = 10
y = 0 ' Erreur potentielle : division par zéro
z = x / y
MsgBox "Résultat: " & z
Exit Sub
ErrorHandler:
MsgBox "Une erreur s'est produite !" & vbCrLf & _
"Numéro d'erreur: " & Err.Number & vbCrLf & _
"Description: " & Err.Description, vbCritical, "Erreur d'exécution"
Err.Clear ' Important pour réinitialiser l'erreur
' Ici, on pourrait logger l'erreur, proposer une alternative, etc.
End Sub
Err.Raise
.Resume
, Resume Next
, Resume Label
.Debug.Print
).Stop
pour interrompre l'exécution.La POO permet de structurer le code de manière plus modulaire et réutilisable en créant ses propres objets.
Property Get
, Property Let
, Property Set
.
' --- Contenu du Module de Classe "clsClient" ---
Private m_Nom As String
Private m_NumeroCompte As Long
Private m_DateCreation As Date
Public Property Get Nom() As String
Nom = m_Nom
End Property
Public Property Let Nom(ByVal Value As String)
If Len(Value) > 0 Then
m_Nom = Value
Else
Err.Raise vbObjectError + 513, "clsClient", "Le nom ne peut pas être vide."
End If
End Property
Public Property Get NumeroCompte() As Long
NumeroCompte = m_NumeroCompte
End Property
Public Property Let NumeroCompte(ByVal Value As Long)
If Value > 0 Then
m_NumeroCompte = Value
Else
Err.Raise vbObjectError + 514, "clsClient", "Le numéro de compte doit être positif."
End If
End Property
' Propriété en lecture seule
Public Property Get DateCreation() As Date
DateCreation = m_DateCreation
End Property
' Constructeur
Private Sub Class_Initialize()
m_DateCreation = Now
Debug.Print "Instance de clsClient créée."
End Sub
' Destructeur
Private Sub Class_Terminate()
Debug.Print "Instance de clsClient détruite."
End Sub
' Méthode
Public Sub AfficherDetails()
MsgBox "Client: " & m_Nom & vbCrLf & _
"Numéro de compte: " & m_NumeroCompte & vbCrLf & _
"Créé le: " & m_DateCreation
End Sub
Class_Initialize
(constructeur) et Class_Terminate
(destructeur).Dim obj As New clsMaClasse
ou Set obj = New clsMaClasse
.
' --- Contenu d'un Module Standard ---
Sub TestClient()
Dim monClient As clsClient
Set monClient = New clsClient
On Error GoTo GestionErreursClient
monClient.Nom = "Dupont"
monClient.NumeroCompte = 12345
' monClient.DateCreation = Date ' Erreur, propriété en lecture seule
monClient.AfficherDetails
MsgBox "Date de création : " & monClient.DateCreation
Set monClient = Nothing ' Libère l'objet et déclenche Class_Terminate
Exit Sub
GestionErreursClient:
MsgBox "Erreur lors de la manipulation du client: " & Err.Description
Set monClient = Nothing
End Sub
clsMonDocument
avec les propriétés suivantes : CheminComplet
(lecture seule), NomFichier
(lecture seule), NombreDeMots
(lecture seule), EstEnregistre
(lecture seule). Ajouter une méthode EnregistrerSousPDF(NouveauNom As String)
qui enregistre le document au format PDF. Tester cette classe sur le document actif.
Aller au-delà des UserForms basiques pour créer des interfaces utilisateur plus dynamiques et interactives.
MultiPage
: organiser les contrôles en onglets.Frame
: grouper des contrôles.RefEdit
: permettre la sélection de plages dans Word.ListView
et TreeView
(nécessitent des contrôles ActiveX supplémentaires, parfois complexes à distribuer). Alternative : simuler avec des ListBox.
' Dans le code d'un UserForm
Private Sub UserForm_Initialize()
Dim newButton As MSForms.CommandButton
Dim i As Integer
For i = 1 To 3
Set newButton = Me.Controls.Add("Forms.CommandButton.1", "btnDynamique" & i, True)
With newButton
.Caption = "Bouton " & i
.Left = 10
.Top = 10 + (i - 1) * 30
.Width = 100
.Height = 25
End With
' Note: Pour gérer les événements de ces boutons, il faudra une classe et WithEvents
Next i
End Sub
Change
, Click
, KeyPress
, Exit
).UserForm.Show vbModeless
) vs. Modal.WithEvents
pour gérer les événements de contrôles ajoutés dynamiquement.
' --- Module de Classe: clsButtonEvents ---
Public WithEvents EvtButton As MSForms.CommandButton
Private Sub EvtButton_Click()
MsgBox "Vous avez cliqué sur : " & EvtButton.Caption & " (Nom: " & EvtButton.Name & ")"
End Sub
' --- Dans le code du UserForm ---
Dim colButtonsEvents As Collection
Private Sub UserForm_Initialize()
Set colButtonsEvents = New Collection
Dim newButton As MSForms.CommandButton
Dim btnHandler As clsButtonEvents
Dim i As Integer
For i = 1 To 3
Set newButton = Me.Controls.Add("Forms.CommandButton.1", "btnDyn" & i, True)
With newButton
.Caption = "Bouton Dyn " & i
.Left = 10
.Top = 10 + (i - 1) * 30
End With
Set btnHandler = New clsButtonEvents
Set btnHandler.EvtButton = newButton ' Associer le bouton à l'objet gestionnaire
colButtonsEvents.Add btnHandler ' Important: garder le gestionnaire en mémoire
Next i
End Sub
Private Sub UserForm_Terminate()
Set colButtonsEvents = Nothing ' Libérer la collection et les gestionnaires
End Sub
Étendre les capacités de VBA Word en communiquant avec le système d'exploitation et d'autres logiciels.
FileSystemObject
(FSO)
Sub FSO_Example()
Dim fso As Object ' Ou As Scripting.FileSystemObject si référence ajoutée
Set fso = CreateObject("Scripting.FileSystemObject")
Dim folderPath As String
folderPath = "C:\MesTestsVBA"
' Créer un dossier
If Not fso.FolderExists(folderPath) Then
fso.CreateFolder folderPath
MsgBox "Dossier créé : " & folderPath
End If
' Créer et écrire dans un fichier texte
Dim filePath As String
filePath = fso.BuildPath(folderPath, "monFichier.txt")
Dim ts As Object ' Ou As Scripting.TextStream
Set ts = fso.CreateTextFile(filePath, True) ' True pour écraser s'il existe
ts.WriteLine "Bonjour depuis VBA !"
ts.WriteLine "Ceci est un test FSO."
ts.Close
MsgBox "Fichier texte créé et écrit."
' Lire un fichier texte
If fso.FileExists(filePath) Then
Set ts = fso.OpenTextFile(filePath, 1) ' 1 pour lecture (ForReading)
Dim content As String
content = ts.ReadAll
ts.Close
MsgBox "Contenu du fichier :" & vbCrLf & content
End If
Set fso = Nothing
Set ts = Nothing
End Sub
TextStream
).CreateObject
) vs. liaison anticipée (références).
Sub ExportTableToExcel_LateBinding()
Dim xlApp As Object
Dim xlWorkbook As Object
Dim xlSheet As Object
Dim wdTable As Table
Dim i As Long, j As Long
' Vérifier s'il y a au moins un tableau dans le document
If ActiveDocument.Tables.Count = 0 Then
MsgBox "Aucun tableau trouvé dans ce document.", vbExclamation
Exit Sub
End If
Set wdTable = ActiveDocument.Tables(1) ' Prend le premier tableau
On Error Resume Next ' Gestion d'erreur basique pour la création d'objet Excel
Set xlApp = GetObject(, "Excel.Application") ' Tente de récupérer une instance existante
If Err.Number <> 0 Then
Set xlApp = CreateObject("Excel.Application") ' Crée une nouvelle instance
Err.Clear
End If
On Error GoTo 0 ' Réactive la gestion d'erreur normale
If xlApp Is Nothing Then
MsgBox "Impossible de démarrer Excel.", vbCritical
Exit Sub
End If
xlApp.Visible = True ' Rendre Excel visible
Set xlWorkbook = xlApp.Workbooks.Add
Set xlSheet = xlWorkbook.Sheets(1)
' Copier les données du tableau Word vers Excel
For i = 1 To wdTable.Rows.Count
For j = 1 To wdTable.Columns.Count
On Error Resume Next ' Ignorer les erreurs de cellules fusionnées etc.
xlSheet.Cells(i, j).Value = WorksheetFunction.Clean(Trim(wdTable.Cell(i, j).Range.Text))
' Alternative plus robuste pour le texte:
' Dim cellText As String
' cellText = wdTable.Cell(i, j).Range.Text
' cellText = Left(cellText, Len(cellText) - 2) ' Enlève les 2 caractères de fin de cellule
' xlSheet.Cells(i, j).Value = Trim(cellText)
On Error GoTo 0
Next j
Next i
xlSheet.Columns.AutoFit ' Ajuster la largeur des colonnes
MsgBox "Tableau exporté vers Excel.", vbInformation
' Nettoyage (optionnel si on veut laisser Excel ouvert)
' Set xlSheet = Nothing
' Set xlWorkbook = Nothing ' Ne pas fermer si on veut que l'utilisateur sauvegarde
' xlApp.Quit ' Ne pas quitter si on veut que l'utilisateur interagisse
' Set xlApp = Nothing
End Sub
Sub SendEmailWithAttachment_LateBinding()
Dim outlookApp As Object
Dim mailItem As Object
Dim strSubject As String
Dim strBody As String
Dim strRecipient As String
strRecipient = "destinataire@example.com" ' À adapter
strSubject = "Document Word: " & ActiveDocument.Name
strBody = "Bonjour," & vbCrLf & vbCrLf & _
"Veuillez trouver ci-joint le document " & ActiveDocument.Name & "." & vbCrLf & vbCrLf & _
"Cordialement," & vbCrLf & Application.UserName
' S'assurer que le document est sauvegardé pour pouvoir l'attacher
If ActiveDocument.Path = "" Then
MsgBox "Veuillez d'abord enregistrer le document.", vbExclamation
Exit Sub
End If
' Optionnel: Sauvegarder les changements avant d'envoyer
' If Not ActiveDocument.Saved Then ActiveDocument.Save
On Error Resume Next
Set outlookApp = GetObject(, "Outlook.Application")
If Err.Number <> 0 Then
Set outlookApp = CreateObject("Outlook.Application")
Err.Clear
End If
On Error GoTo 0
If outlookApp Is Nothing Then
MsgBox "Impossible de démarrer Outlook.", vbCritical
Exit Sub
End If
Set mailItem = outlookApp.CreateItem(0) ' 0 = olMailItem
With mailItem
.To = strRecipient
.Subject = strSubject
.Body = strBody
.Attachments.Add ActiveDocument.FullName
.Display ' ou .Send pour envoyer directement
End With
MsgBox "Email préparé.", vbInformation
Set mailItem = Nothing
Set outlookApp = Nothing
End Sub
.docx
de ce dossier dans une nouvelle feuille Excel. Pour chaque fichier, afficher son nom, sa date de dernière modification et sa taille.
Réagir automatiquement à des actions de l'utilisateur ou à des changements dans Word.
Application
Application
avec WithEvents
dans un module de classe.
' --- Module de Classe "clsAppEvents" ---
Public WithEvents App As Word.Application
Private Sub App_DocumentOpen(ByVal Doc As Document)
MsgBox "Document ouvert : " & Doc.Name
End Sub
Private Sub App_DocumentChange()
' Se déclenche quand le document actif change
If ActiveDocument Is Nothing Then
StatusBar = "Aucun document actif"
Else
StatusBar = "Document actif : " & ActiveDocument.Name
End If
End Sub
Private Sub App_NewDocument(ByVal Doc As Document)
MsgBox "Nouveau document créé basé sur : " & Doc.AttachedTemplate.Name
' Doc.Paragraphs(1).Range.Text = "Modèle de document personnalisé."
End Sub
Private Sub App_WindowActivate(ByVal Doc As Document, ByVal Wn As Window)
Debug.Print "Fenêtre activée pour : " & Doc.Name
End Sub
' Et d'autres événements : DocumentBeforeClose, DocumentBeforeSave, Quit, etc.
' --- Module Standard pour initialiser ---
Dim AppEventHandler As clsAppEvents
Sub InitializeAppEvents()
Set AppEventHandler = New clsAppEvents
Set AppEventHandler.App = Application ' Lier à l'instance courante de Word
MsgBox "Gestionnaire d'événements d'application initialisé."
End Sub
' Appeler InitializeAppEvents() au démarrage de Word (par ex. via AutoExec)
' ou manuellement pour tester.
' Pour arrêter la surveillance : Set AppEventHandler = Nothing
DocumentOpen
, DocumentChange
, NewDocument
, Quit
.Document
ThisDocument
du projet VBA d'un document spécifique.
' --- Dans le module ThisDocument d'un document ou modèle spécifique ---
Private Sub Document_Open()
MsgBox "Bienvenue dans le document : " & Me.Name
' Me fait référence au document lui-même
End Sub
Private Sub Document_Close()
' Attention: peut être déclenché avant la sauvegarde demandée à l'utilisateur
Dim answer As VbMsgBoxResult
If Not Me.Saved Then
answer = MsgBox("Le document a été modifié. Voulez-vous sauvegarder les changements ?", _
vbYesNoCancel + vbQuestion, "Sauvegarder ?")
If answer = vbYes Then
Me.Save
ElseIf answer = vbCancel Then
' Annuler la fermeture (nécessite une gestion plus complexe, souvent via Application.DocumentBeforeClose)
' Pour simplifier ici, on laisse fermer ou on ne fait rien si l'utilisateur choisit Non.
End If
End If
Debug.Print "Fermeture du document : " & Me.Name
End Sub
Private Sub Document_New()
' Se déclenche si ce document est un modèle (.dotm, .dotx) et qu'un nouveau document est créé basé sur lui.
MsgBox "Nouveau document créé à partir du modèle : " & Me.Name
End Sub
' Événements pour les Contrôles de Contenu (si présents dans ce document)
Private Sub Document_ContentControlOnEnter(ByVal ContentControl As ContentControl)
StatusBar = "Vous êtes entré dans le contrôle de contenu : " & ContentControl.Title
End Sub
Private Sub Document_ContentControlOnExit(ByVal ContentControl As ContentControl, Cancel As Boolean)
If ContentControl.ShowingPlaceholderText Then
If ContentControl.Type = wdContentControlText Then ' Pour les contrôles de texte simples
MsgBox "Veuillez remplir le champ : " & ContentControl.Title, vbExclamation
ContentControl.Range.Select ' Remettre le focus
' Cancel = True ' Pourrait empêcher de quitter le contrôle, mais peut être frustrant
End If
End If
StatusBar = "Vous avez quitté le contrôle : " & ContentControl.Title
End Sub
Open
, Close
, New
(pour les modèles).ContentControlOnEnter
, ContentControlOnExit
.App_DocumentBeforeSave
. Avant chaque sauvegarde, afficher une MsgBox demandant confirmation. Si l'utilisateur annule, la sauvegarde doit être annulée (Cancel = True
).ThisDocument
d'un modèle spécifique, utiliser l'événement Document_New
pour insérer automatiquement la date du jour et le nom de l'utilisateur dans le premier paragraphe lors de la création d'un document basé sur ce modèle.Félicitations ! Vous avez exploré des aspects avancés de la programmation VBA pour Word.
.dotm
placés dans le dossier STARTUP de Word).La clé est la pratique : appliquez ces concepts à vos propres besoins d'automatisation pour consolider vos compétences.