Excel VBA:On Error Goto语句在For-Loop中不起作用

问题描述 投票:15回答:4

我正试图在excel中遍历一个表。该表的前三列有文本标题,其余部分的日期为标题。我想按顺序将这些日期分配给Date类型变量,然后根据日期执行一些操作

为此,我在myTable.ListColumns上使用foreach循环。由于前三列没有日期标题,我试图设置循环,以便,如果将标题字符串分配给日期类型变量时出错,则循环直接进入下一列

这似乎适用于第一列。但是,当第二列的标题被“赋值”给日期类型变量时,即使宏位于错误处理块内,宏也会遇到错误

Dim myCol As ListColumn
For Each myCol In myTable.ListColumns
    On Error GoTo NextCol

    Dim myDate As Date
    myDate = CDate(myCol.Name)

    On Error GoTo 0

    'MORE CODE HERE

NextCol:
    On Error GoTo 0
Next myCol

重申一下,在语句的第二轮循环中抛出错误

myDate = CDate(myCol.Name)

任何人都可以解释为什么On Error语句停止工作?

excel vba excel-vba for-loop error-handling
4个回答
33
投票

使用所示的代码,当您敲击next语句时,您实际上仍被认为是在错误处理例程中。

这意味着在从当前错误处理程序恢复之前,不允许使用后续错误处理程序。

更好的架构是:

    Dim myCol As ListColumn
    For Each myCol In myTable.ListColumns
        On Error GoTo ErrCol
        Dim myDate As Date
        myDate = CDate(myCol.Name)
        On Error GoTo 0
        ' MORE CODE HERE '
NextCol:
    Next myCol
    Exit Sub ' or something '

ErrCol:
    Resume NextCol

这清楚地描述了常规代码的错误处理,并确保在您尝试设置另一个处理程序之前当前正在执行的错误处理程序完成。

This site对问题有很好的描述:


错误处理块和错误转到

错误处理块(也称为错误处理程序)是通过On Error Goto <label>:语句传输执行的代码段。此代码应设计为修复问题并在主代码块中恢复执行或终止程序的执行。您不能仅使用On Error Goto <label>:语句跳过行。例如,以下代码将无法正常工作:

    On Error GoTo Err1:
    Debug.Print 1 / 0
    ' more code
Err1:
    On Error GoTo Err2:
    Debug.Print 1 / 0
    ' more code
Err2:

当引发第一个错误时,执行转移到Err1:之后的行。当第二个错误发生时,错误处理程序仍处于活动状态,因此第二个错误不会被On Error语句捕获。


8
投票

您需要在错误处理代码中添加某些类型的resume,以指示错误处理已结束。否则,第一个错误处理程序仍处于活动状态,您永远不会“解决”。

请参阅http://www.cpearson.com/excel/errorhandling.htm(特别是标题“错误处理块和错误转到”和以下部分)


5
投票

跟随paxdiablo接受的答案。这是可能的,允许同一个子中的两个错误陷阱,一个接一个:

Public Sub test()
    On Error GoTo Err1:
    Debug.Print 1 / 0
    ' more code
Err1:
    On Error GoTo -1     ' clears the active error handler
    On Error GoTo Err2:  ' .. so we can set up another
    Debug.Print 1 / 0
    ' more code
Err2:
    MsgBox "Got here safely"
End Sub

使用On Error GoTo -1取消活动错误处理程序并允许另一个设置(并且err.clear不会这样做!)。这是否是一个好主意留给读者练习,但它的工作原理!


0
投票

清除Err对象的所有属性设置与重置错误处理程序不同。

试试这个:

Sub TestErr()
Dim i As Integer
Dim x As Double
    On Error GoTo NextLoop
    For i = 1 To 2
10:     x = i / 0
NextLoop:
        If Err <> 0 Then
            Err.Clear
            Debug.Print "Cleared i=" & i
        End If
    Next
End Sub

你会注意到就像OP一样,它会在i =1时正确地捕获错误,但是当i = 2在第10行会失败,即使我们使用了Err.Clear

© www.soinside.com 2019 - 2024. All rights reserved.