【发布时间】:2012-12-18 23:53:23
【问题描述】:
谁能在 VBA 中找到“On error goto -1”和“on error goto 0”之间的区别?我试过google和msdn,但都没有运气。
【问题讨论】:
-
这个documentation 是针对 Visual Basic,而不是 VBA,但在这种情况下,概念非常相似,应该可以解释差异。
谁能在 VBA 中找到“On error goto -1”和“on error goto 0”之间的区别?我试过google和msdn,但都没有运气。
【问题讨论】:
On Error GoTo 0 禁用过程中当前存在的任何错误捕获。
On Error GoTo -1 清除错误处理并将其设置为空,这样您就可以创建另一个错误陷阱。
示例:On Error 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
示例:On Error GoTo 0
引发第一个错误后,您将收到错误,因为错误处理已被禁用。
Sub OnErrorGotoZeroTest()
On Error GoTo 0
Err.Raise Number:=9999, Description:="Forced Error"
End Sub
【讨论】:
On Error Goto -1 将允许在错误捕获中进行进一步的错误捕获。事实上,即使On Error Resume Next 仍然会导致未捕获的错误导致操作停止。
On Error Goto -1 和 Err.Clear 有什么区别吗?
Resume、Resume Next 或Resume <label> 退出错误处理块。此外,正如您在这里所说,您可以使用On error goto -1
&hFFFFFFFF,VBE 将其解析/自动更正为-1。在这种情况下,On Error Goto -1 实际上会转到编号为 -1 的行
这个答案解决了错误对象和错误处理程序之间的混淆。
错误对象可以使用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 Error Handling In VBA Chip Pearson 在他的文章中没有提到On error goto -1。引用他的话:
我故意不包括 On Error GoTo -1 因为它没有 真正的目的,除非使用,否则可以锁定整个 Excel 应用程序 以完全正确的方式。是的,On Error GoTo -1 在语法上是 有效,但这就像把枪给醉酒的少年。没什么好的 会来自它。
您也可以使用错误对象在不使用错误处理程序的情况下内联处理错误:MSDN Inline Error Handling
【讨论】:
Err.Clear 和On Error GoTo -1 之间的区别在于第一个不退出(重置)错误处理程序,但第二个退出。只有在退出(重置)错误处理程序后,您才能启用另一个错误处理程序。
On Error GoTo -1 相当于Err.Clear 后跟Resume ... 语句。
On Error GoTo -1 不等于Err.Clear 后跟Resume ...,因为Resume ... 重定向(某处)而On Error GoTo -1 没有。无论如何Err.Clear 被合并到Resume ... 因此是多余的。
重要的是要意识到当 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: 的行。
例如
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
ie 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 非常重要,因为它允许您将错误传播到调用程序并引发您自己的错误号,称为“用户定义的错误”,它提供了一种告诉调用程序它无法继续执行一段时间的方法逻辑原因。 (例如,违反了业务规则)。
您可以使用以下语句控制接下来执行哪一行代码
出错时转到 ALabelName 出错时转到 ANonZeroLineNumber 和 On Error Goto 0 ' 这是一种特殊情况,因为它实际上表示“在当前范围内(通常是子或函数),如果发生错误,则将错误对象传递回调用当前子或函数的代码.
VBA 中的错误处理很棘手,尤其是 MSDN 页面并没有真正给出如何使用错误处理的完整示例。
【讨论】:
Err.Clear 和 On Error Goto -1 不等价。如果您在代码中将On Error Goto -1 替换为Err.Clear,您将看到第二个错误未使用Err.Clear 处理。它们不等价。
Err.Clear 等同于 On Error GoTo -1 后跟 On Error GoTo 0 (在错误处理程序中) ,而是等同于单独的On Error GoTo 0。事实上,On Error GoTo 0 似乎覆盖了On Error GoTo -1 的任何效果。