VBA基础入门2
- VBA 程序结构
- VBA 程序结构入门(认识 VBA 程序骨架)
- 循环结构
- 判断结构
- VBA 变量的声明和赋值(使程序动起来)
- 不同变量类型声明语句
- 如何声明多个变量
- 声明变量是必须的嘛?
- 变量赋值
- VBA 程序顺序结构(VBA 程序默认执行顺序)
- VBA 程序选择结构(选择性的执行 VBA 代码)
- If … Then 结构
- If … Else 结构
- If ElseIf Else 结构
- Select Case 结构
- VBA 程序循环结构(重复执行一段代码)
- For 循环
- Do While 循环
- Do Until 循环
- VBA With 结构(简化程序书写)
- With 语法
- With 结构实例
- 嵌套 With 结构
- VBA GoTo 结构(程序之间跳转执行)
- 语法
- 实例
VBA 程序结构
VBA 程序结构入门(认识 VBA 程序骨架)
循环结构
'循环开始
For i = 2 To 10'这里是循环的代码
Next i
判断结构
'如果为空,则用上方的单元格的值填充当前单元格
If isBlank ThenCells(i, 1) = Cells(i - 1, 1)
End If
程序示例
Sub MyCode()'声明循环变量和是否为空变量Dim i As IntegerDim isBlank As Boolean'循环 A2-A10 单元格For i = 2 To 10'存储单元格是否为空的结果isBlank = Cells(i, 1).Value = ""'如果为空,则用上方的单元格的值填充当前单元格If isBlank ThenCells(i, 1) = Cells(i - 1, 1)End IfNext iEnd Sub
VBA 变量的声明和赋值(使程序动起来)
不同变量类型声明语句
- 基本类型变量
'语法
Dim [变量名] As [数据类型]'实例
Dim name As String
Dim age As Integer
Dim height As Double
Dim birthday As Date
- 通用变量
声明 Variant 类型变量时,如果忽略数据类型,默认情况是 Variant 类型,因此下方两种方式是相同的。
'语法
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 中声明变量不是必须的。也就是说,没有声明变量,而直接开始用,也没有错误。
但是,不声明变量,是一种不好的习惯,也常常会带来很多错误。这也是为什么之前的教程中都没有提到这点的原因。
不声明变量典型弊端包括:
- 数据类型自动设置为 Variant 类型,效率低。
- 变量名写错,不会提示错误。
- 无法使用 VBA 代码自动补全。
- 数据类型不匹配时,不会提示错误。
基于以上原因,强烈建议,每次使用变量,都要声明其变量名和数据类型。
VBA 提供一个选项,可以强制变量声明,即在模块头部写上以下语句:
Option Explicit
变量赋值
基本类型变量的赋值
VBA 中,给基本类型变量赋值,以 Let关键词开头。赋值操作是给=左侧的变量,用=右边的数据,指定其代表的值。在后续的代码中,该变量就代表指定的数据。
在实际开发中,给基本类型变量赋值时,Let关键词可以忽略不写,直接以变量开头写赋值语句。
给基本类型变量赋值语法如下:
'语法,两种写法相同
Let [变量名] = [数据]
[变量名] = [数据]'实例
Dim name As String
Let name = "Zhang San"Dim age As Integer
Let age = 30Dim birthday As Date
Let birthday = #2000-1-1#
赋值语句中,=右侧可以是包含其他变量、函数、复杂计算的表达式。该表达式返回的值的类型,与变量类型一致就可以正常赋值。
Dim birthday As Date
Dim age As Integerbirthday = #2000-1-1#
age = Year(Now) - Year(birthday)
一种特殊情况是,=右侧可以是变量本身。这种方式多用于循环结构中。
Dim i As IntegerDo While i < 10Msgbox ii = i + 1Loop'返回 => 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
VBA 程序顺序结构(VBA 程序默认执行顺序)
从左到右,从上到下:
VBA 程序选择结构(选择性的执行 VBA 代码)
If … Then 结构
选择结构中,If Then 结构是最基础的一个。它只有条件表达式真时,执行的代码。
If Then结构基本语法如下,其中 End If是选择结构的结束标志。
If 条件表达式 Then'表达式为真时,执行的代码
End If
现在我们看实际的例子,判断学生是否及格,及格条件是成绩 ≥60。如果及格,在C列对应单元格填写“及格”。具体代码如下:
Sub MyCode()Dim i As IntegerFor i = 2 To 5If Cells(i, "B").Value >= 60 ThenCells(i, "C") = "及格"End IfNext iEnd Sub
If … Else 结构
很多时候,我们根据表达式的真假,真时执行一块代码,假时执行另一块代码。这种需求可以使用 If Else结构实现。
If Else结构中,条件表达式在真时,执行Then后的代码;条件表达式为假时,执行 Else后的代码。基本语法如下:
If 条件表达式 Then'真时执行的代码
Else'假时执行的代码
End If
我们继续看实际的例子。在上一个例子的基础上,这次对不及格的学生,在C列填入不及格。代码如下:
Sub MyCode()Dim i As IntegerFor i = 2 To 10If Cells(i, "B").Value >= 60 ThenCells(i, "C") = "及格"ElseCells(i, "C") = "不及格"End IfNext iEnd Sub
If ElseIf Else 结构
前面两种结构中,最多有两种选择,即 ≥ 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 IntegerFor i = 2 To 10If Cells(i, "B").Value >= 85 ThenCells(i, "D") = "优"ElseIf Cells(i, "B").Value >= 75 ThenCells(i, "D") = "良"ElseIf Cells(i, "B").Value >= 60 ThenCells(i, "D") = "及格"ElseCells(i, "D") = "不及格"End IfNext iEnd Sub
Select Case 结构
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 IntegerFor i = 2 To 10Select Case Cells(i, "B").ValueCase Is >= 85Cells(i, "D") = "优"Case Is >= 75Cells(i, "D") = "良"Case Is >= 60Cells(i, "D") = "及格"Case ElseCells(i, "D") = "不及格"End SelectNext iEnd Sub
VBA 程序循环结构(重复执行一段代码)
VBA 中循环结构有 3 种类型,它们是:
- For 循环
- Do While 循环
- Do Until 循环
For 循环
For 循环是最常用的循环类型,它有两种形式:
- For … Next 循环
- For Each 循环
For … Next 循环
使用 For … Next 循环可以按指定次数,循环执行一段代码。For 循环使用一个数字变量,从初始值开始,每循环一次,变量值增加或减小,直到变量的值等于指定的结束值时,循环结束。
For … Next 循环语法如下:
For [变量] = [初始值] To [结束值] Step [步长]'这里是循环执行的语句
Next
其中:
[变量] 是一个数字类型变量,可在循环执行的语句里使用。
[初始值] 和 [结束值] 是给定的值;
[步长]是每次循环时,变量的增量。如果为正值,变量增大;如果为负值,变量减小。
下面看一个实际的例子,求 1 至 10 数字的累积和。
Sub MyCode()Dim i As IntegerDim sum As IntegerFor i = 1 To 10 Step 1sum = sum + iNextEnd Sub
可以看到,For 循环使用 i 变量,循环 10 次,i 的值从 1 到 10 变化。
值得注意的是,For 循环的 Step 值如果是 1,则 Step 关键词可省略。上述过程循环部分可写成如下方式:
For i = 1 To 10sum = sum + i
Next
For Each 循环
For Each 循环用于逐一遍历一个数据集合中的所有元素。数据集合包括数组、Excel 对象集合、字典等。
For Each 循环不需要一个数字变量,但是需要与数据集合中的元素相同的数据类型变量。其基本语法如下:
For Each [元素] In [元素集合]'循环执行的代码
Next [元素]
其中:
[元素] 是与集合中的元素相同类型的变量,该变量可在循环代码中使用。
[元素集合]是包括多个元素的集合。
下面看一个实际例子,循环打印出工作簿中所有工作表的名称。
Sub MyCode()Dim sh As WorksheetFor Each sh In WorksheetsDebug.Print sh.NameNext shEnd Sub
sh 变量就是元素变量,Worksheets 是工作簿中所有工作表的集合。
Exit For 语句
Exit For 语句用于跳出循环过程,一般在提前结束循环时使用,均适用于 For Next 循环和 For Each 循环。
看一个实际的例子,求 1 – 10 数字的和时,当和大于 30 就停止循环。
Sub MyCode()Dim i As IntegerDim sum As IntegerFor i = 1 To 10sum = sum + iIf sum > 30 ThenExit ForEnd IfNextEnd Sub
在这段代码中,sum 变量大于 30 时,循环就停止。
Do While 循环
Do While 循环用于满足指定条件时循环执行一段代码的情形。循环的指定条件在 While 关键词后书写。
Do While 循环也有两种形式:
- Do While … Loop 循环
- Do … Loop While 循环
Do While … Loop 循环
Do While … Loop 循环,根据 While 关键词后的条件表达式的值,真时执行,假时停止执行。基本语法如下:
Do While [条件表达式]'循环执行的代码
Loop
其中,只要 [条件表达式] 为真,将一直循环执行。[条件表达式] 一旦为假,则停止循环,程序执行 Loop 关键词后的代码。
看一个实际的例子,还是求 1- 10 累积和。
Sub MyCode()Dim i As IntegerDim sum As Integeri = 1Do While i <= 10sum = sum + ii = i + 1LoopEnd 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 Until 循环与 Do While 循环类似。不同点在于,Do While 在条件表达式为真时,继续执行循环;而 Do Until 在条件表达式为真时,停止执行循环。
Do Until 循环也有两种形式:
- Do Until … Loop 循环
- Do … Loop Until 循环
Do Until … Loop 循环
循环开始前判断 Until 后条件表达式的值,如果是真,停止循环;如果是假,继续执行循环。基本语法如下:
Do Until [条件表达式]'循环执行的代码
Loop
Do … Loop Until 循环
先运行一次,再判断 Until 后条件表达式的值,如果是真,停止循环;如果是假,继续执行循环。基本语法如下:
Do'循环执行的代码
Loop Until [条件表达式]
其他使用方法与 Do While 循环一致。
VBA With 结构(简化程序书写)
With 语法
With 结构由 With 和 End With 两个语句构成,对象的属性和方法都写在两者之间。基本语法如下:
With [对象].[属性] = [数据].[方法]'其他属性和方法
End With
With 结构里,对象的属性和方法均由点 (.)符号开始,后接对象的属性名和方法名。
With 结构实例
现在看一个实际的例子,需要将工作簿中 Sheet1 工作表设置新名称,然后设置标签颜色为黑色,最后隐藏工作表。
如果不用 With 结构,代码如下:
Sub MyCode()Worksheets("Sheet1").Name = "新名称"Worksheets("新名称").Tab.ThemeColor = xlThemeColorLight1Worksheets("新名称").Visible = xlSheetHiddenEnd Sub
可以看到,每个语句都重复写 Worksheets(“工作表名称”) 部分。
使用 With 结构,可以避免重复写同一个对象名,代码如下:
Sub MyCode()With Worksheets("Sheet1").Name = "新名称".Tab.ThemeColor = xlThemeColorLight1.Visible = xlSheetHiddenEnd WithEnd Sub
嵌套 With 结构
With 结构还能嵌套编写,即一个 With 结构中,如果父对象的属性是另一个对象,则针对这个子对象,继续使用 With 结构。
在之前的例子中,如果需要将 Sheet1 工作表中,A1:A10 单元格区域设置背景颜色,调整字体和字体大小,可以使用如下代码:
Sub MyCode()With Worksheets("新名称").Name = "new".Tab.ThemeColor = xlThemeColorLight1With .Range("A1:A5").Interior.ThemeColor = xlThemeColorAccent1.Font.Size = 11.Font.Name = "等线"End WithEnd WithEnd Sub
VBA GoTo 结构(程序之间跳转执行)
语法
GoTo 结构由 GoTo 语句和标签语句组成。基本语法如下:
GoTo [标签]
'被跳过的代码
...
[标签]:
'被执行的代码
跳转的位置由 Goto 关键词后的 [标签] 告诉程序,VBA 会在代码中查找对应的 [标签]: 关键词,从标签下一行继续执行程序。
需要注意的是,跳转处的标签,后接冒号 ( : ) 。
实例
下面的例子说明 GoTo 结构的基本用法。使用 VBA 作除法,如果除数是零,则跳转到程序末尾,提示除数不符合规范。
Sub MyCode()Dim num1 As DoubleDim num2 As DoubleDim result As Doublenum1 = 100num2 = 0If num2 = 0 Then GoTo errorresult = num1 / num2Exit Suberror:MsgBox "除数不能为零"End Sub
可以看到,例子中 num2 是除数,程序判断 num2 是否为零,如果是,则跳转到 Error 标签处,除法部分不会被执行。
Goto 结构相对简单,实际开发中不像三大结构使用频繁,但是在一些情形中使用,可以使代码更简洁易读。GoTo 语句常用于错误处理外,还可以用在「上一步/下一步」类情形中,根据用户需求,重复执行同一个步骤,这方面内容在以后做更多介绍。
参考链接: 懒人Excel