`
tangleilei
  • 浏览: 13829 次
  • 来自: 上海
社区版块
存档分类
最新评论

vba error

 
阅读更多
转自http://zhiqiang.org/blog/it/handle-error-in-excel-vba.html

如果不提供错误处理方法,VBA在出错时会停留在出错之处。Excel/VBA提供On Error关键词来处理程序运行过程中的错误,具体有下面两种用法:
1.On Error Resume Next:当出错时跳到下一行继续运行。
2.On Error Goto Line:出错时跳到行号Line。这里行号Line可以为数字(不为0和-1),也可以为字符串。

其它与之相关的还有:
1.On Error Goto 0:运行后,对错误的捕获被关闭。程序出错时将自动中止。
2.On Error Goto -1:运行后,「Resume」和「Resume Next」将失效。
3.Resume:跳回并重新运行出错的行
4.Resume Next:跳回并运行出错位置的下一行。

上面各种语句的组合可以非常复杂。下面是我半天时间的研究成果。

1.VBA处理出错的两种方式

设置On Error Resume Next在出错时直接运行下一行,然后可以通过Err.Number来判断是否出错然后进行相关处理。
Sub Demo1()
    On Error Resume Next

    Call doing_thing1
    If Err.Number > 0 Then
        Call err_handler1   ' err handler deals with err in doing_thing2
        Err.Clear
    End If

    Call doing_thing2
    If Err.Number > 0 Then
        Call err_handler2   ' err handler deals with err in doing_thing2
        Err.Clear
    End If

    On Error GoTo 0
    Call doing_next_thing
End Sub

On Error Goto Line的方法更强大,在错误处理完毕之后还可以通过Resume或Resume Next返回原出错点或出错点的下一行。
Sub Demo2()
    On Error GoTo err_handler_line1
    Call doing_thing1

    On Error GoTo err_handler_line1
    Call doing_thing2

    On Error Resume Next    ' On Error Resume Next和 On Error Goto可以混着用
    Call doing_next_thing

    Exit Sub

err_handler_line1:
    Call err_handler1
    Resume        ' return and re-run the error line
    ' 上面一行Resume、Resume Next、Exit Sub可根据情况任选其一
    ' 而且必须选一个,否则doing_thing1出错时,下面的Err_hander2也会被运行
err_handler_line2:
    Call err_handler2
    Resume Next   ' resume to next of the error line
End Sub

2.Err变量

VBA有一个全局变量Err,它保存了程序运行过程中出现的最后一个错误的相关信息(比如错误编码、错误描述等)。一般我们可以通过Err.Number > 0来判断是否出错;通过Err.Description查看具体出错信息。

Err可以通过Err.Clear手工清除。

VBA在每次碰到On Error Resume Next、On Error Goto、Resume、Resume Next都会自动清空Err。我们需注意重复设置错误处理代码的副作用。比如在上面Demo2添加一行,后面的错误处理程序就失效了:
Sub Demo3()
    On Error Resume Next
    Call doing_thing        '?如果此处出错,Err将保存错误信息

    On Error Resume Next    ' 此处Err对象被清空

    If Err.Number > 0 Then
        Call err_handler    ' 由于Error被清空,此处错误处理程序已经失效。
        Err.Clear
    End If

    Call doing_next_thing
End Sub

Err是全局变量,母函数的错误信息会带入到子函数,子函数的错误信息也会被返回母函数。但实际表现非常复杂,具体请参考本文第五部分。

3.isErrorHanderEnabled

VBA里对错误处理有两个状态。一个是isErrorHanderEnabled,另一个是isErrorHanderActive。这两个变量名不是真实的变量,只是为了更好解释这个问题。

isErrorHanderEnabled指目前是否捕获程序发生的错误,具体而言即是否设置了On Error Resume Next或On Error Goto Line。如果isErrorHanderEnabled == False,一旦某行代码出错,VBA便会中止运行,并提示出错。如果isErrorHanderEnabled == True,则按照设置方法,VBA在出错后直接跳转或者继续运行下一行。

On Error Goto 0相当于取消前面设置的On Error Resume Next和On Error Goto Line,即重设isErrorHanderEnabled = False。接下来代码运行过程中一旦出错,便会中止运行。

isErrorHanderEnabled是一个局部变量,即子函数和母函数的状态互不影响。每个函数刚开始时,isErrorHanderEnabled的默认状态都是False。

4.isErrorHanderActive

isErrorHanderActive是指VBA现在是否正在处理错误。如果设置了On Error Goto Line,然后程序出错时,此时程序自动跳转到Line位置开始运行,并设置isErrorHanderActive = True。

On Error Goto -1用来告诉VBA目前错误已经处理完毕,VBA应该回到正常运行状态,并设置isErrorHanderActive = False。

和isErrorHanderActive一样,isErrorHanderEnabled也是一个局部变量,即子函数和母函数的状态互不影响。每个函数刚开始时,isErrorHanderActive的默认状态也是False。

需注意isErrorHanderActive和Err.Number>0并无直接关系,比如下面例子:
Sub Demo5()
    Dim i As Long
    On Error Resume Next
    i = 1 / 0        ' err occurs
    MsgBox "Here: Err.Number > 0 but isErrorHanderActive = False"

    On Error GoTo err_handler:
    i = 1 / 0        ' err occurs, set isErrorHanderActive = True

err_handler:
    On Error Resume Next        ' this will clear err
    MsgBox "Here: Err.Number = 0 but isErrorHanderActive = True"
End Sub

5.函数调用时发生什么?

VBA的子函数和母函数在处理错误之间的关系比较复杂。一般情况尽量让各自函数处理各自的问题,避免子函数将错误抛给母函数。

在子函数和母函数处理错误时,有两个问题值得讨论:1)子函数的Err变量信息是否传回给母函数;2)子函数的错误是否会触发母函数的错误处理程序。

结合MSDN相关文档和各种测试案例,我发现:
•母函数在进入子函数时,Err变量保存不变,错误信息传入子函数,但不会触发子函数的错误处理程序。
•子函数在On Error Resume Next后形成的错误信息会将向上传递给母函数,但不会触发母函数的错误处理。
•子函数在On Error Goto Line后形成的错误信息不会向上传递给母函数,也不会触发母函数的错误处理。
•子函数在On Error Goto Line跳转后处理错误过程中一旦形成新错误,将触发母函数的错误处理程序;同时如果母函数的错误处理方式是On Error Resume Next,子函数继续运行,并且子函数的错误信息将传给母函数;如果母函数错误方式是On Error Goto Line,子函数终止运行,跳回母函数的错误处理处,但子函数的错误信息并不会向上传递给母函数(即这种情况下,母函数只知道子函数有错位未被处理,但不知道任何错误信息)。

第四种情况子函数错误触发母函数的错误处理程序的原因是当子函数的isErrorHanderActive == True时,子函数的错误处理将被母函数接管,此时子函数一旦出错,错误上传的方式和第二条第三条的一样的,只不过决定于母函数的错误处理方式是「On Error Resume Next」还是「On Error Goto Line」

下面这几个测试案例展示了上述行为特征:
Sub Demo4()
    On Error GoTo err_hander1
    Call Demo4_Sub1
    Debug.Print "Err in sub1:" & Err.Description ' Err description = ""

    On Error GoTo err_hander2
    Call Demo4_Sub2
    Debug.Print "Err in sub2:" & Err.Description ' Err description <> ""

    On Error GoTo err_hander3
    Call Demo4_Sub3
    Debug.Print "Err in sub3:" & Err.Description ' Err description = ""

    On Error Resume Next
    Call Demo4_Sub4
    Debug.Print "Err in sub4:" & Err.Description ' Err description <> ""

    Exit Sub
err_hander1:
    Debug.Print "err_hander1 incurred"  ' not incurred
    Resume Next

err_hander2:
    Debug.Print "err_hander2 incurred" ' not incurred
    Resume Next

err_hander3:
    Debug.Print "err_hander3 incurred" ' incurred
    Resume Next

err_hander4:
    Debug.Print "err_hander4 incurred" ' incurred
    Resume Next
End Sub

Sub Demo4_Sub1()
    On Error GoTo err_hander

    Dim i As Long
    i = 1 / 0

    Exit Sub
err_hander:
    Resume Next
End Sub

Sub Demo4_Sub2()
    On Error Resume Next

    Dim i As Long
    i = 1 / 0
End Sub

Sub Demo4_Sub3()
    On Error GoTo err_hander

    Dim i As Long
    i = 1 / 0

    Exit Sub
err_hander:
    i = 1 / 0
    Resume Next
End Sub

Sub Demo4_Sub4()
    On Error GoTo err_hander

    Dim i As Long
    i = 1 / 0

    Exit Sub
err_hander:
    i = 1 / 0
    Resume Next
End Sub

6.其它一些注意点

6.1.警惕 On Error Resume Next的副作用

一旦启用On Error Resume Next,所有错误都会被自动略过。除非有足够信心,不要用它。启用之后也尽快使用On Error Goto 0关闭它。

另外还要注意副作用。比如If的条件一旦出错,If内部的语句将被执行,这和直观想象并不相符。
Sub Demo6()
    On Error Resume Next
    Dim i As Long
    i = 0
    If 0 / 0 Then i = 1

    MsgBox i  ' i = 1
End Sub



6.2.单元格错误也会触发VBA错误

在VBA中引用单元格的值,如果单元格里是一个公式并且公式出错,那么VBA中连带会抛出一个错误。

6.3.选项中可选强制发生错误时中断程序

在VB编辑器的 工具 - 选项 - 通用 - 错误捕获 选项里,可以强制在程序发生错误时中断程序。这在调试程序时非常有用。

6.4.编程小细节

1)在错误处理程序之前添加Exit Sub或Exit Function,避免程序位出错时也运行错误处理程序。

2)在每个错误程序后都添加Resume、Resume Next、Exit Sub或Exit Function,避免从当前错误处理之后继续运行后面的错误处理程序。
分享到:
评论

相关推荐

    VBA 一句代码解决On error goto line 多次使用的问题 .txt

    一句代码解决On error goto line 多次使用的问题 .txt On error goto line 错误跳转语句只能使用一次 本代码只需要加一句即可重复使用错误跳转 On...VBA错误跳转多次使用的问题 On error goto 0 不行 err.clear也不行

    Excel-VBA宏编程实例源代码-移动指定的文件夹到指定的路径中.zip

    在Excel中,VBA(Visual Basic for Applications)是一种强大的编程工具,可以用来自动化日常的办公任务,提升工作效率。本实例的标题"Excel-VBA宏编程实例源代码-移动指定的文件夹到指定的路径中.zip"揭示了一个...

    AutoCAD-VBA命令大全.zip_AutoCAD_VBA_CAD VBA 命令_VBa_autocad vba_cad命

    8. **错误处理**:使用`On Error`语句可以捕获和处理运行时错误,确保程序的稳定运行。 9. **对象的创建和选择**:VBA可以动态创建新的图形对象,也可以通过选择集(SelectionSet)操作多个已存在的对象。 10. **...

    excel VBA帮助文件.rar_Excel VBA_VBA excel_VBA,Excel_excel_vba exce

    8. **错误处理**:使用On Error语句可以设置错误处理策略,如On Error GoTo 0(关闭错误处理)、On Error Resume Next(忽略错误继续执行)和On Error GoTo (跳转到指定标签处理错误)。 9. **事件驱动编程**:...

    VBA manual(微软官方VBA手册)

    **调试和错误处理(Debugging and Error Handling)** VBA中的调试用于诊断和修正代码中的错误。错误类型包括编译错误、运行时错误和逻辑错误。VBA提供调试工具,比如断点、单步执行、监视表达式和即时窗口。错误...

    WPSVBA、ExcelVBA编程实例(150例).zip

    VBA提供了一些工具,如断点、步进执行和错误处理结构(如On Error语句),以帮助开发者找出和解决程序中的问题。 7. **模块、子程序与函数**:在VBA中,可以将代码组织成模块,其中包含子程序(Sub)和函数...

    ExcelVBAComm.rar_EXCEL 串口 VBA_excel vba OpenComm_excel串口_vba串口程序

    在VBA代码中,应添加适当的错误处理机制,例如`On Error GoTo`语句,以便在发生错误时能够恢复或提供反馈。 8. **同步与异步通信**:根据应用程序的需求,可以选择同步(等待数据接收后才继续执行后续代码)或异步...

    VBA7.1帮助文档中文版

    VBA7.1还引入了错误处理机制,通过`On Error`语句,开发者可以在代码中设定错误处理策略,避免程序因未预见的问题而崩溃。同时,`With...End With`结构让代码更加简洁易读,它可以让你一次性设置多个对象的属性,...

    VBA程序解释器

    8. **错误处理(Error Handling)**:通过On Error语句,程序员可以设置错误处理机制,当程序出错时,可以捕获错误并执行相应的错误处理代码,提高程序的健壮性。 9. **对象导向编程(Object-Oriented Programming,...

    VBA解析outlook邮件

    例如,我们可以使用`On Error Resume Next`语句来忽略错误,然后使用`If`语句来判断错误是否出现。 8. 数据存储: 在VBA宏中,我们可以使用数据存储来存储邮件信息。例如,我们可以使用`ADODB.Recordset`对象来存储...

    VBA精粹修订版

    1. **错误处理**:使用On Error语句设置错误处理方式,如On Error GoTo 0、On Error Resume Next等。 2. **事件驱动编程**:通过订阅对象的事件,实现程序响应特定操作。 3. **记录宏**:快速生成VBA代码的工具,...

    VBA调用dll实例

    ### VBA调用DLL实例详解 #### 一、引言 在Visual Basic for Applications (VBA)编程中,经常需要扩展其功能以实现更复杂的任务。一种常见的做法是通过调用动态链接库(Dynamic Link Library,简称DLL)来实现。...

    Excel VBA 经典代码应用大全

    5. **错误处理**:学习使用On Error语句进行错误处理,理解Resume、Resume Next和Exit Sub/Function的用法,确保程序的健壮性。 6. **用户界面设计**:使用VBA创建自定义的用户界面,如Form或UserForm,添加控件...

    VBA的知识点 VBA教程

    `其他知识点.txt`可能列出了更多VBA的高级主题,如错误处理(On Error)、对象模型(如Workbook、Worksheet、Range对象)、用户窗体(UserForm)设计以及与其他应用程序的接口(如邮件自动化、数据库连接等)。...

    兰色幻想VBA80集第6集:函数与公式.zip_frozenlmd_vba完整_兰色幻想 80_兰色幻想vba从入门到进阶80集

    4. **错误处理**:在使用函数和公式时,可能会遇到错误,学习如何使用 `On Error` 语句来捕获和处理错误,提高程序的健壮性。 5. **参数传递**:讲解函数参数的作用、类型和传递方式,包括传值和传址的区别。 6. **...

    excel vba 帮助文件

    5. **错误处理**:学习如何使用On Error语句进行错误处理,提高代码的健壮性。 6. **用户界面设计**:学习创建自定义对话框、表单(UserForms)和控件,以增强用户交互体验。 7. **文件操作**:了解如何读写文件,...

    ARCGIS_vba编程基础_arcgis_VBa_

    此外,了解错误处理(On Error)和事件处理程序也是必要的,它们可以帮助你编写健壮的代码。 **ArcObjects与GIS编程** ArcObjects是Esri提供的COM组件,包含了所有可以用来编程的GIS对象。通过引用ArcGIS的COM库,...

    Excel2010_VBA离线帮助

    6. **错误处理**:VBA提供了一套错误处理机制,如On Error语句,用于在遇到错误时进行恢复或记录。离线帮助文件会介绍如何有效地处理运行时错误。 7. **其他高级主题**:包括类模块、用户窗体(UserForm)的使用、...

    VBA素材与模板100套.zip

    7. **错误处理**:在VBA中,使用On Error语句进行错误处理,可以确保程序在遇到错误时不会立即终止,而是按照预设的方式继续运行或提供错误信息。 8. **引用库和API调用**:VBA可以引用其他库(如Microsoft Excel ...

    Excel VBA参考手册CHM

    9. **高级主题**:如错误处理(On Error语句)、类的使用、数组、集合、正则表达式等,这些都是提升VBA编程技能的重要部分。 10. **实用示例**:手册可能包含各种实用示例,如数据过滤、排序、查找替换、图表操作、...

Global site tag (gtag.js) - Google Analytics