Ricerca…


introduzione

Il codice che compila può ancora incorrere in errori, in fase di esecuzione. Questo argomento elenca i più comuni, le loro cause e come evitarli.

Errore di run-time '3': Ritorno senza GoSub

Codice non corretto

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

Perché non funziona?

L'esecuzione entra nella procedura DoSomething , DoThis all'etichetta DoThis , stampa "Ciao!" all'output di debug, ritorna all'istruzione immediatamente dopo la chiamata GoSub , stampa "Ciao!" di nuovo, e poi incontra un'istruzione Return , ma non c'è nessun luogo in cui tornare ora, perché non siamo arrivati ​​qui con un'istruzione GoSub .

Codice corretto

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

Perché funziona?

Introducendo un'istruzione Exit Sub prima DoThis Line DoThis , abbiamo separato la subroutine DoThis dal resto del corpo della procedura - l'unico modo per eseguire la subroutine DoThis è tramite GoSub jump.

Altre note

GoSub / Return è deprecato e dovrebbe essere evitato a favore delle chiamate di procedura effettive. Una procedura non dovrebbe contenere subroutine, tranne che gestori di errori.

Questo è molto simile all'errore di run-time '20': riprendi senza errori ; in entrambe le situazioni, la soluzione è garantire che il normale percorso di esecuzione non possa entrare in una sottorete (identificata da un'etichetta di linea) senza un salto esplicito (supponendo che On Error GoTo sia considerato un salto esplicito ).

Errore di run-time '6': Overflow

codice non corretto

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

Perché non funziona?

Il tipo di dati Integer è un intero con segno a 16 bit con un valore massimo di 32.767; assegnandolo a qualcosa più grande di quello traboccherà il tipo e aumenterà questo errore.

Codice corretto

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

Perché funziona?

Usando invece un intero Long (32-bit), possiamo ora creare un ciclo che itera più di 32.767 volte senza sovraccaricare il tipo della variabile del contatore.

Altre note

Vedi Tipi di dati e limiti per ulteriori informazioni.

Errore di run-time '9': indice fuori intervallo

codice non corretto

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

Perché non funziona?

foo è un array che contiene 10 elementi. Quando il contatore di loop i raggiunge un valore di 11, foo(i) è fuori portata . Questo errore si verifica ogni volta che si accede a una matrice o a una raccolta con un indice che non esiste in quell'array o raccolta.

Codice corretto

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

Perché funziona?

Utilizzare le funzioni LBound e UBound per determinare rispettivamente i limiti inferiore e superiore di un array.

Altre note

Quando l'indice è una stringa, ad esempio ThisWorkbook.Worksheets("I don't exist") , questo errore indica che il nome fornito non esiste nella raccolta interrogata.

L'errore effettivo è però specifico per l'implementazione; Collection aumenterà l'errore di runtime 5 "Chiamata o argomento procedura non valida" invece:

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

Errore di run-time "13": tipo mancata corrispondenza

codice non corretto

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

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

Perché non funziona?

VBA sta provando davvero a convertire il "42?" argomento in un valore Date . Quando fallisce, la chiamata a DoSomethingElse non può essere eseguita, perché VBA non sa quale data passare, quindi solleva la mancata corrispondenza di errore di tipo 13, perché il tipo dell'argomento non corrisponde al tipo previsto (e può essere implicitamente convertiti entrambi).

Codice corretto

Public Sub DoSomething()
    DoSomethingElse Now
End Sub

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

Perché funziona?

Passando un argomento Date a una procedura che prevede un parametro Date , la chiamata può avere successo.

Errore di run-time '91': variabile dell'oggetto o variabile di blocco With non impostata

codice non corretto

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

Perché non funziona?

Le variabili oggetto contengono un riferimento e i riferimenti devono essere impostati utilizzando la parola chiave Set . Questo errore si verifica ogni volta che viene effettuata una chiamata di membro su un oggetto il cui riferimento è Nothing . In questo caso, foo è un riferimento alla Collection , ma non è inizializzato, quindi il riferimento contiene Nothing - e non possiamo chiamare .Add su Nothing .

Codice corretto

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

Perché funziona?

Assegnando alla variabile oggetto un riferimento valido utilizzando la parola chiave Set , le chiamate .Add esito positivo.

Altre note

Spesso, una funzione o una proprietà possono restituire un riferimento a un oggetto: un esempio comune è il metodo Range.Find di Excel, che restituisce un oggetto Range :

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

Tuttavia, la funzione può restituire Nothing (se il termine di ricerca non viene trovato), quindi è probabile che la chiamata del membro .Row concatenata non riesca.

Prima di chiamare i membri dell'oggetto, verificare che il riferimento sia impostato con una condizione 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

Errore di run-time '20': riprendi senza errori

codice non corretto

Sub DoSomething()
    On Error GoTo CleanFail
    DoSomethingElse

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

Perché non funziona?

Se la procedura DoSomethingElse genera un errore, l'esecuzione salta CleanFail linea CleanFail , stampa il numero dell'errore e l'istruzione Resume Next torna all'istruzione che segue immediatamente la riga in cui si è verificato l'errore, che in questo caso è Debug.Print istruzione: la subroutine di gestione degli errori viene eseguita senza un contesto di errore e quando viene raggiunta l'istruzione Resume Next , viene generato l'errore di run-time 20 perché non è possibile riprendere da nessuna parte.

Codice corretto

Sub DoSomething()
    On Error GoTo CleanFail
    DoSomethingElse

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

Perché funziona?

Introducendo un'istruzione Exit Sub prima CleanFail riga CleanFail , abbiamo separato la subroutine di gestione degli errori di CleanFail dal resto del corpo della procedura - l'unico modo per eseguire la subroutine di gestione degli errori è tramite un On Error ; pertanto, nessun percorso di esecuzione raggiunge l'istruzione Resume al di fuori di un contesto di errore, che evita l'errore di runtime 20.

Altre note

Questo è molto simile all'errore di run-time '3': Return senza GoSub ; in entrambe le situazioni, la soluzione è garantire che il normale percorso di esecuzione non possa entrare in una sottorete (identificata da un'etichetta di linea) senza un salto esplicito (supponendo che On Error GoTo sia considerato un salto esplicito ).



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow