'循环开始
For i = 2 To 10
'这里是循环的代码
Next i
'如果为空,则用上方的单元格的值填充当前单元格
If isBlank Then
Cells(i, 1) = Cells(i - 1, 1)
End If
程序示例
Sub MyCode()
'声明循环变量和是否为空变量
Dim i As Integer
Dim isBlank As Boolean
'循环 A2-A10 单元格
For i = 2 To 10
'存储单元格是否为空的结果
isBlank = Cells(i, 1).Value = ""
'如果为空,则用上方的单元格的值填充当前单元格
If isBlank Then
Cells(i, 1) = Cells(i - 1, 1)
End If
Next i
End Sub
'语法
Dim [变量名] As [数据类型]
'实例
Dim name As String
Dim age As Integer
Dim height As Double
Dim birthday As Date
'语法
Dim [变量名] As Variant
Dim [变量名]
'实例
Dim message As Variant
Dim message
'语法
'固定长度数组声明
Dim [变量名](开始序号 to 结束序号) As [数据类型]
'动态数组声明
Dim [变量名]() As [数据类型]
'实例
'声明包含10个文本类型元素的数组
Dim names(1 to 10) As String
'声明长度未知的文本类型数组
Dim names() As String
'语法
'前期绑定声明语法
Dim [变量名] As [对象类型]
'后期绑定声明语法
Dim [变量名] As Object
'实例
Dim sh As Worksheet
Dim car As Object
通过以上部分的学习,在写多个同类型变量的声明语句时,有人可能会按以下方式写:
'声明两个整数类型的 i、j 变量
Dim i,j As Integer
首先,以上写法,语法上没问题,不会出现错误。但是,这种方式声明变量,Integer 类型只作为第二个 j 变量的数据类型。第一个变量,即 i 变量,它的数据类型是 Variant,并不是 Integer 类型。
因此,VBA 中不能合并声明语句。正确的声明方法如下:
'第一种,按两行写
Dim i As Integer
Dim j As Integer
'第二种,使用 : 符号,在一行写
Dim i As Integer : Dim j As Integer
准确来讲,VBA 中声明变量不是必须的。也就是说,没有声明变量,而直接开始用,也没有错误。
但是,不声明变量,是一种不好的习惯,也常常会带来很多错误。这也是为什么之前的教程中都没有提到这点的原因。
不声明变量典型弊端包括:
基于以上原因,强烈建议,每次使用变量,都要声明其变量名和数据类型。
VBA 提供一个选项,可以强制变量声明,即在模块头部写上以下语句:
Option Explicit
基本类型变量的赋值
VBA 中,给基本类型变量赋值,以 Let关键词开头。赋值操作是给=左侧的变量,用=右边的数据,指定其代表的值。在后续的代码中,该变量就代表指定的数据。
在实际开发中,给基本类型变量赋值时,Let关键词可以忽略不写,直接以变量开头写赋值语句。
给基本类型变量赋值语法如下:
'语法,两种写法相同
Let [变量名] = [数据]
[变量名] = [数据]
'实例
Dim name As String
Let name = "Zhang San"
Dim age As Integer
Let age = 30
Dim birthday As Date
Let birthday = #2000-1-1#
赋值语句中,=右侧可以是包含其他变量、函数、复杂计算的表达式。该表达式返回的值的类型,与变量类型一致就可以正常赋值。
Dim birthday As Date
Dim age As Integer
birthday = #2000-1-1#
age = Year(Now) - Year(birthday)
一种特殊情况是,=右侧可以是变量本身。这种方式多用于循环结构中。
Dim i As Integer
Do While i < 10
Msgbox i
i = i + 1
Loop
'返回 => 0,1,2,3,4,5,6,7,8,9
Variant 类型变量的赋值
我们知道 Variant 类型时通用类型,因此赋值很直接,没有类型强制要求。Variant 类型变量第一次赋值后,可以继续赋值其他类型数据。
'声明变量(两者相同)
Dim message As Variant
Dim message
'赋值
message = "Hello World"
message = 1234567890
message = #2018-12-1#
这里依然强调,虽然 Variant 类型变量比较灵活,但是也有很多弊端,所以在实际开发中,不建议使用该类型,使用确切类型变量。
数组类型变量的赋值
数组是可以存储多个同类型元素的数据类型。声明时一般指定其数据长度。给数组赋值时,一般使用每个元素的序号。
数组赋值基本语法如下:
[数组名](元素序号) = [数据]
下面看一下实际的实例。
'声明数组
Dim arr(1 to 5) As String
'数组赋值
arr(1) = "Zhang San"
arr(2) = "Li Si"
arr(3) = "Wang Wu"
对象类型变量的赋值
VBA 中,对象是程序的一个元素,不同于基本类型数据,它包括多个属性和多个方法。例如,Excel 中工作簿、工作表、单元格、图表等都是对象。
对象类型变量赋值时,不同于基本类型变量使用Let(可以忽略)关键词,对象使用 Set 关键词,并且Set关键词不能省略。
如下是对象类型变量基本的赋值方法:
Set [变量名] = [对象类型数据]
下面看一下实际的用法。
'声明工作表类型的对象
Dim sheet As Worksheet
'将名称为“绩效表”的工作表,赋到 sheet 变量
Set sheet = Worksheets("绩效表")
由于对象可以包含多个属性,因此 VBA 提供一种同时给多个属性赋值的简单方法。具体方法是对象多个属性赋值语句,放置在 With+对象和End With关键词中间。
Dim sheet As Worksheet
Set sheet = Worksheets("绩效表")
With sheet
.Name = "旧绩效"
.Visible = False
End With
选择结构中,If Then 结构是最基础的一个。它只有条件表达式真时,执行的代码。
If Then结构基本语法如下,其中 End If是选择结构的结束标志。
If 条件表达式 Then
'表达式为真时,执行的代码
End If
现在我们看实际的例子,判断学生是否及格,及格条件是成绩 ≥60。如果及格,在C列对应单元格填写“及格”。具体代码如下:
Sub MyCode()
Dim i As Integer
For i = 2 To 5
If Cells(i, "B").Value >= 60 Then
Cells(i, "C") = "及格"
End If
Next i
End Sub
很多时候,我们根据表达式的真假,真时执行一块代码,假时执行另一块代码。这种需求可以使用 If Else结构实现。
If Else结构中,条件表达式在真时,执行Then后的代码;条件表达式为假时,执行 Else后的代码。基本语法如下:
If 条件表达式 Then
'真时执行的代码
Else
'假时执行的代码
End If
我们继续看实际的例子。在上一个例子的基础上,这次对不及格的学生,在C列填入不及格。代码如下:
Sub MyCode()
Dim i As Integer
For i = 2 To 10
If Cells(i, "B").Value >= 60 Then
Cells(i, "C") = "及格"
Else
Cells(i, "C") = "不及格"
End If
Next i
End Sub
前面两种结构中,最多有两种选择,即 ≥ 60 和 < 60。有时针对同一个变量,可能存在多种判断标准。例如,对及格的学生,继续评级及格、良和优。
选择结构中,可以使用 If ElseIf Else结构,对同一个变量进行多次判断,并且为每一个判断结果编写不同的代码块,达到执行式 n 选 1 的效果。
If ElseIf Else结构的基本语法如下:
If 条件表达式1 Then
'表达式1真时,执行的代码
ElseIf 条件表达式2 Then
'表达式2真时,执行的代码
ElseIf 条件表达式3 Then
'表达式3真时,执行的代码
...
ElseIf 条件表达式n Then
'表达式n真时,执行的代码
Else
'以上表达式都不为真时,执行的代码
End If
这种选择结构需要注意的是:
条件表达式是从第一个开始判断。
判断过程中,只要有一个表达式结果为真,那么执行对应的代码块,然后退出选择结构,不再继续判断剩下的表达式。
当所有的表达式都不为真时,执行 Else后的代码块。
根据以上规律,我们写一下判断学生成绩评级的代码。思路是,拿学生成绩,分别于85、75、60分比较,在 D 列填写对应的评级。
Sub MyCode()
Dim i As Integer
For i = 2 To 10
If Cells(i, "B").Value >= 85 Then
Cells(i, "D") = "优"
ElseIf Cells(i, "B").Value >= 75 Then
Cells(i, "D") = "良"
ElseIf Cells(i, "B").Value >= 60 Then
Cells(i, "D") = "及格"
Else
Cells(i, "D") = "不及格"
End If
Next i
End Sub
Select Case结构是对同一个变量进行多次判断的另一种方式。相对于If ElseIf Else结构,它把条件表达式中的变量提取出来,使得代码结构更简洁,也更易于阅读。
Select Case结构的基本语法如下:
Select Case 变量
Case 判断条件 1
'条件 1 真时,执行的代码
Case 判断条件 2
'条件 2 真时,执行的代码
Case 判断条件 3
'条件 3 真时,执行的代码
Case Else
'之前的所有条件都不为真时,执行的代码
End Select
可以看到,Select Case结构把 If结构中的条件表达式拆分了,即把变量和判断条件分开了。
我们看前一个例子,使用Select Case结构,代码如下:
Sub MyCode()
Dim i As Integer
For i = 2 To 10
Select Case Cells(i, "B").Value
Case Is >= 85
Cells(i, "D") = "优"
Case Is >= 75
Cells(i, "D") = "良"
Case Is >= 60
Cells(i, "D") = "及格"
Case Else
Cells(i, "D") = "不及格"
End Select
Next i
End Sub
For 循环是最常用的循环类型,它有两种形式:
For … Next 循环
使用 For … Next 循环可以按指定次数,循环执行一段代码。For 循环使用一个数字变量,从初始值开始,每循环一次,变量值增加或减小,直到变量的值等于指定的结束值时,循环结束。
For … Next 循环语法如下:
For [变量] = [初始值] To [结束值] Step [步长]
'这里是循环执行的语句
Next
其中:
[变量] 是一个数字类型变量,可在循环执行的语句里使用。
[初始值] 和 [结束值] 是给定的值;
[步长]是每次循环时,变量的增量。如果为正值,变量增大;如果为负值,变量减小。
下面看一个实际的例子,求 1 至 10 数字的累积和。
Sub MyCode()
Dim i As Integer
Dim sum As Integer
For i = 1 To 10 Step 1
sum = sum + i
Next
End Sub
可以看到,For 循环使用 i 变量,循环 10 次,i 的值从 1 到 10 变化。
值得注意的是,For 循环的 Step 值如果是 1,则 Step 关键词可省略。上述过程循环部分可写成如下方式:
For i = 1 To 10
sum = sum + i
Next
For Each 循环
For Each 循环用于逐一遍历一个数据集合中的所有元素。数据集合包括数组、Excel 对象集合、字典等。
For Each 循环不需要一个数字变量,但是需要与数据集合中的元素相同的数据类型变量。其基本语法如下:
For Each [元素] In [元素集合]
'循环执行的代码
Next [元素]
其中:
[元素] 是与集合中的元素相同类型的变量,该变量可在循环代码中使用。
[元素集合]是包括多个元素的集合。
下面看一个实际例子,循环打印出工作簿中所有工作表的名称。
Sub MyCode()
Dim sh As Worksheet
For Each sh In Worksheets
Debug.Print sh.Name
Next sh
End Sub
sh 变量就是元素变量,Worksheets 是工作簿中所有工作表的集合。
Exit For 语句
Exit For 语句用于跳出循环过程,一般在提前结束循环时使用,均适用于 For Next 循环和 For Each 循环。
看一个实际的例子,求 1 – 10 数字的和时,当和大于 30 就停止循环。
Sub MyCode()
Dim i As Integer
Dim sum As Integer
For i = 1 To 10
sum = sum + i
If sum > 30 Then
Exit For
End If
Next
End Sub
在这段代码中,sum 变量大于 30 时,循环就停止。
Do While 循环用于满足指定条件时循环执行一段代码的情形。循环的指定条件在 While 关键词后书写。
Do While 循环也有两种形式:
Do While … Loop 循环
Do While … Loop 循环,根据 While 关键词后的条件表达式的值,真时执行,假时停止执行。基本语法如下:
Do While [条件表达式]
'循环执行的代码
Loop
其中,只要 [条件表达式] 为真,将一直循环执行。[条件表达式] 一旦为假,则停止循环,程序执行 Loop 关键词后的代码。
看一个实际的例子,还是求 1- 10 累积和。
Sub MyCode()
Dim i As Integer
Dim sum As Integer
i = 1
Do While i <= 10
sum = sum + i
i = i + 1
Loop
End Sub
i 变量的初始值是 1,根据 While 后的条件,只要 i 变量小于等于 10,后续的代码就可以一直循环执行。
Do … Loop While 循环
与上一种 Do 循环不同的是,Do … Loop While循环至少循环执行代码一次后,再判断条件表达式的值。基本语法如下:
Do
'循环执行的代码
Loop While [条件表达式]
其中,While 和条件表达式写在 Loop 关键词后。
Exit Do 语句
与 Exit For 语句类似,Exit Do 语句用于跳出 Do While 循环。
Do Until 循环与 Do While 循环类似。不同点在于,Do While 在条件表达式为真时,继续执行循环;而 Do Until 在条件表达式为真时,停止执行循环。
Do Until 循环也有两种形式:
Do Until … Loop 循环
循环开始前判断 Until 后条件表达式的值,如果是真,停止循环;如果是假,继续执行循环。基本语法如下:
Do Until [条件表达式]
'循环执行的代码
Loop
Do … Loop Until 循环
先运行一次,再判断 Until 后条件表达式的值,如果是真,停止循环;如果是假,继续执行循环。基本语法如下:
Do
'循环执行的代码
Loop Until [条件表达式]
With 结构由 With 和 End With 两个语句构成,对象的属性和方法都写在两者之间。基本语法如下:
With [对象]
.[属性] = [数据]
.[方法]
'其他属性和方法
End With
With 结构里,对象的属性和方法均由点 (.)符号开始,后接对象的属性名和方法名。
现在看一个实际的例子,需要将工作簿中 Sheet1 工作表设置新名称,然后设置标签颜色为黑色,最后隐藏工作表。
如果不用 With 结构,代码如下:
Sub MyCode()
Worksheets("Sheet1").Name = "新名称"
Worksheets("新名称").Tab.ThemeColor = xlThemeColorLight1
Worksheets("新名称").Visible = xlSheetHidden
End Sub
可以看到,每个语句都重复写 Worksheets(“工作表名称”) 部分。
使用 With 结构,可以避免重复写同一个对象名,代码如下:
Sub MyCode()
With Worksheets("Sheet1")
.Name = "新名称"
.Tab.ThemeColor = xlThemeColorLight1
.Visible = xlSheetHidden
End With
End Sub
With 结构还能嵌套编写,即一个 With 结构中,如果父对象的属性是另一个对象,则针对这个子对象,继续使用 With 结构。
在之前的例子中,如果需要将 Sheet1 工作表中,A1:A10 单元格区域设置背景颜色,调整字体和字体大小,可以使用如下代码:
Sub MyCode()
With Worksheets("新名称")
.Name = "new"
.Tab.ThemeColor = xlThemeColorLight1
With .Range("A1:A5")
.Interior.ThemeColor = xlThemeColorAccent1
.Font.Size = 11
.Font.Name = "等线"
End With
End With
End Sub
GoTo 结构由 GoTo 语句和标签语句组成。基本语法如下:
GoTo [标签]
'被跳过的代码
...
[标签]:
'被执行的代码
跳转的位置由 Goto 关键词后的 [标签] 告诉程序,VBA 会在代码中查找对应的 [标签]: 关键词,从标签下一行继续执行程序。
需要注意的是,跳转处的标签,后接冒号 ( : ) 。
下面的例子说明 GoTo 结构的基本用法。使用 VBA 作除法,如果除数是零,则跳转到程序末尾,提示除数不符合规范。
Sub MyCode()
Dim num1 As Double
Dim num2 As Double
Dim result As Double
num1 = 100
num2 = 0
If num2 = 0 Then GoTo error
result = num1 / num2
Exit Sub
error:
MsgBox "除数不能为零"
End Sub
可以看到,例子中 num2 是除数,程序判断 num2 是否为零,如果是,则跳转到 Error 标签处,除法部分不会被执行。
Goto 结构相对简单,实际开发中不像三大结构使用频繁,但是在一些情形中使用,可以使代码更简洁易读。GoTo 语句常用于错误处理外,还可以用在「上一步/下一步」类情形中,根据用户需求,重复执行同一个步骤,这方面内容在以后做更多介绍。
参考链接: 懒人Excel