Leçon n° 11 : les formulaires

 

Introduction

 

Ceux qui utilisent Access savent ce qu’est un formulaire ; il existe également dans Word des formulaires qui sont des documents structurés contenant des espaces réservés pour la saisie d'informations. Les formulaires que nous allons à présent étudier ne sont pas différents dans leur principe et sont baptisés UserForm  (formulaire utilisateur) ; ils sont créés à l’intérieur de l’éditeur de programmes et offrent un moyen efficace d’échanger des informations entre l’utilisateur et le programmeur. En effet, un programme sert à traiter des données et il faut donc qu’il existe un moyen pour récupérer des informations en provenance de l’utilisateur. Nous avons déjà utilisé pour ce faire les fonctions MsgBox et InputBox ; avec les formulaires UserForm, vous allez pouvoir créer des boîtes de dialogue beaucoup plus sophistiquées qui seront parfaitement adaptées à vos besoins.

Comme tout est objet dans Windows, les formulaires ne dérogent pas à cette règle et ils bénéficient à ce titre d’un modèle d’objets que nous vous présentons ci-dessous :

L’aide électronique sur les objets UserForm se trouve dans le fichier FM20.CHM.

Vous noterez que dans certains ouvrages en français, on emploie le terme feuille  à la place de formulaire.

Un exemple de UserForm pas à pas

 

Si la saisie d’une information avec la fonction InputBox se révèle assez pratique, il faut reconnaître que dès qu’on a plusieurs informations à demander à un utilisateur, ce système ne se révèle pas très pratique ; en effet, l’utilisateur doit valider chaque réponse individuellement et n’a pas une vision globale de l’ensemble de ses choix. Pour remédier à ces problèmes, il faut créer un formulaire UserForm. Nous allons reprendre notre premier exemple de macro de calendrier ; je vous rappelle que cette dernière permet de créer un calendrier du mois en cours. Cette limitation peut poser de nombreux problèmes et il suffirait pour rendre le programme plus efficace de faire choisir à l’utilisateur le mois et l’année pour lesquels il souhaite un calendrier. Deux appels à une fonction InputBox pourraient résoudre notre problème mais vous allez voir que la création d’un formulaire, même si elle est plus complexe, permet une solution beaucoup plus élégante.

Pour réaliser notre nouveau programme, exécutez Word et invoquez l’éditeur Visual Basic (Alt + F11).

Dans la fenêtre Projet, vous devriez voir le projet suivant :

Si le document vide dans lequel vous allez créer le UserForm porte un autre numéro que Document1, cela n’a aucune importance.

Faites un clic droit sur le nom du projet, Project (Document1), et choisissez la commande Insertion | UserForm :

Ceci a pour effet d’afficher une nouvelle fenêtre qui contient une grille ainsi qu’une boîte à outils.

Cette grille est un canevas sur lequel nous allons dessiner notre formulaire et la boîte à outils  renferme des contrôles  que nous pouvons placer sur le formulaire.

Le formulaire comporte des poignées qui permettent de modifier la taille de la fenêtre. Dans la barre de titre de la fenêtre apparaît le libellé UserForm1. Commençons par modifier cela : faites un clic droit sur le formulaire et choisissez Propriétés. Une autre fenêtre apparaît dans l’éditeur :

Il s’agit de la feuille de propriétés du formulaire. En effet, les formulaires, qui sont des objets, sont par conséquent dotés de propriétés et de méthodes. Le grand avantage des formulaires par rapport aux autres objets, c’est que leurs propriétés sont définies de manière interactive, par le biais de la feuille de propriétés , et qu’on n’a pas besoin d’écrire du code pour ce faire. La première propriété qui apparaît dans la feuille est Name et elle a la valeur UserForm1. Changez cette propriété et tapez Calendrier. Vous pouvez constater que ceci ne modifie pas le titre de la fenêtre ce qui signifie qu’il existe une autre propriété pour gérer cela. Il s’agit de la propriété Caption et vous allez modifier sa valeur en saisissant Choix du mois et de l'année. Dès que vous avez modifié la feuille de propriétés, le titre de la fenêtre est changé. Vous remarquerez qu’il existe de nombreuses autres propriétés concernant ce formulaire et vous pouvez découvrir leur utilité en essayant de modifier leur valeur.

Il faut ensuite nous consacrer aux contrôles du formulaire. Un contrôle  est un objet d’interface qui permet de stocker des informations ; vous connaissez tous ces contrôles parce qu’on les rencontre dans les boîtes de dialogue des applications Windows. Examinons cependant l’ensemble des contrôles que propose la boîte à outils. Nous n’évoquerons ici que les contrôles standard mais vous devez savoir qu’il est possible de rajouter à la boîte à outils d’autres contrôles (des contrôles ActiveX ) qui procurent des fonctionnalités supplémentaires. Le tableau ci-dessous décrit les contrôles dans leur ordre d’apparition dans la boîte à outils :

 

Nom de l’outil

Nom du contrôle

Description

Sélectionner des objets

 

L'outil Sélectionner des objets est le seul élément de la boîte à outils qui ne trace pas un contrôle. Une fois sélectionné, il permet de déplacer ou de redimensionner un contrôle précédemment tracé sur un formulaire.

Intitulé

Label

Permet d'insérer une chaîne de texte non modifiable par l'utilisateur, comme la légende d'une image.

Zone de texte

TextBox

Contient du texte insérable ou modifiable par l'utilisateur.

Zone de liste modifiable

ComboBox

Contrôle réunissant les caractéristiques de la zone de liste et de la zone de texte. L'utilisateur peut choisir un élément dans la liste ou entrer une chaîne dans la zone de texte.

Zone de liste

ListBox

Permet d'afficher une liste d'éléments que l'utilisateur peut sélectionner. Il est possible de faire défiler la liste si tous les éléments ne peuvent être affichés simultanément.

Case à cocher

CheckBox

Crée une case que l'utilisateur peut facilement sélectionner pour activer ou désactiver un élément ou sélectionner plusieurs options parmi des choix multiples.

Bouton d’option

OptionButton

Permet d'afficher plusieurs choix, l'utilisateur ne pouvant en sélectionner qu'un seul.

Bouton bascule

ToggleButton

Crée un bouton basculant entre deux positions.

Cadre

Frame

Permet de créer un groupe de contrôles graphique ou fonctionnel. Pour grouper des contrôles, placez d'abord l'élément Frame, puis faites glisser des contrôles à l'intérieur du cadre.

Bouton de commande

CommandButton

Crée un bouton que l'utilisateur peut sélectionner pour exécuter une commande.

Contrôle Onglet

TabStrip

Permet de définir plusieurs pages pour la même zone d'une fenêtre ou d'une boîte de dialogue de votre application.

Multipage

MultiPage

Présente en un même ensemble plusieurs écrans d'informations.

Défilement

ScrollBar

Outil graphique permettant de parcourir rapidement une longue liste d'éléments ou une grande quantité d'informations, d'indiquer une position sur une échelle, d'entrer des données ou d'indiquer une vitesse ou une quantité.

Toupie

SpinButton

Contrôle de compteur utilisable avec un autre contrôle pour incrémenter ou décrémenter des nombres. Il permet également de faire défiler vers l'avant et vers l'arrière une plage de valeurs ou une liste d'éléments.

Image

Image

Affiche une image sur la feuille à partir d'une image bitmap, d'un icone ou d'un métafichier. Les images affichées dans un contrôle Image ont un usage purement décoratif.

 

Quand on parle d’un contrôle, on le désigne aussi bien par le nom de l’outil qui sert à le déposer sur le formulaire que par son nom d’objet. Ainsi, vous entendrez parler de zone de liste ou bien de ListBox.

Pour notre programme, nous avons besoin de trois contrôles :

·         un contrôle pour stocker le mois

·         un contrôle pour stocker l’année

·         un contrôle pour valider le formulaire

 

Le choix du type de contrôle est très important et il n’est pas toujours facile à faire car il existe bien souvent de nombreuses possibilités pour arriver au même résultat. Prenons l’exemple du contrôle pour stocker le mois de notre calendrier : on peut choisir parmi les cinq possibilités suivantes :

·         TextBox

·         ListBox

·         ComboBox

·         OptionButton

·         ScrollBar

Dans la mesure où il s’agit d’une liste fermée (il n’y a que 12 mois), un contrôle TextBox ne paraît pas très approprié. Nous choisirons donc un contrôle ComboBox mais les trois autres types de contrôles sont également possibles.

Pour la saisie de l’année, nous opterons pour un contrôle TextBox. Encore une fois, d’autres choix auraient été aussi légitimes.

Pour la validation du formulaire, seul un contrôle Bouton de commande s’impose véritablement.

 

Pour placer un contrôle sur un formulaire, il faut au préalable choisir l’outil dans la boîte à outils puis dessiner, à l’aide de la souris, un cadre sur le formulaire afin de désigner l’emplacement du contrôle :

Quand on relâche le bouton de la souris, le contrôle est placé sur le formulaire :

Si l’emplacement ne convient pas, on peut déplacer le contrôle, voire le supprimer (clic droit pour appeler un menu contextuel et commande Supprimer). Si les dimensions du contrôle ne sont pas conformes à vos souhaits, vous pouvez également modifier sa taille à l’aide des huit poignées qui encerclent l’objet.

On réalise la même opération pour le contrôle Zone de texte et pour le Bouton de commande pour arriver au résultat suivant :

Vous pouvez constater que la feuille de propriétés ne présente plus les propriétés du formulaire mais celles de l’objet actif (dans notre exemple CommandButton1) :

En fait, la liste déroulante au sommet de la feuille de propriétés présente tous les objets du formulaire (y compris le formulaire lui-même) et on peut donc consulter les propriétés d’un objet particulier en le choisissant dans la liste :

Le fait de sélectionner un des éléments de cette liste ou de cliquer sur un objet dans le formulaire revient au même.

Vous remarquerez que les noms des contrôles sont formés à partir du nom du type de contrôle suivi d’un numéro. Il est bien évidemment possible de modifier ces noms, comme nous l’avons fait pour le nom du formulaire et, grâce à la feuille de propriétés, vous affecterez les noms mois, annee, et valider respectivement aux contrôles ComboBox1, TextBox1 et CommandButton1. De plus, vous modifierez la propriété Caption  du bouton de commande pour lui attribuer la valeur Créer le calendrier. Afin de mieux nous rendre compte de l’aspect visuel de notre boîte de dialogue, nous allons la tester. Pour ce faire, cliquer sur le formulaire pour le sélectionner, puis cliquer sur le bouton Exécuter  Sub/UserForm dans la barre d’outils de l’éditeur :

Ceci a pour effet d’afficher la boîte de dialogue :

Bien évidemment, il ne s’agit pour l’instant que d’une coquille vide et les seules choses que vous puissiez faire avec ce formulaire sont de saisir du texte dans la zone de texte et de fermer la fenêtre en cliquant dans la case de fermeture. Si vous pensez que le titre de la boîte de dialogue n’est pas assez explicite, vous pouvez éventuellement rajouter des contrôles Label affichant les libellés Mois et Année.

Il nous reste encore beaucoup de travail pour que notre programme de calendrier fonctionne.

Occupons-nous de la ComboBox qui, pour l’instant, ne contient rien du tout. En consultant la documentation sur l’objet ComboBox , on peut voir qu’il possède une méthode Additem  qui ajoute un élément à la liste. Pour remplir notre liste avec les noms des mois, il va donc falloir écrire un programme de ce style :

mois.AddItem ("Janvier")

mois.AddItem ("Février")

mois.AddItem ("Mars")

mois.AddItem ("Avril")

mois.AddItem ("Mai")

mois.AddItem ("Juin")

mois.AddItem ("Juillet")

mois.AddItem ("Août")

mois.AddItem ("Septembre")

mois.AddItem ("Octobre")

mois.AddItem ("Novembre")

mois.AddItem ("Décembre")

 

Le véritable problème réside dans le fait qu’on ne sait pas très bien pour l’instant où placer ce code pour qu’il soit exécuté au bon endroit. C’est le moment d’introduire le concept d’événement .

Avant l’apparition de Windows, les programmes qui s’exécutaient sous MS-DOS, dans une interface en mode texte, étaient assez simples à concevoir : une fenêtre unique contenait un menu et l’utilisateur ne pouvait exécuter qu’une seule commande à la fois. Avec l’avènement de Windows, les choses ont considérablement évolué du point de vue du programmeur ; les fenêtres ont envahi l’écran et un périphérique de saisie supplémentaire a vu le jour : la souris. Là où le programmeur devait se contenter de gérer la saisie au clavier d’une commande, les développeurs doivent à présent gérer le multi-fenêtrage, le redimensionnement des fenêtres, la saisie au clavier et les actions de la souris sur tous les objets constituant l’interface utilisateur. Si la vie est devenue plus simple pour l’utilisateur, elle a eu tendance à se complexifier pour le programmeur. Il a donc fallu inventer un nouveau modèle de développement logiciel : le modèle événementiel. Windows considère en effet que chaque objet peut réagir à des événements et définit pour chaque type d’objet une série d’événements. Le plus simple pour comprendre cette notion est de donner quelques exemples. Voici un tableau listant quelques objets et donnant quelques événements auxquels ils sont susceptibles de réagir :

 

Objet

Evénements  associés

Formulaire UserForm

Activation, initialisation, fermeture.

Contrôle ComboBox

Clic, activation, sortie.

Contrôle CommandButton

Clic, double-clic.

Contrôle Zone de texte

Modification, entrée, sortie.

Document Word

Création, fermeture, ouverture.

Feuille Excel

Activation, calcul, modification.

 

Quand on programme sous Windows, il faut donc prévoir les événements qui sont susceptibles de se déclencher pour un objet donné et écrire des programmes pour traiter ces événements. Un programme qui traite un événement s’appelle un gestionnaire d’événement . Dans le cas qui nous occupe, il va falloir, par exemple, écrire un gestionnaire d’événement pour l’événement Click du bouton de commande de notre formulaire qui sert à valider la saisie de l’utilisateur.

Il existe plusieurs méthodes pour connaître la liste des événements rattachés à un objet ; la première consiste tout simplement à consulter l’aide en ligne. Si on consulte la documentation sur l’objet UserForm, on s’aperçoit, qu’outre la liste des propriétés et des méthodes, il existe un hyperlien pour les événements :

La deuxième méthode exploite les facilités de l’éditeur de code Visual Basic. En cliquant avec le bouton droit de la souris sur le formulaire Calendrier (sous-menu Feuilles du projet Document1) :

vous pouvez choisir la commande Code qui affiche la fenêtre de code  du formulaire en lieu et place de la grille de création du formulaire. Cette fenêtre comporte deux listes déroulantes : une liste qui comprend tous les objets du formulaire (y compris l’objet l’UserForm) et une liste baptisée Déclarations :

Si on choisit par exemple l’objet UserForm, la liste Déclarations prend la forme suivante :

Cette liste dénombre tous les événements attachés à l’objet UserForm. Si vous sélectionnez un autre objet (mois, annee ou valider), vous constaterez que la liste Déclarations est modifiée ce qui signifie que tous les objets n’acceptent pas tous les mêmes événements. Le simple fait de sélectionner un événement dans la liste Déclarations fait apparaître un squelette de procédure. Par exemple si je sélectionne l’objet valider et que je clique sur Click , le code suivant apparaît dans l’éditeur :

Private Sub valider_Click()

 

End Sub

et le curseur se place entre ces deux lignes afin de pouvoir taper le code de la procédure . C’est donc entre ces lignes que vous devez placer le code qui sera déclenché quand l’utilisateur cliquera sur le bouton de commande valider. Le mot clé Private  signifie que la procédure est interne au formulaire.

La notion d’événement doit à présent être un peu plus claire mais il demeure cependant encore deux questions : quel événement choisir pour affecter du code à un objet, et dans quel ordre les événements se produisent-ils ?

La réponse à la première question viendra avec l’expérience et en lisant l’aide en ligne. Il ne faut pas cependant être effrayé par la multitude d’événements que peut prendre en compte un objet. Dans la plupart des cas, vous ne gérerez qu’un événement ou deux par objet ; pour reprendre l’exemple des contrôles CommandButtton, on ne se sert en général que de l’événement Click alors que cet objet gère 13 événements.

La deuxième question est liée à la première car, lorsqu’un objet comporte plusieurs événements, il faut absolument connaître l’ordre dans lequel les événements se produisent pour pouvoir affecter le code à l’événement adéquat. Le plus simple pour apprivoiser les événements est encore d’écrire un programme qui démontre l’ordre  dans lequel ils se produisent. Un tel programme est excessivement simple à écrire et vous montrera de manière éclatante les événements en action. Pour ce faire, choisissez l’objet UserForm et écrivez les gestionnaires d’événement suivants :

Private Sub UserForm_Activate()

MsgBox "Evénement Activate déclenché"

End Sub

 

Private Sub UserForm_Click()

MsgBox "Evénement Click déclenché"

End Sub

 

Private Sub UserForm_Initialize()

MsgBox "Evénement Initialize déclenché"

End Sub

 

Private Sub UserForm_Terminate()

MsgBox "Evénement Terminate déclenché"

End Sub

 

Exécutez ensuite votre formulaire et vous pourrez alors constater que c’est l’événement Initialize  qui se déclenche en premier. Lui succède immédiatement l’événement Activate . Si vous cliquez sur le formulaire, vous constaterez sans surprise que l’événement Click  se déclenche. Enfin, en fermant le formulaire, vous verrez que l’événement Terminate  se produit.

 

Cette démonstration nous permet de déterminer l’emplacement du code d’initialisation de la liste de notre ComboBox . Il faut la placer dans le gestionnaire d’événement Initialize de l’objet UserForm ce qui nous donne :

Private Sub UserForm_Initialize()

' Initialize se déclenche avant l'ouverture du formulaire

' On remplit la liste des mois

    mois.AddItem ("Janvier")

    mois.AddItem ("Février")

    mois.AddItem ("Mars")

    mois.AddItem ("Avril")

    mois.AddItem ("Mai")

    mois.AddItem ("Juin")

    mois.AddItem ("Juillet")

    mois.AddItem ("Août")

    mois.AddItem ("Septembre")

    mois.AddItem ("Octobre")

    mois.AddItem ("Novembre")

    mois.AddItem ("Décembre")

End Sub

 

Un autre problème se pose : comment récupérer dans notre programme la valeur du mois choisi par l’utilisateur ? Il n’y a pas dans ce cas de valeur de retour renvoyée par une fonction. Il faut se tourner du côté des propriétés de notre ComboBox  ; la propriété Value  contient l’élément de la liste sélectionné par l’utilisateur. Pour s’en persuader, il suffit d’écrire le gestionnaire d’événement suivant :

Private Sub valider_Click()

MsgBox mois.Value

End Sub

Après avoir sélectionné un mois dans la ComboBox, cliquez sur le bouton de commande du formulaire ; vous devriez alors voir apparaître une boîte de dialogue de ce style :

Pour achever notre formulaire, il ne nous reste plus qu’à écrire le gestionnaire d’événement du bouton de commande. Ce dernier va récupérer les valeurs des contrôles grâce aux propriétés Value des contrôles ComboBox et TextBox. La propriété ListIndex  de la ComboBox permet de connaître le numéro du mois choisi ce qui nous évite d’écrire une fonction qui transforme le nom d’un mois en numéro. Voici le listing complet de la procédure :

Private Sub valider_Click()

Dim premier As Variant

Dim jour As Integer

Dim nannee As Integer

Dim cmois As String

Dim nmois As Integer

jour = 1

' on récupère les valeurs des contrôles du formulaire

nannee = annee.Value

cmois = mois.Value

' calcul du nombre de jours du mois

' on stocke dans nmois le numéro du mois (janvier = 1, etc.)

If mois.ListIndex = -1 Then

' l'utilisateur n'a pas choisi de mois

' on prend le mois de janvier par défaut

nmois = 1

Else

nmois = mois.ListIndex + 1

' 0 est le premier élément de la liste

End If

Select Case nmois

Case 1, 3, 5, 7, 8, 10, 12

nbjours = 31

Case 4, 6, 9, 11

nbjours = 30

Case Else

' il s'agit du mois de février

' il faut calculer si le mois a 28 ou 29 jours

    If Day(DateSerial(nannee, 2, 28) + 1) = 29 Then

    nbjours = 29

    Else

    nbjours = 28

    End If

End Select

' Inscrit le mois et l'année

    Selection.TypeText Text:=cmois + " " + CStr(nannee)

' Centre le titre

    Selection.ParagraphFormat.Alignment = wdAlignParagraphCenter

' Saute une ligne

    Selection.TypeParagraph

    Selection.TypeParagraph

' Insère le tableau

    ActiveDocument.Tables.Add Range:=Selection.Range, _

    NumRows:=6, NumColumns:= 7 _

    DefaultTableBehavior:=wdWord9TableBehavior, _

    AutoFitBehavior:= wdAutoFitFixed

    Selection.TypeText Text:="Lundi"

    Selection.MoveRight Unit:=wdCell

    Selection.TypeText Text:="Mardi"

    Selection.MoveRight Unit:=wdCell

    Selection.TypeText Text:="Mercredi"

    Selection.MoveRight Unit:=wdCell

    Selection.TypeText Text:="Jeudi"

    Selection.MoveRight Unit:=wdCell

    Selection.TypeText Text:="Vendredi"

    Selection.MoveRight Unit:=wdCell

    Selection.TypeText Text:="Samedi"

    Selection.MoveRight Unit:=wdCell

    Selection.TypeText Text:="Dimanche"

    ' calcul du premier jour du mois et de l'année sélectionnés

    premier = Weekday("1 " & cmois & " " & Str(nannee), vbMonday)

    Selection.MoveRight Unit:=wdCell, Count:=premier

    While jour < nbjours + 1

    Selection.TypeText Text:=Str(jour)

    Selection.MoveRight Unit:=wdCell

    jour = jour + 1

    Wend

' Masque le formulaire

Calendrier.Hide

End Sub

A la fin du programme, la méthode Hide  permet de fermer le formulaire. A contrario, on utilisera la méthode Show  pour faire apparaître le formulaire . Il suffit d’écrire la procédure suivante pour pouvoir exécuter le formulaire :

Sub ImprimeCalendrier()

Calendrier.Show

End Sub

 

Notre UserForm est à présent terminé ; il est bien évidemment possible de l’améliorer et vous pouvez par exemple prévoir une valeur par défaut pour la saisie de l’année (Year(Now)). Nous vous proposons, à titre d’exercice, de reprendre le programme de calcul de prêt de la Leçon 7 et de transformer les appels de fonctions InputBox() en un formulaire UserForm. Pour mémoire, voici le code des trois fonctions :

principal = CDbl(InputBox _

("Quel montant désirez-vous emprunter en francs ?"))

' Saisie du taux de l'emprunt

taux = CDbl(InputBox("A quel taux empruntez-vous ?"))

' Saisie du nombre d'années de l'emprunt

annuites = CDbl(InputBox _

("Sur combien d'années empruntez-vous ?"))

Sur le formulaire, créez quatre contrôles :

·         un contrôle TextBox pour saisir le montant du prêt

·         un contrôle TextBox associé à un contrôle SpinButton pour saisir le taux du prêt (valeur par défaut à 5 % et incrément de 0,25 %)

·         un contrôle ComboBox pour saisir le nombre d’années

·         un contrôle CommandButton pour valider la saisie

 

Vous trouverez la solution de cet exercice dans le code fourni sur Internet.

Conclusion

Les formulaires UserForm permettent de donner un aspect professionnel à votre application car vous pouvez créer des boîtes de dialogue similaires à celles que l’on trouve dans les logiciels commerciaux. Ils facilitent aussi grandement l’utilisation des programmes en optimisant la saisie et en la contrôlant. Les formulaires Access fonctionnent exactement sur le même principe que les formulaires UserForm ; ils offrent en revanche plus de propriétés, de méthodes et d’événements parce qu’ils gèrent en plus des bases de données. Ils permettent aussi plusieurs niveaux de formulaires (un formulaire peut contenir un sous-formulaire qui lui-même peut contenir un sous-formulaire).

La notion d’événement est essentielle quand on programme sous Windows et de très nombreux objets dans Office réagissent à des événements ; les documents Word et les feuilles de calcul Excel ne font pas exception à cette règle.