VBA 错误处理:On Error、Err 对象、清理与恢复设置

适用场景

宏运行到一半报错,ScreenUpdating 还关着、打开的工作簿没关、事件被禁用,下一次运行就各种异常。错误处理不只是弹一个提示框,更重要的是无论成功还是失败,都把 Excel 的状态恢复原样。

基本语句

On Error GoTo Handler     ' 出错时跳到 Handler
On Error Resume Next      ' 忽略错误,继续下一句
On Error GoTo 0           ' 关闭当前过程的错误处理

On Error Resume Next 只适合确实可以忽略错误的短小片段,例如关闭一个可能已经关闭的工作簿。不要用它包住整个宏,否则真正的错误会被静默吞掉。

Err 对象

出错后可以用 Err 读取信息:

Debug.Print Err.Number
Debug.Print Err.Description
Debug.Print Err.Source
Err.Clear
属性 含义
Err.Number 错误号,0 表示没有错误
Err.Description 错误描述,随 Office 语言变化
Err.Source 产生错误的对象或项目
Err.Clear 清除当前错误

判断错误类型要看 Err.Number,不要匹配 Description 文本;描述会随语言和版本变化。

常见错误号:

错误号 含义
9 下标越界(工作表名或数组索引不存在)
13 类型不匹配
53 文件未找到
76 路径未找到
91 对象变量未设置(忘了 Set)
1004 应用程序定义或对象定义错误(范围/工作表操作失败)

标准结构

Sub DoWork()
    On Error GoTo CleanFail

    Application.ScreenUpdating = False
    Application.DisplayAlerts = False

    ' 业务代码
    ThisWorkbook.Worksheets("数据").Range("A1").Value = 100

CleanExit:
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
    Exit Sub

CleanFail:
    MsgBox "错误 " & Err.Number & ":" & Err.Description, vbExclamation
    Resume CleanExit
End Sub

关键点:

恢复设置

宏经常临时修改这些状态:

Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual

对应恢复:

Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic

如果用户原本就是手动计算,直接恢复成自动会改变用户设置。更稳的做法是先保存原值:

Dim oldCalc As XlCalculation
oldCalc = Application.Calculation
Application.Calculation = xlCalculationManual
' ...
Application.Calculation = oldCalc

重新抛出错误

底层函数捕获错误、清理资源后,可以把错误继续抛给调用方:

Err.Raise Err.Number, Err.Source, Err.Description

不要用 Err.Raise 1004, ... 伪造一个通用错误号;保留原始错误号更利于排查。

易错点

相关条目

参考链接

读完自测

合上页面,先回答,再展开对照。

  1. On Error Resume Next 为什么不能包住整个宏?
  2. 正常流程执行完为什么要在清理块前 Exit Sub?
  3. Resume 和 Resume Next 有什么区别?
答案
  1. 它会让所有错误都被静默忽略,真正的问题无法发现;只适合确实可忽略的短片段。
  2. 否则正常流程会继续执行错误处理块,弹出不必要的提示或重复清理。
  3. Resume 重试出错的那一句;Resume Next 继续执行出错语句的下一句。
微信小程序码:扫码打开命令速查小程序

小程序版

微信扫码,随时查命令