Как перейти к следующей итерации при ошибке AKA, имитирующей оператор Python "continue" в VBA - PullRequest
0 голосов
/ 17 октября 2018

В следующем коде, как заставить цикл продолжиться на следующей итерации, а не на следующей строке - после того, как возникла ошибка?

В данный момент код не пройдет x = 0:

Sub skip_iteration()

Dim x As Long

For x = 5 To -5 Step -1
    On Error GoTo errhandler:
    Debug.Print 15 / x
    Debug.Print "I don't want this to be printed on error"
Next x

errhandler:
If Err.Number = 11 Then
    Debug.Print ("Error on " & x)
End If

End Sub

Я изучил этот ответ: Перейдите к следующей итерации в цикле vba среди других, но не смог перевести его в мой код.

Ответы [ 3 ]

0 голосов
/ 17 октября 2018

Другой вариант - встроить обработчик ошибок.Это делает очевидным, что вы знаете о потенциальной возможности конкретной строки кода вызвать ошибку, и не полагаетесь на Resume для управления потоком.Разрешение ошибки перейти к вашему обработчику в нижней части функции, а затем вернуться к основной строке кода, делает гораздо менее очевидным, каково ожидаемое поведение цикла.

Sub SkipIteration()
    Dim x As Long

    For x = 5 To -5 Step -1
        On Error Resume Next
        Debug.Print 15 / x
        If Err.Number = 11 Then
            Debug.Print "Expected error on " & x
            On Error GoTo errhandler
        Else
            On Error GoTo errhandler
            Debug.Print "Process the rest of the loop"
        End If
    Next x

    Exit Sub
errhandler:
    Debug.Print "Unexpected error "; Err.Number
End Sub

Еще лучшечтобы разделить проблемы ваших процедур таким образом, чтобы выполняемая часть цикла представляла собой один оператор:

Sub SkipIteration()
    On Error GoTo errhandler

    Dim x As Long
    For x = 5 To -5 Step -1
        If TheThingThatCanError(x) Then
            ActionThatDependsOnAbove x
        End If
    Next x

    Exit Sub
errhandler:
    Debug.Print "Unexpected error "; Err.Number
End Sub

Private Function TheThingThatCanError(x As Long) As Boolean
    On Error Resume Next
    Debug.Print 15 / x
    If Err.Number = 11 Then
        Debug.Print "Expected error on " & x
        Exit Function
    End If
    TheThingThatCanError = True
End Function

Private Sub ActionThatDependsOnAbove(x As Long)
    Debug.Print "I don't want this to be printed on error " & x
End Sub
0 голосов
/ 17 октября 2018

Если вы хотите пропустить Error и продолжить следующую итерацию, возможный способ - использовать GoTo и создать некоторый код спагетти :

Sub SkipIteration()
    Dim x As Long
    For x = 5 To -5 Step -1
        If IsError(Evaluate("15 / " & x)) Then GoTo Skipper
        Debug.Print 15 / x
        Debug.Print x
Skipper:
    Next x
End Sub

илииспользуйте встраивание всей IsError отметки в if и избегайте GoTo.Но тогда вам нужно перейти на одну вкладку вправо и потерять отступ:

Sub SkipIteration()
    Dim x As Long
    For x = 5 To -5 Step -1
        If Not IsError(Evaluate("15 / " & x)) Then
            Debug.Print 15 / x
            Debug.Print x
        End If
    Next x
End Sub
0 голосов
/ 17 октября 2018

Вам нужно Resume Next, чтобы перейти к следующей строке после строки, вызывая ошибку.И Err.Clear также является хорошей практикой.

Exit Sub перед errhandler также является хорошей практикой:

Sub SkipIteration()

    Dim x As Long        
    For x = 5 To -5 Step -1
        On Error GoTo errhandler:
        Debug.Print 15 / x
        Debug.Print "testing"
    Next x        
    Exit Sub

errhandler:
    If Err.Number = 11 Then
        Debug.Print ("Error on " & x)
        Err.Clear
        Resume Next
    End If    
End Sub

Разница между Resume и Resume Next выглядит следующим образом:

  • Resume пытается вернуться туда, где он был вызван.

В процедуре TestMeResume выдается ошибка 11 при отладке..Print a / b и в обработчике ошибок он назначает b = 5. Затем с Resume он повторяет Debug.Print a / b, и, поскольку b не является 0, он запускается.

  • Resume Next идет туда, где она была вызвана, игнорирует линию и переходит к следующей.

В процедуре TestMeResumeNext ошибка 91 генерируется в a = 12 и запускается обработчик ошибок.В обработчике ошибок a назначается Range("A14"), а с Resume Next a = 12 пропускается, а Sub продолжается.


Sub TestMeResumeNext()

    On Error GoTo TestMeResumeNext_Error

    Dim a As Range
    a = 12              'Error 91 here!
    Debug.Print a.Row   'Resume Next goes back here
    Exit Sub

TestMeResumeNext_Error:
    Set a = Range("A14")
    Resume Next
End Sub

Sub TestMeResume()

    On Error GoTo TestMeResume_Error

    Dim a As Long: a = 10
    Dim b As Long: b = 0
    Debug.Print a / b   'Error 11 here the first time
    Exit Sub

TestMeResume_Error:
    b = 5
    Resume
End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...