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 :

 
Sélectionnez
[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.

 
Sélectionnez
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.

image

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.

image

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.

 
Sélectionnez
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.

image

Notre énumération fait maintenant partie de l'application. Voici ce qui se passe lors de son utilisation :

image

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 :

image

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.

 
Sélectionnez
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 :

image

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.

image

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.

image

Grâce à l'opérateur de conjonction binaire, soit « And » en VBA, nous traitons les arguments multiples.

image

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.

 
Sélectionnez
[_NomVariable]  = valeur

Dans l'exemple suivant le dernier membre « Unc » est caché.

 
Sélectionnez
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.

image

Il apparait grisé avec le caractère de soulignement, dans l'explorateur et dans la liste.

image

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é.

 
Sélectionnez
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.

 
Sélectionnez
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 :

 
Sélectionnez
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 :

 
Sélectionnez
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 :

 
Sélectionnez
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 :

image

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.

 
Sélectionnez
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.

 
Sélectionnez
Private Enum eListe
    IdContact
    Nom
    Prenom
    Adresse
    CodePostal
    Ville
    TelephonePro
    TelephoneMob
    TelephonePerso
End Enum

Voici la modification effectuée :

image

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.

 
Sélectionnez
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.

image

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 :

 
Sélectionnez
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.

enum VBA

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.