Icône de la ressource

VBA - Classe pour gérer les évènements Enter() et Exit() des Controls d'un UserForm (TextBox, etc..) V5

Le fichier à télécharger Class for UserForm Control Enter and Exit Events.xlsm contient:
  1. Le Class_ControlEnterExit à importer dans le projet VBA.
  2. Le UserForm1 comme exemple de mise en œuvre.
Note: Voir toutes mes ressources -> https://excel-downloads.com/resources/?creator_id=268468

Les principales caractéristiques:
  • Cette Classe permet de gérer les évènements Control_Enter() et Control_Exit() des Controls d'un UserForm qui ne sont pas disponibles en Classe en VBA.

  • Inconvénient 😪 : le SetFocus sur un Control ne peut plus être fait directement mais doit passer par une fonction de la Classe !
Remarques:
  • Cette ressource repose sur une idée originale de @patricktoulon (qui en a fait sa propre ressource dédiée aux TextBoxes) et initialement développée en collaboration. Elle est ici basée sur un code original et étendue à tous les Controls d'un UserForm y compris ceux créés dynamiquement.

  • Grâce à son paramètre ArrayOfBypassExitControls (V2+) qui permet d'indiquer le ou les Controls autorisés à bypasser les évènements Exit(), cette Classe est une solution de contournement au problème ingérable du blocage sur un Cancel = True des évènements Exit() natifs dans le UserForm lorsqu'on veut par exemple sortir du UserForm par un bouton.

  • Il existe une méthode trouvée sur stackoverflow.com qui fonctionne (testée) mais plus complexe à mettre en œuvre.
Mise en œuvre relativement simple:
  • Placer le Module de Classe Class_ControlEnterExit dans la projet VBA.

  • Dans le code du UserForm: (voir le UserForm1 du fichier comme exemple)
    ...
    1. Dans le UserForm déclarer la Classe et dans UserForm_Activate() appeler la fonction d'initialisation de la Classe en indiquant:
      • Le UserForm concerné,
      • Sous forme d'Array les évènements Enter() et Exit() qui doivent être gérés en utilisant la syntaxe Control TypeName + "_Exit" ou "_Enter", par exemple: Array("TextBox_Exit", "ListBox_Enter"),
      • Optionnellement sous forme d'Array les Controls autorisés à bypasser les évènements Exit().
        VB:
        '-------------------------------------
        'Declaration of Class_ControlEnterExit
        '-------------------------------------
        Private ControlEnterExit As New Class_ControlEnterExit
        
        '-----------------
        'UserForm_Activate
        '-----------------
        Private Sub UserForm_Activate()
            '---------------------------------------
            'Initilization of Class_ControlEnterExit
            '---------------------------------------
            Call ControlEnterExit.Initialization(Me, _
                                                 Array("TextBox_Enter", "TextBox_Exit", "ComboBox_Enter", "ComboBox_Exit"), _
                                                 Array(Me.CommandButton_CancelInputAndQuitForm))
        End Sub
        ...
    2. Dans le code du UserForm, insérer les fonctions correspondantes déclarées Public et coder les traitements selon les besoins.
      • VB:
        '----------------------------------
        'Generic function for TextBox_Enter
        '----------------------------------
        Public Sub TextBox_Enter(TextBox As MSForms.Control)
            Call TraceOnSheet("Enter " & TextBox.Name)
        End Sub
        
        '---------------------------------
        'Generic function for TextBox_Exit
        '---------------------------------
        Public Sub TextBox_Exit(TextBox As MSForms.Control, Cancel As Boolean)
            'Specific check on TextBox2
            If TextBox Is Me.TextBox2 Then
                If Len(TextBox.Value) = 0 Then
                    MsgBox "TextBox2 must contain a value !"
                    Cancel = True
                End If
            End If
        
            Call TraceOnSheet("Exit " & TextBox.Name & ", Cancel = " & Cancel)
        End Sub
        
        '-----------------------------------
        'Generic function for ComboBox_Enter
        '-----------------------------------
        Public Sub ComboBox_Enter(ComboBox As MSForms.Control)
            Call TraceOnSheet("Enter " & ComboBox.Name)
        End Sub
        
        '----------------------------------
        'Generic function for ComboBox_Exit
        '----------------------------------
        Public Sub ComboBox_Exit(ComboBox As MSForms.Control, Cancel As Boolean)
            Call TraceOnSheet("Exit " & ComboBox.Name)
        End Sub
        ...
    3. Pour faire un Control.SetFocus, il faut passer par la Classe ControlEnterExit.SetFocus(Control) sinon le mécanisme ne peut pas suivre.
      • VB:
        'Me.TextBox1.SetFocus NO NO NO !!!
        Call ControlEnterExit.SetFocus(Me.TextBox1)
        ...
    4. Dans le cas où un Control est dynamiquement créé dans le UserForm après l'initialisation, il sera automatiquement intégré à la liste des instances de la Classe. Si on souhaite qu'il soit un Control autorisé à bypasser les évènements Exit() il faut le déclarer via la fonction ControlEnterExit.SetBypassExitControl(Control).
      • VB:
            With Frame1.Controls.Add("forms.TextBox.1")
                .Left = 54
                .Top = 12
                .Width = 72
                .Height = 18
                .Name = "TextBox3"
                DoEvents
            End With
        
           'Set TextBox3 as a "Bypass Exit" Control
            Call ControlEnterExit.SetBypassExitControl(Me.Controls("TextBox3"))
Versions:
  • V1 - Initiale.
  • V2 - Ajout du paramètre ArrayOfBypassExitControlNames qui permet de lister les noms des Controls qui permettent de bypasser les évènements Exit() et donc éviter les situations de blocage d'un Cancel = True.
  • V3 - Détection automatique des ajouts dynamiques de Contols et de la possibilité définir un Control comme autorisé à bypasser les évènements Exit().
  • V4 - Correction bug sur captation des évènements UserForm_AddControl() et UserForm_RemoveControl() et ajout de la fonction SetFocus() dans la Classe.
  • V5 - Ajout du Control ListView sous condition de variable préprocesseur car nécessite une Référence particulière.
    ATTENTION: Modification du type (String -> Control) du 3ème paramètre de la fonction ControlEnterExit.Initialization().
Version
V1