44

谁能在 VBA 中找到“On error goto -1”和“on error goto 0”之间的区别?我已经尝试过 google 和 msdn,但我没有运气。

4

3 回答 3

67

On Error GoTo 0禁用过程中当前存在的任何错误捕获。

On Error GoTo -1清除错误处理并将其设置为空,这样您就可以创建另一个错误陷阱。

示例:错误转到 -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

示例:错误转到 0

引发第一个错误后,您将收到错误,因为错误处理已被禁用。

Sub OnErrorGotoZeroTest()

    On Error GoTo 0

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

End Sub
于 2013-01-04T15:29:22.553 回答
21

这个答案解决了错误对象和错误处理程序之间的混淆。

可以使用 清除错误对象Err.Clear。这不会影响错误处理程序。

使用启用错误处理程序On Error Goto <label>。当发生错误时,它变为活动状态。

当错误处理程序处于活动状态时,您不能分配新的错误处理程序。On Error Goto <label>不会有任何影响。VBA 只是忽略分配新错误处理程序的尝试。

使用Err.Clear不会取消错误处理程序。

跳转到代码中的不同位置 usingGoto <label>不会取消错误处理程序。在错误处理块中使用Goto <label>可能会导致混淆,应该避免。您可能认为错误处理程序不再处于活动状态,而实际上它仍然处于活动状态。

活动错误处理程序的效果是您不能分配新的错误处理程序。On Error Goto <label>不会有任何影响。VBA 只是忽略分配新错误处理程序的尝试。当错误处理程序处于活动状态时,任何其他错误都将被取消处理。

退出活动错误处理程序的唯一方法是:

  1. Resume
  2. Resume Next
  3. Resume <label>
  4. On error goto -1
  5. 退出程序

使用其中任何一种方式退出错误处理程序也将清除错误对象。

优秀来源:VBA 芯片中的 Pearson 错误处理On error goto -1Pearson在他的文章中没有提到。引用他的话:

我故意不包括 On Error GoTo -1,因为它没有真正的用途,并且可以锁定整个 Excel 应用程序,除非以完全正确的方式使用。是的,On Error GoTo -1 在语法上是有效的,但这就像给醉酒的少年一把枪。不会有任何好处。

您还可以使用错误对象在不使用错误处理程序的情况下内联处理错误:MSDN 内联错误处理

于 2015-06-23T04:50:35.207 回答
-1

重要的是要意识到当 VBA 中发生错误时会发生两种不同的事情。

  1. 错误对象设置了它的属性(即 err.number、err.desciption、err.source 等)

  2. 下一行要执行的更改。
    执行哪一行取决于最后执行的“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: 的行。

例如

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 属性设置为非零,您可以通过使用将其重置为零

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

值得注意的是,每当执行任何类型的 Resume 语句、Exit Sub、Exit Function、Exit Property 或任何 On Error 语句时,VBA 都会隐式执行 Err.Clear。

您还可以将错误对象设置为您喜欢使用的任何数字

Err.Raise Number:=, Source:=, Description:=

Err.Raise 非常重要,因为它允许您将错误传播到调用程序并引发您自己的错误编号,称为“用户定义的错误”,这提供了一种告诉调用程序由于逻辑原因它无法继续的方法。(例如,违反了业务规则)。

您可以使用以下语句控制接下来执行哪一行代码

On Error Goto ALabelName On Error Goto ANonZeroLineNumber and On Error Goto 0 ' 这是一种特殊情况,因为它实际上表示“在当前范围内(通常是子或函数),如果发生错误,将错误对象传递回调用当前子或函数的代码。

VBA 中的错误处理很棘手,尤其是 MSDN 页面并没有真正给出如何使用错误处理的完整示例。

于 2015-06-23T08:55:50.193 回答