Macros-commandes VBA/Débogage

Début de la boite de navigation du chapitre
Débogage
Icône de la faculté
Chapitre no 18
Leçon : Macros-commandes VBA
Chap. préc. :Procédures et événements automatiques
Chap. suiv. :Créer des macros complémentaires
fin de la boite de navigation du chapitre
En raison de limitations techniques, la typographie souhaitable du titre, « Macros-commandes VBA : Débogage
Macros-commandes VBA/Débogage
 », n'a pu être restituée correctement ci-dessus.

Toutes les macros, comme tous les codes informatiques, peuvent comporter des erreurs, on pourrait même affirmer : comportent des erreurs. Parmi ces erreurs, on peut trouver différentes causes et effets :

  • Compilation : l'erreur de compilation (ou de syntaxe) survient lorsque VBA rencontre une instruction (ou une donnée) qu’il ne connait pas (par exemple une faute d'orthographe ou de ponctuation sur un mot clé, …). Dans ce cas VBA affiche un message d'erreur avant l'exécution directement sur la ligne comprenant l'erreur de syntaxe, c’est donc l'erreur la plus fréquente et la plus aisée à déceler et réparer.
  • Exécution : l'erreur d'exécution survient lorsque VBA rencontre une instruction interdite (par exemple lancer une impression vers une imprimante qui n'existe pas). Dans ce cas VBA affiche un message d'erreur pendant l'exécution, c’est une erreur assez fréquente et assez aisée à déceler et réparer, par exemple : une division par zéro, une valeur recherchée au-delà d'une limite d'un tableau, …
  • Logique : l'erreur de logique survient lorsque le programmeur constate un résultat inattendu suite à une série d'instructions qu’il a programmé (par exemple le fait de ne pas mettre en gras les bonnes cellules). La macro s'exécute mais ne réalise pas ce qu'elle est censée faire. C'est l'erreur la moins fréquente et la moins aisée à déceler et réparer, par exemple : un test si erroné, une boucle de trop dans un calcul, …

Exemple d'erreur d'exécution : erreur de débordement

modifier

On désire créer une macro qui supprime certaines lignes Excel en rencontrant la valeur "fauteuil" sur cette ligne, soit les données suivantes de la feuille : cellule A1 = "chaise", A2 = "fauteuil", A3 = "fauteuil", A4 = "tabouret"... L'algorithme suivant qui semble juste à première vue est cependant faux :

Pour i de 1 à 3
 Si A(i)= "fauteuil" Alors SupprimerLigne(i)
Suivant
Début de l'exemple
Fin de l'exemple


POURQUOI : dès le second tour de boucle, la ligne 2 (avec "fauteuil") sera supprimée ce qui entrainera le passage de la ligne 3 (avec encore "fauteuil") en ligne 2, la ligne 2 étant déjà traitée par le programme ce nouveau "fauteuil" ne sera pas supprimé

SOLUTION : inverser le sens de parcours de la boucle en partant de la dernière ligne

Début de l'exemple
Fin de l'exemple


Exemple d'erreur de logique : boucle sans fin

modifier

On désire créer une boucle qui tourne tant qu'une condition de sortie n’est pas atteinte, ici la rencontre du libellé "fauteuil" sur une ligne, soit les données suivantes de la feuille (1000 lignes renseignées) : cellule A1 = "chaise", A2 = "tabouret", A3 = "tabouret", A4 = "tabouret"... L'algorithme suivant qui semble juste à première vue est cependant faux :

Tant que la ligne lue est différente de "fauteuil"
 Afficher "je n'ai pas encore trouvé un fauteuil"
 Passer à la ligne suivante
Fin Tant que
Afficher "j'ai trouvé un fauteuil"
Début de l'exemple
Fin de l'exemple


POURQUOI : le mot "fauteuil" n'existant pas dans la feuille Excel, la boucle deviendra infinie et visitera toutes les lignes du classeur (plusieurs millions). Une telle boucle est très souvent considérée comme un problème car elle sollicite trop de ressources ordinateur.

SOLUTION : ajouter une condition d'arrêt obligatoire, ici dès que le programme aura parcouru plus de 1000 lignes Excel

Début de l'exemple
Fin de l'exemple


Erreur d'encodage

modifier

Si une importation vers une base de données remplace tous les caractères non ANSI (ex : "é"), il faut convertir le fichier de PC ANSI en PC DOS.

Types d'erreurs

modifier

content_types.xml

modifier

Il s'agit d'une erreur apparaissant après un publipostage Word : résolue en désinstallant un Office 2003 qui était à côté d'un 2007.

Erreur d'exécution '7': Mémoire insuffisante

modifier

Une variable a dépassé la valeur prévue (listée dans le chapitre Les types en VB). Il convient donc de changer son type (par exemple passer d'Integer à Long), ou bien de diminuer sa valeur.

Erreur d'exécution '9': L'indice n'appartient pas à la sélection

modifier

Cela se produit par exemple :

  • Quand on appelle une feuille qui n'existe pas (Worksheets("MaFeuille")), on peut donc rendre le traitement plus générique avec des numéros (Worksheets(1)).
  • Quand on appelle un tableau avec un indice qui le dépasse, il faut donc le redimensionner :
 ReDim MonTableau(5)
 MsgBox IsEmpty(MonTableau(4))

Erreur d'exécution '28': Espace pile insuffisant

modifier

Peut survenir en cas de boucle infinie ou de récursion infinie.

Erreur d'exécution '70': Accès refusé

modifier

Un objet de formulaire possède une propriété ControlSource non vide, donc on ne peut pas le modifier en appelant sa méthode .AddItem.

Erreur d'exécution '70': Permission refusée

modifier

Un fichier ouvert est peut-être en train d’être rouvert.

Erreur d'exécution '75': Erreur d'accès Chemin/Fichier

modifier

Un fichier ouvert ne peut pas être supprimé avant sa fermeture.

Erreur d'exécution '91': Variable objet ou variable de bloc With non définie

modifier

Il se peut qu'une fonction soit appliquée à une variable vide. Ex :

 set searched = Nothing
 MsgBox searched   ' Erreur
 x = Len(searched) ' Erreur

Il faut donc lever l'exception.

Erreur d'exécution '424': Objet requis

modifier

Une méthode est appliquée sur un objet déclaré qui n'en dispose pas.

  1. Est-il bien initialisé ?
  2. Si oui, l'explorateur d'objets permet de vérifier l’existence de la méthode.
  3. Si la méthode existe, c’est que l’objet est mal initialisé. Par exemple à cause de plusieurs déclarations sur la ligne du New :
' Pas bien :
Dim Command, Command2 As New ADODB.Command

' Bien :
Dim Command As New ADODB.Command
Dim Command2 As New ADODB.Command

Erreur d'exécution '462': Le serveur distant n'existe pas ou n’est pas défini

modifier

Il faut libérer la ressource avant sa deuxième exécution.

Erreur d'exécution '450': Nombre d'arguments incorrect ou affectation de propriété incorrecte

modifier

Se produit quand on tente d'affecter un objet à une variable dont le type est incompatible.

Erreur d'exécution '1004': Erreur définie par l’application ou par l’objet

modifier

Si cela se produit lors de la fermeture du classeur, il faut modifier l'évènement[1].

Sinon, regarder si le programme n'appelle pas une cellule Excel avec des coordonnées non entières (ex : B3,33).

Enfin, il faut savoir que le VBA ne peut pas ajouter de formule Excel en français. Celles en anglais fonctionnent avec une syntaxe un peu différente pour qu’elles soient interprétées pendant son exécution :

  1. Positions absolues avec R pour row et C pour column, et pour les relatives entre crochets (ex : C[0] = C = colonne courante).
  2. Virgule au lieu de point-virgule.
  3. Caractère d'échappement pour les guillemets.

Par exemple :

 ' Affiche la valeur correspondant à la date d'une table liée
 Range("C7").Value = "=SUMIFS(Feuil2!C1,Feuil2!C3,TEXT(R5C[-1], ""aaaammjj""),Feuil2!C2, RC1)"

Affichera dans Excel :

=SOMME.SI.ENS(Feuil2!$A:$A;Feuil2!$C:$C;TEXTE(B$5; "aaaammjj")Feuil2!$B:$B; $A7)

Remarque : ne pas ajouter d'addition dans ces formules (R[5]C[-1+2]).

Erreur d'exécution '1004': La méthode 'Add' de l'objet 'Workbooks' a échoué

modifier

Si on ne peut plus créer de classeur Excel sans VBA, Excel n’a plus assez de ressources : redémarrer la machine.

Erreur d'exécution '1004': La méthode de la classe Range a échoué

modifier

Le type d'un argument placé dans Range() n'est pas une cellule.

Erreur d'exécution '3421': L'application utilise une valeur d'un type incorrect pour l'opération en cours

modifier

Une variable a dépassé la valeur prévue. Il convient donc de modifier sa valeur, gérer une exception, ou bien de changer son type (par exemple passer de Command.CreateParameter("@Variable1", adInteger, adParamInput) ou Command.CreateParameter("@Variable1", adVarChar, adParamInput, 4), à Command.CreateParameter("@Variable1", adVarChar, adParamInput, 10)).

Erreur d'exécution '3704': Cette opération n’est pas autorisée si l’objet est fermé

modifier

Apparait quand on cherche à accéder à un objet ADODB.Recordset vide, par exemple avec ResultSet.BOF.

Erreur d'exécution '-2147217900': La procédure ou fonction 'xxx' attend le paramètre 'xxx', qui n'a pas été fourni

modifier

Ce message peut survenir alors que le paramètre d'une procédure stockée est parfaitement bien renseigné ! On peut le vérifier avec :

 MsgBox Command.Parameters.Item(0).Name & " = " & Command.Parameters.Item(0).Value

Il faut juste éviter d'utiliser les ADODB.Parameter :

 Command.CommandText = "MaProcédureStockée @Param1=" & Valeur1 & ", @Param2=" & Valeur2

Erreur de compilation: Argument non facultatif

modifier

L'affectation en erreur doit être précédée de Set.

Erreur de compilation: Impossible d'affecter à un tableau

modifier

Le compilateur a trouvé une affectation à un tableau, il faut donc la remplacer. Ex :

 Dim Tableau(2)
 'Tableau = 1
 Tableau(0) = 1

Erreur de compilation: Procédure trop grande

modifier

Les Sub et Function sont limitées à 64 ko (environ 2 000 lignes, sans les commentaires, ni tabulations), en .xls et .xlsm. Il faut donc par exemple :

  • Faire des appels (Call) à d'autres fonctions contenant des traitements séparés.
  • S'orienter vers la pseudo programmation objet VBA (variable Collection).
  • Remplacer les conditions récurrentes par un test de booléen.

Impossible de définir la propriété ControlSource. Valeur de propriété non valide.

modifier

Le champ ControlSource de la fenêtre Propriétés d'un formulaire pointe vers une feuille inexistante.


Impossible de définir un type Public défini par l'utilisateur à l'intérieur d'un module objet

modifier

Ajouter la visibilité Private avant la variable concernée.

Sinon, dans le module de classe au paramètre "Instancing" (à côté de son nom), choisir dans le menu déroulant "Private" au lieu de "Public".

Mode d'accès au fichier incorrect

modifier

Remplacer Input par Output ou Append lors de l'ouverture de fichier. Exemple sur la première ligne :

 Open "C:\Fichier1.csv" For Output As #1
 Print #1, Ligne1
 Close #1

Nom ambigu détecté

modifier

Une variable ou fonction de même nom et de même portée a été déclarée deux fois. Attention : ce n’est pas forcément celle sélectionnée par le message d'erreur.

Projet ou bibliothèque introuvable

modifier

Si cela porte sur des fonctions comme trim, mid, left et right, alors décocher la bibliothèque manquante dans l'éditeur de code, Outils, Références.

Sinon, une DLL est probablement à cocher dedans.

Type d'argument Byref incompatible

modifier

Il faut convertir la variable en cause, par exemple avec Cstr() ou Cint().

Type défini par l'utilisateur non défini

modifier

Il faut ajouter une bibliothèque contenant ce type (en cochant une case dans Outils\Références). Attention : si le programme ne coche pas cette case automatiquement chaque utilisateur de chaque ordinateur devra la cocher manuellement.

Une erreur s'est produite : External table is not in the expected format

modifier

Lors d'un publipostage VBA, la source de données n’est pas prise en compte par Word. Essayer de le faire manuellement pour en savoir plus. Si le message persiste, changer le format de la source (ex : Fichier.SaveAs test.xls, FileFormat:=xlNormal).

Variable non définie

modifier

La mention Option Explicit impose de déclarer chaque variable, on peut donc soit l'enlever, soit tout déclarer avec Dim.

Variable requise. Impossible de l'affecter à cette expression

modifier

Peut survenir quand on appelle len(Tableau) au lieu de UBound(Tableau).

  Si en cas de division par zéro le compilateur renvoie bien cette erreur, en cas de modulo zéro il renvoie le premier nombre.
  Quand on effectue des opérations mathématiques avec des chaines de caractères, VBA ne les convertit pas toujours automatiquement, il est donc plus sûr d’utiliser les fonctions de conversions.

Gestion d'exception par VBA

modifier

La VBA ne possède pas de levée d'exception proprement dite, il faut donc désactiver les messages d'erreur bloquants puis tester si l'opération à risque s'est bien déroulée :

On Error Resume Next ' Désactivation des erreurs
x = 1
On Error GoTo 0 ' Réactivation des erreurs
If IsNull(x) Or IsEmpty(x) Then Exit Sub

Débogage

modifier

Introduction

modifier

Toute correction de programme, de logiciel, ou d'application suite à une anomalie de fonctionnement s’appelle débogage. Dans notre cas, il s'agira donc de la correction d'une erreur liée à une Macro VBA. L'outil débogueur aide à corriger une anomalie empêchant le fonctionnement de la macro, son objectif est donc de cerner l'instruction en erreur ou responsable de l'erreur. Pour ce faire, l'outil utilise quelques modes de fonctionnement :

  • Mode pas à pas => sur des portions courtes de code, l'assistant erreur propose le passage en mode pas à pas, si le programmeur choisit ce mode, le programme alors s'arrête sur chaque instruction pour permettre de repérer la cause de l'erreur grâce à de nombreuses options d'affichage. Ce mode "pas à pas" peut aussi être directement demandé par le concepteur dès le début de la procédure (touche F8).
  • Point d'arrêt : pour éviter le fastidieux mode "pas à pas" sur des portions longues de code, il est possible de marquer par des points d'arrêt les lignes d'instruction sur lesquelles le programme doit s'arrêter, le programme alors s'arrête sur chaque arrêt positionné par le programmeur.
Début de l'exemple
Fin de l'exemple


Outils de débogage

modifier

Il existe différentes fonctions permettant le débogage de macros créées par l'utilisateur. Ces outils permettent de vérifier le bon fonctionnement des macros une fois celles-ci créées. Nous avons par exemple, le message de syntaxe, le message d'exécution, l'instruction stop, le point d'arrêt, l'afficheur d’état d'une variable, la fenêtre variable locale, la fenêtre espion, la fenêtre exécution, ...

  • CTRL + Pause envoie une interruption qui met en pause le programme en cours d'exécution (un peu comme CTRL + ALT + Suppr dans Windows).
  • F8 lance le mode pas à pas (ligne par ligne).
  • F5 lance le programme jusqu'à fin de l'exécution, ou ce qu’il rencontre un point d'arrêt.
  • F9 définit un point d'arrêt, équivalent d'un clic gauche dans la marge.

Pendant le débogage, en sélectionnant une variable sur clic droit, il est possible d'y ajouter un espion. Cela permet d'afficher sa valeur variable dans une fenêtre en bas, et même de suspendre l'exécution si cette valeur change. Il est aussi possible de connaitre ces valeurs en passant la souris sur les variables pendant l'exécution.

Message d'erreur d'exécution

modifier

Lors de l’affichage du message d'exécution, VBA affiche une boite de dialogue à 2 boutons (Fin ou Débogage)

  • Le bouton Fin fait en sorte de quitter la macro en erreur
  • Le bouton Débogage met en surbrillance la ligne de la macro qui a décelé l'erreur.

Instruction Stop

modifier

Il suffit de l'insérer dans le code d'une macro. Lorsque de l'exécution de la macro, celle-ci s'arrêtera à l'endroit où le "Stop" est placé. Le but ici est de vérifier que la portion de code précédent le stop ne contient aucune erreur.

Début de l'exemple
Fin de l'exemple


Point d'arrêt

modifier

Le but du point d'arrêt est identique au stop, le but premier étant d'interrompre l'exécution de la macro et donc de vérifier si son exécution est correcte

Début de l'exemple
Fin de l'exemple


L'affichage de l'état de variable

modifier

L'état de variable permet de vérifier la valeur que prend chaque variable pendant l'exécution, extrêmement utile lorsque la découverte de l'erreur n’est pas triviale

Début de l'exemple
Fin de l'exemple


Références

modifier
  • Greg Harvey et John Walkenbach, 2013, Excel 2013 et VBA Pour Les Nuls, FIRST, Hoboken

Liens internes

modifier

Liens externes

modifier