web-dev-qa-db-fra.com

Comment arrêter la macro VBA automatiquement?

Je sais que vous pouvez arrêter manuellement une macro VBA en cours d'exécution avec Ctrl+Break, mais existe-t-il un moyen d’arrêter automatiquement le code si une certaine condition est remplie? exit function/exit sub ne fonctionnent pas, car ils ne font que mettre fin à la méthode dans laquelle ils sont appelés.

Par exemple,

sub a
    call b
    msgbox "a complete"
end sub

sub b
    call c
    msgbox "b complete"    'this msgbox will still show after the `exit sub` in 'c'
end sub

sub c
    msgbox "entering c"
    exit sub               'this will only `exit sub` 'c', but not 'a' or 'b'
    msgbox "exiting c"
end sub

'OUTPUT:

'entering c
'b complete
'a complete

Je suppose que je pourrais transformer ces noms sub en function et utiliser les codes de retour pour savoir si la méthode a été exécutée avec succès, mais existe-t-il un moyen plus simple de procéder?

6
iliketocode

Vous pouvez générer votre propre erreur définie par l'utilisateur avec err.raise. Ceci est similaire à votre exemple, mais un peu plus puissant dans le sens où il s’agit d’une erreur réelle qui arrêtera l’exécution de code, même s’il s’applique à un appel imbriqué.

Par exemple,

sub a
on error goto exitCode
    call b
    msgbox "a complete"
    exit sub       'you need this to prevent the error handling code from always running
exitCode:
    msgbox "code is exiting..."
    'clean up code here
end sub

sub b
    call c
    msgbox "b complete"
end sub

sub c
    msgbox "entering c"
    err.raise 555, "foo", "an error occurred"
    msgbox "exiting c"
end sub

'OUTPUT:

'entering c
'code is exiting...

La ligne err.raise enverra le contrôle à l'étiquette exitCode: même s'il a été appelé en dehors de a. Vous pouvez utiliser toutes les conditions pour vérifier si cette erreur personnalisée doit être générée.

En savoir plus sur l'objet err et la gestion des erreurs VBA - 

https://msdn.Microsoft.com/en-us/library/ka13cy19(v=vs.90).aspx

http://www.cpearson.com/Excel/errorhandling.htm

9
iliketocode

Je crois que ce que vous voulez faire est de générer une nouvelle erreur dans votre code de traitement des erreurs. Essayez quelque chose comme ceci (non testé):

Private Sub Test
    On Error Goto bad
    x = 0
    debug.print 1/x
    Exit Sub

    bad:
        'Clean up code
        Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext
End Sub

Lorsque vous utilisez On Error Goto, vous avez besoin d'un Exit Sub avant l'étiquette. Sinon, votre code tombera dans le gestionnaire d'erreurs même s'il n'y a pas d'erreur.

Votre première gestion d'erreur ne détecte pas les erreurs pouvant survenir pendant l'exécution autres que celles que vous testez. En outre, il n'existe pas de moyen pratique de signaler à la fonction d'appel que quelque chose s'est mal passé, sauf si vous ajoutez des vérifications à toutes les routines d'appel. 

Notez qu’il est généralement considéré comme une mauvaise conception de générer une erreur uniquement pour le contrôle de flux:

Private Sub Test
    If x = 0 Then
        Err.Raise 
    End If
End Sub
1
Ceres