跳转至

02 条件/循环语句

VBA也是一门编程语言,因此也有自己的条件语句和循环语句,本期就给大家介绍一下各个语句是怎么用的,结构到底如何

一、条件语句

1.1 单层的IF语句

在VBA中如果需要表示条件判断,我们可以使用if语句,单层的结构,我们可以将其组织为:

1
2
3
if 条件 then
    执行的语句
end if 
例如下面这个例子,判断a是否等于3,写作:

1
2
3
4
5
6
7
sub test()
    a = 3
    '使用if判断a是否等于3
    if a = 3 then
        msgbox "a等于3"
    end if
End sub
当然对于简单的判断,VBA支持单行的写法,例如:

if a = 3 then msgbox "a等于3"
这样子就不需要end if来作为if语句的结束标志了,如果满足后要干两件事,则用 : 隔开实现,如下:

'使用if判断a是否等于3,如果等于3,则弹出消息框,并将a1单元格的值设为"a等于3"
if a = 3 then msgbox "a等于3": range("a1").value = "a等于3"

1.2 多层嵌套的IF语句

对于有不同情况的IF,比如我们有两种情况需要判断,经常组织成如下的结构

1
2
3
4
5
if 条件 then
    执行的语句
else
    执行的语句
end if
例如下面这个例子,在两种情况下我们都要进行对应的操作,就可以加上else承接:

1
2
3
4
5
6
7
8
9
sub test()
    a = 3
    '使用if判断a是否等于3,如果等于3,则弹出消息框"a等于3",否则弹出消息框"a不等于3"
    if a = 3 then
        msgbox "a等于3"
    Else
        msgbox "a不等于3"
    end if
End sub 
对于更加复杂的嵌套,我们可以使用到elseif 语句,结构如下:

1
2
3
4
5
6
7
if 条件1 then
    执行的语句
elseif 条件2 then
    执行的语句
else
    执行的语句
end if
比如下面这个例子,根据不同的分数层级进行IF的分支判断:

sub test()
    score = 80
    '使用if判断score是否大于等于90,如果大于等于90,则弹出消息框"优秀",
    '否则判断是否大于等于80,如果大于等于80,则弹出消息框"良好",
    '否则判断是否大于等于70,如果大于等于70,则弹出消息框"中等",
    '否则判断是否大于等于60,如果大于等于60,则弹出消息框"及格",否则弹出消息框"不及格"
    if score >= 90 then
        msgbox "优秀"
    elseif score >= 80 then
        msgbox "良好"
    elseif score >= 70 then
        msgbox "中等"
    elseif score >= 60 then
        msgbox "及格"
    Else
        msgbox "不及格"
    end if
End sub 

1.3 Select 语句

对于情况比较多的时候,我们通常也会使用select语句进行实现,其结构如下:

1
2
3
4
5
6
7
8
select case 变量
    case 值1
      语句1
    case 值2
      语句2
    case Else
      不满足任何一种情况
end select

一样的,我们看下面这个例子:

sub test()
    score = 80
    '使用select case判断score的等级
    select case score
        case 90 to 100 '这里To表示包含90和100
            msgbox "优秀"
        case 80 to 89
            msgbox "良好"
        case 70 to 79
            msgbox "中等"
        case 60 to 69
            msgbox "及格"
        case else
            msgbox "不及格"
    end select
End sub 

二、循环语句

2.1 For 循环

对于最基础的for循环,写法如下:

1
2
3
for 变量名 = 起始值 to 终止值 step 步长
    执行的语句
next 变量名
来看下面这个例子,使用for循环实现依次打印10个数字

1
2
3
4
5
6
7
sub test()
    dim i as integer
    '使用for循环弹出消息框,显示1到10的数字
    for i = 1 to 10
        msgbox i
    next i
End sub 
步长是一个可选参数,代表变量值变化的尺度大小,比如我们可以改成,打印的值就是1、3、5、7、9,间隔为2:

'使用for循环弹出消息框,显示1到10的奇数
for i = 1 to 10 step 2
for 语句也可以实现嵌套语法,可以看下面这个示意图:

同样我们结合一个具体的案例,看一下运行的过程是什么样的,其中Debug.Print用于在立即窗口中输出信息:

1
2
3
4
5
6
7
8
9
Sub test()
    Dim i As Integer
    Dim j As Integer
    For i = 1 To 3
        For j = 1 To 2
            Debug.Print "i=" & i & ",j=" & j
        Next j
    Next i
End Sub
运行上面的程序之后,在立即窗口我们可以看到结果如下,就是从外层循环到内层循环,然后遍历完内层循环,继续下一个外层循环,在每个外层循环中都要将内部的循环跑完,直到内外层循环都结束:

1
2
3
4
5
6
i=1,j=1
i=1,j=2
i=2,j=1
i=2,j=2
i=3,j=1
i=3,j=2

2.2 For each 循环

上面的for循环主要是对于数值类型或者一个普通的变量,而对于对象类型,我们经常使用for each循环,常见的对象有工作簿,工作表,单元格等等,其基本结构写作:

1
2
3
for each 单一对象 in 对象集合
    循环的内容
next
比如下面这段代码,循环遍历每一个单元格对象,输出对应的值:

1
2
3
4
5
6
7
sub test()
    dim s as Range
    '使用for each循环遍历a1:a10单元格,并弹出每个单元格的值
    for each s in range("a1:a10")
        msgbox s.value
    next s
end sub
除了单元格,我们还可以遍历工作表和工作簿,或者其他的任意对象:

1
2
3
for each ws in workbooks("book1").worksheets '遍历book1工作簿中的所有工作表
for each wb in workbooks '遍历所有工作簿
for each s in selection '遍历当前选中的单元格

2.3 Do Loop循环

Loop循环主要有两大类,一类是while循环,即满足某个条件才执行,还有一类是until循环,即到了某个条件成立的时候就停止,语法结构可以参考下面的写法:

样式1(基础样式)
Do
    执行的语句
Loop

==========================================================================

样式2(直到...成立就停止)                   样式2(直到...成立就停止)→写法2
Do Until 条件                             Do
    执行的语句                                  执行的语句
Loop                                     Loop Until 条件

==========================================================================

样式3(如果...成立则执行)                   样式3(如果...成立则执行)→写法2
Do While条件                              Do
    执行的语句                                  执行的语句
Loop                                     Loop While条件

下面仅仅只对do...while循环进行举例,其他的以此类推:

1
2
3
4
5
6
7
8
sub test()
    a = 0
    '使用do while循环,循环10次,每次弹出消息框显示当前循环次数
    do while a < 10
        msgbox a
        a = a + 1
    loop
end sub

2.4 Exit语句和Goto语句

在下面这个语句中,我们使用了exit do来实现,当某个条件满足的时候,就退出循环,此写法可以防止程序进入死循环,除了exit do,还有Exit for(退出for循环),exit sub(退出Sub模块),但是需要注意的是:

Exit相当于给代码提前结束的出口,Exit和sub语句不能彼此替代,Exit不定义程序结尾(和End不同)

1
2
3
4
5
6
7
8
9
sub test()
    a = 0
    '使用do while循环 当循环次数大于等于3时,退出循环
    do while true
        msgbox a
        a = a + 1
        if a >= 3 then exit do
    loop
end sub
除了exit语句,我们还可使用goto语句实现程序的直接跳转,比如下面这段代码,只要a > 3满足,就跳到exitloop处执行
Sub test()
    a = 0
    '使用do while循环 当循环次数大于3时,退出循环
    Do While a <= 10
        If a > 3 Then GoTo exitloop
        a = a + 1
    Loop
exitloop:
    MsgBox "循环结束"
End Sub
有了goto语句,我们就能结合错误处理语句进行更加多样的处理,错误处理主要有以下几个不同的表达形式:

  • on error resume next:忽略错误
  • on error goto 0:取消忽略错误
  • on error goto XXX:当发生错误时,跳转到XXX处执行

来看下面这段代码,当运行到 a=0的时候,就会出现除0错误,程序发生跳转,执行exitloop后的内容:

Sub test()
    On Error GoTo exitloop '当发生错误时,跳转到exitloop标签
    a = 5
    Do While True
        Debug.Print 2 / a
        a = a - 1
    Loop
exitloop:
    MsgBox "循环结束"
    If Err.Number <> 0 Then MsgBox Err.Number ' 弹出错误编号
End Sub
我们可以使用 err.number来获取错误的编号,不同错误有不同编号(除零错误是11),如果exitloop后续还有其他的重要代码执行,养成习惯使用err.clear来清除错误信息,因为程序不终止,错误信息还在,会影响后续错误的判断。