在下面的代码中,在遇到错误后,如何使循环在下一次迭代(而不是下一行(继续?
现在代码不会超过 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
我已经研究了这个答案: 跳到循环 vba 中的下一次迭代,但无法将其转换为我的代码。
您需要Resume Next
转到该行之后的下一行,从而导致错误。Err.Clear
也是一种很好的做法。
errhandler
前的Exit Sub
也是一种很好的做法:
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
此处的另一个选项是内联错误处理程序。这很明显,您知道特定代码行引发错误的可能性,并且不依赖于流控制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
如果你想跳过Error
并继续下一次迭代,一种可能的方法是使用GoTo
并制作一些意大利面条代码:
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
检查一个if并避免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