Création d'un formulaire

Les UserForms sont des boîtes de dialogue personnalisées utilisées pour recueillir les données d'entrée de l'utilisateur au début d'une macro. Le UserForm Builder inclus dans Code VBA crée automatiquement des UserForms. Les formulaires utilisateur générés sont dotés d'un code de validation des entrées afin de s'assurer que toutes les entrées requises sont du bon type. Cela rendra la macro plus fiable. La génération des contrôles et du code de validation permet d'économiser le temps nécessaire à la création manuelle du formulaire utilisateur. Le UserForm peut être modifié à la fois pour rendre la conception visuellement plus attrayante en déplaçant et en redimensionnant les contrôles. En outre, vous pouvez étendre le code vba du UserForm pour répondre à des besoins supplémentaires.

Utiliser le constructeur de formulaires d'utilisateur (UserForm Builder)

Le UserForm Builder est lancé à partir du menu Code VBA :

Nom du formulaire utilisateur : Contrôles Nom Type de données Type de contrôle Exigée Sélectionner les noms... Créer Constructeur de formulaire d'utilisateur

Dans le UserForm Builder, vous allez spécifier

  • Nom du formulaire : donnez un nom au formulaire, qui correspond aux données qui seront saisies. Dans l'exemple, le nom était "Order" (commande)
  • La grille Contrôles est la zone dans laquelle vous spécifiez les contrôles que vous souhaitez inclure dans le UserForm que vous êtes en train de créer. Chaque contrôle est spécifié dans une ligne séparée avec ses propriétés :
    • Nom : sera utilisé comme étiquette pour le contrôle d'entrée.
    • Type de données : si l'utilisateur saisit une valeur d'un type incorrect dans le contrôle, le fait d'appuyer sur le bouton OK entraîne l'envoi d'un message à l'utilisateur indiquant que la valeur de ce champ est incorrecte et ramène le curseur sur ce champ pour que l'utilisateur le corrige.
    • Type de contrôle : permet de spécifier le type de contrôle préféré. Un booléen (oui/non) peut être représenté de manière conviviale à l'aide d'un contrôle
    • Obligatoire : si l'utilisateur ne saisit pas de valeur dans le contrôle, le fait d'appuyer sur le bouton OK entraîne l'envoi d'un message à l'utilisateur indiquant qu'il manque une valeur pour ce champ et place le curseur dans ce champ.
  • Sélectionner les noms... : ouvre une fenêtre boîte de saisie pour la sélection de l'intervalle pour vous permettre de sélectionner un ou plusieurs noms dans votre feuille Excel. Cette fonction est utile si votre dialogue est créé pour remplir un formulaire ou un tableau Excel existant.
  • Create : crée le UserForm - image ci-dessous - et insère le code pour démarrer le UserForm.
Constructeur de formulaire d'utilisateur

Code VBA UserForm

En plus de l'objet UserForm, le constructeur ajoute également trois éléments de code :

Code pour ouvrir / afficher le formulaire

En supposant que le curseur se trouve à l'intérieur de la procédure Sub Demo, après avoir appuyé sur OK dans le UserForm Builder, la procédure se présente comme suit.


Sub Demo()
    Dim udtOrder As Order
    With udtOrder
        .Client = ""
        .EntryDate = Date
        .Product = ""
        .Attention = True
    End With
    ufmOrder.FillList "cboProduct", Array("v1", "v2", "v3")
    ufmOrder.SetValues udtOrder
    ufmOrder.Show
    If Not ufmOrder.IsCancelled Then
        ufmOrder.GetValues udtOrder
        ''continue process after OK here
        With udtOrder

        End With
    End If
    Unload ufmOrder
End Sub

Pour obtenir une interface propre, on utilise un type défini par l'utilisateur qui comprend les contrôles de données avec leurs définitions de type sur le formulaire de l'utilisateur. Vous pouvez modifier le code entre le premier With et End With pour changer les valeurs initiales ou par défaut. Le passage des valeurs au formulaire se fait dans la méthode SetValues

La procédure FillList est utilisée pour transmettre un tableau de valeurs à la zone de liste Produit. Les valeurs du tableau ("v1",...) ne sont qu'un exemple que vous devrez adapter.

La méthode Show est le moyen standard d'ouvrir le UserForm.

L'utilisateur peut cliquer sur OK ou annuler la boîte de dialogue. Ceci est déterminé en testant la propriété .IsCancelled.

Si l'utilisateur a appuyé sur OK, la macro continue à utiliser les données fournies par l'utilisateur dans le formulaire. Pour ce faire, vous devez ajouter votre propre code de processus entre le deuxième With et End With.

Type défini par l'utilisateur pour une interface propre

Le type défini par l'utilisateur généré fournit une interface propre entre votre macro et le formulaire utilisateur. Si la procédure à partir de laquelle vous appelez le UserForm se trouve dans un module standard, le User Defined Type y sera placé. Sinon, il sera placé dans un module appelé "modTypes". Dans l'exemple, la déclaration de type ressemble à ceci :


Public Type Order
    Client As String
    EntryDate As Date
    Product As String
    Attention As Boolean
End Type
Note - Constructeur de type défini par l'utilisateur
Comme le constructeur expliqué ici, Code VBA comprend également un constructeur de types définis par l'utilisateur :

Validation du UserForm et autre code

A l'intérieur du UserForm généré, il y a encore beaucoup de code qui est utilisé pour :

Manipuler OK et Annuler

Le code ci-dessous illustre la gestion des boutons Ok et Annuler. Le bouton Fermer est également géré de manière adéquate en tant qu'Annuler sans nécessiter de code supplémentaire. La variable publique IsCancelled est utilisée pour indiquer à la macro appelante si l'utilisateur a appuyé sur Ok ou sur Cancel.


Public IsCancelled As Boolean

Private Sub UserForm_Initialize()
    IsCancelled = True
End Sub

Private Sub btnCancel_Click()
    Me.Hide
End Sub

Private Sub btnOk_Click()
    If IsInputOk Then
        IsCancelled = False
        Me.Hide
    End If
End Sub

Transmission de données au formulaire utilisateur

Les données sont transmises au formulaire utilisateur et obtenues à partir de celui-ci par SetValues et GetValues respectivement. Tous deux utilisent la variable User Defined Type (type défini par l'utilisateur).


Public Sub SetValues(udtOrder As Order)
    With udtOrder
        SetValue Me.txtClient, .Client
        SetValue Me.txtEntryDate, .EntryDate
        SetValue Me.cboProduct, .Product
        SetValue Me.cbxAttention, .Attention
    End With
End Sub

Public Sub GetValues(ByRef udtOrder As Order)
    With udtOrder
        .Client = GetValue(Me.txtClient, TypeName(.Client))
        .EntryDate = GetValue(Me.txtEntryDate, TypeName(.EntryDate))
        .Product = GetValue(Me.cboProduct, TypeName(.Product))
        .Attention = GetValue(Me.cbxAttention, TypeName(.Attention))
    End With
End Sub

SetValues et GetValues sont mis en œuvre à l'aide des procédures ci-dessous :


Private Sub SetValue(ctl As MSForms.Control, value As Variant)
    On Error GoTo HandleError
    ctl.value = value
HandleExit:
    Exit Sub
HandleError:
    Resume HandleExit
End Sub

Private Function GetValue(ctl As MSForms.Control, strTypeName As String) As Variant
    On Error GoTo HandleError
    Dim value As Variant
    value = ctl.value
    If IsNull(value) And strTypeName <> "Variant" Then
        Select Case strTypeName
        Case "String"
            value = ""
        Case Else
            value = 0
        End Select
    End If
HandleExit:
    GetValue = value
    Exit Function
HandleError:
    Resume HandleExit
End Function

Validation des données saisies par l'utilisateur

Lorsque l'utilisateur appuie sur OK, les données du UserForm sont validées par la fonction IsInputOk. Celle-ci vérifie pour chaque contrôle d'entrée IsInputControl s'il a une valeur HasValue au cas où elle serait requise IsRequired. Ensuite, elle vérifie que la valeur est du bon type IsCorrectType - comme spécifié dans UserForm Builder. En cas d'échec de l'un ou l'autre test, un message est envoyé à l'utilisateur et le focus est mis sur le contrôle dont la valeur a échoué ctl.SetFocus.


Private Function IsInputOk() As Boolean
    Dim ctl As MSForms.Control
    Dim strMessage As String
    IsInputOk = False
    For Each ctl In Me.Controls
        If IsInputControl(ctl) Then
            If IsRequired(ctl) Then
                If Not HasValue(ctl) Then
                    strMessage = ControlName(ctl) & " must have value"
                End If
            End If
            If Not IsCorrectType(ctl) Then
                strMessage = ControlName(ctl) & " is not correct"
            End If
        End If
        If Len(strMessage) > 0 Then
            ctl.SetFocus
            GoTo HandleMessage
        End If
    Next
    IsInputOk = True
HandleExit:
    Exit Function
HandleMessage:
    MsgBox strMessage
    GoTo HandleExit
End Function

Notez que IsCorrectType utilise la fonction ControlDataType qui renvoie simplement le type du contrôle donné à l'aide des déclarations Select Case insérées par le UserForm Builder. Une approche similaire mais plus simple est suivie pour IsRequired.


Private Function IsCorrectType(ctl As MSForms.Control) As Boolean
    Dim strControlDataType As String, strMessage As String
    Dim dummy As Variant
    strControlDataType = ControlDataType(ctl)
    On Error GoTo HandleError
    Select Case strControlDataType
    Case "Boolean"
        dummy = CBool(GetValue(ctl, strControlDataType))
    Case "Byte"
        dummy = CByte(GetValue(ctl, strControlDataType))
    Case "Currency"
        dummy = CCur(GetValue(ctl, strControlDataType))
    Case "Date"
        dummy = CDate(GetValue(ctl, strControlDataType))
    Case "Double"
        dummy = CDbl(GetValue(ctl, strControlDataType))
    Case "Decimal"
        dummy = CDec(GetValue(ctl, strControlDataType))
    Case "Integer"
        dummy = CInt(GetValue(ctl, strControlDataType))
    Case "Long"
        dummy = CLng(GetValue(ctl, strControlDataType))
    Case "Single"
        dummy = CSng(GetValue(ctl, strControlDataType))
    Case "String"
        dummy = CStr(GetValue(ctl, strControlDataType))
    Case "Variant"
        dummy = CVar(GetValue(ctl, strControlDataType))
    End Select
    IsCorrectType = True
HandleExit:
    Exit Function
HandleError:
    IsCorrectType = False
Resume HandleExit
End Function

Private Function ControlDataType(ctl As MSForms.Control) As String
    Select Case ctl.Name
    Case "txtClient": ControlDataType = "String"
    Case "txtEntryDate": ControlDataType = "Date"
    Case "cboProduct": ControlDataType = "String"
    Case "cbxAttention": ControlDataType = "Boolean"
    End Select
End Function

Private Function IsRequired(ctl As MSForms.Control) As Boolean
    Select Case ctl.Name
    Case "txtClient", "txtEntryDate", "cboProduct", "cbxAttention"
        IsRequired = True
    Case Else
        IsRequired = False
    End Select
End Function