21

我正在尝试循环浏览excel中的表格。该表的前三列有文本标题,其余的有日期作为标题。我想将这些日期按顺序分配给日期类型变量,然后根据日期执行一些操作

为此,我在 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 语句停止工作?

4

4 回答 4

45

使用所示的代码,当您敲击语句时,您实际上仍被认为处于错误处理例程中。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

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

这个网站很好地描述了这个问题:


错误处理块和错误转到

错误处理块,也称为错误处理程序,是通过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语句捕获。

于 2012-08-17T02:19:08.087 回答
8

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

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

于 2012-08-17T02:18:40.677 回答
7

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

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

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

于 2015-07-21T15:48:10.453 回答
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 一样,它会正确捕获错误 wheni =1但它会在第 10 行时失败i = 2,即使我们使用了Err.Clear

于 2015-04-20T18:47:31.750 回答