Voir le flux RSS

Pierre Fauconnier

VBA: A quoi sert un code évènementiel?

Noter ce billet
par , 22/04/2020 à 16h54 (452 Affichages)
Salut.

Je vois souvent des codes événementiels qui font "plein de choses"... Pas sûr que ce soit une bonne pratique!

Dans ce billet, j'explique déjà pourquoi il ne faut jamais appeler du code événementiel, chose que je vois trop fréquemment sur le forum et qui est pour moi une mauvaise pratique. Un code événementiel ne peut être "appelé" que par l'événement considéré, sinon ce n'est plus du code événementiel. Certains ont déjà du mal à ce stade, apparemment.

Un code événementiel est un code qui s'exécute lorsqu'un événement survient dans l'application. Les événements les plus souvent utilisés, en VBA et dans Excel notamment, sont ceux qui surviennent à la suite d'une action de l'utilisateur (ouverture d'un fichier, activation d'un onglet, modification de la valeur d'une cellule, clic sur un bouton, ...). Il faut bien noter qu'un événement ne survient qu'avec des objets. Je ne vais pas lister ici tous les événements qui pourraient survenir, mais vous pouvez les détecter dans un module de classe, pour autant que la classe gère les événements.

A titre d'exemple, voici les événements que vous pouvez gérer dans une feuille de classeur

Nom : 2020-04-23_075733.png
Affichages : 155
Taille : 41,5 Ko


Voici ceux que vous pouvez gérer pour un bouton de commande

Nom : 2020-04-23_080017.png
Affichages : 129
Taille : 22,7 Ko




Ici, je vais simplement exposer le cas où, à l'ouverture d'Excel, on a besoin qu'un certain code soit utilisé. Comme exemple, je vais prendre le cas de devoir masquer toutes les feuilles sauf une*.

On pourrait programmer ainsi, et ça fonctionnerait fort bien:

Code vba : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
Private Sub Workbook_Open()
   Dim sh As Object
 
   Worksheets("Accueil").Visible = xlSheetVisible
   For Each sh In Sheets
     If sh.Name <> "Accueil" Then sh.Visible = xlSheetHidden
   Next
End Sub

Le problème va surgir lorsqu'il va falloir réaliser également d'autres tâches lors de l'ouverture, par exemple, récupérer le username de l'utilisateur pour afficher sur la feuille d'accueil certaines données le concernant et qui se trouvent dans une autre feuille du classeur. Voici l'événement adapté pour récupérer la liste des collaborateurs de l'utilisateur est l'afficher dans un tableau structuré sur la feuille d'accueil

Code vba : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Private Sub Workbook_Open()
  Dim sh As Object
  Dim r As Range
  Dim User As String
  Dim Target As Range
 
  Worksheets("Accueil").Visible = xlSheetVisible
  For Each sh In Sheets
    If sh.Name <> "Accueil" Then sh.Visible = xlSheetHidden
  Next
 
  User = Environ("username")
  If Not Range("t_MesCollaborateurs").ListObject.DataBodyRange Is Nothing Then _
    Range("t_MesCollaborateurs").ListObject.DataBodyRange.Delete
  For Each r In Range("t_Collaborateurs[Resp]")
    If r.Value = User Then
      Set Target = Range("t_Mescollaborateurs").ListObject.ListRows.Add().Range
      Target.Value = r(1, 2).Value
    End If
  Next
End Sub

Et là, notre code devient du code poubelle. On multiplie les variables au sein de la procédure, et pour peu que l'on ait un troisième "truc" à réaliser à l'ouverture, le code devient ingérable et une chatte n'y retrouverait pas ses jeunes...

Ce qu'il faut faire, pour utiliser une architecture professionnelle et ne pas coder comme un goret, c'est respecter la règle "une procédure = une responsabilité"... La procédure sur ouverture a la responsabilité d'appeler les procédures qui vont préparer le classeur, chaque procédure ayant une responsabilité propre.

Dès lors, dans un module standard, on devrait trouver les deux procédures suivantes:
Code vba : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Sub ShowMenu()
  Dim sh As Object
 
  Worksheets("Accueil").Visible = xlSheetVisible
  For Each sh In Sheets
    If sh.Name <> "Accueil" Then sh.Visible = xlSheetHidden
  Next
End Sub
 
Sub RetrieveStaff()
  Dim r As Range
  Dim User As String
  Dim Target As Range
 
  User = Environ("username")
  If Not Range("t_MesCollaborateurs").ListObject.DataBodyRange Is Nothing Then _
    Range("t_MesCollaborateurs").ListObject.DataBodyRange.Delete
  For Each r In Range("t_Collaborateurs[Resp]")
    If r.Value = User Then
      Set Target = Range("t_Mescollaborateurs").ListObject.ListRows.Add().Range
      Target.Value = r(1, 2).Value
    End If
  Next
End Sub

La procédure événementielle à l'ouverture se réduit alors à ceci:
Code vba : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
Private Sub Workbook_Open()
  ShowMenu
  RetrieveStaff
End Sub

Voilà, pour moi, comment on code proprement, en rendant son code compréhensible, maintenable, évolutif...



Bon travail avec Excel et VBA...

* J'écris ce billet en réaction aux "solutions" vues sur cette discussion.


Et vous, comment codez-vous vos évènements?

Envoyer le billet « VBA: A quoi sert un code évènementiel? » dans le blog Viadeo Envoyer le billet « VBA: A quoi sert un code évènementiel? » dans le blog Twitter Envoyer le billet « VBA: A quoi sert un code évènementiel? » dans le blog Google Envoyer le billet « VBA: A quoi sert un code évènementiel? » dans le blog Facebook Envoyer le billet « VBA: A quoi sert un code évènementiel? » dans le blog Digg Envoyer le billet « VBA: A quoi sert un code évènementiel? » dans le blog Delicious Envoyer le billet « VBA: A quoi sert un code évènementiel? » dans le blog MySpace Envoyer le billet « VBA: A quoi sert un code évènementiel? » dans le blog Yahoo

Commentaires