Zoeken…


Invoering

Code die wordt samengesteld, kan tijdens runtime nog steeds fouten bevatten. Dit onderwerp geeft een overzicht van de meest voorkomende oorzaken, hun oorzaken en hoe u ze kunt vermijden.

Runtime error '3': Return zonder GoSub

Foute code

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

Waarom werkt dit niet?

Uitvoering voert de DoSomething procedure in, springt naar het DoThis label en drukt "Hallo!" naar de foutopsporingsuitvoer, keert onmiddellijk na de GoSub oproep terug naar de instructie en drukt "Hallo!" en ontmoet vervolgens een Return instructie, maar er is nergens om naar terug te keren , omdat we hier niet zijn gekomen met een GoSub instructie.

Juiste code

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

Waarom werkt dit

Door een Exit Sub instructie voor het DoThis introduceren, hebben we de DoThis subroutine gescheiden van de rest van de procedure - de enige manier om de DoThis subroutine uit te voeren is via de GoSub sprong.

Andere notities

GoSub / Return is verouderd en moet worden vermeden ten gunste van daadwerkelijke procedureaanroepen. Een procedure mag geen subroutines bevatten, behalve foutafhandelaars.

Dit lijkt erg op Runtime-fout '20': zonder fout hervatten ; in beide situaties is de oplossing ervoor te zorgen dat het normale uitvoeringspad geen subroutine (geïdentificeerd door een lijnlabel) kan betreden zonder een expliciete sprong (ervan uitgaande dat On Error GoTo als een expliciete sprong wordt beschouwd).

Runtime error '6': Overflow

foute code

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

Waarom werkt dit niet?

Het gegevenstype Integer is een 16-bits geheel getal met teken met een maximale waarde van 32.767; toe te wijzen aan iets groter dan die van het type overstromen, en deze fout te verhogen.

Juiste code

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

Waarom werkt dit

Door in plaats daarvan een Long (32-bits) geheel getal te gebruiken, kunnen we nu een lus maken die meer dan 32.767 keer itereert zonder het type van de tellervariabele te overlopen.

Andere notities

Zie Gegevenstypen en -limieten voor meer informatie.

Runtime-fout '9': subscript buiten bereik

foute code

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

Waarom werkt dit niet?

foo is een array met 10 items. Wanneer de i lusteller een waarde van 11 bereikt, is foo(i) buiten bereik . Deze fout treedt op wanneer een matrix of verzameling wordt geopend met een index die niet bestaat in die matrix of verzameling.

Juiste 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

Waarom werkt dit

Gebruik de functies LBound en UBound om respectievelijk de onderste en bovenste grenzen van een array te bepalen.

Andere notities

Wanneer de index een tekenreeks is, bijvoorbeeld ThisWorkbook.Worksheets("I don't exist") , betekent deze fout dat de opgegeven naam niet voorkomt in de opgevraagde collectie.

De werkelijke fout is echter implementatiespecifiek; Collection zal runtime-fout 5 "Ongeldige procedureaanroep of argument" veroorzaken:

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

Runtime error '13': Type mismatch

foute code

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

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

Waarom werkt dit niet?

VBA probeert heel hard om de "42?" argument in een Date waarde. Als het mislukt, kan de aanroep van DoSomethingElse niet worden uitgevoerd, omdat VBA niet weet welke datum moet worden doorgegeven, dus het leidt tot run-time error 13 type mismatch , omdat het type argument niet overeenkomt met het verwachte type (en kan worden ook niet impliciet geconverteerd).

Juiste code

Public Sub DoSomething()
    DoSomethingElse Now
End Sub

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

Waarom werkt dit

Door een Date argument door te geven aan een procedure die een Date parameter verwacht, kan de aanroep slagen.

Runtime-fout '91': objectvariabele of met blokvariabele niet ingesteld

foute code

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

Waarom werkt dit niet?

Objectvariabelen bevatten een referentie en referenties moeten worden ingesteld met het trefwoord Set . Deze fout treedt op wanneer een lid wordt gebeld op een object waarvan de referentie Nothing . In dit geval is foo een Collection , maar het is niet geïnitialiseerd, dus de referentie bevat Nothing - en we kunnen niet bellen. .Add Nothing .

Juiste code

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

Waarom werkt dit

Door de objectvariabele een geldige referentie toe te wijzen met behulp van het trefwoord Set , slagen de .Add aanroepen.

Andere notities

Vaak kan een functie of eigenschap een objectverwijzing retourneren - een veelvoorkomend voorbeeld is de methode Range.Find Excel, die een Range object retourneert:

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

De functie kan echter heel goed Nothing retourneren (als de zoekterm niet wordt gevonden), dus het is waarschijnlijk dat de geketende .Row lid-oproep mislukt.

Voordat u objectleden oproept, controleert u of de referentie is ingesteld met de voorwaarde 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

Runtime-fout '20': zonder fout hervatten

foute code

Sub DoSomething()
    On Error GoTo CleanFail
    DoSomethingElse

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

Waarom werkt dit niet?

Als de procedure DoSomethingElse een fout oproept, springt de uitvoering naar het CleanFail , drukt het foutnummer af en springt de instructie Resume Next terug naar de instructie die onmiddellijk volgt op de regel waar de fout is opgetreden, in dit geval Debug.Print instructie: de foutafhandelingssubroutine wordt uitgevoerd zonder een foutcontext, en wanneer de instructie Resume Next wordt bereikt, wordt runtime-fout 20 opgeworpen omdat er nergens naartoe kan worden hervat.

Juiste code

Sub DoSomething()
    On Error GoTo CleanFail
    DoSomethingElse

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

Waarom werkt dit

Door een Exit Sub instructie voor het CleanFail introduceren, hebben we de CleanFail -foutafhandelings-subroutine gescheiden van de rest van de procedure - de enige manier om de foutafhandelings-subroutine uit te voeren is via een On Error sprong; daarom bereikt geen uitvoeringspad de instructie Resume buiten een foutcontext, waardoor runtime-fout 20 wordt vermeden.

Andere notities

Dit lijkt erg op Run-time error '3': Return without GoSub ; in beide situaties is de oplossing ervoor te zorgen dat het normale uitvoeringspad geen subroutine (geïdentificeerd door een lijnlabel) kan betreden zonder een expliciete sprong (ervan uitgaande dat On Error GoTo als een expliciete sprong wordt beschouwd).



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow