jwo*_*ard 71 vba exception-handling exception
VBA中的错误处理有哪些好的模式?
特别是在这种情况下我应该怎么做:
... some code ...
... some code where an error might occur ...
... some code ...
... some other code where a different error might occur ...
... some other code ...
... some code that must always be run (like a finally block) ...
Run Code Online (Sandbox Code Playgroud)
我想处理这两个错误,并在可能发生错误的代码之后恢复执行.此外,最后的代码必须始终运行 - 无论先前抛出什么异常.我怎样才能达到这个目的?
gui*_*ooo 98
On Error Goto ErrorHandlerLabel Resume(Next| ErrorHandlerLabel)On Error Goto 0 (禁用当前错误处理程序)Err 宾语该Err对象的属性通常被重置为零或错误处理程序零长度字符串,但它也可以用显式执行Err.Clear.
错误处理例程中的错误正在终止.
范围513-65535可用于用户错误.对于自定义类错误,您可以添加vbObjectError错误号.请参阅MS文档Err.Raise和错误编号列表.
对于派生类中未实现的接口成员,应使用常量E_NOTIMPL = &H80004001.
Option Explicit
Sub HandleError()
Dim a As Integer
On Error GoTo errMyErrorHandler
a = 7 / 0
On Error GoTo 0
Debug.Print "This line won't be executed."
DoCleanUp:
a = 0
Exit Sub
errMyErrorHandler:
MsgBox Err.Description, _
vbExclamation + vbOKCancel, _
"Error: " & CStr(Err.Number)
Resume DoCleanUp
End Sub
Sub RaiseAndHandleError()
On Error GoTo errMyErrorHandler
' The range 513-65535 is available for user errors.
' For class errors, you add vbObjectError to the error number.
Err.Raise vbObjectError + 513, "Module1::Test()", "My custom error."
On Error GoTo 0
Debug.Print "This line will be executed."
Exit Sub
errMyErrorHandler:
MsgBox Err.Description, _
vbExclamation + vbOKCancel, _
"Error: " & CStr(Err.Number)
Err.Clear
Resume Next
End Sub
Sub FailInErrorHandler()
Dim a As Integer
On Error GoTo errMyErrorHandler
a = 7 / 0
On Error GoTo 0
Debug.Print "This line won't be executed."
DoCleanUp:
a = 0
Exit Sub
errMyErrorHandler:
a = 7 / 0 ' <== Terminating error!
MsgBox Err.Description, _
vbExclamation + vbOKCancel, _
"Error: " & CStr(Err.Number)
Resume DoCleanUp
End Sub
Sub DontDoThis()
' Any error will go unnoticed!
On Error Resume Next
' Some complex code that fails here.
End Sub
Sub DoThisIfYouMust()
On Error Resume Next
' Some code that can fail but you don't care.
On Error GoTo 0
' More code here
End Sub
Run Code Online (Sandbox Code Playgroud)
Joe*_*win 35
我还要补充一下:
Err对象是您与异常对象最接近的对象Err.Raise而且只是为了好玩:
On Error Resume Next 是魔鬼的化身和被避免,因为它默默地隐藏错误Joh*_*lan 18
所以你可以这样做
Function Errorthingy(pParam)
On Error GoTo HandleErr
' your code here
ExitHere:
' your finally code
Exit Function
HandleErr:
Select Case Err.Number
' different error handling here'
Case Else
MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical, "ErrorThingy"
End Select
Resume ExitHere
End Function
Run Code Online (Sandbox Code Playgroud)
如果你想烘焙自定义异常.(例如违反业务规则的那些)使用上面的示例,但使用goto根据需要改变方法的流程.
Lim*_*awk 11
这是我的标准实现.我喜欢标签是自我描述的.
Public Sub DoSomething()
On Error GoTo Catch ' Try
' normal code here
Exit Sub
Catch:
'error code: you can get the specific error by checking Err.Number
End Sub
Run Code Online (Sandbox Code Playgroud)
或者,用一个Finally块:
Public Sub DoSomething()
On Error GoTo Catch ' Try
' normal code here
GoTo Finally
Catch:
'error code
Finally:
'cleanup code
End Sub
Run Code Online (Sandbox Code Playgroud)
Professional Excel Development有一个很好的错误处理方案。如果您打算在 VBA 中花费任何时间,那么这本书可能是值得的。VBA 在许多领域都缺乏,本书对管理这些领域提出了很好的建议。
PED 描述了两种错误处理方法。主要的是一个系统,其中所有入口点过程都是子过程,所有其他过程都是返回布尔值的函数。
入口点过程使用 On Error 语句来捕获几乎按照设计的错误。如果没有错误,非入口点过程返回 True,如果有错误,则返回 False。非入口点过程也使用 On Error。
两种类型的过程都使用中央错误处理过程来保持错误状态并记录错误。
小智 5
与讨论相关的还有相对未知的Erl功能。如果您的代码过程中有数字标签,例如,
Sub AAA()
On Error Goto ErrorHandler
1000:
' code
1100:
' more code
1200:
' even more code that causes an error
1300:
' yet more code
9999: ' end of main part of procedure
ErrorHandler:
If Err.Number <> 0 Then
Debug.Print "Error: " + CStr(Err.Number), Err.Descrption, _
"Last Successful Line: " + CStr(Erl)
End If
End Sub
Run Code Online (Sandbox Code Playgroud)
该Erl函数返回最近遇到的数字行标签。在上面的示例中,如果运行时错误发生在 label 之后1200:但之前1300:,该Erl函数将返回1200,因为这是最近成功遇到的行 label。我发现在错误处理块的正上方放置一个行标签是一个很好的做法。我通常用来9999表示程序的主要部分已达到预期的结论。
笔记:
行标签必须是正整数——像这样的标签MadeItHere:不能被 识别Erl。
行标签与 的实际行号完全无关VBIDE CodeModule。您可以按照您想要的顺序使用任何您想要的正数。在上面的示例中,只有 25 行左右的代码,但行标签编号从 开始1000。与 一起使用的编辑器行号和行标签号之间没有关系Erl。
行标签编号不需要按任何特定顺序,虽然如果它们不是按升序、自上而下的顺序,则功效和好处Erl会大大减弱,但Erl仍会报告正确的编号。
线路标签特定于它们出现的过程。如果过程ProcA调用过程并且在将控制权传递回过程ProcB中发生错误,(in ) 将返回调用之前最近遇到的行标签号。从内部,您无法获取可能出现在 中的行标签号。ProcBProcAErlProcAProcAProcBProcAProcB
在循环中放置行号标签时要小心。例如,
For X = 1 To 100
500:
' some code that causes an error
600:
Next X
Run Code Online (Sandbox Code Playgroud)
如果行标签后面500但之前的代码600导致错误,并且该错误在循环的第 20 次迭代中出现,Erl则将返回500,即使600在循环的前 19 次迭代中已成功遇到该错误。
Erl在程序中正确放置行标签对于使用该功能获取真正有意义的信息至关重要。
互联网上有许多免费实用程序可以自动在过程中插入数字行标签,因此您在开发和调试时可以获得细粒度的错误信息,然后在代码上线后删除这些标签。
如果您的代码在发生意外错误时向最终用户显示错误信息,则提供Erl该信息中的值可以使查找和修复问题变得比不报告值时简单得多。Erl
| 归档时间: |
|
| 查看次数: |
135263 次 |
| 最近记录: |