乐于分享
好东西不私藏

Excel VBA 编程基础 — 语句(八)- 循环语句

Excel VBA 编程基础 — 语句(八)- 循环语句

前面几篇我们详细讨论了条件语句,所谓条件语句,就是根据条件来决定执行哪个分支的语句。从今天开始,我们讨论循环语句。
VBA 提供了丰富的循环语句,我们先从最简单的 For 循环讲起。
还是先来看一个例子:
Dim total As IntegerDim i As Integertotal = 0For i = 0 to 9total = total + iNext iDebug.Print "The sum of 0 to 9: " & total
For … Next 就是 For 循环的基本结构,位于其间的语句在循环期间不断执行。在上面的代码中,total 和 i 都声明为 Integer 类型,接下来将 total 初始化(赋初值 0),然后进入 For … Next 循环。循环的过程是:i 从 0 以每次增加 1 的方式连续变化直到 9,每变化一次,循环结构之间的 total = total + 1 赋值语句就执行一次,循环的结果就是计算 0 到 9 的和。
如果不用循环结构,只用赋值语句计算 0 到 9 的和,可以写成下面的代码:
Dim total As Integertotal = 0total = total + 1total = total + 2...total = total + 9Debug.Print "The sum of 0 to 9: " & total
为了节省篇幅,上面的代码省略了一些行。
可以看出,采用循环结构来实现一些重复性动作,不仅经济,而且优美。
For 循环语句的一般格式是:
图1 For 循环的一般格式
在这个一般格式中,counter 称为循环控制变量(loop control variable),用于控制循环的执行,方括号 [ ] 表示里面的内容是可选的。
Stepstep ]:这部分是可选的,如果没有这部分,则默认步长为 1。如果步长不为 1,则使用这部分指定循环步长,如下面的代码:
Dim total As IntegerDim i As Integertotal = 0For i = 0 To 9 Step 2total = total + iNext iDebug.Print "The sum of 0 to 9 stepping by 2: " & total
这段循环的步长为 2,说明 i 每循环一次就增加 2,则在整个循环过程中,i 的取值将分别是:0, 2, 4, 6, 8。所以,此时 total 的结果将是 0 到 9 之间所有偶数的和。
循环的步长也可以是负数。上面代码可以使用负数步长重写如下:
Dim total As IntegerDim i As Integertotal = 0For i = 8 To 0 Step -2total = total + iNext iDebug.Print "The sum of 8 to 0 stepping by -2: " & total
这段循环步长为 -2 的代码与上面步长为 2 的代码是等价的:i 从 8 开始,每循环一次,i 的值就增加 -2,亦即减 2,一直到 0,结束循环。所以整个循环过程中,i 的变化为:8, 6, 4, 2, 0。与上面循环中 i 的变化相同,只不过方向相反。
仔细观察,步长为 -2 的代码和步长为 2 的代码,除了步长不同之外,还有一点不同,就是循环的起始值 start。步长为 -2 时,起始值必须设定为 8,如果设定为 9 的话,就变成 9, 7, 5, 3, 1 这几个奇数的和了。
关于 For 循环的讨论
例1.
Dim i As IntegerFor i = 0 To 9 Step 1Debug.Print iNext i
这段循环代码运行的结果是打印出 0 到 9 这 10 个数字。
例2. 
Dim i As IntegerFor i = 0 To 9 Step -1Debug.Print iNext i
这段循环代码根本就不执行。为什么?
要解释这个现象,需要先了解 VBA 中的 For 循环执行流程。
根据 VBA 的语言规范,For 循环的执行流程是:
  1. 计算起始值(start)、终止值(end)、步长(step
  2. 检查循环是否需要执行:
    1. 如果步长 > 0 且 起始值 > 终止值,则跳过循环
    2. 如果步长 < 0 且 起始值 < 终止值,则跳过循环
    3. 否则,执行 counter = start 并进入循环
  3. 每次循环后,执行 counter = counter + step
  4. 检查:
    1. 如果 步长 > 0 且 counter > 终止值,则结束循环
    2. 如果步长 < 0 且 counter < 终止值,则结束循环
    3. 否则,继续循环
根据这个流程,我们就可以来解释上面的循环为什么不执行了:因为 步长 < 0 且 起始值 < 终止值,因此这个循环不会执行。
我们可以再问一句:为什么 VBA 中的 For 循环要先做上面第 2 步那样的检查呢?
如果不做那样的检查,则对于例2 那样的循环代码,第一次循环,i 的值是 0,然后 i = i + step = -1,再次进入循环,如此循环下去,i 离终止值越来越远,永远也到不了终止值,从而陷入无限循环,术语叫“死循环”。
虽然 VBA 的 For 循环因为做了第 2 步那样的检查,可以避免如例2 那样的循环陷入死循环,但仍然避免不了下面的死循环:
例3.
Dim i As IntegerFor i = 0 To 9 Step 0Debug.Print iNext i
VBA 的语言规范没有规定 For 循环的步长不得为 0,上面的代码执行时就会陷入死循环。
因此,写循环代码时要特别小心!
我们下面用一种办法来避免上面这种死循环。
例4.
Dim i As IntegerDim pi As Integerpi = -10000For i = 0 To 9 Step 0If pi <> i Thenpi = iElseExit ForEnd IfDebug.Print iNext i
上面这段代码中,我们增加了一个变量用来保存 i 的上一个值,并且 pi 被初始化为一个不同于循环初始值的值。在循环过程中,判断 i 的当前值和前一个值 pi 是否相等,不相等则将 i 的当前值赋给 pi,相等就表明循环控制变量没有变化。循环控制变量没有变化就表明这是一个死循环,因此执行 Exit For 语句强制跳出这个 For 循环。因此,上面这段 For 循环代码只执行一次就跳出了循环,从而避免了死循环。
当然,这只是为了说明 Exit For 语句的作用而“硬编出来”的一个例子,实际编程中没有人会这么做。但通过这个例子,我们知道了 Exit For 语句的作用就是中途退出循环。