用于开始以结束变量中间循环结束循环

时间:2015-01-07 17:18:11

标签: excel vba loops excel-vba

从测试数据开始:

Start

运行代码:

Sub TestLoop()

Dim LastRow As Long, CurRow As Long
LastRow = Range("A" & Rows.Count).End(xlUp).Row

For CurRow = 1 To LastRow
    Range("B" & CurRow).Value = "Done"
    LastRow = 2
Next CurRow

End Sub

我希望循环在第2行结束,因为我更改了变量LastRow。但结果是:

Done

MSDN Reference FOR VB.NET has this to say

  

For...Next循环开始时,Visual Basic会评估startendstep。 Visual Basic仅在此时评估这些值,然后将start分配给counter。在语句块运行之前,Visual Basic会将counterend进行比较。如果counter已经大于end值(如果step为负,则更小),For loop结束并控制传递给{{1}之后的语句声明。否则,语句块将运行。

     

每次Visual Basic遇到Next语句时,它会Next递增counter并返回step语句。 再次将Forcounter 进行比较,并再次运行阻止或退出循环,具体取决于结果。此过程一直持续到end通过counter或遇到end语句为止。 [强调我的]

鉴于它会在每次迭代时检查Exit Forcounter,不应更改变量end

3 个答案:

答案 0 :(得分:4)

鉴于Correct MSDN Reference提及:

  

表达式<start-value><end-value><step-increment>按顺序评估一次,并且在以下任何计算之前进行评估。

即使包含end数量的变量发生变化,Visual Basic CAN 似乎也能记住循环期间end的值。

答案 1 :(得分:2)

我想在这里注意一些事情。首先,您需要参考 VB.Net 文档。所以,在谈论 VBA 时,我不会依赖它。事实上,VBA Documentation for the For...Next statement根本没有提到这种行为。所以,我深入挖掘一下,VBA确实在这里与VB.Net的行为相同。以下内容来自[MS-VBAL]: VBA Language Specification

  

表达式<start-value><end-value><step-increment>按顺序 评估 ,并且在任何以下计算。

这意味着您的示例中的LastRow仅在首次进入循环时计算。之后更改它对循环运行的次数没有影响。 (并不是说我开始尝试这样做。)

这也意味着您无法更改循环执行中步骤的步骤大小,此片段显示&#34; odd&#34;这两种行为同时发生。

Sub TestLoop()

    Dim LastRow As Long, CurRow As Long, StepsToTake As Integer
    LastRow = 100
    StepsToTake = 2

    For CurRow = 1 To LastRow Step StepsToTake
        Range("B" & CurRow).Value = "Done"
        LastRow = 2
        StepsToTake = 1
    Next CurRow

End Sub

对于那些感兴趣的人,这里是For...Next语句的整个运行时语义。

  

运行时语义。

     
      
  • 表达式<start-value><end-value><step-increment>按顺序评估,并且在任何   以下计算。如果<start-value>的值,   <end-value><step-increment>不是可以强制加倍的,   错误13(类型不匹配)立即引发。否则,继续   使用原始的未校正值,使用以下算法。

  •   
  • 根据以下算法执行<for-statement>

         
        
    1. 如果<step-increment>的数据值为零或正数,且<bound-variable-expression>的值大于   <end-value>的值,然后执行<forstatement>   立即完成;否则,请进入第2步。

    2.   
    3. 如果<step-increment>的数据值为负数,且<bound-variable-expression>的值小于该值   <end-value>的{​​{1}},立即执行<for-statement>   完成;否则,请进入第3步。

    4.   
    5. 执行<statement-block>。如果存在<nested-for-statement>,则执行该<bound-variable-expression>。最后,   <step-increment>的值被添加到值   <bound-variable-expression>并让我们回到   <goto-statement>。然后在步骤1重复执行。

    6.   
  •   
  • 如果在<for-statement>之外定义的<statement>导致<statement-block>内的<start-value>被执行,   表达式<end-value><step-increment><statement-block>是   没有评估。如果执行<statement-block>完成并且   在没有评估的情况下到达<start-value>的末尾   在此过程中<end-value><step-increment><bound-variable-expression>   执行封闭过程时,会生成错误(编号   92,&#34; For循环未初始化&#34;)。即使这发生了   包含初始化的赋值表达式   明确地<start-value>。否则,如果   表达式<end-value><step-increment><for-statement>   已经评估过,算法在步骤3继续   根据为执行<for-statement>而定义的规则。

  •   
  • <bound-variable-expression>执行完毕后,{{1}}的值仍为其所持有的值   循环完成。

  •   

答案 2 :(得分:1)

在@ Chrismas007上面的答案的基础上,如果你想在For结构的范围内使循环短路,你可以将增量变量设置为终止值:

For CurRow = 1 To LastRow
    Range("B" & CurRow).Value = "Done"

    ' This will end the loop.
    ' When Next is hit, CurRow will be LastRow + 1.
    CurRow = LastRow

    ' Alternately, you can exit the for loop immediately.
    ' Usually this would be inside an If statement.
    Exit For
Next CurRow