你能帮我理解更多关于VBA错误处理的良好实践吗?

Har*_*nch 0 error-handling excel vba excel-vba

我花了最近两天试图更好地理解VBA错误处理,但仍然存在实际问题.下面的文字描述了我所做的一些实现,并且在描述中嵌入了一些问题.我真的在追求人们帮助我提高理解力并给我一些指导.我已经掌握了常用的基础知识,并且我正在尝试更多地关注细微的功能.

我期待你的任何答案!

重要的是要意识到在VBA中发生错误时会发生两种截然不同的事情.

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

  2. 要执行的下一行发生变化.
    接下来执行哪一行由最后执行的"On Error Goto"语句确定 - 如果有的话.

这些是独立但高度相关的主题,您将编写实际上不同但交织在一起的代码来管理它们.

当发生任何错误或您使用Err.Raise时,始终设置Err对象.即使使用了"On Error Resume next"或任何其他On错误语句.

所以这样的代码总是可以使用:

Dim i as integer 
On error resume next 
i = 100/0  ' raises error
if err.number <> 0 then 
   ' respond to the error
end if
Run Code Online (Sandbox Code Playgroud)

非常重要的是要意识到当错误对象的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   '' THIS LINE ACTUALLY WILL RAISE AN unhandled ERROR!

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

End Sub
Run Code Online (Sandbox Code Playgroud)

将err.number属性设置为非零后,可以使用将其重置为零

On Error Goto -1 
Run Code Online (Sandbox Code Playgroud)

请注意,Err.Clear也将其重置为零,但它实际上相当于:

On Error Goto -1 
On Error Goto 0
Run Code Online (Sandbox Code Playgroud)

即Err.Clear删除当前存在的"On Error Goto".因此,最好使用:

On Error Goto -1   
Run Code Online (Sandbox Code Playgroud)

因为使用Err.clear你经常需要添加一个额外的行来重新安装已经存在的错误处理程序或者另外一个错误处理程序.

Err.Clear
On Error Goto MyErrorHandlerLabel
Run Code Online (Sandbox Code Playgroud)

"或者,您可以将错误编号设置为零(Err.Number = 0),但不如Clear方法有效,因为它不会清除描述属性." (来自MSDN页面)

我在MSDN上阅读了下一段我认为并且不明白如何将错误对象实例化(即err.number <> 0),它的值在执行End Sub时传递给任何调用过程.

Q1:帮忙!

"值得注意的是,只要执行任何类型的Resume语句,Exit Sub,Exit Function,Exit Property或任何On Error语句,Err.Clear就会由VBA隐式执行." (来自MSDN页面)

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

Err.Raise Number:=,来源:=,说明:=

Err.Raise非常重要,因为它允许您将错误传播到调用程序,并且一直"向上"到处理用户的顶级程序.您还可以提出自己的错误编号,称为"用户定义的错误".这提供了一种告诉调用程序由于某种原因无法继续(即发生意外错误或业务规则被破坏)的方法.

通过这种方式,调用过程可以决定如何处理错误,而不是错误发生的过程(这不了解用户正在做什么,最高调用程序在哪里做什么) !)

Q2:我对此是对的吗?
问题3:您是否会为此目的提出用户定义的异常?

您可以使用类似的语句控制下一行代码的执行

On Error Goto ALabelName

On Error Goto ANonZeroLineNumber
Run Code Online (Sandbox Code Playgroud)

On Error Goto 0
Run Code Online (Sandbox Code Playgroud)

On Error Goto 0是一种特殊情况,因为它实际上表示"在当前范围内(通常是子或函数),如果发生错误,则将错误对象传递回调用当前子函数或函数的代码,不再在当前子或函数中执行任何代码.

在VBA中使用简单的错误处理非常简单,但是当事情变得棘手时,我常常发现自己陷入了困境.

没有SQL Server和VBA所使用的常用TRY CATCH语句是一种耻辱,所以我现在成功地设法模拟了这个:

https://codereview.stackexchange.com/questions/94415/try-catch-statement-in-vba-using-the-standard-vba-error-handling-statements

我希望上面的帖子能让你更深入地了解我一直在做的实验,如果你感兴趣的话,并帮助你理解我为什么要挣扎.

简而言之,虽然有一些有用的网站在那里喜欢:

http://www.cpearson.com/excel/errorhandling.htm

但是,我觉得我可以做更多的指导.

哈维

小智 6

有三种错误模式.

  1. On Error Goto 0默认.没有错误处理.VBA在所有错误上崩溃,从而修复了基本信息.

  2. On Error Resume Next.您正在处理所有错误.在任何可能产生错误的行之后(但不是每一行 - msgbox将始终有效)你会这样做If err.number <> 0 then FixErrorOrCrash.任何涉及文件,注册表密钥,网络或互联网的内容都不能依赖于存在或在那一刻工作.同样非Office系统对象.

  3. On Error Goto Label.您还处理所有错误,除了您不知道错误的位置.这用于撤消功能.如果有任何失败,这将使您有机会回滚函数可能已完成的所有操作.

此外,在编程时,执行和捕获错误是有效的,而不是测试然后执行.与第一种磁盘访问方式相比,第二种方式访问​​文件需要两次成功访问.