VBA错误处理例程消息重复打印原因及指定代码异常输出疑问
解析你的VBA错误处理流程问题
这是个非常有意思的VBA错误处理细节问题,咱们一步步拆解代码的执行逻辑,就能完全明白为什么会出现这样的输出顺序了。
首先先贴出你的测试代码:
Sub error_test() On Error GoTo errorhandler Err.Raise (7) MsgBox "one" errorhandler: MsgBox "two" Resume Next End Sub
完整执行流程拆解
咱们按代码执行的先后顺序一步步梳理:
- 初始化错误陷阱:进入
error_test过程后,第一行On Error GoTo errorhandler告诉VBA:如果后续发生运行时错误,立刻跳转到errorhandler标签位置执行代码。 - 触发第一个错误:执行
Err.Raise (7)手动抛出错误7(内存不足),VBA触发错误陷阱,直接跳转到errorhandler标签。 - 第一次执行错误处理代码:运行
MsgBox "two"→ 这是你看到的第一个弹窗“two”。随后执行Resume Next,这个语句的核心作用是回到触发错误的语句的下一行,恢复正常流程执行。这里触发错误的语句是Err.Raise (7),它的下一行是MsgBox "one",所以VBA跳去执行这条语句。 - 执行正常流程代码:运行
MsgBox "one"→ 这是弹窗“one”。 - 流程自然进入错误处理标签:执行完
MsgBox "one"后,程序按从上到下的顺序继续执行,接下来就到了errorhandler:标签——注意!这个标签只是一个代码位置标记,不是只有错误发生时才会走到这里,正常流程也会路过这里!所以程序再次运行MsgBox "two"→ 这是第二个弹窗“two”。 - 触发第二个错误(Resume without error):现在执行
Resume Next,但此时程序并没有处于错误状态(之前的错误已经通过Resume Next处理完毕)。在非错误状态下调用Resume类语句,会触发错误20:Resume without error,VBA再次触发错误陷阱跳转到errorhandler标签。 - 第二次处理错误(新错误):运行
MsgBox "two"→ 这是第三个弹窗“two”。随后执行Resume Next,这次是在处理错误20的上下文里,Resume Next会回到触发错误20的语句(也就是上一行的Resume Next)的下一行——也就是End Sub,过程到此结束。
解答你的两个问题
1. 为什么末尾的“two”会重复打印两次?
你看到的末尾两次“two”,对应上面流程的第5步和第7步:
- 第一次是程序执行完
MsgBox "one"后,正常流程走到errorhandler标签触发的弹窗; - 第二次是因为在非错误状态下执行
Resume Next触发了新的错误,再次跳转到errorhandler标签触发的弹窗。
2. 为什么错误处理例程中的消息会打印两次?
其实准确来说,错误处理例程里的MsgBox "two"总共执行了三次:
- 第一次是处理初始抛出的错误7;
- 第二次是正常流程路过
errorhandler标签; - 第三次是处理“Resume without error”的错误20。
你觉得是“两次”,可能是把第一次错误触发的弹窗当成了独立的,而把后面两次归为“重复打印”——本质是因为你没有在错误处理完成后退出过程,导致正常流程会再次进入错误处理代码块,还触发了新的错误。
如果想让错误处理只执行一次,正确的做法是在错误处理完成后退出过程,比如:
Sub error_test() On Error GoTo errorhandler Err.Raise (7) MsgBox "one" errorhandler: MsgBox "two" Exit Sub ' 退出过程,避免正常流程进入错误处理代码 Resume Next End Sub
内容的提问来源于stack exchange,提问作者Colin Hicks




