错误处理

良好的错误处理可防止最终用户看到 VBA 运行时错误,并帮助开发人员轻松诊断和纠正错误。

VBA 中有三种主要的错误处理方法,除非代码中特别要求,否则应避免分布式程序中的两种方法。

On Error GoTo 0 'Avoid using

要么

On Error Resume Next 'Avoid using

喜欢使用:

On Error GoTo <line> 'Prefer using

On Error GoTo 0

如果你的代码中未设置错误处理,则 On Error GoTo 0 是默认的错误处理程序。在此模式下,任何运行时错误都将启动典型的 VBA 错误消息,允许你结束代码或进入 debug 模式,以识别源。在编写代码时,这种方法是最简单和最有用的,但是对于分发给最终用户的代码应始终避免使用,因为这种方法非常难看并且最终用户难以理解。

On Error Resume Next

On Error Resume Next 将导致 VBA 忽略错误调用之后所有行在运行时抛出的任何错误,直到更改错误处理程序。在非常具体的情况下,这条线可能很有用,但在这些情况之外应该避免使用。例如,从 Excel 宏启动单独的程序时,如果你不确定该程序是否已打开,则 On Error Resume Next 调用可能很有用:

'In this example, we open an instance of Powerpoint using the On Error Resume Next call
Dim PPApp As PowerPoint.Application
Dim PPPres As PowerPoint.Presentation
Dim PPSlide As PowerPoint.Slide

'Open PPT if not running, otherwise select active instance
On Error Resume Next
Set PPApp = GetObject(, "PowerPoint.Application")
On Error GoTo ErrHandler
If PPApp Is Nothing Then
    'Open PowerPoint
    Set PPApp = CreateObject("PowerPoint.Application")
    PPApp.Visible = True
End If

如果我们没有使用 On Error Resume Next 调用并且 Powerpoint 应用程序尚未打开,则 GetObject 方法会抛出错误。因此,On Error Resume Next 是避免创建应用程序的两个实例所必需的。

注意: 一旦不再需要 On Error Resume Next 调用,立即重置错误处理程序也是最佳做法

On Error GoTo <line>

建议将此错误处理方法用于分发给其他用户的所有代码。这允许程序员通过将代码发送到指定行来准确控制 VBA 如何处理错误。标记可以填充任何字符串(包括数字字符串),并将代码发送到后面跟冒号的相应字符串。通过对 On Error GoTo <line> 进行不同的调用,可以使用多个错误处理块。下面的子例程演示了 On Error GoTo <line> 调用的语法。

注意: 必须将 Exit Sub 行放在第一个错误处理程序之上,并且在每个后续错误处理程序之前,以防止代码在没有调用错误的情况下自然地进入块。因此,在代码块的末尾放置错误处理程序是函数和可读性的最佳实践。

Sub YourMethodName()
    On Error GoTo errorHandler
    ' Insert code here
    On Error GoTo secondErrorHandler

    Exit Sub 'The exit sub line is essential, as the code will otherwise
             'continue running into the error handling block, likely causing an error

errorHandler:
    MsgBox "Error " & Err.Number & ": " & Err.Description & " in " & _
        VBE.ActiveCodePane.CodeModule, vbOKOnly, "Error"
    Exit Sub

secondErrorHandler:
    If Err.Number = 424 Then 'Object not found error (purely for illustration)
        Application.ScreenUpdating = True
        Application.EnableEvents = True
        Exit Sub
    Else
        MsgBox "Error " & Err.Number & ": " & Err.Desctription
        Application.ScreenUpdating = True
        Application.EnableEvents = True   
        Exit Sub
    End If      
    Exit Sub

End Sub

如果你使用错误处理代码退出方法,请确保清理:

  • 撤消部分完成的任何内容
  • 关闭文件
  • 重置屏幕更新
  • 重置计算模式
  • 重置事件
  • 重置鼠标指针
  • End Sub 之后持续存在的对象实例上调用 unload 方法
  • 重置状态栏