Comme toute suite d’instructions, les macros VBA n’échappent pas aux dures erreurs de la programmation.
Parmi ces erreurs, nous pouvons remarquer que certaines sont liées à la syntaxe (ce qui empêche le programme de comprendre l’instruction) ou encore que d’autres sont liées à la logique (ce qui fait que le programme plante ou donne des résultats erronés). S’il est en général facile de se prémunir et de corriger les premières, les secondes peuvent vite donner un peu plus de fil à retordre !
Au cours de ce billet, nous allons voir comment tirer profit de l’éditeur VBE et du VBA pour éviter ces désagréments et pour déboguer nos macros.
C’est parti !
Se prémunir des erreurs
Les erreurs ne sont pas fatidiques, mais pas inévitables non plus. Quoiqu’il en soit, il existe différentes approches pour nous en prémunir le plus possible et nous allons en étudier quelques unes durant cette première section.
Se prémunir des erreurs de syntaxe
Les erreurs liées à la syntaxe sont de légers problèmes dus bien souvent à un manque d’attention ou à une méconnaissance du langage.
Debug.Print ("Hello World!")
Debug.Print "Hello", "World!"
'Debug.Print("Hello", "World!") 'Erreur de syntaxe
L’éditeur met en avant le code problématique afin de nous alerter qu’il y a quelque chose qui cloche :
Si nous souhaitons avoir plus de précisions sur l’erreur, nous devons faire apparaître cette petite fenêtre :
Dans celle-ci, se trouvent un message plus ou moins parlant ainsi qu’un bouton "Aide" qui, dans notre cas, nous redirigera vers cette page où nous pouvons apprendre dans le point "Expected: )" qu’il ne faut pas mettre de parenthèses ici.
La traduction française de la documentation n’est pas toujours très compréhensive, c’est pourquoi je vous recommande de passer en anglais lorsque c’est possible et que ce n’est pas moins compréhensif pour vous en changeant le "/fr-fr/" en "/en-us/" dans l’URL.
Pour faire apparaître ces petites fenêtres, il y a plusieurs possibilités.
Vérification automatique de la syntaxe
Tout d’abord, nous pouvons activer l’option "Vérification automatique de la syntaxe" de la fenêtre "Options" accessible via le menu "Outils" de l’éditeur.
En cochant celle-ci, la fenêtre d’erreur s’affichera directement une fois le code erroné écrit.
C’est une option intéressante pour débuter, mais qui peut devenir un peu énervante avec de l’expérience, car la fenêtre est assez intempestive et la coloration de l’erreur suffit à nous alerter.
Compilation du projet
Un autre moyen de vérifier son code et d’afficher les erreurs est de compiler le projet. Cela se fait via le menu "Débogage".
Cette solution est moins dérangeante. Néanmoins la compilation s’arrêtant à la première erreur trouvée, il peut être judicieux de la lancer régulièrement pour éviter de tout rattraper d’un coup.
Se prémunir des erreurs de logique
Les erreurs liées à la logique peuvent être causées par différentes choses (boucle incorrecte, variable prenant une mauvaise valeur, etc.). Elles peuvent amener en conséquence des erreurs à l’exécution ou un résultat erroné mais sans erreur d’exécution.
Là encore, nous pouvons noter quelques façons de se prémunir de ces erreurs.
Déclarer ses variables
Par défaut, il n’est pas obligatoire de déclarer ses variables. Toutefois, il est recommandé de le faire. En plus d’obtenir un gain de clarté et de performance, cela évite des problèmes induits par des erreurs de saisie.
iNombre1 = 5
iNombre2 = 10
Debug.Print ("Résultat : " & iNombre1 + iNombre3) ' Résultat : 5
Pour être sûr de ne pas oublier une déclaration, nous pouvons ajouter Option Explicit
en début de module. Cela aura pour effet de lever une erreur en de cas variable non déclarée :
Remarquons qu’en cochant l’option "Déclaration des variables obligatoire" de la fenêtre "Options" vue précédemment, ce code est automatiquement ajouté dans les nouveaux modules.
Concevoir son programme
Concevoir son programme ou son algorithme en amont en langage naturel peut aider à l’établir avec clarté pour le transcrire ensuite en langage informatique, réduisant ainsi les possibles erreurs de logique.
Tester
Enfin, il peut être bienvenue d’effectuer des tests manuels ou automatisés pour se convaincre que le code a effectivement le comportement attendu.
Au fil de cette section, nous avons vu comment éviter et corriger certaines erreurs. Certaines erreurs seront plus coriaces et il faudra lors chercher à comprendre leur origine.
Analyser l'évolution des données...
Durant l’exécution du programme, les données vont vivre. Elles vont prendre une valeur, puis potentiellement évoluer au fil des opérations.
Si elles n’ont pas la valeur que nous pensons qu’elles doivent avoir, c’est que quelque chose ne va pas. Il faut alors comprendre ce qui ne fonctionne pas correctement.
Il y a plusieurs façons de suivre ces données.
…en les écrivant
Nous pouvons les écrire quelque part.
Dans une boîte de dialogue avec MsgBox
La fonction MsgBox
permet d’ouvrir une fenêtre de dialogue avec le texte voulu.
Dim iNombre1 As Integer
Dim iNombre2 As Integer
iNombre1 = 5
iNombre2 = 10
MsgBox "Nombre 1 = " & iNombre1 & vbNewLine & _
"Nombre 2 = " & iNombre2 & vbNewLine & _
"Résultat = " & iNombre1 + iNombre2
L’avantage de cette approche est de bloquer l’exécution le temps que la fenêtre est ouverte. Par contre, elle n’est pas adaptée s’il faut suivre beaucoup d’informations comme dans une boucle par exemple.
Dans la fenêtre d’exécution avec Debug.Print
La méthode Print
de l’objet Debug
permet d’écrire du texte dans la fenêtre d’exécution.
Si la fenêtre d’exécution n’est pas visible, il faut l’afficher via le sous-menu "Fenêtre Exécution" dans le menu "Affichage" (raccourci Ctrl+G)
C’est l’approche que nous avons suivie jusqu’à présent et que j’utilise principalement. Elle a l’avantage d’être simple et non bloquante. Le fait qu’elle soit non bloquante peut être vu comme un inconvénient, car on peut se noyer dans la masse de données à moins d’écrire que sous certaines conditions en rajoutant des structures conditionnelles.
Pour nettoyer le contenu de la fenêtre d’exécution, nous pouvons cliquer dedans, tout sélectionner avec Ctrl+A et supprimer avec <-.
Ailleurs
Enfin, nous pouvons aussi imaginer écrire des données ailleurs (feuille de calcul, fichier texte, base de données, etc.). Cela est tout de suite plus complexe et doit être le fait de besoins bien spécifiques.
Pensez à supprimer vos instructions Debug.Print
ou MsgBox
dès que vous n’en avez plus besoin pour ne pas gêner l’exécution du programme ou afficher des données par inadvertance.
…en les visualisant
Il peut être fastidieux de tracer les données soi-même quand il faut procéder à une analyse poussée. En mode débogage, il existe une fenêtre accessible via "Fenêtre Variables locales" du menu "Affichage".
Celle-ci liste pour nous à un instant T les valeurs pour la procédure ou fonction dans laquelle nous nous trouvons.
Qu’est-ce que ce point rouge et cette ligne jaune ?
Pour les besoins de cette section, j’ai un peu triché et j’ai utilisé le débogueur avant l’heure.
Le point rouge est ce que l’on appelle un point d’arrêt. Il sert à indiquer qu’il faut faire une pause dans l’exécution à cet endroit là. Je l’ai placé sur l’entête de la fonction Somme, mais j’aurais pu le mettre plus bas si souhaité. Lorsque la procédure Main est exécutée, la fonction est appelée et le point d’arrêt provoque le passage en mode pas à pas (la ligne jaune).
Les valeurs affichées correspondent à leur état avant exécution de la ligne jaune, comme illustré ci-dessous :
…en les espionnant
Une dernière possibilité est d’espionner les valeurs.
Contrairement à la fenêtre des variables locales, c’est à nous d’indiquer les variables à suivre. Néanmoins, nous avons accès ici à une portée plus étendue ainsi qu’à des possibilités plus intéressantes.
Pour ajouter un espion sur une variable, nous pouvons soit faire clique droit dessus et choisir "Ajouter un espion", soit passer par le sous-menu "Ajouter un espion" du menu "Débogage". Avec le clique droit, le contexte est automatiquement rempli.
Espionnage simple
Pour ce premier exemple, nous faisons de l’espionnage simple en regardant une variable.
Nous pouvons voir que nous avons bien accès à des données dans une portée plus large que la fenêtre des variables locales.
Espionnage conditionné
Autre possibilité avec l’espionnage, c’est de provoquer un arrêt sous certaines conditions, soit si la valeur de l’expression est vraie, soit si la valeur de l’expression change. Cela convient pour suivre l’évolution d’une variable ou s’arrêter à une itération voulue d’une boucle par exemple.
Dans cet exemple, j’ai enlevé le point d’arrêt manuel et nous pouvons constater que le résultat de la somme dépassant 10 provoque bien le passage en mode pas à pas.
Il y a donc plusieurs façons de suivre l’évolution des données. Certaines sont faites pour être utilisées avec le débogueur. L’usage dépendra des besoins.
Recourir au débogueur
Le débogueur permet de maîtriser l’exécution du code (en plaçant des arrêts à des endroits, en exécutant une ligne après l’autre, etc.).
Il est vrai que nom peut faire un peu peur, mais c’est grâce à lui que nous allons pouvoir voir le résultat d’opérations et l’évolution des données à des endroits précis.
Début débogage
Le débogage peut se lancer suite à une erreur d’exécution ou de façon manuelle.
Débogage suite erreur exécution
Lorsque l’exécution du programme est lancée et qu’une erreur se produit, une fenêtre apparaît.
Private Sub Exemple_ErreurExecution()
Dim iNombre1 As Integer
Dim iNombre2 As Integer
Dim iResultat As Integer
iNombre1 = 10
iNombre2 = 0
iResultat = iNombre1 / iNombre2
End Sub
Dans celle-ci, nous pouvons notamment trouver un message plus ou moins parlant ainsi qu’un bouton "Aide".
De plus, nous pouvons aussi voir un bouton "Débogage" et c’est lui qui nous intéresse tout particulièrement. En cliquant dessus, le programme se place sur la ligne ayant planté. Nous pouvons alors analyser les données via les différents moyens étudiés précédemment ainsi qu’en déplaçant la souris sur les variables.
J’ai été assez généreux pour vous montrer différentes possibilités, remarquez l’utilisation de code dans la fenêtre d’exécution
Pour mettre fin à l’exécution et au débogage, il faut cliquer sur le bouton "Réinitialiser".
Débogage manuel
Pour lancer le débogage manuel, nous avons parlé des points d’arrêt qui sont à placer et des espions qui permettent de lancer le débogage sous conditions.
Point d’arrêt
Les points d’arrêt sont ces petits points rouges dans la marge grise. Ils sont là pour signaler qu’il faut faire une pause à ces endroits.
Ils peuvent être ajoutés et supprimés en cliquant dans cette marge grise à côté d’une ligne ou encore via les sous-menus "Basculer le point d’arrêt") (raccourci F9) pour une ligne après avoir cliquée sur celle-ci. Certaines lignes ne permettent pas de placer un point d’arrêt (déclaration de variable, ligne vide, …).
Il est possible de supprimer tous les points d’arrêt via le raccourci Ctrl+Maj+F9.
Usage
Une fois le programme figé, il y a plusieurs possibilités.
Continuer ou arrêter
Outre continuer l’exécution jusqu’au prochain point d’arrêt ou jusqu’à la fin, nous avons vu qu’il était possible de stopper l’exécution :
Ensuite, le menu débogage permet d’avancer au rythme voulu :
Pas à pas détaillé
Ce mode permet de dérouler au détail ligne par ligne en rentrant dans les procédures ou fonctions appelées également. Dans notre exemple, cela a pour effet de dérouler y compris dans la fonction Somme.
Pas à pas principal
Ce mode a pour effet de dérouler sans aller dans le détail des procédures ou fonctions appelées. Dans notre exemple, seules les lignes de la procédure Main seront parcourues.
Pas à pas sortant
Ce mode a pour effet de sortir de la fonction ou procédure en cours (ou d’aller jusqu’au prochain arrêt) pour se placer sur l’instruction suivante. Dans notre exemple, si la fonction Somme avait un point d’arrêt, et que nous faisions pas à pas sortant, nous nous retrouverions sur la ligne suivant l’appel, donc Debug.Print (Somme(5, 4))
.
Exécuter jusqu’au curseur
Cette option permet d’aller jusqu’au prochain point d’arrêt ou à défaut à la fin du programme.
Définir l’instruction suivante
Cette option permet, après avoir au préalable cliqué sur une ligne, de dérouler le programme jusqu’à cette dernière. Elle devient la ligne jaune. Remarquons que les points d’arrêt intermédiaires sont ignorés.
À travers cette dernière section, nous avons étudié l’usage du débogueur de l’éditeur Visual Basic Editor.
C’est déjà la fin de ce billet.
Au cours de celui-ci, nous avons vu comment nous prémunir d’erreurs liées à la syntaxe et de logique ainsi que comment comprendre les erreurs provenant de la logique de notre code, en analysant les données et les instructions.
Certaines erreurs durant l’exécution demande parfois une gestion particulière. Par exemple, si l’utilisateur saisit une mauvaise donnée, nous pourrions vouloir l’alerter plutôt que le programme s’arrête des suites d’un bogue. Le langage VBA offre alors des instructions pour faire cela.
À bientôt !
Quelques ressources :
- Livre Programmation VBA pour Excel pour les nuls (Excel 2010, 2013 et 2016), de John Walkenbach
- La documentation