0. Introduction▲
Les énumérations peuvent rendre de précieux services dans la conception d'une application. Pourtant elles sont peu utilisées. Est-ce par méconnaissance de leurs possibilités ? Dans ce tutoriel nous allons faire un tour d'horizon des utilisations possibles et de leurs capacités à améliorer la lisibilité du code.
L'énumération dans VBA est apparue avec la version 2000 d'Office. Elle est disponible dans toutes les applications qui utilisent ce langage.
I. Définition▲
Les énumérations permettent d'attribuer des noms à des valeurs numériques, de la même manière que les constantes, à la différence que ces noms sont regroupés dans un ensemble. Elles sont donc plus faciles à retrouver.
II. Déclaration▲
Les énumérations se déclarent de la manière suivante :
[Public
][Private
] Enum Nom_Enumération
MembreEnum1 =
[Valeur_Constante]
MembreEnum2 =
[Valeur_Constante]
End
Enum
L'argument de portée, « Public » ou « Private », est facultatif. S'il est omis l'énumération sera publique.
Les valeurs des constantes sont toujours de type Long, donc un entier positif ou négatif. Elles peuvent être omises mais dans ce cas le premier membre aura pour valeur 0. Les autres membres auront la valeur du membre précédent plus 1.
Les valeurs de l'énumération suivante, qui n'a aucun sens pratique, sont volontairement omises pour démontrer la règle précédente.
Public
Enum eMois
Janvier =
1
Fevrier
Mars
End
Enum
Debug.
Print
eMois.
Fevrier
'
donne
2
Debug.
Print
eMois.
Mars
'
donne
3
II-A. Énumération et classe▲
L'énumération déclarée publique « Public » dans une classe à la particularité d'être visible dans l'ensemble de l'application. Pour qu'elle ne soit pas visible dans les autres modules, sa portée doit être privée « Private ».
II-B. Énumération et bibliothèque▲
Lorsque vous déclarez des énumérations publiques portant le même nom dans une même bibliothèque (ou fichier ACCESS), vous avez un message d'ambigüité.
Dans le cas où les énumérations de même nom sont dans des bibliothèques différentes, c'est celle qui est déclarée dans la bibliothèque qui est utilisée, sinon Microsoft ACCESS utilise l'ordre des références.
Vous pouvez cependant jouer sur la portée (« Public/Private ») pour des énumérations différentes portant le même nom au sein de modules différents. Bien qu'elles s'affichent dans la liste d'autocomplétion, les membres seront ceux de l'énumération de la portée courante.
Personnellement, j'évite d'utiliser le même nom pour des énumérations différentes, car cela n'ajoute que de la confusion au code.
III. Utilisations▲
Les utilisations sont nombreuses, nous n'allons pas en dresser la liste exhaustive mais plutôt démontrer celles qui me paraissent importantes, soit dans un but didactique, soit pour leur côté astucieux ou pratique.
III-A. Énumération dans les paramètres de fonction▲
Lorsque vous utilisez certaines commandes de VBA, par exemple « Docmd.OpenForm », vous pouvez constater que certaines options comportent des constantes qui sont reprises dans une liste au moment de l'écriture.
Il s'agit de simples énumérations natives. Nous pouvons l'appliquer à nos propres fonctions ou procédures.
Commencez par créer un module VBA, puis créez l'instruction « Enum » et ses membres dans l'en-tête du module.
Option
Compare Database
Option
Explicit
Public
Enum efFichierExt
Unite =
8
Chemin =
16
Fichier =
32
Extension =
64
End
Enum
Pour le nom de l'énumération, j'utilise un « e » comme « énumération », suivi du nom de la fonction. Il ne s'agit pas là d'une convention mais d'un moyen pour les retrouver facilement dans l'autocomplétion.
Les membres doivent avoir un nom explicite pour s'y retrouver. Ne perdez pas de vue que l'énumération doit permettre une meilleure lisibilité du code.
Maintenant vous avez accès à un nouvel élément dans la liste des objets de VBA.
Pressez F2 et tapez « eff » dans la liste des éléments puis cliquez sur le bouton de recherche.
Notre énumération fait maintenant partie de l'application. Voici ce qui se passe lors de son utilisation :
On indique que le paramètre est du type « efFichierExt », soit notre énumération.
Lorsque vous faites référence au paramètre « iType » dans la fonction, voici ce que vous obtenez :
Je vous livre ici la fonction complète qui utilise l'énumération en paramètre. N'oubliez pas de créer l'énumération fournie précédemment.
Public
Function
fFichierExt
(strCheminFichier As
String
, iType As
efFichierExt) As
String
'
Fabrice
CONSTANS
(MVP)
'
Page
personnelle
:
http://loufab.developpez.com
'
Blog
:
2gm.free.fr
'
Retourne
l'un
des
éléments
suivant
le
chemin/fichier
passé
en
référence
'
strCheminFichier
contient
le
chemin
et
fichier
'
iType
=
enum
efFichierExt
'
64
renvoie
l'extension
du
fichier
sans
le
point
'
32
renvoie
le
nom
du
fichier
sans
son
extension
'
16
renvoie
le
chemin
sans
le
nom
ni
l'extension
'
8
renvoie
l'unité
On
Error
GoTo
errSub
Dim
vRetour As
String
If
iType And
Unite Then
'
l'unité
vRetour =
Left
(strCheminFichier, InStr
(strCheminFichier, "
:
"
))
End
If
If
iType And
Chemin Then
'
renvoie
le
chemin
vRetour =
vRetour &
Mid
(strCheminFichier, 3
, InStrRev
(strCheminFichier, "
\
"
) -
2
)
End
If
If
iType And
Fichier Then
'
renvoie
le
nom
du
fichier
Dim
tmpFic As
String
tmpFic =
Right
(strCheminFichier, Len
(strCheminFichier) -
InStrRev
(strCheminFichier, "
\
"
))
vRetour =
vRetour &
Left
(tmpFic, InStrRev
(tmpFic, "
.
"
) -
1
)
End
If
If
iType And
Extension Then
'
renvoie
l'extension
If
iType And
Fichier Then
vRetour =
vRetour &
"
.
"
'
ajoute
un
point
si
le
nom
du
fichier
est
demandé
vRetour =
vRetour &
Right
(strCheminFichier, Len
(strCheminFichier) -
InStrRev
(strCheminFichier, "
.
"
))
End
If
fFichierExt =
vRetour
Exit
Function
errSub
:
On
Error
GoTo
0
Exit
Function
End
Function
Cette fonction traite une chaine contenant un chemin et un nom de fichier. Elle renvoie le ou les composants demandés par le paramètre d'énumération.
Voici son comportement lors de l'appel :
On voit clairement la liste des membres de l'énumération.
L'énumération étant disponible dans l'ensemble du code, on l'utilise pour tester les valeurs passées en argument à l'intérieur de la fonction.
III-A-1. Astuce▲
Lorsque vous faites un appel aux commandes, fonctions ou propriétés, vous avez peut-être remarqué que certaines d'entre elles acceptent plusieurs paramètres additionnés, c'est notamment le cas de « Msgbox ».
La fonction « fFichierExt » a le même comportement parce que les valeurs des membres de l'énumération s'y prêtent.
Grâce à l'opérateur de conjonction binaire, soit « And » en VBA, nous traitons les arguments multiples.
Ce traitement est possible grâce à la valeur utilisée dans les constantes (8, 16, 32, 64.) qui correspondent aux décalages de bits suivants :
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Valeur | 64 | 32 | 16 | 8 | 4 | 2 | 1 | 0 |
Pour plus d'information sur l'algèbre de Boole et les opérations binaires, référez-vous à un cours d'algèbre de Boole et binaire.
III-B. Masquer les membres▲
Pour qu'un membre n'apparaisse pas dans la liste ou dans l'explorateur d'objets « F2 », vous devez ajouter le préfixe « _ » à son nom. En VBA, le caractère « souligné » (_ ou underscore) n'est pas admis au début d'un nom. Le nom doit être entouré de crochets.
[_NomVariable] = valeur
Dans l'exemple suivant le dernier membre « Unc » est caché.
Public
Enum efFichierExt
Unite =
8
Chemin =
16
Fichier =
32
Extension =
64
[_UNC] =
128
End
Enum
Comme pour la liste d'autocomplétion, l'explorateur d'objets « F2 » ne l'affiche pas. Cependant vous pouvez faire apparaitre les membres masqués en faisant « clic-droit » sur la fenêtre de l'explorateur d'objet et choisir d'Afficher les membres masqués.
Il apparait grisé avec le caractère de soulignement, dans l'explorateur et dans la liste.
Attention ! L'option Afficher les membres masqués n'est valable que le temps de la session Microsoft ACCESS.
Pour faire un appel à un membre masqué, vous devez utiliser le nom tel qu'il apparait dans la liste, sans crochet, et non comme il a été déclaré.
efFichierExt._UNC
III-C. Constantes métiers▲
Dans le code, nous avons souvent besoin de faire appel à des constantes métiers, plutôt que de mettre ces valeurs en dur dans le code. On aura tout intérêt à les associer dans une énumération. D'une part pour la praticité de la relecture du code mais également en cas de modification de celui-ci.
Prenons l'exemple d'alertes pour un circuit de livraison.
Public
Enum eLivraison
Achat =
-
1
EnStock =
0
Emballe =
2
Entrepot =
3
Livraison =
4
Livre =
5
End
Enum
Dans le code vous testez les écarts de dates à différents moments du circuit. Voici sans l'utilisation de l'énumération :
Select
Case
Etat
Case
=
-
1
MsgBox
"
Cet
article
est
en
commande.
"
Case
=
0
MsgBox
"
Cet
article
est
en
stock.
"
Case
=
2
MsgBox
"
Cet
article
est
emballé.
"
Le même code avec l'énumération :
Select
Case
Etat
Case
=
eLivraison.
Achat
MsgBox
"
Cet
article
est
en
commande.
"
Case
=
eLivraison.
EnStock
MsgBox
"
Cet
article
est
en
stock.
"
Case
=
eLivraison.
Emballe
MsgBox
"
Cet
article
est
emballé.
"
C'est déjà plus clair. Mais là où il y a un sérieux avantage c'est lorsque les valeurs changent ou que vous ajoutez des étapes, vous n'intervenez plus qu'à un seul endroit, dans la déclaration de l'énumération. Vous vous épargnez ainsi de longues recherches dans le code, des oublis possibles et les bugs qui en découlent.
IV. Application à l'interface▲
L'énumération peut également rendre d'autres services, notamment lors de la relation avec l'interface. En effet, tous les contrôles qui utilisent un entier pour identifier un élément sont potentiellement concernés : les listes modifiables ou non, les onglets et à moindre effet les groupes d'options.
IV-A. Liste, onglet et groupe d'options▲
L'intérêt principal est d'évoluer vers un code plus clair et donc d'accroitre la rapidité de correction et d'évolution.
Commençons par créer un formulaire avec une zone de liste (liste0) basée sur une table contenant plusieurs colonnes.
Dans mon exemple il s'agit d'une table Contacts avec les colonnes habituelles : Id, Nom, Prénom, etc.
Une fois cette liste définie, nous allons récupérer dans le code quelques informations lors d'un double-clic. Créez l'événement « Sur Double-clic » et insérez-y le code suivant :
Private
Sub
Liste0_DblClick
(Cancel As
Integer)
MsgBox
Me.
Liste0
.
Column
(0
) &
vbCrLf
&
_
Me.
Liste0
.
Column
(1
) &
vbCrLf
&
_
Me.
Liste0
.
Column
(2
) &
vbCrLf
&
_
Me.
Liste0
.
Column
(3
)
End
Sub
Comme vous le voyez il n'utilise pas l'énumération. Le code est difficile à analyser au premier coup d'oeil puisqu'il faudra se référer à la liste pour le comprendre. Dans le cas où l'ordre des colonnes change vous devrez, comme dans l'exemple précédent, faire une recherche pour remettre le tout dans le nouvel ordre.
Voici le résultat :
Maintenant en utilisant l'énumération, voici comment ce code serait écrit. D'abord on définit l'énumération puis on l'utilise dans l'évènement.
Private
Enum eListe
IdContact
Nom
Prenom
TelephonePro
TelephoneMob
TelephonePerso
Adresse
CodePostal
Ville
End
Enum
Private
Sub
Liste0_DblClick
(Cancel As
Integer)
MsgBox
Me.
Liste0
.
Column
(eListe.
IdContact
) &
vbCrLf
&
_
Me.
Liste0
.
Column
(eListe.
Nom
) &
vbCrLf
&
_
Me.
Liste0
.
Column
(eListe.
Prenom
) &
vbCrLf
&
_
Me.
Liste0
.
Column
(eListe.
TelephonePro
)
End
Sub
Avouez que c'est nettement plus lisible !
À présent, vos utilisateurs demandent à réorganiser l'ordre des colonnes en plaçant l'adresse complète avant les numéros de téléphone. Côté IHM vous allez modifier la liste, puis du côté du code, grâce à l'Enum, vous n'aurez qu'à modifier l'ordre de ses membres.
Private
Enum eListe
IdContact
Nom
Prenom
Adresse
CodePostal
Ville
TelephonePro
TelephoneMob
TelephonePerso
End
Enum
Voici la modification effectuée :
Vous avez gagné un temps précieux et évité des oublis générateurs de retours de la part de vos utilisateurs.
Cette technique peut être appliquée aux listes modifiables, aux onglets et aux groupes d'options dans la mesure où ils sont fortement présents dans votre code.
Le code suivant s'applique à un onglet.
Private
Enum eOnglet
Contact
Factures
Reglements
End
Enum
Private
Sub
btnContact_Click
()
Me.
CtlTab
=
eOnglet.
Contact
End
Sub
Private
Sub
btnFactures_Click
()
Me.
CtlTab
=
eOnglet.
Factures
End
Sub
Private
Sub
btnReglements_Click
()
Me.
CtlTab
=
eOnglet.
Reglements
End
Sub
Les boutons de commande ont été utilisés à la place des onglets classiques car l'utilisateur souhaitait avoir les étiquettes en bas.
Comme pour la liste, en cas de modification, vous n'intervenez que dans l'IHM et dans la déclaration de l'énumération.
Par exemple, entre les pages Contact et Factures nous rajoutons Commandes.
Voici ce que devient le code :
Private
Enum eOnglet
Contact
Factures
Reglements
Commandes
End
Enum
Private
Sub
btnContact_Click
()
Me.
CtlTab
=
eOnglet.
Contact
End
Sub
Private
Sub
btnFactures_Click
()
Me.
CtlTab
=
eOnglet.
Factures
End
Sub
Private
Sub
btnReglements_Click
()
Me.
CtlTab
=
eOnglet.
Reglements
End
Sub
Private
Sub
btnCommandes_Click
()
Me.
CtlTab
=
eOnglet.
Commandes
End
Sub
Nous avons rajouté Commandes dans la déclaration de l'énumération, dans la procédure pour le bouton ainsi que la nouvelle page avec le numéro d'index 3. Nous aurions pu tout aussi bien l'insérer entre Contacts et Factures et décaler les index.
V. Conclusion▲
Comme nous l'avons vu, l'énumération rend le code plus lisible et l'application plus facile à maintenir. Simple à mettre en oeuvre comme à utiliser, elle peut servir en toute circonstance. Vous n'aurez plus d'excuses pour ne pas l'utiliser.
VI. Remerciements▲
Je remercie Arkham46 et Pierre Fauconnier pour leur relecture technique et leurs conseils avisés ainsi que Dolphy35 et F-leb pour la correction orthographique.