VBA-如何有条件地跳过for循环迭代


101

我在数组上有一个for循环。我想做的是在循环中测试特定条件,如果为true,则跳至下一个迭代:

For i = LBound(Schedule, 1) To UBound(Schedule, 1)
    If (Schedule(i, 1) < ReferenceDate) Then
        PrevCouponIndex = i
        Continue   '*** THIS LINE DOESN'T COMPILE, nor does "Next"
    End If
    DF = Application.Run("SomeFunction"....)
    PV = PV + (DF * Coupon / CouponFrequency)
Next

我知道我可以做:

 If (Schedule(i, 1) < ReferenceDate) Then Continue For

但我希望能够在PrevCouponIndex变量中记录i的最后一个值。

有任何想法吗?

谢谢


3
您说:“我知道我能做:If (Schedule(i, 1) < ReferenceDate) Then Continue For”您确定吗? Continue不是VBA关键字。
mwolfe02 2011年

@ mwolfe02-不确定,但在某处的示例中看到了(cpearson?)
Richard H

可能是一个VB.NET示例
匿名类型

Answers:


31

你不可以做这样简单的事情吗?

For i = LBound(Schedule, 1) To UBound(Schedule, 1)
  If (Schedule(i, 1) < ReferenceDate) Then
     PrevCouponIndex = i
  Else
     DF = Application.Run("SomeFunction"....)
     PV = PV + (DF * Coupon / CouponFrequency)
  End If
Next

4
确实,这正是我所做的:)但仍然令我感到困扰,我必须将其他内容包装起来。谢谢
理查德H

4
+1 @RichardH好,您必须使用an IF进行测试,因此这并不是那么昂贵的代码。你应该确保,虽然是最常见的结果是Schedule(i, 1)小于ReferenceDate避免执行的Else往往比必要的。否则使用(ReferenceDate>=Schedule(i, 1))。(如果测试为50/50,则无需进行优化)
brettdj

大量嵌套的ifs可能会有点混乱...例如,如果您需要在每次迭代中检查大量Application.Match结果,以便在使用结果之前找不到匹配项。但是,生活中还有更糟糕的事情!
JeopardyTempest,

182

VBA没有Continue立即跳转到下一个循环迭代的关键字或任何其他等效关键字。我建议明智地将其Goto用作解决方法,尤其是在这只是一个人为的示例而您的实际代码更复杂的情况下:

For i = LBound(Schedule, 1) To UBound(Schedule, 1)
    If (Schedule(i, 1) < ReferenceDate) Then
        PrevCouponIndex = i
        Goto NextIteration
    End If
    DF = Application.Run("SomeFunction"....)
    PV = PV + (DF * Coupon / CouponFrequency)
    '....'
    'a whole bunch of other code you are not showing us'
    '....'
    NextIteration:
Next

但是,如果这确实是您的所有代码,则@Brian绝对正确。只需Else在您的If陈述中加入一个子句即可。


18
谢谢,这对GoTo是一个很好的提示(VBA-让您回到1964年)
Richard H

3
@George:GoTo可能会被滥用(这就是为什么我要声明我的资格;请参阅明智的说法),但这并不是天生的邪恶。严重的是,如果没有Goto语句,就不可能仅仅因为您需要它来进行错误处理(即On Error Goto)而编写健壮的VBA 。
mwolfe02 '02

3
@乔治:我在这里建议的是一种针对该语言的另一种限制的解决方法(无Continue声明)。可以说Continue应该避免使用其他语言,因此也应避免在其他语言中使用。在某些方面,您发布的链接可以说明我的意思。链接是GoToVB.Net中的语句。VB.Net具有结构化的错误处理和Continue For/ Continue Do语句。GoTo在VB.Net中确实不需要。我怀疑它留在原地是为了支持更容易地转换现有VBA / VB6代码。
mwolfe02

4
@George GoTo具有减少嵌套的好处。IMO是跳过循环迭代而不添加缩进级别的方法,这是GoToVBA / VB6中少数合法使用的方法之一。特别是如果您将循环的主体提取到其自己的过程中
Mathieu Guindon 2015年

4
@George我见过嵌套不破的代码,但沉船一个人的大脑 ;)
马蒂厄·金敦

35

您可以continue通过嵌套使用一种Do ... Loop While False

'This sample will output 1 and 3 only

Dim i As Integer

For i = 1 To 3: Do

    If i = 2 Then Exit Do 'Exit Do is the Continue

    Debug.Print i

Loop While False: Next i

1
有趣..比使用goto更好!
ozmike

这太棒了
Kubie

1
这应该是答案
Stian Ulriksen

非常优雅,漂亮
AlexisSánchezTello

5
聪明!我不愿成为没有评论的人。大声笑
卡托尔

14

Continue For 在VBA或VB6中无效。

从此MSDN页面,它似乎已被引入VS 2005./Net 2中的VB.Net。

正如其他人所说,除了使用Goto或之外,没有其他选择Else


2

嗨,我也遇到了这个问题,我使用下面的示例代码解决了这个问题

For j = 1 To MyTemplte.Sheets.Count

       If MyTemplte.Sheets(j).Visible = 0 Then
           GoTo DoNothing        
       End If 


'process for this for loop
DoNothing:

Next j 

不知道为什么投票失败,下一个答案有超过100票赞成,而他们是相同的答案!
rryanp

4
可能是因为此答案是在该答案之后5年编写的,并且是完全相同的概念。为什么要接受投票?
Tyler StandishMan

-2

如果可能,请尝试将所有内容放到最后,然后使用else跳过将使之生效的代码,以使您无法使用GoTo。

                        If 6 - ((Int_height(Int_Column - 1) - 1) + Int_direction(e, 1)) = 7 Or (Int_Column - 1) + Int_direction(e, 0) = -1 Or (Int_Column - 1) + Int_direction(e, 0) = 7 Then
                Else
                    If Grid((Int_Column - 1) + Int_direction(e, 0), 6 - ((Int_height(Int_Column - 1) - 1) + Int_direction(e, 1))) = "_" Then
                        Console.ReadLine()
                    End If
                End If
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.