Soyons clair, b
déclenche automatiquement l'exécut loc étiquettes de lignes, c'est-à-dire la
Celles-ci suivent les règles suivantes :
¾ Elles sont composées de n'importe quelle combinaison de caractères commençant par une lettre et se terminant par le signe d
¾ Elles ne distinguent pas les majuscules des minuscules
¾ Elles doivent commencer au niveau de la première colonne (le plus à l'éditeur)
L'instruction de gestion d'erreurs sera alors de la forme n d'erreurs en fin d
on place le code de gestio de sortie d'une instruction
d'erreur ne s'exécute pas en cas de fonction
Pour que les explications soient plus claires, partons de l'exemple suivant : = 3.14159265
Private Const PI
lcCylindree(ByVal Alesage
Private Function Ca bCyli
As Single, ByVal Course As Single, ByVal N ndre As Byte) As Single
Alesa
If Sgn(
Err.
ge) < 1 Or Sgn(Course) < 1 Then
Raise 5 ', "Cylindree", "Les valeurs d'alésage et de course doivent être strictement positives"
ElseIf NbCylindre = 0 Then
Err.Raise 5 ', "Cylindree", "Le Nombre de cylindre ne peut pas être nul"
End If
CalcCylindree = (PI * Course * Alesage ^ 2) / 4 / 1000 * NbCylindre
End Function
Private Function CalcRapVol(ByVal Cylindree As Single, ByVal VolChambre As Single) As Single
CalcRapVol = (Cylindree + VolChambre) / VolChambre
End Function
Public Sub CalculMoteur()
Dim Ales As Single, Course As Single, NCyl As Integer, VolumeC As Single
Dim Cylindree As Single, RapportVolu As Single
On Error GoTo TraiteErreur
Ales = Application.InputBox("Entrer la valeur d'alésage en mm", "Saisie", Type:=1)
Course = Application.InputBox("Entrer la valeur de la course en mm", "Saisie", Type:=1)
NCyl = Application.InputBox("Entrer le nombre de cylindre", "Saisie", Type:=1)
VolumeC = Application.InputBox("Entrer le volume de la chambre de combustion en cm^3", "Saisie", Type:=1)
Cylindree = CalcCylindree(Ales, Course, NCyl) RapportVolu = CalcRapVol(Cylindree, VolumeC) MsgBox Cylindree & vbNewLine & RapportVolu Exit Sub
TraiteErreur:
If Err.Number = 5 Then
If NCyl = 0 Then
NCyl = Application.InputBox("Le nombre de cylindre doit être positif", "Erreur", 1, Type:=1)
ElseIf Sgn(Ales) < 1
Ales = 0 Then
Then
If
Ales = Application.InputBox("L'alésage doit être strictement positif", "Erreur", 1, Type:=1)
Else Ales = -1 * Ales End If Else If Course = 0 Then e = Application.InputBox
Cours ("La course doit être
strictement positive", "Erreur", 1, Type:=1)
Else ourse = C -1 * Course End If End If Resume End If End Sub re 'C Observons la procédu Celle-ci signif
alculMoteur'. Nous activons la récupération d'erreur avec la première ie donc que si une erreur se produit dans le code, le curseur d'exécution raiteErreur' et le code de traitement sera exécuté. Si le code se déroule sans era erreur se produit, la propriété t va être différente de 0.
s alors tester le numéro de l'erreur. Si celui-ci est égal à 5, c'est que nous avons levé l'exc
instruction.
atteindra la ligne 'T
encombre, la procédure se terminera sur l'instruction Exit Sub (et non sur End Sub) et le code ne s pas traité.
aintenant le code de traitement des erreurs. Si une Regardons m
Number de ErrObjec Nous allon
eption de la fonction 'CalcCylindree', c'est-à-dire qu'un des trois arguments n'est pas strictement positif. Nous allons donc appliquer la stratégie suivante, si l'argument faux est négatif, je vais le multiplier par -1, s'il est nul, nous allons redemander la saisie d'une valeur pour cet argument. Puis nous allons tenter de ré exécuter la ligne qui a levé l'erreur.
Pour atteindre cette ligne, nous utiliserons l'instruction Resume.
Resume Etiquette → Va à la ligne de l'étiquette.
Évitez d'utilisez Resume Etiquette qui peut rapidement compliquer la lecture de votre code. N.B : L'instruction Resume réinitialise l'objet ErrObject, comme si on faisait Err.Clear.
Attention, Resume atteint la ligne qui a déclenchée l'erreur dans la procédure qui contient le code estion d'erreur. Dans notre cas,
Cylindree = CalcCylindree(Ales, Course, NCyl) de g
Supposons maintenant qu'au lieu d'un argument faux, il y en ait deux, que va-t-il se passer? Le code va entrer dans le code de gestion d'erreur une première fois et traiter la première erreur dans l'ordre des conditions, puis l'instruction Resume va remettre le curseur d'exécution sur la ligne d'appel de la fonction 'CalcCylindree'. Une erreur va de nouveau se produire puisque n
ement d'erreur ne corrige qu'un argument à la fois. Cette nouvelle erreur va renv
otre code de
trait oyer le code dans
ond argument. Notre gestion d'erreur est donc bien écrite.
e traitement de l'erreur explicitement levée par la fonction se de dépassement de capacité puisque qui ne peut pas excéder 255. Cette erreur est l'erreur 6. Le pour cela otre code le tr
Où du moins l'est-il pour l aitement d'erreur pour traiter le sec
'CalcCylindree'. Imaginons que notre opérateur rêveur entre 300 comme nombre de piston. Il ne passera rien à l'écran et rien ne sera calculé.
fait, cette erreur de saisie va déclencher une erreur En
l'argument 'NbCylindre' est de type Byte
code d'erreur va alors être exécuté, mais tel qu'il est écrit, il ne traite que l'erreur 5 et c'est qu'en apparence il ne se passe rien. Pour parer à cette éventualité nous allons donc modifier n d'erreur tel que :
TraiteErreur:
Select Case Err.Number
Case 5
If NCyl = 0 Then
NCyl = Application.InputBox("Le nom ur", 1, Type:=1)
bre de cylindre doit être positif", "Erre
ElseIf Sgn(Ales) < 1 Then
If Ales = 0 Then
Ales = Application.InputBox(
"L'alésage doit être
strictement positif", "Erreur", 1, Type:=1)
Else Ales = -1 * Ales End If Else If Course = Course 0 Then
= Application.InputBox("La course doit être
strictement positive", "Erreur", 1, Type:=1)
Else Course = -1 * Course End If End If Case 6
NCyl = Application.InputBox("Le nombre de cylindre doit être compris entre 1 et 255", "Erreur", 1, Type:=1)
End Select
Resume
Nous voilà donc avec un code de gestion d'erreur prêt à tout. Et bien non, pas encore. Imag maintenant que ce diable d'utilisateur entre 0 comme valeur
inons de volume. La fonction de calcul de la entre dans la fonction 'CalcRapVol'. Le calcul e division par zéro. Cette fonction ne possède ourtant l'exécution ne va pas s'arrêter.
concept à appréhender correctement. Dés lors qu'il y a un gestionnaire eurs vont remonter le courant, comme les saumons, sauf que dans le cas des cylindrée va bien se passer, puis le curseur d'exécution
rreur puisqu'il y aura un de cette fonction va lever une e
r et p pas de gestionnaire d'erreu
le deuxième C'est la
d'erreur actif, les err
Le mécanisme est le suivant. L'erreur va d'abord être traitée au niveau de la procédure où elle se e gestionnaire d'erreur dans celle-ci, il va remonter l'erreur au gestionnaire de la avez prévu cette remontée, pas de problème. Mais si il s'est produit une erreur prévue, vous allez déclencher un traitement qui n'est probablement pas adapté en produit. S'il n'y a pas d
procédure appelante et ainsi de suite jusqu'à trouver un gestionnaire actif. Ce mécanisme n'est pas inintéressant mais il est extrêmement périlleux.
En effet, si vous z pas que vous n'avie
plus de rendre plus difficile la détection de l'erreur.
Nous aurions trois possibilités dans notre exemple, désactiver le gestionnaire après le calcul de la cylindrée, traiter la division par zéro au niveau de la fonction de calcul du rapport volumique ou la traiter au niveau du gestionnaire de la procédure.
Pour désactiver le gestionnaire d'erreur, on utilise l'instruction On Error Goto 0. Ce qui donnerais un code tel que
Public Sub CalculMoteur()
Dim Ales As Single, Course As Single, NCyl As Integer, VolumeC As Single
Dim Cylindree As Single, RapportVolu As Single
On Error GoTo TraiteErreur
Ales = Application.InputBox("Entrer la valeur d'alésage en mm", "Saisie", Type:=1)
Course = Application.InputBox("Entrer la valeur de la course en mm", "Saisie", Type:=1)
NCyl = Application.InputBox("Entrer le nombre de cylindre", "Saisie", Type:=1)
VolumeC = Application.InputBox("Entrer le volume de la chambre de combustion en cm^3", "Saisie", Type:=1)
Cylindree = CalcCylindree(Ales, Course, NCyl) On Error GoTo 0
RapportVolu = CalcRapVol(Cylindree, VolumeC) MsgBox Cylindree & vbNewLine & RapportVolu Exit Sub
TraiteErreur: . . . . .
Sinon la modification du gestionnaire de la procédure serait : TraiteErreur:
Select Case Err.Number
Case 5
If NCyl = 0 Then
NCyl = Application.InputBox("Le nombre de cylindre doit être positif", "Erreur", 1, Type:=1)
ElseIf Sgn(Ales) < 1 Then
If Ales = 0 Then
Ales = Application.InputBox("L'alésage doit être strictement positif", "Erreur", 1, Type:=1)
Else
Ales = -1 * Ales
End If
Else
If Course = 0 Then
Course = Application.InputBox("La course doit être strictement positive", "Erreur", 1, Type:=1)
Else Course = -1 * Course End If End If
Case 11
VolumeC = Application.InputBox("Entrer un volume supérieur à 0 pour la chambre de combustion en cm^3", "Saisie", Type:=1)
End Select
Resume
Il n'est pas toujours facile de savoir quel choix ter to
prendre. En théorie, lorsqu'on commence à écrire utes les erreurs sauf lorsqu'on fait du traitement ans un gestionnaire situé assez loin dans la pile des avoir des effets de bord non négligeable. L'instruction Resume ne renverra pas le curseur d'ex
avant le déclenchement de l'erreur, et un deuxième parcours de la pile des appels énéralement pour cela que
a source de l'erreur et ans la procédure ple cependant, le traitement de la division par 0 dans le code de la procédure océdure n programme. Tout à coup, la valeur du volume de la chambre de combustion sur son banc. enté, il sait que tout trajet qui croise la machine à café peut s'avérer vu pour le parcourir. Il décide donc de cliquer sur le de l'alésage. Et la quelle ne sera pas sa surprise de re de cylindres. Que se passe-t-il donc ?
de l'objet Application renvoie la valeur saisie si vous cliquez sur 'OK' et
r t la forme :
e suivante. La ligne suivante va donc endue est t. Généralement on traite donc l'erreur dans le bloc If qui suit la ligne
ésactive le gestionnaire pour l'erreur en ligne. aire général, on désactive à l'aide de l'instruction :
0
tive le gestionnaire en cours en reprécisant l'étiquette avec :
On Error Goto Etiquette
du code de gestion d'erreur, on cherche à trai médiat. Cependant la remontée des erreurs d im
appels peut
écution au niveau de la ligne en erreur mais au niveau de l'appel ayant déclenché celle-ci. Si lors des appels de fonction vous avez utilisé des variables globales ou des variables statiques, leurs valeurs ont pu être changées
aura un contexte différent et probablement un résultat différent. C'est g rsqu'on écrit du code de gestion d'erreur, on essaye de l'écrire assez près de l lo
qu'on écrit des petits gestionnaires dans les procédures appelées plutôt qu'un grand d principale.
Dans notre exem
appelante ne pose pas de problème, et nous avons enfin écrit un code robuste où les erreurs sont gérées correctement.
Et pourtant ce n'est pas vraiment le cas, car si nous avons bien traités les erreurs, notre pr est boguée. Imaginons que notre utilisateur distrait commence à exécuter so
il se rend compte qu'il a oublié expérim Comme c'est un utilisateur
nettement plus long que le temps normalement pré ètre bouton 'Annuler' quand on lui demande le diam
oir que le programme va lui demander le nomb v
La méthode InputBox
False si vous cliquez sur 'Annuler'. En cliquant sur 'Annuler', le programme va tenter d'affecter la valeur False à la variable 'Ales'. Il y a là une incompatibilité de type, ce qui va lever une erreur de type 6, celle-ci va déclencher le code de gestion d'erreur, et le traitement de l'erreur numéro 6 provoque l'affichage d'une boîte de saisie pour le nombre de cylindre.
Dans cet exemple, le bug est relativement évident, mais ce n'est pas toujours le cas et parfois il est assez ardu de retrouver le bug lorsque le gestionnaire est activé. Vous avez toujours la possibilité de repasser l'éditeur en mode 'Arrêt sur toute les erreurs' pour le retrouver plus facilement.