Suche…


Einführung

Code, der kompiliert wird, kann zur Laufzeit noch fehlerhaft sein. In diesem Thema werden die häufigsten Ursachen, ihre Ursachen und Möglichkeiten zur Vermeidung aufgeführt.

Laufzeitfehler '3': Rückgabe ohne GoSub

Falscher Code

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

Warum funktioniert das nicht?

Die Ausführung tritt in die DoSomething Prozedur ein, springt zum DoThis Label und gibt "Hi!" Aus. kehrt der Befehl unmittelbar nach dem Aufruf von GoSub zur Anweisung zurück und druckt "Hi!" wieder, und trifft dann auf eine Return - Anweisung, aber es gibt nirgendwo jetzt zurück, weil wir hier nicht mit bekommen haben GoSub - Anweisung.

Code korrigieren

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

Warum funktioniert das?

Durch die Einführung eines Exit Sub Anweisung vor der DoThis Label Linie haben wir die getrennt DoThis Unterprogramm von dem Rest des Verfahrens Körper - der einzige Weg , die auszuführen DoThis Unterprogramm ist über den GoSub Sprung.

Weitere Hinweise

GoSub / Return ist veraltet und sollte zu Gunsten von Prozeduraufrufen vermieden werden. Eine Prozedur sollte keine anderen Unterprogramme als Fehlerbehandlungsroutinen enthalten.

Dies ist dem Laufzeitfehler '20' sehr ähnlich : Ohne Fehler fortfahren ; In beiden Situationen besteht die Lösung darin, sicherzustellen, dass der normale Ausführungspfad nicht ohne expliziten Sprung in eine Subroutine (durch ein Leitungsetikett gekennzeichnet) einsteigen kann (vorausgesetzt, On Error GoTo wird als expliziter Sprung betrachtet ).

Laufzeitfehler '6': Überlauf

Falscher Code

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

Warum funktioniert das nicht?

Der Integer Datentyp ist eine vorzeichenbehaftete 16-Bit-Ganzzahl mit einem Maximalwert von 32.767. Wenn Sie es einer größeren Größe zuweisen, wird der Typ überlaufen und dieser Fehler wird ausgelöst .

Korrigieren Sie den Code

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

Warum funktioniert das?

Durch die Verwendung einer Long -Ganzzahl (32-Bit) können wir jetzt eine Schleife erstellen, die mehr als 32.767-mal durchläuft, ohne den Typ der Zählervariable zu überlaufen.

Weitere Hinweise

Weitere Informationen finden Sie unter Datentypen und Grenzwerte .

Laufzeitfehler '9': Index außerhalb des gültigen Bereichs

Falscher Code

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

Warum funktioniert das nicht?

foo ist ein Array, das 10 Elemente enthält. Wenn der i Schleifenzähler einen Wert von 11 erreicht, ist foo(i) außerhalb des Bereichs . Dieser Fehler tritt auf, wenn auf ein Array oder eine Sammlung mit einem Index zugegriffen wird, der in diesem Array oder dieser Sammlung nicht vorhanden ist.

Korrigieren Sie den Code

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

Warum funktioniert das?

Verwenden LBound Funktionen LBound und UBound , um die Unter- bzw. Obergrenze eines Arrays zu bestimmen.

Weitere Hinweise

Wenn der Index eine Zeichenfolge ist, z. B. ThisWorkbook.Worksheets("I don't exist") , bedeutet dieser Fehler, dass der angegebene Name in der abgefragten Sammlung nicht vorhanden ist.

Der tatsächliche Fehler ist jedoch implementierungsspezifisch. Collection wird stattdessen der Laufzeitfehler 5 "Ungültiger Prozeduraufruf oder -argument" ausgelöst:

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

Laufzeitfehler '13': Typenkonflikt

Falscher Code

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

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

Warum funktioniert das nicht?

VBA ist sehr bemüht, die "42?" Argument in einen Date . Wenn es fehlschlägt, wird der Anruf an DoSomethingElse kann nicht ausgeführt werden, weil VBA nicht weiß , zu welchem Zeitpunkt zu passieren, so dass es wirft Laufzeitabgleichfehler 13 - Typ, da der Typ des Arguments nicht den erwarteten Typ übereinstimmt (und kann (kann nicht implizit konvertiert werden).

Korrigieren Sie den Code

Public Sub DoSomething()
    DoSomethingElse Now
End Sub

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

Warum funktioniert das?

Durch das Übergeben eines Date Arguments an eine Prozedur, die einen Date Parameter erwartet, kann der Aufruf erfolgreich sein.

Laufzeitfehler '91': Objektvariable oder Mit Blockvariable nicht gesetzt

Falscher Code

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

Warum funktioniert das nicht?

Objektvariablen halten einen Verweis, und Referenzen müssen die gesetzt werden mit Set - Schlüsselwort. Dieser Fehler tritt immer dann auf, wenn ein Member-Aufruf für ein Objekt ausgeführt wird, dessen Referenz Nothing . In diesem Fall ist foo eine Collection , die jedoch nicht initialisiert ist. .Add enthält die Referenz Nothing - und wir können .Add on Nothing nicht aufrufen.

Korrigieren Sie den Code

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

Warum funktioniert das?

Durch das Zuweisen der Objektvariablen mit dem Schlüsselwort Set eine gültige Referenz, sind die Aufrufe von .Add erfolgreich.

Weitere Hinweise

Häufig kann eine Funktion oder Eigenschaft eine Objektreferenz zurückgeben. Ein häufiges Beispiel ist die Range.Find Methode von Excel, die ein Range Objekt zurückgibt:

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

Die Funktion kann jedoch sehr gut Nothing (wenn der Suchbegriff nicht gefunden wird), so dass der verkettete .Row Member-Aufruf wahrscheinlich fehlschlägt.

Stellen Sie vor dem Aufrufen von Objektmitgliedern sicher, dass der Verweis mit der Bedingung " If Not xxxx Is Nothing ist:

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

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

Laufzeitfehler '20': Ohne Fehler fortsetzen

Falscher Code

Sub DoSomething()
    On Error GoTo CleanFail
    DoSomethingElse

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

Warum funktioniert das nicht?

Wenn die DoSomethingElse Prozedur einen Fehler DoSomethingElse , springt die Ausführung zur CleanFail Zeilenbeschriftung, gibt die Fehlernummer aus und die Anweisung Resume Next springt zurück zu der Anweisung, die unmittelbar auf die Zeile folgt, in der der Fehler aufgetreten ist, in diesem Fall Debug.Print Anweisung: Die Fehlerbehandlungs-Subroutine wird ohne einen Fehlerkontext ausgeführt. Wenn die Anweisung Resume Next erreicht wird, wird der Laufzeitfehler 20 ausgelöst, da nirgends weitergegangen werden kann.

Code korrigieren

Sub DoSomething()
    On Error GoTo CleanFail
    DoSomethingElse

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

Warum funktioniert das?

Durch die Einführung einer Exit Sub Anweisung vor der CleanFail Zeilenbezeichnung haben wir die CleanFail Fehlerbehandlungs-Subroutine vom Rest des Prozedurenkörpers getrennt. Die einzige Möglichkeit, die Fehlerbehandlungs-Subroutine auszuführen, ist über einen On Error Sprung. Daher erreicht kein Ausführungspfad die Resume Anweisung außerhalb eines Fehlerkontexts, wodurch der Laufzeitfehler 20 vermieden wird.

Weitere Hinweise

Dies ist dem Laufzeitfehler '3' sehr ähnlich : Return ohne GoSub ; In beiden Situationen besteht die Lösung darin, sicherzustellen, dass der normale Ausführungspfad nicht ohne expliziten Sprung in eine Subroutine (durch ein Leitungsetikett gekennzeichnet) einsteigen kann (vorausgesetzt, On Error GoTo wird als expliziter Sprung betrachtet ).



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow