我正在尝试在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语句停止工作吗?
答案 0 :(得分: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
语句不会捕获第二个错误。
答案 1 :(得分:8)
您需要在错误处理代码中添加某些类型的resume
,以指示错误处理已结束。否则,第一个错误处理程序仍处于活动状态,您永远不会“解决”。
请参阅http://www.cpearson.com/excel/errorhandling.htm(特别是“错误处理块和错误转到”标题及以下部分)
答案 2 :(得分: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
不执行此操作!)。这是否是一个好主意留给读者练习,但它的确有效!
答案 3 :(得分: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