在以下代码中,如何在遇到错误后使循环在下一个迭代(而不是下一行)上继续?
现在,代码不会超过x = 0:
Sub skip_iteration()
Dim x As Long
For x = 5 To -5 Step -1
On Error GoTo errhandler:
Debug.Print 15 / x
Debug.Print "I don't want this to be printed on error"
Next x
errhandler:
If Err.Number = 11 Then
Debug.Print ("Error on " & x)
End If
End Sub
我调查了这个答案: Skip to next iteration in loop vba等,但无法将其翻译为我的代码。
答案 0 :(得分:2)
您需要Resume Next
转到该行之后的下一行,从而导致错误。而且Err.Clear
也是一种好习惯。
在Exit Sub
之前的errhandler
也是一个好习惯:
Sub SkipIteration()
Dim x As Long
For x = 5 To -5 Step -1
On Error GoTo errhandler:
Debug.Print 15 / x
Debug.Print "testing"
Next x
Exit Sub
errhandler:
If Err.Number = 11 Then
Debug.Print ("Error on " & x)
Err.Clear
Resume Next
End If
End Sub
Resume
和Resume Next
之间的区别如下:
Resume
尝试返回到它的调用位置。在TestMeResume
过程中,它在Debug.Print a / b上引发错误11,并在错误处理程序中为其分配b =5。然后使用Resume
重试Debug.Print a / b
,并且只要b
不是0
,它就会运行。
Resume Next
转到被调用的位置,忽略该行并继续下一行。 在TestMeResumeNext
过程中,在a = 12
处引发错误91,并触发了错误处理程序。在错误处理程序中,将a分配给Range("A14")
,并使用Resume Next
跳过a = 12
,并继续Sub
。
Sub TestMeResumeNext()
On Error GoTo TestMeResumeNext_Error
Dim a As Range
a = 12 'Error 91 here!
Debug.Print a.Row 'Resume Next goes back here
Exit Sub
TestMeResumeNext_Error:
Set a = Range("A14")
Resume Next
End Sub
Sub TestMeResume()
On Error GoTo TestMeResume_Error
Dim a As Long: a = 10
Dim b As Long: b = 0
Debug.Print a / b 'Error 11 here the first time
Exit Sub
TestMeResume_Error:
b = 5
Resume
End Sub
答案 1 :(得分:1)
这里的另一个选项是内联错误处理程序。显而易见,您已经意识到特定代码行可能引发错误,并且不依赖Resume
进行流控制。将错误放到函数底部的处理程序中,然后跳回代码的主行,可以使循环的预期行为变得不那么明显。
Sub SkipIteration()
Dim x As Long
For x = 5 To -5 Step -1
On Error Resume Next
Debug.Print 15 / x
If Err.Number = 11 Then
Debug.Print "Expected error on " & x
On Error GoTo errhandler
Else
On Error GoTo errhandler
Debug.Print "Process the rest of the loop"
End If
Next x
Exit Sub
errhandler:
Debug.Print "Unexpected error "; Err.Number
End Sub
更好的方法是将过程的关注点分开,以使执行的循环部分是一条语句:
Sub SkipIteration()
On Error GoTo errhandler
Dim x As Long
For x = 5 To -5 Step -1
If TheThingThatCanError(x) Then
ActionThatDependsOnAbove x
End If
Next x
Exit Sub
errhandler:
Debug.Print "Unexpected error "; Err.Number
End Sub
Private Function TheThingThatCanError(x As Long) As Boolean
On Error Resume Next
Debug.Print 15 / x
If Err.Number = 11 Then
Debug.Print "Expected error on " & x
Exit Function
End If
TheThingThatCanError = True
End Function
Private Sub ActionThatDependsOnAbove(x As Long)
Debug.Print "I don't want this to be printed on error " & x
End Sub
答案 2 :(得分:-1)
如果您想跳过Error
并继续下一次迭代,则一种可能的方法是使用GoTo
并进行一些spaghetti code:
Sub SkipIteration()
Dim x As Long
For x = 5 To -5 Step -1
If IsError(Evaluate("15 / " & x)) Then GoTo Skipper
Debug.Print 15 / x
Debug.Print x
Skipper:
Next x
End Sub
或使用整个IsError
嵌入检查是否要使用GoTo
。但是然后您必须在右侧转到一个选项卡并丢失缩进:
Sub SkipIteration()
Dim x As Long
For x = 5 To -5 Step -1
If Not IsError(Evaluate("15 / " & x)) Then
Debug.Print 15 / x
Debug.Print x
End If
Next x
End Sub