IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

La gestion des erreurs dans Access

Par Maxence HUBICHE (access-maxence)
 

J'ai une erreur !
Combien de fois a-t-on entendu cette exclamation se produire sur les forums de Developpez.com, comme si tous les malheurs du monde arrivaient en même temps.
Il est vrai que l'apparition d'une erreur dans notre code peut faire peur.
Mais, en réalité, cela devrait être un soulagement. Pourquoi ? C'est ce que je vous invite à comprendre à travers cet article qui vous expliquera les raisons de l'apparition des erreurs, mais aussi les moyens de s'en affranchir.


I. Généralités sur les erreurs
I-A. Les Erreurs de Syntaxe
I-B. Les Erreurs de Nommage
I-C. Les Erreurs d'Exécution
II. Comment gérer les erreurs
II-A. Une bonne convention de nommage
II-B. Le bon usage des "OPTION"
II-C. La compilation
II-D. La gestion des erreurs
II-D-1. L'objet Err
II-D-2. Que se passe-t-il lorsque survient une erreur ?
II-D-3. On Error Resume Next
II-D-4. On Error Goto 0
II-D-5. On Error Goto étiquette


I. Généralités sur les erreurs

Souvent, les erreurs sont interprétées à tort comme une catastrophe. En fait, c'est mélanger plusieurs notions et avoir un état d'esprit négatif que d'appréhender les erreurs sous ce jour.

Aussi, je vous propose de changer de point de vue...
Essayez un instant d'imaginer les erreurs comme des aides !
En voici les explications... Prenez votre temps, c'est important !

Réfléchissons un moment : Quand une erreur se produit-elle ?

Globalement, nous allons faire une distinction entre les différentes 'sortes' d'erreurs
Par exemple, les erreurs de syntaxe, les erreurs d'exécution, les erreurs de nommage ou encore les erreurs de logique.


I-A. Les Erreurs de Syntaxe

Les erreurs de syntaxe se produisent lorsque ce qui est écrit est syntaxiquement incorrect. En général, l'erreur est immédiatement repérée par l'éditeur, et la ligne passe en rouge. Voici un exemple d'erreur de syntaxe :
'La ligne suivante produit une erreur
MsgBox("Ce code fait une erreur ?",vbOkOnly + vbQuestion,"Essai")
Ceux qui ne me croient pas n'ont qu'à essayer de copier-coller ce code dans une procédure, et ils verront ! La ligne passe bien en rouge ! Pourquoi ?

Parce que l'usage des parenthèse en VBA implique la récupération d'un résultat qu'on souhaite utiliser ultérieurement, et cela, de manière systématique. Dans cette syntaxe, nous demandons donc de récupérer le résultat de la fonction MsgBox.

Mais nous ne permettons pas à l'interpréteur de VBA de savoir ce que nous souhaitons faire de ce résultat attendu ! Faut-il le stocker dans une variable ? Si oui, où est-elle ?

Comment corriger cette simple erreur de syntaxe ?

En corrigeant notre syntaxe ! tout simplement ! D'ailleurs, le message d'erreur nous indique le problème très rapidement :

Signe égal attendu
Voici deux moyens de corriger cet exemple d'erreur de syntaxe :
'La ligne suivante ne produit pas d'erreur car nous indiquons que faire du résultat
'Nous trouvons le symbole = qui était attendu, et signalé dans le message d'erreur
reponse = MsgBox("Ce code fait une erreur ?",vbOkOnly + vbQuestion,"Essai")

'Celle-ci non plus, car nous ne demandons pas de résultat
'Cette fois, il n'y a pas de symbole égal, mais il n'y a pas non plus les parenthèses !
MsgBox "Ce code fait une erreur ?",vbOkOnly + vbQuestion,"Essai"
Voilà ! problème de syntaxe réglé.


I-B. Les Erreurs de Nommage

Cela, c'est certainement l'erreur la plus difficile à identifier lorsqu'on n'a pas toutes les billes en main. Prenon un exemple (aprtiel) de code :
Sub CeciEstUnTest()
    'Déclaration d'une variable de type Entier Long
Dim Mavariableàmoi as Long

'Mettre 2 dans la variable
    Mavariableamoi=2
    
    'ici, quelques lignes de code bidon qui n'ont aucun intérêt
    'donc, nous les omettons
    
    'Enfin, nous affichons la variable
    Msgbox Mavariableàmoi
End sub
Ce code ne contient aucune erreur de syntaxe. La syntaxe est correcte ! Cependant, contrairement à ce que nous attendons, la MsgBox de la fin de la procédure affichera toujours 0, alors que nous attendons un 2 ! Pourquoi ?

Tout simplement parce que nous avons fait une erreur dans les noms. Dans les faits, il y a DEUX variables dans cette procédure : Mavariableamoi et Mavariableàmoi.

Oui, je sais que c'est mesquin de faire une erreur sur un accent, mais je pense que tout le monde à, au moins une fois dans sa vie, fait une inversion dans les lettres d'un mot, écris le mot en question au singulier au lieu du pluriel, à moins que ce ne soit l'inverse... etc.

Bref, tous, vous reconnaitrez avoir fait au moins une fois dans votre vie une erreur de saisie, tout simplement.

Ce genre d'erreur de saisie PEUT générer une erreur de syntaxe. Mais c'est plutôt rare.

Rechercher ce genre d'erreurs à la main devient un vrai casse-tête car il ne faut absolument rien oublier, tout vérifier, chaque mot... à moins de mettre les bonnes options en place.

Bref, il est important de connaître les outils qui sont à votre disposition pour éviter de faire des erreurs ... ce qui est bien l'objet de ce petit cours.
En l'occurence, l'usage approprié des options limitera l'apparitions d'erreurs graves dans votre programme.


I-C. Les Erreurs d'Exécution

Les erreurs d'exécutions sont plus sournoises. Ce sont des erreurs qu'on ne voit pas forcément lors de la 'compilation' des modules. L'erreur se produira, par exemple, parce qu'une opération illicite a été réalisée. Voici un exemple de code produisant une erreur :
Sub TestErreur()
    Dim i as long
Dim n as long
Dim t as long
i=2
t=i/n
End sub
Il n'y a NI erreur de nommage, NI erreur de syntaxe. Par contre, la variable n'ayant pas été initialisée par une ligne de code, et étant déclarée explicitement AS LONG, elle est de type numérique automatiquement initialisée à 0.

Nous produisons donc une belle division par zéro, ce qui est une des multiples sources d'erreurs possibles en cours d'exécution.


II. Comment gérer les erreurs

Nous avons vu qu'il était très facile de générer des erreurs au sein du code VBA.

Sommes-nous donc désemparés face à celà ?

Non, pas du tout ! Bien au contraire même...
Nous allons, voir, à partir de maintenant que, sous réserve de pratiquer quelques règles de bonne conduite, le nombre d'erreurs dans notre code risque de diminuer plus que fortement, s'approcher de zéro.


II-A. Une bonne convention de nommage

Il y a une erreur quelque peu particulière qui peut se produire lorsqu'on est "tête en l'air" ou qu'on n'a pas de convention de nommage stricte. Ainsi par exemple, imaginons 2 modules, contenant les codes suivants :
Module 1
Public MaVar As Long
Module 2
Dim MaVar As Long

Sub MaSub()
    Dim MaVar as Long
    MaVar=10
End Sub

Sub Main()
    MaSub
    Msgbox MaVar
End Sub
Ce code vous paraît (je l'espère) bizarre, n'est-ce pas ?
Et pour cause ! Trois variables, de même type, de même nom, mais de portée différente. vous ne vous étonnerez donc certainement pas de ne pas avoir de message d'erreur, mais plutôt une boîte de message contenant un 0 au lieu d'un 10 !

Retour sur erreur de portée de variable
Pour éviter ce genre d'erreurs, nous devrions nous référer à l'EXCELLENT ARTICLE de UNTEL sur les concepts des conventions de nommage. Bien sûr, je ne saurais que trop vous recommander d'en faire un usage abusif. D'ailleurs, pour vous en donner un aperçu, voici le même code, auquel une convention de nommage précise a été appliquée :
Module 1
Public p_lngMaVar As Long
Module 2
Dim m_lngMaVar As Long

Sub MaSub()
    Dim MaVar as Long
    p_lngMaVar=10
End Sub

Sub Main()
    MaSub
    Msgbox p_lngMaVar
End Sub
Cette fois, le doute sur la variable affectée, et sur celle affichée n'existe plus. Et le retour de la boîte de dialogue sera 10. Voilà pourquoi, pour éviter les problèmes, il FAUT avoir une convention de nommage stricte.

Retour sans erreur de portée de variable

II-B. Le bon usage des "OPTION"

Comme nous l'avons vu, dans le cas des erreurs de nommage, la recherche d'une erreur risque d'être fastidieuse.

Par contre, le simple usage de l'option EXPLICIT, en haut de chaque module, même si cela est, de fait, un peu contraignant pour les non initiés, est une absolue nécessité, notamment parce que ce dernier implique que toute variable soit déclarée et empèche donc l'usage de mots inconnus dans le code. Une simple compilation fera ressourtir ce genre d'erreur.

Profitons-en pour faire un rappel sur les différentes options qu'on peut mettre en tête de module.

OPTION EXPLICIT

C'est l'instruction utilisée au niveau module (donc en haut du module, avant toute procédure, dans la zone de déclaration) pour imposer la déclaration explicite de toutes les variables de ce module.

Il est recommandé d'utilisez l'instruction Option Explicit pour éviter toute faute de frappe lors de la saisie du nom d'une variable existante ou pour écarter tout risque de confusion dans un code où la portée de la variable n'apparaît pas clairement

OPTION BASE

C'est l'instruction utilisée au niveau module pour déclarer la limite inférieure par défaut des indices d'un tableau. Sans déclaration d'option de base, tous les tableaux sont basés à une limite inférieure 0 (premier indice dans le tableau). On écrira soit OPTION BASE 0 soit OPTION BASE 1.

Mais dans les faits, l'option base 0 étant celle par défaut, seul l'affichage de l'option base 1 est éventuellement intéressante. Elle est cependant rarement mise en place.

OPTION COMPARE

Cette option est importante à connaître. Elle détermine la méthode de comparaison des chaines de caractère au sein du module. Comme les autres options, elle se déclare en haut du module.

Le choix de paramétrage se fait sur 3 positions : OPTIONS COMPARE TEXT qui considère qu'un caractère majuscule et égale à son pendant minuscule. OPTION COMPARE BINARY considère que les caractères sont classés dans leur ordre d'apparence dans la table ASCII. Donc, une majuscule (A=65) a un poids inférieur à son pendant minuscule (a=91).

Enfin, nous avons également OPTION COMPARE DATABASE qui ne peut être utilisée que dans Microsoft Access. Elle fournit des comparaisons de chaînes basées sur l'ordre de tri déterminé par l'identificateur de paramètres régionaux de la base de données dans laquelle la comparaison de chaînes est effectuée.

OPTION PRIVATE MODULE

Lorsqu'elle est utilisée, tout élément publique du module (procédure, variable, ...) continuera d'être publique au niveau du projet, mais ne pourra plus être référencé à l'extérieur de ce dernier.


II-C. La compilation

Une pratique très intéressante vous permettant de détecter des erreurs AVANT qu'elles ne se produisent consiste à 'compiler' votre projet. Bien qu'il s'agisse en fait d'une pseudo compilation, les actions entreprises lors de cette pseudo compilation permettent la lise en évidence de certains erreurs.

Par exemple, il pourrait ne pas y avoir d'erreur de syntaxe apparente, comme dans l'exemple suivant :
Option Explicit

Sub TestCompilation()
    Dim c As currnecy
    Dim i As Integer
    Dim l As Long
    i = 200
    l = 3000
    c = i * l
End Sub
Si je compile ce code, j'obtiens une erreur :

Erreur de compilation n°1
Pourtant, le type de la variable c contient une erreur dans son libellé, une simple inversion dans les lettres. Le fait est que cette syntaxe n'est pas une erreur !

En effet, il est tout à fait possible de déclarer un type différent des types standards, et rien ne m'empèche, par exemple de créer le type Currnecy. Je m'y prendrais, par exemple, ainsi :
Public Type Currnecy
    x As Long
    y As Long
End Type
Admettons que la compilation a échoué ; je me rends compte que la définition de mon type manque. J'ai modifié mon code pour que le type soit déclaré, ce qui donne ceci :
Option Explicit

Public Type Currnecy
    x As Long
    y As Long
End Type

Sub TestCompilation()
    Dim c As Currnecy
    Dim i As Integer
    Dim l As Long
    i = 200
    l = 3000
    c = i * l
End Sub
Si je recompile, j'obtiens à nouveau une erreur car, cette fois, le type n'est pas affecté de la manière qui convient !

Erreur de compilation n°2
Bref, comme nous le constatons, cette simple opération de compilation nous permet d'éviter les soucis avant même qu'ils ne se produisent.

Par conséquent, il faut prendre l'habitude de cliquer sur cette commande avant toute exécution de procédure.


II-D. La gestion des erreurs

Entrons maintenant dans le vif du sujet.

Jusqu'à présent, nous nous étions concentrés sur les moyens à notre disposition pour éviter les erreurs AVANT qu'elles ne se produisent ; des erreurs de code essentiellement.

Cependant, même avec la meilleure volonté du monde, nous ne pouvons nous prémunire totalement des erreurs. Par exemple, Le simple fait d'ouvrir un fichier peut générer une erreur !

  • Le fichier n'existe plus
  • Le chemin d'accès n'est plus le bon
  • Le serveur hébergeant le fichier est tombé
  • Le format du fichier n'est pas valide pour l'application qui l'ouvre
  • Le fichier est déjà ouvert par quelqu'un d'autre
  • etc.
Faut-il pour autant baisser les bras ? Certainement pas.

Ce que je vous propose maintenant est de découvrir comment il nous est possible de gérer les erreurs qui peuvent arriver, en cours de programme.


II-D-1. L'objet Err

Voici la première bonne nouvelle : une erreur est un objet - l'objet Err

S'il s'agit d'un objet, nous allons pouvoir le manipuler à volonté grâce à ses propriétés et méthodes. Découvrons-en quelques-unes :

Propriétés de l'objet Err
  • Description (Texte descriptif de l'erreur)
  • HelpFile (Chemin d'accès complet à un fichier d'aide)
  • LastDLLError (Code d'erreur système produit par un appel à une DLL)
  • Number (Numéro de l'erreur, tel qu'il apparait dans les boîtes de dialogue prédéfinies)
  • Source (Nom de l'objet ou de l'application qui a généré l'erreur à l'origine)
Méthodes de l'objet Err
  • Clear (Effacer les erreurs)
  • Raise (Déclencher les erreurs)
Si vous souhaitez vous documenter plus avant sur l'ensemble des propriétés et méthodes de l'objet Err, je vous recommande de vous intéresser à la classe Errobject de la bibliothèque VBA

La classe ErrObject
Par défaut, l'objet Err a sa propriété Number définie à 0. Tant que la propriété Number de Err est à 0, il n'y a pas d'erreur de déclenchée.


II-D-2. Que se passe-t-il lorsque survient une erreur ?

Nous avons d'ores et déjà presque tout examiné, et il doit nous être assez évident de décrire ce qui se passe lorsqu'une erreur survient :

L'Objet Err est présent, et sa propriété Number est à 0
L'erreur survient
Les diverses propriétés de l'objet Err sont modifiées
Le gestionnaire d'erreur est déclenché
L'horrible boîte de dialogue suivante apparait

Nous venons de parler de gestionnaire d'erreur. par défautn, le système de gestion des erreurs est celui décrit précédemment : Faire apparaitre une boîte de dialogue qui, s'il y a pression sur le bouton débogage mettra le code en mode arrêt et basculera dans la fenêtre de code.

Ce système qui semble très intéressant est cependant néfaste, car justement, il permet à l'utilisateur d'arriver sur une page de code. Il est donc à proscrire, et nous allons examiner comment ci-après.

Une fois qu'on sait qu'il y a un objet Err, gérer les erreurs devient un jeu d'enfant. Cela est d'autant plus vrai qu'il n'y a que 3 phrases à retenir. Voyez les maintenant


II-D-3. On Error Resume Next

Cette phrase est très souvent utilisée... par les néophytes.

Sa signification est : S'il y a une erreur passe à la suite sans t'en occuper.

Il est bien question de passer sans s'occuper de l'erreur. Il n'est pas question d'empécher l'erreur. L'erreur a bien lieu, elle se produit, mais le programme ne s'arrête pas et continue. C'est la principale raison pour laquelle la plupart des néophytes l'utilisent : "Ainsi, il n'y a plus d'erreur". Or, cette remarque est FAUSSE ! Il y a erreur ! Simplement, on ne la voit plus. et c'est bien le plus gros problème de ce que cette petite phrase induit. Puisqu'on ne VOIT plus les erreurs, on ne SAIT plus ce qui se passe dans le programme, et on ne peut plus comprendre le POURQUOI cela se produit.

L'usage de cette solution de facilité est donc à proscrire quand on souhaite avoir un code solide.


II-D-4. On Error Goto 0

Voilà une phrase, encore une fois peu utilisée. Elle est plutôt réservée à l'usage du développeur.

Sa signification est : Je rends la main au système de gestion d'erreurs par défaut

Il faut proscrire l'utilisation car elle affiche la boîte de dialogue du gestionnaire d'erreur par défaut de VBA, et que cette boîte de dialogue propose le bouton Débogage, qui amène dans le code. Bien évidemment, l'utilisateur ne doit pas arriver dans le code.

Le développeur pourra utiliser cette instruction pour repérer une erreur bien particulière. Mais il n'oubliera pas de retirer chaque occurence de cette dernière avant de proposer l'application finalisée.


II-D-5. On Error Goto étiquette

Puisqu'il n'y a que 3 formes d'instructions pour gérer les erreurs, et que j'ai indiqué que les deux précédentes n'étaient pas à utiliser dans une application solide, il parait évident que la seule vraiment valide soit celle-ci.

Copyright © 2006 Maxence Hubiche. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.