Principe de la gestion des erreurs

Comment gérer les erreurs prévisibles dans une macro. Où mettre les codes ?

Structure recommandée :

For i = 1 to 100  
On Error goto zut  
[instructions susceptibles de produire une erreur] 
 Next i  
...  
End  
Zut:  Resume next    

Et comment gérer des erreurs multiples dans une macro ?

"une erreur ça va, deux erreurs, bonjour le beaujolais !"

La réponse se trouve dans ce passage (un peu abscons, je l'admets!) de
l'aide VBA:

"Un gestionnaire d'erreurs est "validé" lorsqu'il a été désigné par une instruction On Error; le gestionnaire d'erreurs "actif" est un gestionnaire validé qui traite une erreur. Si une erreur se produit
alors qu'un gestionnaire d'erreurs est actif (c'est-à-dire entre la ligne où survient une erreur et une instruction Resume, Exit Sub, Exit Function ou Exit Property), le gestionnaire d'erreurs de la procédure en cours ne peut gérer l'erreur. Le contrôle revient à la procédure appelante. Si la procédure appelante possède un gestionnaire d'erreurs validé, il est activé afin de gérer l'erreur. Si le gestionnaire d'erreurs de la procédure appelante est également actif, le contrôle est restitué aux procédures appelantes antérieures jusqu'à ce qu'un gestionnaire d'erreurs validé mais inactif soit trouvé. Si aucun gestionnaire d'erreurs validé et inactif n'est trouvé, l'erreur est fatale à l'emplacement où elle s'est produite."

Quand la première erreur se produit, ton programme se trouve *dans* le gestionnaire d'erreur "actif" TiersInex1. Le gestionnaire d'erreur, c'est en fait tout le bloc de code qui se trouve entre:

EtiquetteErreur:
  ' blablablabla.....
  ' .....
Resume [Etiquette / Next], ou Exit [Sub / Function / Property]

Comme il n'y a aucune instruction Resume dans ta macro, le premier gestionnaire d'erreur, c'est donc tout ce qui se trouve entre TiersInex1et... Exit Sub!

Du coup, quand la deuxième erreur est rencontrée, le programme est *dans* un gestionnaire d'erreur actif (et même le seul gestionnaire de toute la macro) et comme le précise l'aide en ligne, dans ce cas "si aucun gestionnaire d'erreurs validé et inactif n'est trouvé [c'est le cas ici!], l'erreur est fatale à l'emplacement où elle s'est produite."

Et le "On Error Goto TiersInex2" ne peut rien y changer du tout... Les 'On Error' n'ont de sens qu'en dehors des gestionnaires d'erreurs, ils ne peuvent pas modifier les gestionnaires actifs en cours d'exécution.

La solution : mettre tout simplement un Resume à la fin du premier gestionnaire, pour le clore. Comme apparemment tu ne veux pas que l'exécution reprenne à l'endroit où s'est produite l'erreur, il suffit
de mettre Resume FinTiers1 à la place de Resume Next:

  ' ..........
  On error goto TiersInex1
  MaVar1=MonCombo.column(5,MonCombo.ListIndex)
  ' ..........
  Goto FinTiers1
TiersInex1:
   Select case Err
      Case 381
         MaVar1=Range(Xy)
      Case Else
      ' ........
   End select
   Resume FinTiers1  ' <======= Resume ICI
FinTiers1:
   On error Goto 0
   ' ..........

Et ainsi de suite pour tous les autres gestionnaires. La règle, très simple, c'est que dès lors qu'il y a plusieurs gestionnaires d'erreur dans la même procédure, chaque gestionnaire doit être terminé par une instruction Resume.

C'est vrai que tout ça est assez piégeux et pas très bien expliqué...

Auteur :

Mots clefs associés à cette page : , , ,