从测试数据开始:
运行代码:
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
。但结果是:
MSDN Reference FOR VB.NET has this to say:
当
For...Next
循环开始时,Visual Basic会评估start
,end
和step
。 Visual Basic仅在此时评估这些值,然后将start
分配给counter
。在语句块运行之前,Visual Basic会将counter
与end
进行比较。如果counter
已经大于end
值(如果step
为负,则更小),For loop
结束并控制传递给{{1}之后的语句声明。否则,语句块将运行。每次Visual Basic遇到
Next
语句时,它会Next
递增counter
并返回step
语句。 再次将For
与counter
进行比较,并再次运行阻止或退出循环,具体取决于结果。此过程一直持续到end
通过counter
或遇到end
语句为止。 [强调我的]
鉴于它会在每次迭代时检查Exit For
与counter
,不应更改变量end
?
答案 0 :(得分:4)
表达式
<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>
:
如果
<step-increment>
的数据值为零或正数,且<bound-variable-expression>
的值大于<end-value>
的值,然后执行<forstatement>
立即完成;否则,请进入第2步。如果
<step-increment>
的数据值为负数,且<bound-variable-expression>
的值小于该值<end-value>
的{{1}},立即执行<for-statement>
完成;否则,请进入第3步。执行
<statement-block>
。如果存在<nested-for-statement>
,则执行该<bound-variable-expression>
。最后,<step-increment>
的值被添加到值<bound-variable-expression>
并让我们回到<goto-statement>
。然后在步骤1重复执行。如果在
<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