VBA
Formulaires utilisateur
Recherche…
Les meilleures pratiques
Un objet UserForm
est un module de classe avec un concepteur et une instance par défaut . Vous pouvez accéder au concepteur en appuyant sur Maj + F7 tout en affichant le code-behind , et vous pouvez accéder au code-behind en appuyant sur F7 tout en affichant le concepteur .
Travaillez avec une nouvelle instance à chaque fois.
En tant que module de classe , un formulaire est donc un modèle pour un objet . Un formulaire pouvant contenir des états et des données, il est préférable de travailler avec une nouvelle instance de la classe, plutôt qu'avec une instance par défaut / globale:
With New UserForm1
.Show vbModal
If Not .IsCancelled Then
'...
End If
End With
Au lieu de:
UserForm1.Show vbModal
If Not UserForm1.IsCancelled Then
'...
End If
Travailler avec l'instance par défaut peut conduire à des bogues subtils lorsque le formulaire est fermé avec le bouton rouge "X" et / ou lorsque Unload Me
est utilisé dans le code-behind.
Implémenter la logique ailleurs.
Un formulaire ne doit concerner que la présentation : un bouton Le gestionnaire de Click
qui se connecte à une base de données et exécute une requête paramétrée en fonction des entrées de l'utilisateur fait trop de choses .
Au lieu de cela, implémentez la logique applicative dans le code responsable de l'affichage du formulaire, ou même mieux, dans les modules et les procédures dédiés.
Écrivez le code de manière à ce que l'objet UserForm ne soit responsable que de savoir comment afficher et collecter des données: la provenance des données ou les événements ultérieurs ne sont pas concernés.
L'appelant ne devrait pas être dérangé par les contrôles.
Créez un modèle bien défini pour le formulaire avec lequel travailler, soit dans son propre module de classe dédié, soit encapsulé dans le code-behind du formulaire - exposez le modèle avec les procédures Property Get
, et faites en sorte que le code client fonctionne avec ceci: la forme une abstraction sur les contrôles et leurs détails les plus concrets, exposant uniquement les données pertinentes au code client.
Cela signifie un code qui ressemble à ceci:
With New UserForm1
.Show vbModal
If Not .IsCancelled Then
MsgBox .Message, vbInformation
End If
End With
Au lieu de cela:
With New UserForm1
.Show vbModal
If Not .IsCancelled Then
MsgBox .txtMessage.Text, vbInformation
End If
End With
Gérez l'événement QueryClose.
Les formulaires ont généralement un bouton Fermer et les invites / boîtes de dialogue ont les boutons Ok et Annuler ; l'utilisateur peut fermer le formulaire en utilisant la boîte de contrôle du formulaire (le bouton rouge "X"), qui détruit l'instance de formulaire par défaut (une autre bonne raison de travailler avec une nouvelle instance à chaque fois ).
With New UserForm1
.Show vbModal
If Not .IsCancelled Then 'if QueryClose isn't handled, this can raise a runtime error.
'...
End With
End With
Le moyen le plus simple de gérer l'événement QueryClose
consiste à définir le paramètre Cancel
sur True
, puis à masquer le formulaire au lieu de le fermer :
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Cancel = True
Me.Hide
End Sub
De cette façon, le bouton "X" ne détruira jamais l'instance et l'appelant peut accéder en toute sécurité à tous les membres publics.
Cachez, ne fermez pas.
Le code qui crée un objet doit être responsable de sa destruction: ce n'est pas la responsabilité du formulaire de se décharger et de se terminer.
Évitez d'utiliser Unload Me
dans le code d'un formulaire. Appelez Me.Hide
place, afin que le code appelant puisse toujours utiliser l'objet créé lors de la fermeture du formulaire.
Nommez les choses.
Utilisez les propriétés (F4 de) de nommer soigneusement chaque contrôle sur un formulaire. Le nom d'un contrôle est utilisé dans le code-behind, à moins que vous n'utilisiez un outil de refactoring capable de gérer cela, renommer un contrôle va casser le code - il est donc beaucoup plus facile de faire les choses en premier lieu. pour définir exactement laquelle des 20 zones de TextBox12
représente.
Traditionnellement, les contrôles UserForm sont nommés avec des préfixes de style hongrois:
-
lblUserName
pour un contrôleLabel
qui indique un nom d'utilisateur. -
txtUserName
pour un contrôleTextBox
où l'utilisateur peut entrer un nom d'utilisateur. -
cboUserName
pour un contrôleComboBox
lequel l'utilisateur peut entrer ou sélectionner un nom d'utilisateur. -
lstUserName
pour un contrôleListBox
où l'utilisateur peut choisir un nom d'utilisateur. -
btnOk
oucmdOk
pour un contrôleButton
libellé "Ok".
Le problème est que lorsque par exemple l'interface utilisateur obtient redessinée et un ComboBox
des modifications à un ListBox
, le nom doit changer pour refléter le nouveau type de contrôle: il est préférable de contrôles de nom pour ce qu'ils représentent, plutôt qu'après leur type de contrôle - à découpler la code de l'interface utilisateur autant que possible.
-
UserNameLabel
pour une étiquette en lecture seule qui indique un nom d'utilisateur. -
UserNameInput
pour un contrôle où l'utilisateur peut entrer ou choisir un nom d'utilisateur. -
OkButton
pour un bouton de commande intitulé "Ok".
Quel que soit le style choisi, tout est meilleur que de laisser tous les contrôles à leurs noms par défaut. La cohérence dans le style de nommage est également idéale.
Gestion de la requêteClose
L'événement QueryClose
est QueryClose
chaque fois qu'un formulaire est sur le point d'être fermé, qu'il s'agisse d'une action utilisateur ou d'un programme. Le paramètre CloseMode
contient une valeur enum VbQueryClose
qui indique comment le formulaire a été fermé:
Constant | La description | Valeur |
---|---|---|
vbFormControlMenu | Le formulaire se ferme en réponse à l'action de l'utilisateur | 0 |
vbFormCode | Le formulaire se ferme en réponse à une instruction Unload | 1 |
vbAppWindows | La session Windows se termine | 2 |
vbAppTaskManager | Le gestionnaire de tâches Windows ferme l'application hôte | 3 |
vbFormMDIForm | Non pris en charge dans VBA | 4 |
Pour une meilleure lisibilité, il est préférable d'utiliser ces constantes au lieu d'utiliser directement leur valeur.
Un objet utilisateur annulable
Étant donné un formulaire avec un bouton Annuler
Le code-behind du formulaire pourrait ressembler à ceci:
Option Explicit
Private Type TView
IsCancelled As Boolean
SomeOtherSetting As Boolean
'other properties skipped for brievety
End Type
Private this As TView
Public Property Get IsCancelled() As Boolean
IsCancelled = this.IsCancelled
End Property
Public Property Get SomeOtherSetting() As Boolean
SomeOtherSetting = this.SomeOtherSetting
End Property
'...more properties...
Private Sub SomeOtherSettingInput_Change()
this.SomeOtherSetting = CBool(SomeOtherSettingInput.Value)
End Sub
Private Sub OkButton_Click()
Me.Hide
End Sub
Private Sub CancelButton_Click()
this.IsCancelled = True
Me.Hide
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = VbQueryClose.vbFormControlMenu Then
Cancel = True
this.IsCancelled = True
Me.Hide
End If
End Sub
Le code d'appel peut alors afficher le formulaire et savoir s'il a été annulé:
Public Sub DoSomething()
With New UserForm1
.Show vbModal
If .IsCancelled Then Exit Sub
If .SomeOtherSetting Then
'setting is enabled
Else
'setting is disabled
End If
End With
End Sub
La propriété IsCancelled
renvoie True
lorsque le bouton Annuler est cliqué ou lorsque l'utilisateur ferme le formulaire à l'aide de la boîte de contrôle .