Pour partager cette vidéo sur les réseaux sociaux ou sur un site, voici son url :
Sujets que vous pourriez aussi aimer :
Remplir un document avec un formulaire
L'un des intérêts majeurs du
VBA Word est de pouvoir automatiser des traitements mais aussi des tâches utilisateur.
Dans l'exemple finalisé présenté par la capture, l'utilisateur débouche sur un
document modèle prêt à remplir. Mais pour éviter les mauvaises manipulations, c'est un
formulaire qui se dresse au premier plan. Tous les renseignements attendus doivent être inscrits dans les zones de saisie et choisis dans les listes déroulantes. Une fois toutes les informations fournies et après avoir cliqué sur le bouton de validation, ces données s'insèrent dans le
document précisément là où elles sont attendues. Ce
document est
automatiquement enregistré sous un nom personnalisé pour préserver le modèle. Il ne reste plus qu'à exploiter la fiche du courrier ainsi conçue automatiquement.
Document source
Nous proposons de débuter l'étude à partir d'un
document Word offrant une ébauche de
courrier modèle ainsi qu'un
formulaire programmé pour se déclencher à l'ouverture.
Télécharger le document courrier-type.docm en cliquant sur ce lien ,
Double cliquer sur le fichier réceptionné pour l'ouvrir dans Word,
Cliquer sur le bouton Activer la modification du bandeau de sécurité,
Puis, cliquer sur le bouton Activer le contenu du nouveau bandeau de sécurité,
Dès lors et comme vous pouvez le voir, le
formulaire de saisie surgit effectivement. Tous ses champs doivent être renseignés puisque toutes ces informations sont attendues dans le document modèle situé à l'arrière-plan.
Cliquer sur le bouton Annuler pour fermer le formulaire,
Le Userform en conception
La main est rendue au
document Word . Le courrier est très dépouillé mais il est volontairement allégé pour simplifier la mise en place de la solution.
Réaliser le raccourci clavier Alt + F11 pour basculer dans l'éditeur VBA Word ,
Dans l'explorateur de projet sur la gauche de l'écran, déployer le dossier Feuilles ,
Puis, double cliquer sur l'élément Renseignements ,
Il s'agit du
UserForm , soit du
formulaire . Et cette action a pour effet de l'afficher au centre de l'écran, dans sa vue en conception.
C'est le
bouton Créer que nous allons devoir principalement développer.
L'ouverture automatique du formulaire
Nous l'avons évoqué, des fragments de code existent déjà . Ce n'est pas par magie que le
formulaire surgit automatiquement à l'activation du document.
Toujours dans l'explorateur de projet , double cliquer cette fois sur l'élément thisDocument ,
Nous affichons ainsi la
feuille de code VBA associée au
document actif , soit au courrier modèle. Et nous y trouvons une petite
procédure événementielle .
Private Sub Document_Open()
On Error Resume Next
Renseignements.Show
End Sub
Son code se déclenche à l'
ouverture du document . C'est donc cette procédure qui
affiche le formulaire au démarrage grâce à sa
méthode Show . Vous notez la présence d'une instruction pour ignorer les erreurs (On Error Resume Next). Avec
Word , dans un tel cas de figure, elles sont susceptibles de se déclencher. Nous choisissons donc d'ignorer les messages d'alerte.
Les actions du formulaire
Nous l'avons constaté précédemment, un clic sur le
bouton Annuler permet de
fermer le formulaire . Mais ce n'est pas le seul
code VBA déjà présent.
Dans l'explorateur de projet, double cliquer de nouveau sur l'élément Renseignements ,
Sur le formulaire en conception , double cliquer sur le bouton Annuler ,
Nous basculons ainsi sur la feuille de code entre les bornes de la
procédure Annuler_Click .
Private Sub Annuler_Click()
Renseignements.Hide
End Sub
Son code se déclenche
au clic sur le bouton . Et c'est la
méthode Hide de l'
objet Formulaire qui permet de masquer ce dernier. Plus bas dans la feuille, la
procédure UserForm_Activate remplit les listes déroulantes au
chargement du formulaire .
Private Sub UserForm_Activate()
Civilite.Clear
Civilite.AddItem "Madame"
Civilite.AddItem "Monsieur"
texteType.Clear
texteType.AddItem "Demande augmentation de salaire"
texteType.AddItem "Demande entretien individuel"
texteType.AddItem "Demande heure supplémentaire"
End Sub
Ces listes déroulantes se nomment respectivement
Civilite et
texteType . Une autre procédure et une fonction existent mais elles sont vides pour l'instant. Nous y reviendrons.
Les noms des contrôles
Pour remplir le
document Word des informations saisies dans les
champs du formulaire , nous allons avoir besoin de piloter ces derniers. Et pour cela, nous devons connaître leurs noms d'objets.
Dans l'explorateur de projet, double cliquer sur l'élément Renseignements ,
Sur le formulaire en conception, cliquer sur la deuxième zone de texte , celle du nom,
En consultant sa
propriété (Name) dans sa
feuille de propriétés , vous remarquez que ce champ est intitulé
Nom . Si cette
fenêtre de propriétés n'est pas visible dans votre environnement, vous devez cliquer sur le
menu Affichage et choisir
Fenêtre Propriétés .
En sélectionnant tour à tour les zones du formulaire, vous pouvez constater qu'elles sont respectivement nommées Civilite, Nom, Prenom, Adresse, CP, Ville, Sujet et texteType.
Les marques d'insertion dans le document
C'est précisément dans l'ordre de ces contrôles que les informations sont attendues sur le
courrier modèle du
document Word . Une
astuce va permettre de considérablement simplifier l'implémentation du
code VBA . Nous avons marqué les zones à enrichir par des repères invisibles. Ces repères invisibles sont des
signets . Ces
signets sont des objets que le
code VBA Word peut piloter pour y insérer les informations attendues issues du
formulaire .
Revenir sur le document Word ,
En haut de la fenêtre, cliquer sur l'onglet Insertion pour activer son ruban,
Dans la section Liens de ce ruban, cliquer alors sur le bouton Signet ,
Le
signet Zone1 pointe sur le
texte Civilité à remplacer par l'information définie par l'utilisateur depuis le
formulaire . Ils suivent le même ordre que ceux des zones sur le
UserForm (Zone2 pour le texte Nom, Zone3 pour le texte Prénom etc..). Et c'est judicieusement que nous leur avons attribué des intitulés identiques simplement différenciés par un numéro incrémenté. Grâce à cette
astuce , en même temps que nous parcourrons toutes les
zones du formulaire avec une
boucle for each , nous pointerons sur les
signets correspondants sur le document. C'est ainsi que nous allons pouvoir simplifier et optimiser le
code VBA .
Cliquer sur le bouton Annuler de la boîte de dialogue pour revenir sur le document,
Dernière remarque, vous avez sans doute noté la présence de deux
signets ne respectant pas cette chronologie, Nom et Prénom. Ces informations sont répétées en bas du document. C'est la raison de leur présence. Nous les traiterons à part.
Vérifier si les champs sont bien renseignés
Il est temps maintenant de plonger les mains dans la
programmation VBA . Toutes les informations du
formulaire sont requises. Avant d'enclencher tout traitement, nous devons donc nous assurer que l'utilisateur a bien renseigné tous les champs. Et pour cela, nous devons les parcourir tous à l'aide d'une
boucle afin de vérifier les contenus respectifs.
Revenir dans l'éditeur VBA Word (Alt + Tab ou Alt + F11),
Sur le formulaire en conception , double cliquer sur le bouton Annuler ,
Dans la feuille de code, cliquer entre les bornes (Function et End Function) de la fonction test ,
Puis, ajouter les déclarations et affectations de variables suivantes :
Function test() As Boolean
Dim zone As Control: Dim compteur As Byte
test = True: compteur = 1
End Function
La
variable Zone est définie comme un
objet de type Control au sens large. C'est elle que nous allons utiliser dans une
boucle pour parcourir
tous les objets du formulaire . La
variable compteur est définie comme un
entier court (Byte). Nous l'incrémenterons à chaque passage dans la
boucle pour mettre fin à cette dernière à l'indice 8, soit à partir de la dernière zone de saisie. Les boutons ne sont en effet pas concernés par ce contrôle et ne disposent pas des mêmes propriétés. Ensuite, nous initialisons la valeur de la
fonction booléenne à True . Par défaut et jusqu'à preuve du contraire, nous considérons que tous les
champs du formulaire sont renseignés. Puis, nous initialisons la
variable compteur sur le chiffre 1.
Nous devons maintenant parcourir tous les
contrôles du formulaire .
Pour cela, à la suite du code VBA , créer la boucle For Each comme suit :
Function test() As Boolean
Dim zone As Control: Dim compteur As Byte
test = True: compteur = 1
For Each zone In Me.Controls
Next zone
End Function
L'
objet VBA Me désigne le
formulaire actif .
Controls est une propriété qui renvoie la
collection des contrôles hébergés par le
formulaire . Il s'agit en quelques sortes d'un tableau énumérant tous ces éléments. Et comme nous avons déclaré notre
objet Zone sur le même type, grâce à la
boucle For Each , nous pouvons tous les parcourir un à un.
Nous devons maintenant nous assurer que chaque zone est bien renseignée. Pour cela, une
instruction conditionnelle est nécessaire. A chaque passage dans la
boucle , elle doit vérifier que le contenu du contrôle en cours d'analyse n'est pas vide.
Dans les bornes de la boucle For Each , ajouter les instructions VBA suivantes :
Function test() As Boolean
Dim zone As Control: Dim compteur As Byte
test = True: compteur = 1
For Each zone In Me.Controls
If (zone.Value = "") Then
test = False
Exit For
End If
Next zone
End Function
Grâce à la
propriété Value , nous vérifions l'état du contenu pour chaque zone. Dès que l'une d'entre elles n'est pas renseignée (""), nous basculons l'état de la
fonction Ã
False pour informer son appelant et nous quittons la boucle (Exit For). Donc nous stoppons le traitement.
Dans le cas où toutes les zones ont correctement été renseignées et donc que le critère n'est jamais vérifié, nous devons stopper le traitement avant d'atteindre l'indice 9. Car après les zones de texte et les listes déroulantes, les
boutons ne proposent pas de
propriété Value . En conséquence, le test ferait déjouer le
code VBA .
A la suite et dans les bornes de la boucle , ajouter les instructions VBA suivantes :
Function test() As Boolean
Dim zone As Control: Dim compteur As Byte
test = True: compteur = 1
For Each zone In Me.Controls
If (zone.Value = "") Then
test = False
Exit For
End If
If (compteur = 8) Then Exit For
compteur = compteur + 1
Next zone
End Function
Lorsque la dernière zone d'information est atteinte (compteur = 8), nous mettons fin au traitement de la
boucle . Sinon, nous n'oublions pas d'
incrémenter la variable compteur pour continuer de suivre la chronologie du traitement.
Pour être utile, cette
fonction doit être appelée depuis la procédure principale, soit au clic sur le
bouton Créer . Sa procédure existe déjà .
Dans les bornes de la procédure Créer_Click , ajouter le code VBA suivant :
Private Sub Creer_Click()
If test = False Then
MsgBox "Tous les champs doivent être renseignés"
Exit Sub
End If
End Sub
C'est une
instruction conditionnelle qui se charge de lancer la
fonction test . Si son verdict est négatif (false), nous en informons l'utilisateur par le biais d'une boîte de message grâce à la
fonction VBA MsgBox . Puis, nous mettons fin au traitement de la procédure (Exit Sub).
Le cas échéant, nous devrons de nouveau parcourir tous les contrôles en même temps que les signets du document pour entreprendre les injections automatisées et croisées.
Enregistrer les modifications (CTRL + S) puis exécuter le code (F5),
Sans renseigner les champs, cliquer directement sur le bouton Créer du formulaire ,
Comme vous pouvez le voir, la route est barrée. Le message de la boîte de dialogue en informe effectivement l'utilisateur.
En revanche, si vous remplissez tous les champs et que vous cliquez sur le bouton Créer, aucune alerte ne surgit.
Cliquer sur le bouton Annuler du formulaire puis revenir dans l'éditeur VBA Word ,
Insérer les données dans le document
Il est temps maintenant de
remplir automatiquement le document Word en établissant la correspondance entre les
zones de signet et les
zones de texte du
formulaire .
Dans la procédure Créer_Click , ajouter les déclarations de variables suivantes :
Private Sub Creer_Click()
Dim zone As Control: Dim compteur As Byte
Dim Signet As Bookmarks: Dim plage As Word.Range
If test = False Then
MsgBox "Tous les champs doivent être renseignés"
Exit Sub
End If
End Sub
Pour parcourir tous les
contrôles du formulaire comme précédemment, nous déclarons de nouveau les
variables zone et compteur . Ensuite, nous déclarons la
variable Signet comme un
objet de type Bookmarks , soit comme un
signet . Puis, nous déclarons la
variable plage comme un
objet de type Word.Range . Cet objet va nous permettre de pointer sur les emplacements définis par les
signets du document pour y insérer les informations respectives du
formulaire .
Ces
objets doivent
instancier les classes qu'ils pointent pour hériter de leurs
méthodes et propriétés . Il est donc temps de passer à l'
affectation de quelques variables .
Après le test sur l'appel de la fonction test, ajouter les deux affectations suivantes :
Private Sub Creer_Click()
Dim zone As Control: Dim compteur As Byte
Dim Signet As Bookmarks: Dim plage As Word.Range
If test = False Then
MsgBox "Tous les champs doivent être renseignés"
Exit Sub
End If
compteur = 1
Set Signet = ActiveDocument.Bookmarks
End Sub
Classiquement,nous initialisons tout d'abord le
compteur de boucle . Puis, nous exploitons la
propriété Bookmarks de l'
objet VBA Word ActiveDocument . Elle renvoie la collection des
signets . Désormais, ils sont tous représentés dans un tableau stocké dans la
variable Signet .
La suite des
affectations se fera à chaque passage dans la
boucle pour redéfinir les signets sur les nouveaux emplacements. Grâce à cette
collection de signets stockée dans la
variable Signet , nous allons maintenant pouvoir les parcourir tous très simplement, en même temps que les
contrôles du formulaire . Souvenez-vous, ils sont disposés dans le même ordre.
A la suite du code de la procédure Créer_Click , créer la boucle de parcours , comme suit :
Private Sub Creer_Click()
Dim zone As Control: Dim compteur As Byte
Dim Signet As Bookmarks: Dim plage As Word.Range
If test = False Then
MsgBox "Tous les champs doivent être renseignés"
Exit Sub
End If
compteur = 1
Set Signet = ActiveDocument.Bookmarks
For Each zone In Me.Controls
If compteur = 8 Then Exit For
compteur = compteur + 1
Next zone
End Sub
Nous exploitons la même technique que pour la
fonction test . Lorsque le huitième contrôle est atteint, nous mettons fin à l'
analyse récursive .
Maintenant, Ã chaque passage dans cette
boucle , nous devons
pointer sur le signet en cours d'analyse et faire la correspondance avec l'information contenue dans la
zone de texte du formulaire .
Dans les bornes de la boucle , avant l'instruction If, ajouter les deux lignes VBA suivantes :
Private Sub Creer_Click()
Dim zone As Control: Dim compteur As Byte
Dim Signet As Bookmarks: Dim plage As Word.Range
If test = False Then
MsgBox "Tous les champs doivent être renseignés"
Exit Sub
End If
compteur = 1
Set Signet = ActiveDocument.Bookmarks
For Each zone In Me.Controls
Set plage = Signet("Zone" & compteur).Range
plage.Text = zone.Value
If compteur = 8 Then Exit For
compteur = compteur + 1
Next zone
End Sub
Nous initialisons (set) la
variable plage , sur la zone reconnue par le signet en cours (Signet("Zone" & compteur)), grâce à sa
propriété Range . Maintenant que l'emplacement est défini, il ne reste plus qu'à y insérer l'information attendue. C'est ce que nous réalisons par affectation (plage.Text = zone.Value).
Bien sûr pour la dernière zone soit, celle de la seconde liste déroulante, il conviendrait de faire correspondre un texte modèle à insérer. Il suffirait de l'importer depuis le disque dur comme nous l'avons démontré au cours des
astuces VBA Word précédentes.
A ce stade donc, tous les éléments attendus sur le
document Word sont susceptibles d'être renseignés, à l'exception du rappel sur le nom et le prénom en conclusion du courrier. Nous devons donc les enrichir indépendamment.
Après la boucle , ajouter les instructions VBA suivantes :
Private Sub Creer_Click()
Dim zone As Control: Dim compteur As Byte
Dim Signet As Bookmarks: Dim plage As Word.Range
If test = False Then
MsgBox "Tous les champs doivent être renseignés"
Exit Sub
End If
compteur = 1
Set Signet = ActiveDocument.Bookmarks
For Each zone In Me.Controls
Set plage = Signet("Zone" & compteur).Range
plage.Text = zone.Value
If compteur = 8 Then Exit For
compteur = compteur + 1
Next zone
Set plage = Signet("Nom").Range
plage.Text = Nom.Value
Set plage = Signet("Prenom").Range
plage.Text = Prenom.Value
End Sub
Nous répliquons le même principe d'
instanciation et d'
affectation que celui de la
boucle , mais cette fois en version statique.
Pour parfaire la solution, il ne nous reste plus qu'à enregistrer cette fiche individuelle de renseignement sous un nom unique. Pour cela, nous pouvons rassembler l'information sur le nom et le prénom et l'associer à l'indication sur la date en cours.
A la fin de la procédure , ajouter l'instruction VBA suivante :
Private Sub Creer_Click()
Dim zone As Control: Dim compteur As Byte
Dim Signet As Bookmarks: Dim plage As Word.Range
If test = False Then
MsgBox "Tous les champs doivent être renseignés"
Exit Sub
End If
compteur = 1
Set Signet = ActiveDocument.Bookmarks
For Each zone In Me.Controls
Set plage = Signet("Zone" & compteur).Range
plage.Text = zone.Value
If compteur = 8 Then Exit For
compteur = compteur + 1
Next zone
Set plage = Signet("Nom").Range
plage.Text = Nom.Value
Set plage = Signet("Prenom").Range
plage.Text = Prenom.Value
ThisDocument.SaveAs2 ThisDocument.Path & "\" & Nom.Value & "-" & Prenom.Value & "-" & Replace(Replace(Replace(Now, "/", "-")," ", "-"), ":", "-") & ".docm"
End Sub
La
méthode SaveAs de l'
objet VBA Word ThisDocument attend le chemin complet en argument. Nous désignons l'emplacement du document actuel grâce à la
propriété Path de ce même
objet ThisDocument . Puis, nous lui associons les informations sur le nom, le prénom et la date séparées de tirets, pour livrer un nom bien formé. Notez l'emploi en cascade de la
fonction VBA Replace afin de purger les caractères interdits dans les noms de fichiers comme le
symbole du slash ou celui des deux points.
Si vous exécutez le code, que vous remplissez le
formulaire et cliquez sur le
bouton Créer , vous notez avec plaisir que le
document Word est parfaitement rempli. Dans le même temps, il est parfaitement archivé sur le disque dur à l'emplacement du courrier type. Sur ces copies, pour que le formulaire ne se déclenche par à l'ouverture, il suffit simplement d'ajouter une gestion d'exception sur le nom du fichier dans la procédure événementielle Document_Open :
If(ThisDocument.Name = "courrier-type.docm") Then
Renseignements.Show
End if