Recherche…


Introduction

Le code qui compile peut encore présenter des erreurs lors de l'exécution. Cette rubrique répertorie les plus courantes, leurs causes et comment les éviter.

Erreur d'exécution '3': Retour sans GoSub

Code incorrect

Sub DoSomething()
    GoSub DoThis
DoThis:
    Debug.Print "Hi!"
    Return
End Sub

Pourquoi cela ne marche pas?

L'exécution entre dans la procédure DoSomething , passe à l'étiquette DoThis , imprime "Hi!" à la sortie de débogage, retourne à l'instruction immédiatement après l'appel GoSub , imprime "Hi!" encore une fois, et rencontre ensuite une déclaration de Return , mais il n'y a nulle part où revenir maintenant, car nous ne sommes pas GoSub ici avec une déclaration GoSub .

Code correct

Sub DoSomething()
    GoSub DoThis
    Exit Sub
DoThis:
    Debug.Print "Hi!"
    Return
End Sub

Pourquoi ça marche?

En introduisant une instruction Exit Sub avant le DoThis ligne DoThis , nous avons séparé la sous-routine DoThis du reste du corps de la procédure. La seule manière d'exécuter la sous-routine DoThis est le saut GoSub .

Autres notes

GoSub / Return est obsolète et devrait être évité en faveur des appels de procédure réels. Une procédure ne doit pas contenir de sous-routines autres que les gestionnaires d'erreurs.

Ceci est très similaire à l' erreur d'exécution '20': reprendre sans erreur ; dans les deux cas, la solution consiste à s'assurer que le chemin d'exécution normal ne peut pas entrer dans une sous-routine (identifiée par une étiquette de ligne) sans saut explicite (en supposant que On Error GoTo soit considéré comme un saut explicite ).

Erreur d'exécution '6': débordement

code incorrect

Sub DoSomething()
    Dim row As Integer
    For row = 1 To 100000
        'do stuff
    Next
End Sub

Pourquoi cela ne marche pas?

Le type de données Integer est un entier signé 16 bits avec une valeur maximale de 32 767; l'affecter à quelque chose de plus grand que celui qui débordera le type et provoquera cette erreur.

Code correct

Sub DoSomething()
    Dim row As Long
    For row = 1 To 100000
        'do stuff
    Next
End Sub

Pourquoi ça marche?

En utilisant un entier Long (32 bits) à la place, on peut maintenant faire une boucle qui itère plus de 32 767 fois sans déborder le type de la variable du compteur.

Autres notes

Voir Types de données et limites pour plus d'informations.

Erreur d'exécution '9': indice hors limites

code incorrect

Sub DoSomething()
    Dim foo(1 To 10)
    Dim i As Long
    For i = 1 To 100
        foo(i) = i
    Next
End Sub

Pourquoi cela ne marche pas?

foo est un tableau qui contient 10 éléments. Lorsque le compteur de boucles i atteint la valeur 11, foo(i) est hors limites . Cette erreur se produit chaque fois qu'un tableau ou une collection est accessible avec un index qui n'existe pas dans ce tableau ou cette collection.

Code correct

Sub DoSomething()
    Dim foo(1 To 10)
    Dim i As Long
    For i = LBound(foo) To UBound(foo)
        foo(i) = i
    Next
End Sub

Pourquoi ça marche?

Utilisez les fonctions LBound et UBound pour déterminer respectivement les limites inférieure et supérieure d'un tableau.

Autres notes

Lorsque l'index est une chaîne, par exemple ThisWorkbook.Worksheets("I don't exist") , cette erreur signifie que le nom fourni n'existe pas dans la collection interrogée.

L'erreur réelle est spécifique à l'implémentation bien que; Collection déclenchera l'erreur d'exécution 5 "Appel ou argument de procédure non valide" à la place:

Sub RaisesRunTimeError5()
    Dim foo As New Collection
    foo.Add "foo", "foo"
    Debug.Print foo("bar")
End Sub

Erreur d'exécution '13': incompatibilité de type

code incorrect

Public Sub DoSomething()
    DoSomethingElse "42?"
End Sub

Private Sub DoSomethingElse(foo As Date)
'    Debug.Print MonthName(Month(foo))
End Sub

Pourquoi cela ne marche pas?

VBA essaie vraiment de convertir le "42?" argument dans une valeur de Date . En cas d'échec, l'appel de DoSomethingElse ne peut pas être exécuté, car VBA ne sait pas quelle date doit être transmise, ce qui provoque une incompatibilité de type erreur d'exécution 13, car le type de l'argument ne correspond pas au type attendu (et peut ne soit pas implicitement converti non plus).

Code correct

Public Sub DoSomething()
    DoSomethingElse Now
End Sub

Private Sub DoSomethingElse(foo As Date)
'    Debug.Print MonthName(Month(foo))
End Sub

Pourquoi ça marche?

En transmettant un argument Date à une procédure qui attend un paramètre Date , l'appel peut aboutir.

Erreur d'exécution '91': variable d'objet ou variable de bloc With non définie

code incorrect

Sub DoSomething()
    Dim foo As Collection
    With foo
        .Add "ABC"
        .Add "XYZ"
    End With
End Sub

Pourquoi cela ne marche pas?

Les variables d'objet contiennent une référence et les références doivent être définies à l'aide du mot-clé Set . Cette erreur se produit chaque fois qu'un appel de membre est effectué sur un objet dont la référence est Nothing . Dans ce cas, foo est une référence de Collection , mais elle n'est pas initialisée. La référence contient donc Nothing - et nous ne pouvons pas appeler .Add sur Nothing .

Code correct

Sub DoSomething()
    Dim foo As Collection
    Set foo = New Collection
    With foo
        .Add "ABC"
        .Add "XYZ"
    End With
End Sub

Pourquoi ça marche?

En attribuant à la variable d'objet une référence valide à l'aide du mot clé Set , les appels .Add réussissent.

Autres notes

Souvent, une fonction ou une propriété peut renvoyer une référence d'objet - un exemple courant est la méthode Range.Find d'Excel, qui renvoie un objet Range :

Dim resultRow As Long
resultRow = SomeSheet.Cells.Find("Something").Row

Cependant, la fonction peut très bien retourner Nothing (si le terme de recherche n'est pas trouvé), il est donc probable que l'appel de membre chaîné .Row échoue.

Avant d'appeler des membres d'objet, vérifiez que la référence est définie avec la condition If Not xxxx Is Nothing :

Dim result As Range
Set result = SomeSheet.Cells.Find("Something")

Dim resultRow As Long
If Not result Is Nothing Then resultRow = result.Row

Erreur d'exécution '20': reprendre sans erreur

code incorrect

Sub DoSomething()
    On Error GoTo CleanFail
    DoSomethingElse

CleanFail:
    Debug.Print Err.Number
    Resume Next
End Sub

Pourquoi cela ne marche pas?

Si la procédure DoSomethingElse une erreur, l'exécution passe à l' CleanFail ligne CleanFail , imprime le numéro d'erreur et l'instruction Resume Next retourne à l'instruction qui suit immédiatement la ligne où l'erreur s'est produite, à savoir Debug.Print instruction: le sous-programme de traitement des erreurs s'exécute sans contexte d'erreur et lorsque l'instruction Resume Next est atteinte, l'erreur d'exécution 20 est déclenchée car il n'y a aucun endroit où reprendre.

Code correct

Sub DoSomething()
    On Error GoTo CleanFail
    DoSomethingElse

    Exit Sub    
CleanFail:
    Debug.Print Err.Number
    Resume Next
End Sub

Pourquoi ça marche?

En introduisant une instruction Exit Sub avant le CleanFail ligne CleanFail , nous avons séparé le CleanFail -programme de gestion des erreurs CleanFail du reste du corps de la procédure. Le seul moyen d'exécuter le sous-programme de traitement des erreurs est un saut d' On Error ; par conséquent, aucun chemin d'exécution n'atteint l'instruction Resume dehors d'un contexte d'erreur, ce qui évite l'erreur d'exécution 20.

Autres notes

Ceci est très similaire à l' erreur d'exécution "3": Retour sans GoSub ; dans les deux cas, la solution consiste à s'assurer que le chemin d'exécution normal ne peut pas entrer dans une sous-routine (identifiée par une étiquette de ligne) sans saut explicite (en supposant que On Error GoTo soit considéré comme un saut explicite ).



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow