Разница между «при ошибке goto 0» и «при ошибке goto -1» - VBA

32

Может ли кто-нибудь найти разницу между 'On error goto -1' и 'on error goto 0' в VBA? Я пробовал google и msdn, но мне не повезло.

  • 0
    Эта документация для Visual Basic, а не VBA, но концепции в этом случае достаточно похожи, чтобы объяснить разницу.
Теги:
excel
msdn

4 ответа

40
Лучший ответ

On Error GoTo 0 отключает любое обнаружение ошибок, присутствующее в данной процедуре.

On Error GoTo -1 очищает обработку ошибок и устанавливает ее в ничто, что позволяет создать другую ловушку ошибок.

Пример: при ошибке GoTo -1

После того, как первая ошибка будет поднята, она будет GoTo ErrorFound, которая затем очистит процедуру обработки ошибок и установит новую, которая будет GoTo AnotherErrorFound при обнаружении ошибки.

Sub OnErrorGotoMinusOneTest()

    On Error GoTo ErrorFound

    Err.Raise Number:=9999, Description:="Forced Error"

    Exit Sub

ErrorFound:

    On Error GoTo -1 'Clear the current error handling
    On Error GoTo AnotherErrorFound 'Set a new one
    Err.Raise Number:=10000, Description:="Another Forced Error"

AnotherErrorFound:

    'Code here

End Sub

Пример: при ошибке GoTo 0

После того, как первая ошибка будет поднята, вы получите сообщение об ошибке при отключении обработки ошибок.

Sub OnErrorGotoZeroTest()

    On Error GoTo 0

    Err.Raise Number:=9999, Description:="Forced Error"

End Sub
  • 2
    +1, хорошее объяснение. Интересно отметить, что ТОЛЬКО при On Error Goto -1 позволит дальнейшее отслеживание ошибок в рамках отслеживания ошибок. Infact, даже On Error Resume Next все равно будет приводить к неперехваченной ошибке, которая останавливает работу.
  • 0
    Спасибо вам обоим, @Francis Дин и Дэниел Кук. Я закончил тем, что использовал это в своем коде давным-давно, но никогда не знал, почему я смог заставить его работать после Goto -1.
Показать ещё 4 комментария
7

В этом ответе рассматривается путаница между объектом ошибки и обработчиком ошибок.

Объект можно очистить с помощью Err.Clear. Это не влияет на обработчик ошибок.

Обработчик ошибок активируется с помощью On Error Goto <label>. Он становится активным при возникновении ошибки.

В то время как обработчик ошибок активен, вы не можете назначить новый обработчик ошибок. On Error Goto <label> не будет иметь эффекта. VBA просто игнорирует попытку назначить новый обработчик ошибок.

Использование Err.Clear не отменяет обработчик ошибок.

Переход на другое место в коде с помощью Goto <label> не отменяет обработчик ошибок. Использование Goto <label> в блоке обработки ошибок может вызвать путаницу и его следует избегать. Вы можете подумать, что обработчик ошибок больше не активен, поскольку на самом деле он все еще активен.

Эффект активного обработчика ошибок заключается в том, что вы не можете назначить новый обработчик ошибок. On Error Goto <label> не будет иметь эффекта. VBA просто игнорирует попытку назначить новый обработчик ошибок. Любые дополнительные ошибки будут необработаны, пока обработчик ошибок активен.

Единственный способ выхода из активного обработчика ошибок:

  • Resume
  • Resume Next
  • Resume <label>
  • On error goto -1
  • выйти из процедуры

Используя любой из этих способов выхода из обработчика ошибок, также будет очищен объект ошибки.

Отличный источник: Обработка ошибок Pearson в VBA Чип Пирсон не упоминает On error goto -1 в своей статье. Процитировать его:

Я намеренно не включал On Error GoTo -1, потому что он не обслуживает реальной цели и может заблокировать все приложение Excel, если оно не используется точно так же. Да, On Error GoTo -1 синтаксически действительно, но это похоже на то, что пистолет пил подросток. Ничего хорошего придет от него.

Вы также можете обрабатывать ошибки inline без использования обработчика ошибок с использованием объекта ошибки: MSDN Inline Error Handling

  • 0
    Visual Basic вызывает метод Clear автоматически всякий раз, когда выполняется любой тип оператора Resume, Exit Sub, Exit Function, Exit Property или любого оператора On Error. Нет разницы между Err.Clear и On Error GoTo -1 в том, что они оба сбрасывают любое возбужденное исключение. Т.е. ошибочный объект становится ничем.
  • 2
    @HarveyFrench Разница между Err.Clear и On Error GoTo -1 в том, что первый не Err.Clear (сбрасывает) обработчик ошибок, а второй - нет. Только после выхода (сброса) обработчика ошибок вы можете включить другой обработчик ошибок.
Показать ещё 1 комментарий
3

Здесь еще один

http://www.excelfox.com/forum/f23/error-goto-1-a-894/

Показывает немного больше о том, какая разница между GoTo 0 и GoTo -1

-2

Важно осознать, что в VBA возникают ошибки, связанные с ошибкой.

  • У объекта ошибки есть его набор свойств (например, err.number, err.desciption, err.source и т.д.)

  • Следующая строка, которая будет выполнена, изменится.
    Какая строка выполняется, определяется последним оператором "On Error Goto" , который был выполнен - ​​если есть.

Это отдельные, но связанные темы, и вы напишете то, что в действительности является отличным, но переплетенным кодом для управления ими.

Когда возникает ЛЮБАЯ ошибка или вы используете Err.Raise, объект Err устанавливается ВСЕГДА. Даже если используется "On Error Resmue next" или любой другой оператор On error.

Таким образом, такой код можно использовать ВСЕГДА:

Dim i as integer 
On error resume next 
i = 100/0  ' raises error
if err.number <> 0 then 
   ' respond to the error
end if

Очень важно понять, что, когда объект ошибки имеет ненулевое значение для err.number, было поднято исключение И что если вы затем попытаетесь выполнить любое действие "On Error Goto" , это приведет к возникновению ошибки и выполнение будет передано любому коду, который вызывает текущую процедуру. (или где не вызывается каким-либо кодом, предоставляется обычный диалог ошибок VBA). Обратите внимание, что в этом случае "On Error Goto ALabel1" НЕ изменит следующую строку, чтобы быть строкой с Label1: на ней.

eg

Sub ErrorTest()

    Dim dblValue        As Double

    On Error GoTo ErrHandler1
    dblValue = 1 / 0

ErrHandler1:
    debug.print "Exception Caught"
    debug.print Err.Number

    On Error GoTo ALabel1
    dblValue = 1 / 0

Exit sub
ALabel1:
    debug.print "Again caught it."

End Sub

Как только свойство err.number будет установлено на ноль, вы можете reset его на ноль, используя

On Error Goto -1 

Обратите внимание, что Err.Clear также сбрасывает его до нуля, но на самом деле это эквивалентно:

On Error Goto -1 
On Error Goto 0

т.е. Err.Clear удаляет "On Error Goto" , который в настоящее время существует. Поэтому лучше всего использовать:

On Error Goto -1   

как использование Err.clear Вам часто нужно писать

Err.Clear
On Error Goto MyErrorHandlerLabel

Стоит отметить, что Err.Clear неявно выполняется VBA всякий раз, когда он выполняет любой оператор Resume, Exit Sub, Exit Function, Exit Property или любой оператор On Error.

Вы также можете установить для объекта ошибки все, что вам нравится, используя

Err.Raise Number: =, Источник: =, Описание: =

Err.Raise очень важен, так как он позволяет распространять ошибку на вызывающую программу. И повышайте свои собственные номера ошибок, известные как "пользовательские ошибки", которые предоставляют способ сообщить вызывающей программе, что она не может продолжить логическая причина. (например, бизнес-правило было нарушено).

Вы можете управлять тем, какая строка кода выполняется следующим, используя выражения типа

Вкл. Ошибка Перейти к ALabelName По ошибке Перейти к ANONZeroLineNumber а также On Error Goto 0 'Это особый случай, когда он говорит "внутри текущей области (как правило, sub или function)), в случае, если произошла ошибка, возвращает объект ошибки обратно к коду, который вызывает текущую подфункцию или функцию.

Обработка ошибок в VBA сложна, особенно, поскольку страницы MSDN действительно не дают полных примеров того, как можно использовать обработку ошибок.

  • 2
    Err.Clear и On Error Goto -1 НЕ эквивалентны. Если вы замените On Error Goto -1 на Err.Clear в своем коде, вы увидите, что вторая ошибка не Err.Clear с Err.Clear . Они НЕ эквивалентны.
  • 0
    Боже, твое право. Из моих экспериментов: On Error Goto -1 устанавливает нулевой объект err (т. Е. Err.number равным 0). Err.clear эквивалентен On Error Goto -1 ', за которым следует On Error Goto 0. Я изменю свой код соответствующим образом. Вы согласитесь @D_Bester?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню