Gérer correctement les erreurs en VBA (Excel)

Je travaille avec VBA depuis un bon moment maintenant, mais je ne suis toujours pas très sûr de la gestion des erreurs.

Un bon article est celui de
CPearson.com

Cependant, je me demande toujours si la façon dont je faisais la gestion des erreurs était/est complètement fausse :
Bloc 1

On Error Goto ErrCatcher
   If UBound(.sortedDates) > 0 Then

       // Code

   Else
ErrCatcher:
       // Code

   End If

La clause if, parce que si elle est vraie, sera exécutée et si elle échoue, le Goto ira dans la partie Else, puisque le UBound d’un tableau ne devrait jamais être zéro ou moins sans une erreur, cette méthode a assez bien fonctionné jusqu’à présent.

Si j’ai bien compris, cela devrait être comme ceci :

Bloc 2

On Error Goto ErrCatcher
    If Ubound(.sortedDates) > 0 Then

       // Code
    End If

    Goto hereX

ErrCatcher:
       //Code
    Resume / Resume Next / Resume hereX

hereX:

Ou même comme ceci :
Bloc 3

On Error Goto ErrCatcher
    If Ubound(.sortedDates) > 0 Then

       // Code
    End If

ErrCatcher:
    If Err.Number <> 0 then
       //Code
    End If

La manière la plus courante que je vois est celle où le “Catcher” d’erreurs est à la fin d’une sub et la Sub se termine en fait avant avec un “Exit Sub”, mais n’est-ce pas un peu déroutant si la Sub est assez grande de devoir aller d’avant en arrière pour lire le code ?

Bloc 4

Source du code suivant :
CPearson.com

  On Error Goto ErrHandler:
   N = 1 / 0    ' cause an error
   '
   ' more code
   '
  Exit Sub

  ErrHandler:

   ' error handling code'

   Resume Next

End Sub

Cela devrait-il être comme dans le Bloc 3 ?

Vous avez une réponse vraiment formidable de ray023, mais votre commentaire disant que c’est probablement excessif est pertinent. Pour une version “plus légère”…

Bloc 1 est, à mon humble avis, une mauvaise pratique. Comme l’a déjà souligné osknows, mélanger la gestion des erreurs avec le code du chemin normal n’est pas bien. Entre autres choses, si une nouvelle erreur est levée pendant qu’il y a une condition d’erreur active, vous n’aurez pas l’occasion de la gérer (sauf si vous appelez depuis une routine qui a aussi un gestionnaire d’erreurs, où l’exécution va “remonter”).

Bloc 2 ressemble à une imitation d’un bloc Try/Catch. Cela devrait être correct, mais ce n’est pas la manière VBA. Bloc 3 est une variation du Bloc 2.

Bloc 4 est une version minimale de la manière VBA. Je vous conseillerais fortement de l’utiliser, ou quelque chose de similaire, car c’est ce que tout autre programmeur VBA héritant du code s’attendra à trouver. Permettez-moi de présenter une petite extension, cependant :

Private Sub DoSomething()
On Error GoTo ErrHandler

'Dim as required

'functional code that might throw errors

ExitSub:
    'any always-execute (cleanup?) code goes here -- analagous to a Finally block.
    'don't forget to do this -- you don't want to fall into error handling when there's no error
    Exit Sub

ErrHandler:
    'can Select Case on Err.Number if there are any you want to handle specially

    'display to user
    MsgBox "Something's wrong: " & vbCrLf & Err.Description

    'or use a central DisplayErr routine, written Public in a Module
    DisplayErr Err.Number, Err.Description

    Resume ExitSub
    Resume
End Sub

Notez ce second Resume. C’est une astuce que j’ai apprise récemment : il ne s’exécutera jamais dans le traitement normal, puisque l’instruction Resume <label> enverra l’exécution ailleurs. Cela peut être une bénédiction pour le débogage, cependant. Lorsque vous recevez une notification d’erreur, choisissez Déboguer (ou appuyez sur Ctrl-Break, puis choisissez Déboguer lorsque vous recevez le message “L’exécution a été interrompue”). L’instruction suivante (surlignée) sera soit le MsgBox soit l’instruction suivante. Utilisez “Définir l’instruction suivante” (Ctrl-F9) pour surligner le Resume seul, puis appuyez sur F8. Cela vous montrera exactement où l’erreur a été levée.

Quant à votre objection sur ce format qui “saute partout”, A) c’est ce que les programmeurs VBA s’attendent à trouver, comme indiqué précédemment, et B) vos routines devraient être suffisamment courtes pour que le saut ne soit pas long.