2016-10-28 2 views
1

Я ожидаю, что этот простой VBA молча обрабатывать все 10 ошибок, но по какой-то причине, только первый обрабатывается тихо:Почему этот обработчик ошибок VBA не работает?

Public Sub HandleError() 
    For i = 1 To 10 
     On Error GoTo Continue 
     ThrowError 

Continue: 
     Err.Clear 
    Next i 
End Sub 

Public Sub ThrowError() 
    Err.Raise vbObjectError + 1000 
End Sub 

Является ли это правильное поведение для приведенного выше кода? Или это ошибка в VBA?

+2

Правильное использование 'On Error GoT Для правильной повторной активации o требуется одна из двух вещей: (1) 'Resume',' Resume Next' или 'Resume

+0

Это сработало. Благодаря! –

+0

Добро пожаловать! Хотя я надеюсь, что это всего лишь игрушечный проект, который поможет лучше понять вещи, а не начало какой-то реальной схемы использования обработки ошибок VBA таким образом. Потому что это закончится слезами. – rskar

ответ

4

Вы перекручивание через ошибки обработки этикетки, так что вторая ошибка возникает в контексте обработчика ошибок, даже если Next i инструкция перемещает выполнение кода в строке выше метки. Вам необходимо перенести выполнение из контекста обработки ошибок, вызвав Resume после устранения ошибки. Это означает, что обработчик ошибок должен либо быть вне цикла ...

Public Sub HandleError() 
    For i = 1 To 10 
     On Error GoTo Continue 
     ThrowError 
    Next i 

    Exit Sub 
Continue: 
    Err.Clear 
    Resume Next 
End Sub 

... или есть второй ярлык для Resume на:

Public Sub HandleError() 
    For i = 1 To 10 
     On Error GoTo Continue 
     ThrowError 

Continue: 
     Err.Clear 
     Resume NextLoop 
NextLoop: 
    Next i 
End Sub 

Много лучше было бы просто проверить конкретную ошибку в конкретной строке кода:

Public Sub HandleError() 
    For i = 1 To 10 
     On Error Resume Next 
     ThrowError 
     If Err.Number = vbObjectError + 1000 Then Err.Clear 
     On Error GoTo 0 
     Debug.Print i 
    Next i 
End Sub 
+0

Если это можно сделать без необходимости в 'On Error Resume Next', *, что *, как правило, лучший способ. Только ради производительности может быть оправданным, и даже тогда либо обильные комментарии к whys, либо, еще лучше, им необходимо, чтобы он был помещен в свою собственную функцию. Это просто слишком склонно к злоупотреблениям (наряду с 'Goto'). – rskar

+0

@rskar - Я не уверен, что могу представить себе ситуацию, когда использование обработчика ошибок будет более результативным, чем использование обработчика ошибок. 'On Error Resume Next', за которым следует тест, гораздо яснее в отношении кода, и я бы сказал, что это почти идентичный VBA эквивалент блоку try \ catch. Обратите внимание, что IMHO, это *** *** *** причина использовать 'On Error Resume Next'. – Comintern

+0

«... использование обработчика ошибок было бы более эффективным, чем использование обработчика ошибок ...» Я думаю, что вы меня неправильно поняли, я конкретно обращался к выбору между «On Error Resume Next» и «On Error GoTo

Смежные вопросы