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

Ric*_*d H 97 conditional vba loops

我有一个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
Run Code Online (Sandbox Code Playgroud)

我知道我能做到:

 If (Schedule(i, 1) < ReferenceDate) Then Continue For
Run Code Online (Sandbox Code Playgroud)

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

有任何想法吗?

谢谢

mwo*_*e02 173

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
Run Code Online (Sandbox Code Playgroud)

如果这确实是你的所有代码,那么@Brian是绝对正确的.只需Else在你的If陈述中加上一个条款并完成它.

  • 谢谢,这是GoTo的一个很好的提示(VBA - 让你回到1964年) (18认同)
  • @George`GoTo`有减少嵌套的好处.在没有添加缩进级别的情况下跳过循环迭代是IMO,VBA/VB6中少数合法使用`GoTo`的用法之一.特别是如果你[将循环体提取到自己的程序中](https://github.com/retailcoder/Rubberduck/wiki/Features#refactorings). (4认同)
  • @George:GoTo可以被滥用(这就是为什么我对我的陈述有资格;见[judicious](http://dictionary.reference.com/browse/judicious)),但它本身并不是邪恶的.但是说真的,如果没有Goto语句就编写健壮的VBA是不可能的,因为你需要它来进行错误处理(即,On On Goto`). (3认同)
  • @George:我在这里推荐的是另一种语言限制的解决方法(没有`Continue`语句).有人可以说,应该避免在其他语言中使用"继续",因此也应该避免使用.在某些方面,您发布的链接提出了我的观点.链接是VB.Net中的`GoTo`语句.VB.Net具有结构化错误处理和"Continue For"/"Continue Do"语句.在VB.Net中确实没有"GoTo"; 我怀疑它的存在主要是为了支持更容易地转换现有的VBA/VB6代码. (3认同)
  • @George我见过没有打破*代码*的嵌套,但是破坏了一个人的*大脑*;) (3认同)
  • GoTo真是邪恶!不要使用GoTo或你的代码下地狱!说真的,请不要在代码中使用GoTo. (2认同)
  • @Mat's Mug 我不认为这种权衡是有益的。我宁愿有嵌套(在大多数情况下这不是什么大问题),也不愿有混乱且不可预测的控制流。嵌套不会破坏你的代码,GoTo 可能会破坏你的代码。我的意思是,在一个非常小的和孤立的场景中你可能有一个好的解决方案。然而,如果您决定将来扩展代码,风险就会很大。它只是不值得。 (2认同)
  • “GoTo”似乎是克服 VBA 缺乏“Continue”语句的最合乎逻辑的方法。所以我打字了!效果很好!就这一次不会有什么坏处……其他人都在这样做;所以它不会那么糟糕......我可以随时停止使用“GoTo”...... (2认同)

Bri*_*ian 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
Run Code Online (Sandbox Code Playgroud)

  • +1 @ RichardH你必须使用`IF`进行测试,所以这不是代码那么昂贵.你应该确保最常见的结果是`Schedule(i,1)`小于`ReferenceDate`以避免经常执行'Else`.否则使用`(ReferenceDate> = Schedule(i,1))`.(如果测试是50/50则不需要优化) (4认同)
  • 确实,这正是我所做的:)但是它仍然让我感到烦恼,我必须在Else中包装东西.谢谢 (3认同)

AHe*_*yne 29

你可以使用一种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
Run Code Online (Sandbox Code Playgroud)

  • 聪明!我不愿成为没有评论的人。大声笑 (3认同)
  • 有趣..比使用 goto 更好! (2认同)
  • 这应该是答案 (2认同)
  • 我同意这个解决方案有一定的聪明,但不同意它很优雅。它实际上掩盖了正在完成的事情的要点,使编码变得不那么明显,需要注释来解释它(正如 Caltor 所指出的)。 (2认同)
  • 这非常聪明(尽管我并不一定意味着这是一种恭维......[不要编写聪明的代码](https://nolongerset.com/dont-write-clever-code/))。当您将良好的_一般性建议_(“不要在代码中使用 GoTo”)视为永远不会被打破的_不可违反的规则_时,您会得到这种废话。 (2认同)

Jon*_*ton 13

Continue For 在VBA或VB6中无效.

这个MSDN页面看起来它已经被引入到VS 2005./Net 2中的VB.Net中.

正如其他人所说,除了使用Goto或者使用之外,实际上并没有其他选择Else.


Sin*_*lan 5

您好,我也面临这个问题,我使用下面的示例代码解决了这个问题

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 
Run Code Online (Sandbox Code Playgroud)

  • 可能是因为这个答案是在那个答案五年后写的,并且是完全相同的概念。为什么这应该获得赞成票? (5认同)