• Aucun résultat trouvé

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.