Cours VBA : UserForm

Pour ajouter un UserForm, procédez de la même manière que pour un nouveau module :
usf - userform La fenêtre de l'UserForm ainsi que la "Boîte à outils" apparaissent :
usf2 - userform Si la fenêtre des propriétés n'est pas présente, affichez-la et commencez par modifier le nom de l'UserForm (pour mieux s'y retrouver par la suite) :
proprietes - userform Tout comme le classeur ou les feuilles, l'UserForm a ses propres événements. Pour ajouter des événements, double-cliquez sur la fenêtre de l'UserForm :
evenements - userform Pour prendre un exemple, nous allons créer deux événements. Le premier pour définir les dimensions initiales de l'UserForm et le second pour augmenter ses dimensions de 50 pixels au clic.
L'événement UserForm_Initialize se déclenche au lancement de l'UserForm :
height - userform La propriété Height est la hauteur, Width la largeur :
Private Sub UserForm_Initialize()
    Mon_userform.Height = 100
    Mon_userform.Width = 100
End Sub
Pour simplifier le code, nous pouvons remplacer le nom de l'UserForm par Me (puisque ce code est placé dans l'UserForm sur lequel on souhaite agir) :
Private Sub UserForm_Initialize()
    Me.Height = 100
    Me.Width = 100
End Sub
Le second événement est déclenché au clic sur l'UserForm :
Private Sub UserForm_Initialize()
    Me.Height = 100
    Me.Width = 100
End Sub

Private Sub UserForm_Click()
    Me.Height = Me.Height + 50
    Me.Width = Me.Width + 50
End Sub
fenetre - userform

Lancer un UserForm

Pour lancer un UserForm depuis une procédure, utilisez Show :
Sub lancer_userform()
    Mon_userform.Show
End Sub
 

Cours VBA : les contrôles

Les contrôles ont également toute une panoplie de propriétés et d'événements qui diffèrent d'un contrôle à l'autre, nous ne verrons ici que quelques unes des nombreuses possibilités liées à ces contrôles.
Commencez par ajouter les 3 contrôles suivants : un intitulé (Label), une zone de texte (TextBox) et un bouton (CommandButton) :
label - controles Modifiez le nom et les propriétés des contrôles (dont la propriété Caption pour le texte) pour obtenir ceci :
num - controles Pour le moment, lorsque l'on rentre un numéro et que l'on valide, il ne se passe rien.
Pour y remédier, nous allons commencer par ajouter un événement pour entrer la valeur de la zone de texte dans la cellule A1 et fermer l'UserForm.
En double-cliquant sur un contrôle, vous aurez accès à ceci :
evenements - controles La liste déroulante contient les différents contrôles ainsi que l'UserForm.
Choisissez le bouton et l'événement Click :
Private Sub CommandButton_valider_Click()

    Range("A1") = TextBox_numero.Value
    'TextBox_numero est le nom de la zone de texte
    'Value est la propriété contenant la valeur de la zone de texte
 
    Unload Me
    'Unload ferme l'UserForm
    'Le nom de l'UserForm a été remplacé par Me (puisque ce code est placé dans l'UserForm à fermer)
End Sub
La valeur est alors enregistrée dans A1 avant la fermeture de l'UserForm.
Ajoutez un second Label et modifiez les propriétés suivantes : Caption, Forecolor (couleur rouge) et Visible (False, pour masquer le contrôle par défaut) :
erreur - controles Nous allons maintenant ajouter un événement qui s'active au changement de valeur de la zone de texte et qui va afficher le message d'erreur si la valeur n'est pas numérique.
Private Sub TextBox_numero_Change()
    If IsNumeric(TextBox_numero.Value) Then 'SI valeur numérique ...
        Label_erreur.Visible = False 'Label masqué
    Else 'SINON ...
        Label_erreur.Visible = True 'Label visible
    End If
End Sub
Le test de la valeur est effectué à chaque entrée de caractère ...
Il nous reste encore à empêcher la validation du formulaire si la valeur n'est pas numérique :
Private Sub CommandButton_valider_Click()
    If IsNumeric(TextBox_numero.Value) Then 'SI valeur numérique ...
        Range("A1") = TextBox_numero.Value 'Copie en A1
        Unload Me 'Fermeture
    Else 'SINON ...
        MsgBox "Valeur incorrecte"
    End If
End Sub
erreur2 - controles Pour ne pas laisser vide la partie droite de l'UserForm lorsqu'il n'y a pas d'erreur, nous pouvons la réduire en modifiant la propriété Width de l'UserForm :
Private Sub TextBox_numero_Change()
    If IsNumeric(TextBox_numero.Value) Then 'SI valeur numérique ...
        Label_erreur.Visible = False 'Label masqué
        Me.Width = 156 'Largeur de l'UserForm
    Else 'SINON ...
        Label_erreur.Visible = True 'Label visible
        Me.Width = 244 'Largeur de l'UserForm
    End If
End Sub
Le fichier : userform1.xls
Aperçu :
reduc - controles reduc2 - controles

Les cases à cocher (CheckBox)

Voici un exemple d'utilisation de cases à cocher :
cc - controles Si une case est cochée/décochée la valeur de la cellule correspondante sera modifiée, avec l'événement Click :
Private Sub CheckBox1_Click() 'N°1
    If CheckBox1.Value = True Then 'Si coché ...
       Range("A2") = "Coché"
    Else 'Si non coché ...
       Range("A2") = "Non coché"
    End If
End Sub

Private Sub CheckBox2_Click() 'N°2
    If CheckBox2.Value = True Then 'Si coché ...
       Range("B2") = "Coché"
    Else 'Si non coché ...
       Range("B2") = "Non coché"
    End If
End Sub

Private Sub CheckBox3_Click() 'N°3
    If CheckBox3.Value = True Then 'Si coché ...
       Range("C2") = "Coché"
    Else 'Si non coché ...
       Range("C2") = "Non coché"
    End If
End Sub
cc2 - controles Dans cet exemple, les cases ne sont pas cochées au lancement de l'UserForm.
Pour cocher les cases dont la valeur de la cellule correspondante est "Coché", un test est effectué au lancement de l'UserForm avec l'événement UserForm_Initialize :
Private Sub UserForm_Initialize() 'Cocher si "Coché"
    If Range("A2") = "Coché" Then
        CheckBox1.Value = True
    End If
   
    If Range("B2") = "Coché" Then
        CheckBox2.Value = True
    End If
   
    If Range("C2") = "Coché" Then
        CheckBox3.Value = True
    End If
End Sub
Le fichier : userform2.xls

Les boutons d'option (OptionButton)

Contrairement aux cases à cocher, l'utilisateur ne peut choisir qu'un seul bouton d'option par "groupe".
Pour créer un groupe, insérez d'abord un cadre (Frame) puis les boutons d'option :
bo - controles Le fichier : userform3.xls
Une fois le formulaire validé, nous entrerons une donnée dans la cellule correspondant aux numéros de colonne et de ligne choisis.
Pour connaître le bouton qui a été coché, nous pourrions procéder de la même manière qu'avec le précédent exemple (cases à cocher) mais nous allons le faire à l'aide d'une boucle pour alléger le code.
Nous utiliserons la boucle For Each que nous n'avions pas encore abordé jusque-là. Elle permet d'exécuter des instructions pour chaque objet d'un "groupe d'objet" :
Private Sub CommandButton1_Click()
    Dim colonne As String, ligne As String
   
    'Boucle pour chaque contrôle de Frame_colonne
    For Each bouton_colonne In Frame_colonne.Controls
        'Si la valeur du contrôle = True (donc si coché) ...
        If bouton_colonne.Value Then
           'La variable "colonne" prend comme valeur le texte du bouton
           colonne = bouton_colonne.Caption
        End If
    Next
   
    'Boucle pour l'autre frame
    For Each bouton_ligne In Frame_ligne.Controls
        If bouton_ligne.Value Then
            ligne = bouton_ligne.Caption
        End If
    Next

    Range(colonne & ligne) = "Cellule choisie !"
    Unload Me
End Sub
Ce formulaire entre alors la valeur "Cellule choisie !" dans la cellule choisie (pour autant que le formulaire soit complet).
Pour éviter d'avoir ce bug, nous avons besoin de vérifier que l'utilisateur a bien coché les deux boutons d'option.
Pour cet exemple, tant que le formulaire sera incomplet, le bouton "Valider" restera désactivé. Ce n'est pas la solution la plus simple, mais cela vous démontrera l'intérêt d'utiliser des fonctions/procédures dans un UserForm.
Modifiez le texte ainsi que la propriété Enabled pour désactiver le bouton :
bo2 - controles Ce qui nous donne :
bo3 - controles Dans le code ci-dessus, nous avons utilisé 2 boucles For Each pour obtenir les valeurs des boutons cochés. Nous allons avoir besoin de ces mêmes valeurs dans les événements Click du bouton "Valider" ainsi que des 10 boutons d'option.
Pour éviter de copier ces boucles dans chaque événement, nous allons les appeler à l'aide d'une fonction.
En reprenant le dernier code et en le transformant, cela nous donne :
Private Function colonne()
'La fonction renvoie comme valeur le texte du bouton choisi (colonne)
    For Each bouton_colonne In Frame_colonne.Controls
        If bouton_colonne.Value Then
            colonne = bouton_colonne.Caption
        End If
    Next
End Function

Private Function ligne()
'La fonction renvoie comme valeur le texte du bouton choisi (ligne)
    For Each bouton_ligne In Frame_ligne.Controls
        If bouton_ligne.Value Then
            ligne = bouton_ligne.Caption
        End If
    Next
End Function

Private Sub CommandButton1_Click() 'Action quand clic sur "Valider le choix"
    Range(colonne & ligne) = "Cellule choisie !"
    'colonne et ligne sont les valeurs renvoyées par les fonctions
    Unload Me
End Sub
Il ne reste plus qu'à créer une procédure qui vérifie si les boutons sont bien cochés (en faisant appel aux deux fonctions) et qui active le bouton si c'est le cas.
Là encore, le test est effectué dans une procédure à part pour éviter de copier 10x le code dans les événements des boutons d'option :
Private Sub activer()
'Activation du bouton si la condition est vérifiée
    If colonne <> "" And ligne <> "" Then
    'colonne et ligne sont les valeurs renvoyées par les fonctions
        CommandButton1.Enabled = True
        CommandButton1.Caption = "Valider le choix"
    End If
End Sub

Private Sub OptionButton11_Click()
    activer 'Lance la procédure "activer"
End Sub
Private Sub OptionButton12_Click()
    activer
End Sub
Private Sub OptionButton13_Click()
    activer
End Sub
Private Sub OptionButton14_Click()
    activer
End Sub
Private Sub OptionButton15_Click()
    activer
End Sub
Private Sub OptionButton16_Click()
    activer
End Sub
Private Sub OptionButton17_Click()
    activer
End Sub
Private Sub OptionButton18_Click()
    activer
End Sub
Private Sub OptionButton19_Click()
    activer
End Sub
Private Sub OptionButton20_Click()
    activer
End Sub
bo4 - controles Le fichier : userform3b.xls


Les barres de défilement (ScrollBar)

Les contrôles peuvent être utilisés en dehors des UserForms. Pour cet exemple, nous utiliserons les contrôles directement sur la feuille.
Notez tout d'abord que le "Mode Création" doit être activé pour modifier un contrôle placé sur une feuille (et désactivé pour utiliser le contrôle).
mode - controles suite
Pour les versions d'Excel inférieures à 2007 : bouton sur la barre "Boîte à outils Contrôles".
Avant de détailler cet exemple, en voici un aperçu :
sb - controles suite L'objectif est de colorer et sélectionner une cellule grâce aux barres de défilement dans la zone définie de 30 lignes x 10 colonnes.
Les propriétés de la barre de défilement verticale :
  • Min : 1
  • Max : 30 (puisque 30 lignes)
  • Value : position de la barre (entre 1 et 30 ici)
Même chose avec la barre horizontale avec un Max à 10 ...
Voici le code qui sera appliqué à chaque changement de valeur (Value) de la barre verticale :
'Couleur grise sur les cellules
Cells.Interior.Color = RGB(240, 240, 240)

'Couleur et sélection de la cellule
With Cells(ScrollBar_verticale.Value, ActiveCell.Column) 'Cellule par rapport à Value
    .Interior.Color = RGB(255, 220, 100) 'Couleur orange
    .Select 'Sélection de la cellule
End With
Ce code sera exécuté avec les événements Change et Scroll pour lancer les instructions quelle que soit la partie de la barre de défilement qui est cliquée.
Voici le code pour la barre verticale :
Private Sub barre_verticale()
    'Couleur grise sur les cellules
    Cells.Interior.Color = RGB(240, 240, 240)
   
    'Couleur et sélection de la cellule
    With Cells(ScrollBar_verticale.Value, ActiveCell.Column)
        .Interior.Color = RGB(255, 220, 100) 'Orange
        .Select 'Sélection de la cellule
    End With
End Sub

Private Sub ScrollBar_verticale_Change()
    barre_verticale
End Sub

Private Sub ScrollBar_verticale_Scroll()
    barre_verticale
End Sub
Et celui de la barre horizontale :
Private Sub barre_horizontale()
    'Couleur grise sur les cellules
    Cells.Interior.Color = RGB(240, 240, 240)

    'Couleur et sélection de la cellule
    With Cells(ActiveCell.Row, ScrollBar_horizontale.Value)
        .Interior.Color = RGB(255, 220, 100) 'Orange
        .Select 'Sélection de la cellule
    End With
End Sub

Private Sub ScrollBar_horizontale_Change()
    barre_horizontale
End Sub

Private Sub ScrollBar_horizontale_Scroll()
    barre_horizontale
End Sub
Le fichier : scrollbar.xls

La liste déroulante (ComboBox) et la zone de liste (ListBox)

Voici le point de départ de ce nouvel exemple :
listes - controles suite Le fichier : userform4.xls
Au lancement de l'UserForm, nous voulons que les 4 pays soient chargés dans la liste déroulante (avec la méthode AddItem) :
Private Sub UserForm_Initialize()
    For i = 1 To 4 ' => pour lister les 4 pays
       ComboBox_Pays.AddItem Cells(1, i) 'Ajoute les valeurs des cellules A1 à A4 avec la boucle
   Next
End Sub
Au changement de valeur de la liste déroulante, nous voulons ajouter les villes correspondant au pays choisi avec une boucle semblable à celle ci-dessus.
Pour le faire, nous avons besoin du n° de colonne et du nombre de lignes.
La propriété ListIndex correspond au n° de la sélection dans la liste (contrairement à Value qui correspond à la valeur), à noter que ListIndex commence à 0.
Le n° de colonne est donc :
no_colonne = ComboBox_Pays.ListIndex + 1
Pour obtenir le nombre de lignes de la colonne du pays choisi, nous pouvons rechercher le n° de ligne de la dernière cellule d'un bloc de cellules non vides :
nb_lignes = Cells(1, no_colonne).End(xlDown).Row
Grâce à ces informations, il est désormais possible de créer la boucle pour ajouter les villes dans la zone de liste :
Private Sub ComboBox_Pays_Change()
    'Zone de liste vidée (sinon les villes sont ajoutées à la suite)
    ListBox_Villes.Clear
   
    Dim no_colonne As Integer, nb_lignes As Integer
   
    'Numéro de la sélection (ListIndex commence à 0) :
    no_colonne = ComboBox_Pays.ListIndex + 1
    'Nombre de lignes de la colonne du pays choisi :
    nb_lignes = Cells(1, no_colonne).End(xlDown).Row

    For i = 2 To nb_lignes ' => pour lister les villes
       ListBox_Villes.AddItem Cells(i, no_colonne)
    Next
End Sub
Remarque : nous pourrions réduire le code ci-dessus, néanmoins cela rendrait sa lecture plus difficile :
Private Sub ComboBox_Pays_Change()
    ListBox_Villes.Clear
    For i = 2 To Cells(1, ComboBox_Pays.ListIndex + 1).End(xlDown).Row
        ListBox_Villes.AddItem Cells(i, ComboBox_Pays.ListIndex + 1)
    Next
End Sub
La ville choisie est ensuite entrée dans la zone de texte :
Private Sub ListBox_Villes_Click()
    TextBox_Choix.Value = ListBox_Villes.Value
End Sub
listes2 - controles suite Le fichier : userform4b.xls

Aller plus loin

N'oubliez pas qu'avec l'aide Excel vous pouvez obtenir des informations rapidement sur les différentes propriétés et événements des contrôles (entre autres).
En voici un aperçu avec la recherche du contrôle Label :
aide - controles suite L'aide Excel est très riche en informations, n'hésitez pas à l'utiliser en cas de besoin ...

 

Aucun commentaire:

Enregistrer un commentaire