第3章 VBA基本语法
本章视频教学录像:38分钟
高手指引
前面章节对VBA的历史、发展及VBA的集成开发环境分别进行了介绍,使读者熟悉了VBA的集成开发环境的结构和使用方法。从本章开始,我们循序渐进,逐步开始接触VBA的基本语法,其中涉及VBA的数据类型、变量及常量、数运算符、基本语句结构、函数,以及过程的使用。这些内容是VBA编程的基础,如果有过其他语言基础的同学,会发现这部分内容很熟悉,VBA的这些语法知识和其他语言的语法知识类似,下面分别给予介绍。
重点导读
VBA的数据类型
VBA的变量及常量
VBA的数组
VBA运算符与基本语句
VBA函数
VBA过程
VBA数据排序
3.1 VBA的数据类型
本节视频教学录像:5分钟
数据是程序处理的基本对象,在介绍语法之前,有必要先了解数据的相关知识。VBA提供了系统定义的多种数据类型,并允许用户根据需要定义自己的数据类型。
3.1.1 为什么要区分数据类型
在高级程序设计语言中,广泛使用“数据类型”,通过使用数据类型可以体现数据结构的特点和数据用途。请看下面这个Excel表。
在这个Excel表格中,有5列基本数据:学号、姓名、出生日期、籍贯、入学成绩。每一列的数据都是同一类的数据,例如“入学成绩”都是数值型的数据,“出生日期”都是日期型的数据,将同一类数据统称为数据类型,类似容器一样,里面可以装入同一类型的数据。这样便于程序中对数据的统一管理。
不同的数据类型所表示的数据范围不同,因此定义数据类型的时候,如果定义错误会导致程序的错误。
3.1.2 VBA的数据类型
在VBA中有很多数据类型,不同的数据类型有不同的存储空间,对应的数值范围也不同。有些数据类型常用,有的并不常用,读者在使用过程中会慢慢体会到。下面分类介绍。
1. 数值型数据
⑴ 整型数据(Integer):就是通常所说的整数,在机器内存储为两字节(16位),其表示的数据范围为-32678~32767,整型数据除了表示一般的整数外,还可以表示数组变量的下标。整型数据的运算速度较快,而且比其他数据类型占用的内存少。
⑵ 长整型数据(Long):通常用于定义大型数据时采用的数据类型,在机器内存储为4字节(32位),其表示的数据范围为-2147483648~+2147483647。
⑶ 单精度型浮点数据(Single):主要用于定义单精度浮点值,在机器内存储为4字节(32位),通常以指数形式(科学计数法)来表示,以“E”和“e”表示指数部分,其表示的数据范围对正数和负数不同,负数范围为-3.402823E38~-1.401298E-45,正数范围为1.401298E-45~3.402823E38。
⑷ 双精度型浮点数据(Double):主要用于定义双精度浮点值,在机器内存储为8字节(64位),其表示的数据范围对正数和负数不同,负数范围为-1.797693134862E368~-4.94065645841247E-324,正数范围为4.94065645841247E-324~1.79769313486232E308。
⑸ 字节型数据(Byte):主要用于存放较少的整数值,在机器内存储为1字节(8位),其数据范围为0~255之间的数值。
2. 字符串型数据
字符串是一个字符序列,字符串型数据在VBA中使用非常广泛,在VBA中,字符串包括在双引号内,主要有以下两种。
固定长度的字符串:是指字符串的长度是固定的。该固定长度可以存储1~64000(216)个字符。对于不满足固定长度设定的字符串,使用“差补长截”的方法。例如,定义一个长度为3的字符串,输入一个字符“a”,则结果为“a”,其后面补2个空格,若干输入“student”,则结果为“stu”。
可变长度的字符串:是指字符串的长度是不确定的。最多可以存储2亿个(231)字符。
提示
包含字符串的双引号是半角状态下输入的双引号“”,不是全角状态下的双引号“”,这一点在使用的时候一定要注意,初学者会出现这种定义错误。
长度为零的字符串(即双括号内不包含任何字符)称为空字符串。
3. 其他数据类型
日期型(Date):主要用于存储日期。在机器内存储为8字节(64位)浮点数值形式,所表示的日期范围为100年1月1日~9999年12月31日之间的数值。而时间从00:00:00到23:59:59。
可以辨认的文本日期都可以赋值给日期型的变量,日期文字必须用数字符号“#”括起来,例如:
#10/01/2008#,#May 1,2009#
货币性(Currency):主要用于货币表示和计算。在机器内存储为8字节(64位)的整数数值形式。
布尔型(Boolean):主要用于存储返回结果的Boolean值,其值主要有两种形式,即真(TRUE)和假(FALSE)。
变量型(Variant):是一种可变的数据类型,可以表示任何值,包括数据、字符串、日期、货币等。
4. 枚举类型
枚举是指将一个变量的所有值逐一列举出来,当一个变量具有几种可能值的时候,可以定义枚举类型。
例如可以定义一个枚举类型星期来表示星期几。
Public Enum WorkDays 星期一 星期二 星期三 星期四 星期五 星期六 星期日 End Enum
其中WorkDays就是所定义的枚举型变量(变量在下一节介绍),其取值可以从星期一到星期日中选取。
5. 用户自定义数据类型
在VBA中,还可以根据用户自身的实际需要,使用Type语句定于用户自己的数据类型。其格式为:
Type数据类型名 数据类型元素名As数据类型 数据类型元素名As数据类型 … … End Type
其中,“数据类型”是前面所介绍的基本数据类型,“数据类型元素名”就是要定义的数据类型的名字,例如:
Type Student SNum As String SName As String SBirthDate As Date SSex As Integer End Type
其中“Student”为用户自定义的数据类型,其中含有“SNum”、“SName”、“SBirthDate”、“SSex”4种数据类型。
3.1.3 数据类型的声明与转换
要将一个变量声明为某种数据类型,其基本格式为:
Dim变量名as数据类型
例如:
Dim X1 as Integer
定义一个整型数据变量X1;
Dim X2 as Boolean
定义一个布尔型数据变量X2。
3.2 VBA的变量及常量
本节视频教学录像:4分钟
常量是指在程序执行过程中其值不发生改变;而变量的值则是可以改变的,它主要表示内存中的某一个存储单元的值。
3.2.1 常量的定义与使用
在程序执行过程中其值不发生变化的量称为常量(或者常数),VBA中常量的类型有3种,分别是直接常量、符号常量和系统常量。
1. 直接常量
是指在程序代码中可以直接使用的量,例如:
Height=10+input1
其中数值10就是直接常量。
直接常量也有数据类型的不同,其数据类型由数值本身所表示的数据形式决定。在程序中经常出现的常量有数值常量、字符串常量、日期/时间常量和布尔常量。
数值常量:由数字、小数点和正负符号所构成的量。例如:
3.14;100;-50.2
都是数值常量。
字符串常量:由数字、英文字母、特殊符号和汉字等可见字符组成。在书写时必须使用双引号作为定界符。例如:
"Hello,你好"
特别注意,如果字符串常量中本身包含双引号,此时需要在有引号的位置输入两次双引号。例如:
"他说:""放学后留下来。"""
中间两个双引号是因为内容中有引号,最后出现3个双引号,其中前两个双引号是字符串中有引号,最后一个双引号是整个字符串的定界符。
日期/时间常量:用来表示某一体或者某一个具体时间,使用“#”作为定界符。例如:
#10/01/2000#
表示2010年10月1日。
布尔常量:也称为逻辑常量,只有两个值:True(真)、False(假)。
2. 符号常量
如果在程序中需要经常使用某一个常量,可为该常量命名,在需要使用这个常量的地方引用该常量名即可。使用符号常量有如下优点。
⑴ 提高程序的可读性。
⑵ 减少出错率。
⑶ 易于修改程序。
符号常量在程序运行前必须有确定的值,其定义的语法格式如下:
Const <符号常量名>=<符号常量表达式>
其中Const是定义符号常数的关键字,符号常数表达式计算出的值保存在常量名中。
例如:
Const PI=3.14 Const Name="精通VBA "
提示
在程序运行时,不能对符号常量进行赋值或者修改。
3. 系统常量
也称内置常量,就是VBA系统内部提供的一系列各种不同用途的符号常量,为了方便使用和记忆这些系统常量,通常采用两个字符开头指明应用程序名的定义方式,在VBA中的常量,开头两个字母通常以vb开头,例如“vbBlack”。可通过在VBA的对象浏览器中显示来查询某个系统常量的具体名称及其确定值。
单击【开发工具】选项卡中的【Visual Basic】按钮,打开VBA编辑环境,然后选择菜单【视图】➣【对象浏览器】命令(或者按快捷键【F2】),如下图所示。
此时弹出下图,在箭头所指处输入要查询的系统常量,即可查询。
3.2.2 变量的定义与使用
变量用于保存程序运行过程中的临时值,对应变量,可以在声明时进行初始化,也可以在后面使用中再初始化。每个变量都包含名称与数据类型两部分,通过名称引用变量。变量的声明一般有两种:显示声明和隐式声明。下面分别介绍。
1. 显示声明变量
是指在过程开始之前进行变量声明,也称为强制声明。此时VBA为该变量分配内存空间。其基本语法格式为:
Dim变量名 [As数据类型]
其中:Dim和As为声明变量的关键字;数据类型是上一节介绍的对应类型,例如:String、Integer等;中括号表示可以省略。
例如:
Dim SName AS String; Dim SAge As Integer;
表示分别定义两个变量,其中变量SName为String类型,变量Sage为Integer类型。当然,上述声明变量也可以放到同一行语句中完成,即:
Dim SName AS String, SAge As Integer;
提示
变量名必须以字母(或者汉字)开头,不能包含空格、感叹号、句号、@、#、&、$,最长不能超过255个字符。
2. 隐式声明变量
是指不在过程开始之前显示声明变量,在首次使用变量时,系统自动声明的变量,并指定该变量为Variant数据类型。前面已经提到,Variant数据类型比其他数据类型占用更多的内存空间,当隐形变量过多时,会影响系统性能。因此在编写VBA程序时,最好避免声明变量为Variant数据类型,也就是说强制对所有变量进行声明。
3. 强制声明变量
有两种方法可以确保编程的时候强制声明变量。
方法一:在进入VBE编程环境后,选择菜单【工具】➣【选项】命令,如下图所示。
此时弹出【选项】对话框,如下图所示。
在【编辑器】选项卡里勾选“要求变量声明”复选项,即可实现在程序中强制变量声明。
方法二:在模块的第一行手动输入“Option Explicit”。
具体实现过程是首先打开VBE编程环境,选择菜单【插入】➣【模块】命令,如下图所示。
在弹出的“模块”代码框中的第一行输入代码“Option Explicit”。
这样即可实现强制变量声明,如果程序中某个变量没有声明,编译过程中会提示错误。
4. 变量的作用域
和其他程序设计语言类似,VBA也可以定义3种公共变量:公共变量、私有变量和静态变量。它们的定义格式如下。
公共变量:
Public变量名As数据类型
私有变量:
Private变量名As数据类型
静态变量:
Static变量名As数据类型
前面介绍的变量声明方法是使用Dim关键字,这里这3种定义公共变量的语句,所声明的变量只是作用域不同,其余完全相同。所谓变量的作用域是指变量在哪个模块或者过程中使用,VBA中的变量有3种不同级别的作用域,如下所述。
本地变量:在一个过程中使用Dim或Static关键字声明的变量,作用域为本过程,即只有声明变量的语句所在的过程可以使用它。
模块级变量:在模块的第一个过程之前使用Dim或Private关键字声明的变量,作用域为声明变量的语句所在模块中的所有过程,即该模块中所有过程都可以使用。
公共变量:在一个模块的第一个过程之前使用Public关键字定义的变量,作用域为所有模块,即所有的模块里的过程都可以使用它。
5. 变量的赋值
把数据存储到变量中,称为变量的赋值,其基本语法格式为:
[Let] 变量名称=数据
其中关键字Let可以省略,其含义是把等号右面的数据存储到等号左边的变量里。例如:
Sub test() Dim x1 As String, x2 As Integer X1="Hello! VBA" X2=100; End sub
上面的程序中先定义两个变量X1和X2,其中X1为String类型,X2为Integer类型,然后分别为两个变量赋值。
3.3 VBA的数组
本节视频教学录像:3分钟
上一节介绍的变量在使用中有一定的局限性,即每个变量一次只能存储一个值,若要变量存储n个值,就必须事先声明n个变量,然后再对每个变量赋值,这样会花费很多时间,数组可以解决这类问题。
3.3.1 数组的概念
数组是按顺序存储的一组索引数据值,这些值存储在连续的内存中。其具有如下特点。
⑴ 数组共享同一个名字,即数组名。
⑵ 数组中的元素按照顺序存储在数组中,通过索引号进行访问和区分。
⑶ 数组由具有同种数据类型的元素构成。
⑷ 数组本身也是变量。
3.3.2 数组的定义与使用
和变量一样,为了优化系统运行,避免内存的浪费,数组一般也要先定义再使用。
1. 数组的定义
数组的定义也是使用Dim关键字进行声明,其基本语法格式如下。
Dim数组名(a to b)As数据类型
声明时数组名后跟一对括号,括号中指定数组大小,可以为一个数字,也可以为空。当为一个数值的时候,指明数组的长度;如果是“a to b”情形,表明a和b分别是数组的起始和终止索引号;如果为空,则为动态数组。例如:
Dim MyArray1(20) As String Dim MyArray2(10 to 20) As String Dim MyArray3( ) As String
2. 数组的赋值
给数组赋值的时候,要分别给数组里的每个元素赋值,赋值的方法与给变量的赋值方法一样。例如:
MyArray1(1)="Hello!" MyArray1(2)="VBA" … … MyArray1(20)="Bye!"
3. 多维数组
上面定义的数组是一维数组,还可以定义多维数组,例如下面分别定义一个二维数组和三维数组。
Dim MyArray4(2,6) As String Dim MyArray5(2,6,3) As String
二维数组可以看做是由多个一维数组组成,三维数组可以看成由多个二维数组组成,有关数组的详细信息可以参见其他程序设计教材。
3.4 VBA的运算符
本节视频教学录像:2分钟
运算符是指定某种运算的操作符号,如“+”和“-”等都是常用的运算符,按照数据运算类型的不同,在VBA中常用的运算符主要有算术运算符、比较运算符、连接运算符和逻辑运算符。
3.4.1 算术运算符
算术运算符用于基本的算术运算,例如:5+2,3,14*7等都是常用的算术运算,常用的各种算术运算符如下表所示。
3.4.2 比较运算符
比较运算符用于比较运算,例如:2>1、10<3等,其返回值为Boolean型,只能为True或者False,常用的各种比较运算符如下表所示。
在比较运算的时候,一些通配符经常会用到,如下表所示。
3.4.3 连接运算符
连接运算符用于连接两个字符串,只有两种:“&”和“+”。
“&”运算符将两个其他类型的数据转化为字符串数据,不管这两个数据是什么类型。例如:
"abcefg"="abc"&"efg" "3abc"=3+"abc"
“+”连接两个数据时,当两个数据都是数值的时候,执行加法运算,如果两个数据是字符串的时候,执行连接运算。例如:
"123457"="123"+"457" 46=12+34
3.4.4 逻辑运算符
逻辑运算符用于判断逻辑运算式结果的真假,返回结果为Boolean型,只能为True或者False,常用的各种比较运算符如下表所示。
3.4.5 VBA表达式
表达式是由操作数和运算符组成,表达式中作为运算对象的数据称为操作数,操作数可以是常数、变量、函数或者另一个表达式,例如:
X2=X1^2*3.14 and 1>2
3.4.6 运算符的优先级
当不同运算符在同一个表达式中出现的时候,VBA按照运算符的优先级执行,其优先级如表所示。
例如:
100 >(24-14)and 12*2 <15 = 100 > 10 and 24<15 =true and false =false
3.5 VBA基本语句结构
本节视频教学录像:16分钟
语句是程序的基本组成部分,而控制语句是将各个语句按照一定的语句规则联系在一起,VBA中的基本控制语句包含顺序结构语句、选择结构语句和循环结构语句3种。
3.5.1 顺序结构语句
就是按照语句书写的顺序执行的语句,常见的有赋值语句、输入语句、输出语句、结束语句、暂停语句、Goto语句和注释语句。
1. 赋值语句
赋值语句是最基本的顺序结构语句,用来将一个表达式赋给一个变量。赋值语句的基本格式前面已经提到,基本格式为:
[Let] 变量名称=数据|变量|表达式
其中关键字Let可以省略,其含义是把等号右面的数据(变量、表达式)存储到等号左边的变量里。
提示
等号左边只能是变量,右边可以是常量、变量或者表达式。当是表达式的时候,先计算表达式的值,然后再将该值赋给变量。
如果同时给多个变量赋同一数值,不能写成连等的形式,此时需要多个赋值语句。
2. 输入语句
是用户向应用程序提供数据的主要途径,在VBA中一般使用InputBox函数,其基本语法格式为:
InputBox(prompt[, title] [, default] [, xpos] [, ypos] [, helpfile, context])
该函数的作用是弹出一个输入对话框,等待用户输入一条信息或者单击某个按钮,从而向系统返回用户输入的内容。其中各参数含义如下所述。
⑴ Prompt必需的。作为对话框消息出现的字符串表达式。Prompt的最大长度大约是1024个字符,由所用字符的宽度决定。如果Prompt包含多个行,则可在各行之间用回车符(Chr(13))、换行符 (Chr(10)) 或回车换行符的组合 (Chr(13) & Chr(10)) 来分隔。
⑵ Title可选的。显示对话框标题栏中的字符串表达式。如果省略Title,则把应用程序名放入标题栏中。
⑶Default可选的。显示文本框中的字符串表达式,在没有其他输入时作为默认值。如果省略Default,则文本框为空。
⑷ xpox和ypos是可选参数,用来设定输入对话框与屏幕边界的位置。
⑸ helpfile和context是可选参数,是提供帮助的参数。
3. 输出语句
在VBA中有两种经常使用的输出函数用来输出数据:Print函数和MsgBox函数。
Print函数是输出数据最常用的方法,基本格式为:
Print <表达式表>
例如:
Print 1,10*2
表明把数据1和10*2即20打印出来。默认是输出到当前窗体。
MsgBox函数
在对话框中显示消息,等待用户单击按钮,并返回一个Integer值,说明用户单击了哪一个按钮。其基本语法格式为:
MsgBox(prompt[, buttons] [, title] [, helpfile, context])
各参数含义如下所述。
⑴ Prompt必需的。作为显示在对话框中的消息。prompt的最大长度大约为1024字符,由所用字符的宽度决定。如果prompt的内容超过一行,则可以在每一行之间用回车符(Chr(13))、换行符 (Chr(10)) 或是回车与换行符的组合 (Chr(13) & Chr(10)) 将各行分隔开来。
⑵ Buttons可选的。指定显示按钮的数目及形式、使用的图标样式,默认按钮是什么,以及消息框的强制回应等。如果省略,则buttons的默认值为0,此时只有一个【确定】按钮。
⑶ Title可选的。在对话框标题栏中显示的字符串表达式。如果省略title,则将应用程序名放在标题栏中。
⑷ Helpfile可选的。字符串表达式,识别用来向对话框提供上下文相关帮助的帮助文件。如果提供了helpfile,则也必须提供context。
⑸ Context可选的。数值表达式,由帮助文件的作者指定给适当的帮助主题的帮助上下文编号。如果提供了context,则也必须提供helpfile。
其中buttons参数有下列设置值。
4. End结束语句
End语句强制终止程序代码的执行,其基本语法如下:
End
注意,该语句不能卸载已经打开的用户窗体,如果要使VBA程序完全正常结束,则应全部卸载打开的用户窗体。
5. Stop语句
是在程序中设置断点,使程序运行到断点处自动暂停,其基本语法如下:
Stop
与End语句不同的是,在解释方式下Stop语句不会关闭任何文件或者消除变量。该语句一般用于调试程序时检查程序运行中的某些动态信息。
6. Goto语句
使程序转到Goto语句后面制定的语句位置,Goto语句就类似于方向牌。其基本语法格式为:
Goto标号
7. 注释语句
在程序中如果想对某行代码注释加以说明,可以以“'”开始,后面跟注释内容。
3.5.2 条件结构语句
就是根据给定的逻辑表达式判断条件是否成立,然后根据结果选择执行的语句。
1. 简单If-then条件语句
“If...Then”分支结构在程序中计算条件值,并根据条件值决定下一步执行的操作。
最简单的“If...Then”分支结构可以只写在一行,其语法为:
If逻辑表达式Then语句
其中 “逻辑表达式”是个条件表达式,其结果为True或者False,“语句”是条件有效时执行的语句。例如:
If Score>=100 Then Text1="You Win!"
根据表达式Score>=20的值,程序决定是否把变量Text1的值赋值为“You Win!”。如果Score变量的值大于等于20,Test1值为 "You Win!",否则,Visual Basic跳过这条赋值语句,然后执行事件过程中的下一行语句。
简单If-then条件语句中,如果条件成立时需要执行多个操作,则可将多个语句写到Then后面,其语法格式为:
If逻辑表达式then 语句1 语句2 …… End if
例如:
IF score>=60 then pass=pass+1 Award=100 End if
当逻辑表达式score>=60的时候,把pass的值加1再赋值给pass,然后再把award的值赋为100。
2. If...Then...Else语句
在If-then语句中,当条件为False时,不执行任何语句,Visual Basic还支持另一种格式的“If...Then...else”分支结构,其基本语法格式为:
If逻辑表达式then 语句序列1 Else 语句序列2 End if
该“If...Then...else”当逻辑表达式为True的时候,执行语句序列1,当逻辑表达式结果为False的时候,执行语句序列2。
下面这个例子综合使用了InputBox函数和MsgBox函数,Goto语句,注释语句。
【实例3-1】 用InputBox函数弹出同一个输入框。
用户输入一定范围的数值,程序判断后用MsgBox函数弹出对话框,显示结果。
1 打开VBE编辑环境。
2 执行菜单【插入】 【模块】命令,如下图所示。
3 在模块中输入程序,如图所示。
4 单击执行按钮,弹出下图。
当输入数值不是10到25之间的数值的时候,例如输入3,然后单击“确定”按钮,显示下图。
如果输入10到25之间的数值,例如输入15,则显示下图。
如果同时有多个条件,可使用下面这种格式:
If逻辑表达式1 Then 语句序列1 ElseIf逻辑表达式2 Then 语句序列2 …… Else 逻辑序列n End If
上表是我国2011年9月1日起调整后,也就是2012年实行的7级超额累进个人所得税税率表。个人所得税的计算公司为:
应纳个人所得税税额= 应纳税所得额× 适用税率- 速算扣除数
其中扣除标准3500元/月(2011年9月1日起正式执行)(工资、薪金所得适用)。
例如每月工资5340元,则其应纳税所得额为:
5340-3500=1840
应纳个人所得税税额为:
1840×10%-105=79
这个税费计算就可以使用多行“If...Then”结构,下面的代码展示了如何使用多行“If...Then”结构来确定递进税计算问题。
【实例3-2】 个人所得税计算。
打开VBE编程环境,插入模块,输入下面代码:
Sub tax() Dim MyValue As Integer '定义MyValue为整型变量 MyValue = InputBox("请输入工资总额") '输入工资总额 Income = MyValue -3500 If Income <= 1500 Then '根据不同工资按照不同税率计算应纳所得税 '3%税段 TaxDue = Income * 0.05-0 ElseIf Income <= 4500 Then '10%税段 TaxDue = Income * 0.1-105 ElseIf Income <= 9000 Then '20%税段 TaxDue = Income * 0.2-555 ElseIf Income <= 35000 Then '25%税段 TaxDue = Income * 0.25-1005 ElseIf Income <= 55000 Then '30%税段 TaxDue = Income * 0.3-2755 ElseIf Income <= 80000 Then '35%税段 TaxDue = Income * 0.35-5505 Else '45%税段 TaxDue = Income * 0.45-13505 End If MsgBox "你应缴税是 " & TaxDue '输出所得税 End Sub
其中用输入对话框提示用户输入工资总额,然后多行“If...Then”结构根据不同税率计算应缴税,最后输出。
单击快捷键【F5】,运行程序,如下所示。
在文本框中输入工资总额,然后单击【确定】按钮。显示应缴税,如下图所示。
提示
总之可以添加更多的“ElseIf”块到“If...Then”结构中去。但是,当每个“ElseIf”都将相同的表达式比作不同的数值时,这个结构编写起来很乏味。在这种情况下,可以使用“Select Case”判定结构。
2. Select Case结构
Visual Basic还支持在程序中使用“Select Case”分支结构来控制语句的执行。“Select Case”结构与“If...Then...Else”结构相似,使用“Select Case”结构可以提高程序的可读性。“Select Case”结构的语法如下所示:
Select Case测试表达式 Case表达式1 语句序列1 Case表达式2 语句序列2 Case表达式3 语句序列3 …… End Select
“Select Case”结构以关键字“Select case”开始,以关键字“End Select”结束。“Select Case”结构中的测试表达式可以是变量、属性或者是表达式,“语句序列1”、“语句序列2”,“语句序列3”可以是数值、字符串或与要测试的其他情况相关的其他值,如果其中某个值与变量相匹配,那么该“Case”子句下的语句被执行,然后Visual Basic执行“End Select”语句后面的语句。“Select Case”结构中可以使用任意多个“Case”子句。
下面示例展示了程序中如何使用“Select Case”结构打印与某人考试成绩相关的信息。当Age变量与某个“Case”值匹配时,相应的信息显示在标签对象中。
【实例3-3】个人考试信息查询。
打开VBE编程环境,插入模块,输入下面代码:
Sub test() Dim Score As Integer '定义Score为整型变量 Score = InputBox("请输入你的考试成绩等级") '输入考试成绩等级 Select Case Score Case 1 MsgBox "你考试成绩“不及格”" Case 2 MsgBox "你考试成绩“及格”" Case 3 MsgBox "你考试成绩“中”" Case 4 MsgBox "你考试成绩“良”" Case 5 MsgBox "你考试成绩“优秀”" End Select End Sub
其中通过输入对话框要求使用者输入考试成绩等级,然后根据输入的等级调用“Select Case” 给出结果。
按快捷键【F5】,运行程序,如下所示,然后在文本框中输入考试成绩等级,例如输入5,单击“确定”按钮,如下图所示。
提示
“Select Case”结构比功能等效的“If...Then”结构更清晰易读。“Select Case”结构还支持“Case Else”子句,该子句可用于当不满足所有“Case”条件时显示信息。
下面是说明“Case Else”子句用法的一个示例。
Sub test() Dim Score As Integer '定义Score为整型变量 Score = InputBox("请输入你的考试成绩等级") '输入考试成绩等级 Select Case Score Case 1 MsgBox "你考试成绩“不及格”" Case 2 MsgBox "你考试成绩“及格”" Case 3 MsgBox "你考试成绩“中”" Case 4 MsgBox "你考试成绩“良”" Case 5 MsgBox "你考试成绩“优秀”" Case Else MsgBox "你可能没有参加考试" End Select End Sub
提示
“Select Case”结构每次都要在开始处计算表达式的值,而“If...Then...Else”结构为每个“ElseIf”语句计算不同的表达式,只有在“If”语句和每个“ElseIf”语句计算相同的表达式时,才能使用“Select Case”结构替换“If...Then...Else”结构。
3.5.3 循环结构语句
在实际程序中,有时需要反复操作某一个或者几个语句,这时就需要循环结构语句。VBA的循环结构语句主要有While...Wend语句、Do...Loop语句、For...Next语句和For Each...Next语句。
1. While...Wend语句
基本语法格式为:
While逻辑表达式 循环体 Wend
其中逻辑表达式可以是数值表达式或字符串表达式,其计算结果为True或False。循环体包含一条或多条语句,当条件为True时执行。
【实例3-4】使用While...Wend语句实现1+2+3+...+100的求和。
打开VBE编程环境,插入模块,输入下面代码。
Sub test() Dim a1 As Integer'用于暂存数列各项 Dim sum As Long'用于存放最终结果 Dim counter As Integer '循环计数器 a1 = 1 sum = 0 counter = 1 While counter <= 100 sum = sum + a1 a1 = a1 + 1 counter = counter + 1 '计数器加1 Wend MsgBox "1+2+3+...+100=" & sum, vbOKOnly, "使用while...end循环求数列的和" End Sub
按快捷键【F5】,运行程序,如下所示。
2. Do...Loop语句
Do...Loop语句是条件控制性循环语句,这种循环控制语句有两种形式,第一种基本语法格式为:
Do [{While | Until}逻辑表达式] 循环体 Loop
第二种基本语法格式为:
Do 循环体 Loop [{While | Until}逻辑表达式]
逻辑表达式可以是数值表达式或字符串表达式,其计算结果为True或False。循环体包含一条或多条语句,当条件为True时执行。两种形式的区别是:第一种首先判断循环的条件,如果条件不成立,则不会执行循环体中的语句;第二种会首先执行循环体中的语句,然后再判断循环的条件是否成立,如果不成立,则不再执行循环体中的语句。
【实例3-5】 使用Do…Loop语句实现1+2+3+...+100的求和。
1 打开VBE编程环境,Step2:插入模块,输入下面的代码。
Sub text() Dim a1 As Integer'用于暂存数列各项 Dim sum As Long'用于存放最终结果 Dim counter As Integer '循环计数器 a1 = 1 sum = 0 counter = 1 ' Do While counter <= 100 ' sum = sum + a1 ' a1 = a1 + 1 ' counter = counter + 1 '计数器加1 ' Loop MsgBox "1+2+3+...+100=" & sum, vbOKOnly, "使用do while...loop循环求 数列的和" End Sub
代码和上面的除了循环程序不同外,其他都一样。
2 按快捷键【F5】,运行程序,程序运行结果如下图所示。
如果使用Do…Loop的另外一种形式,只需要如下更改循环程序即可。
'Do ' sum = sum + a1 ' a1 = a1 + 1 ' counter = counter + 1 '计数器加1 'Loop While counter <= 100
3. For...Next语句。
与前面循环格式不同,For...Next语句使用一个叫作计数器的变量,以指定次数来重复执行循环体。其基本语法格式为:
For循环变量=初始值To终值 [Step 步长] 语句序列 Next [循环变量]
其中循环变量是用作循环计数器的数值变量,不能是Boolean或数组元素;初始值和终值指定循环的开始和结束数值,步长为每次循环变量增加的数量。如果没有指定,则step的默认值为1。语句序列是放在For和Next之间的一条或多条语句,它们将被执行指定的次数。
在实现不知道循环体要执行多少次时,应该用Do循环,而在知道循环体要执行的次数时,最好使用For...Next循环。
【实例3-6】使用for…next语句实现1+2+3+...+100的求和。
1 打开VBE编程环境,插入模块,输入下面代码。
Sub text() Dim a1 As Integer '用于暂存数列各项 Dim sum As Long '用于存放最终的结果 Dim counter As Integer '循环计数器 a1 = 1 sum = 0 counter = 1 ' For a1 = 1 To 100 sum = sum + a1 Next MsgBox "1+2+3+...+100=" & sum, vbOKOnly, "使用while...end循环求数列 的和" End Sub
2 按快捷键【F5】,运行程序,运行结果如下。
4. For Each...Next语句
For Each...Next语句是针对集合或者数组中的元素,重复执行循环体中的语句序列。其基本语法格式为:
For Each element In group 语句序列 Next [element]
其中element为必要参数。用来遍历集合或数组中所有元素的变量。对于集合来说,element可能是一个Variant变量、一个通用对象变量或任何特殊对象变量。对于数组而言,element只能是一个Variant变量;group为必要参数,代表对象集合或数组的名称(用户定义类型的数组除外)。
5. 循环的嵌套
即把一个循环放置到另外一个循环体中,例如for-next循环的嵌套格式为:
For循环变量1=初始值1 To终值1 [Step步长1] 语句序列1 For循环变量2=初始值2 To终值2 [Step步长2] 语句序列2 Next [循环变量2] Next [循环变量1]
上述4种循环都可以相互嵌套,但要注意嵌套中各个循环体要一一对应,并且嵌套不能交叉。例如:
【实例3-7】计算1!+2!+…+20!的和。
这需要两层循环,外层控制变量从1到20,内层循环分别计算每个阶乘的值。
步骤如下所述。
1 打开VBE编程环境,插入模块,输入下面的代码。
Sub test() Dim i As Integer '用于暂存循环变量 Dim sum As Double '用于存放最终的结果 Dim jiecheng As Double '用于暂存每个阶乘的值 Dim j As Integer 用于暂存循环变量 sum = 0 For i = 1 To 20 '外层循环 jiecheng = 1 For j= 1 To i '内层循环 jiecheng =jiecheng *j Next sum = sum +jiecheng Next MsgBox "1!+2!+3!+...+20!=" & sum, vbOKOnly, "阶乘的和" End Sub
2 按快捷键【F5】,运行程序,如右图所示。
3.6 VBA函数
本节视频教学录像:8分钟
我们在日常工作中,经常使用各种函数,例如求和、求最大值等。在VBA中也可以定义各种各样的函数,每个函数完成某种特定的计算。在VBA中函数是一种特殊的过程,使用关键字Function定义。VBA中有许多内置的函数,例如前面介绍的InputBox函数和MsgBox函数。本节重点介绍Function函数的定义和使用。
3.6.1 VBA函数的定义
函数具有返回值,即Function函数在处理完所有操作之后,被调用的函数有一个返回值。在VBA中,创建函数有两种方法:手工输入和使用对话框输入。
1. 手工输入
手工输入Function函数的语法格式为:
[public|private|friend [static] Function函数名[(参数列表)] [As返回类型] 语句序列 函数名=表达式1 End Function
其中,function是定义函数的关键字,根据是否有参数传入选择参数列表,同时“as返回类型”定义返回的数值类型,在函数体内部一般要有一个为函数名赋值的语句,否则函数返回默认值:数值函数返回0,字符串函数返回空字符串。其中的public、private、static和前面变量定义时作用一样,这里不再重述。
2. 自动输入
手动输入使用不太方便,有时会书写错误,自动输入通过对话框的方式,方便快捷,下面介绍自动输入的方法。
Function函数保存在模块中,因此首先要插入一个模块,方法前面已经多次提到。这里不再重述。插入模块后,按照下面的方法完成。
1 按菜单【插入】【过程】命令,如下图所示。
2 在弹出的【添加过程】对话框中,在【名称】后面的文本框中输入函数名,我们以前面手动输入函数为例,输入“bignumber”,然后在【类型】中选择【函数】,在【范围】中选择【共有的】,然后单击【确定】按钮。
3 此时弹出添加代码的对话框,如下图所示。
4 在代码中输入对应代码即可,例如上面的求最大数的代码输入后,如下图所示。
3.6.2 VBA函数的使用
有两种方法可以调用自己所定义的函数:一种是在工作表中使用;另外一种是在VBA代码中调用。在工作表中调用自定义函数和调用系统内置函数一样。打开Excel,在两个单元格中分别输入两个数字,如下图所示,单击选择一个单元格,我们使用前面自定义的函数求出两个函数中最大的数字,并把最大的数值放到这个单元格中。
1 执行【公式】 【插入函数】命令,如下图所示。
2 弹出【插入函数】对话框,如下图所示。
3 单击【或选择类别】下拉列表框,从中选择【用户定义】选项,然后在【选择函数】栏中选择自己所定义的函数,最后单击【确定】按钮。即可以使用自定义函数。在代码中调用自定义函数。
在VBA开发环境中,不能按【F5】键运行Function函数,要运行函数,必须从另一个过程中调用。自定义的函数同调用系统的内部函数一样,例如下列调用前面定义的求两个数字中最大的数。
Sub test1() Dim x1 as float Dim x2 as float Dim result as float X1=2 X2=3 Result=bignumber(x1,x2) End sub
调用过程中输入函数的名称,后面跟上参数。例如上面这段程序中语句“Result=bignumber(x1,x2)”就是调用函数,并把结果赋值给变量result。
3.6.3 VBA函数的应用实例
上面介绍了VBA中自定义函数的定义和使用方法,下面通过两个具体的实例,帮助读者进一步熟悉Function的功能。
1. 阶乘函数
阶乘公式在数据分析中经常使用到,其数学计算公式为n!=n*(n-1)*(n-2)…*2*1,当n=0时,阶乘值为1。下面应用实例将阶乘实现过程编程为自定义函数,在主过程中调用。
【实例3-8】编程为自定义函数计算阶乘。
1 打开VBE编辑器。
2 在代码窗口中输入主过程程序。
Sub test() Dim result As Long Dim i As Integer i = Val(InputBox("请输入您需要计算 的阶乘数")) '输入需要计算的阶乘数 result =jiecheng(i) '调用阶乘函数 MsgBox i & "的阶乘为:" & result '显示结果 End Sub
其中通过输入函数输入需要计算阶乘的数值,然后调用阶乘函数result =jiecheng(i),并把值赋值给result,再使用输出函数显示结果。
3 创建阶乘函数,代码如下。
Function jiecheng(i As Integer) If i = 0 Then '如果i=0,则阶乘为1 jiecheng = 1 ElseIf i = 1 Then '如果i=1,则阶乘 为1 jiecheng = 1 Else jiecheng =jiecheng(i -1) * i '递归 调用阶乘函数 End If End Function
计算阶乘中,需要递归调用阶乘函数jiecheng = jiecheng(i -1) * i,实现阶乘的计算。
4 按快捷键【F5】,运行程序,如下图所示。
5 在对话框中输入需要计算的阶乘数,例如输入数值5,然后单击【确定】按钮,显示如下。
2. 彩票号码生成
彩票号码是随机生成的一组数字,具有很大的偶然性,本实例首先创建一个Function函数,在函数体内返回多个随机生成的数值,然后在Excel中调用该函数,下面为具体步骤。
【实例3-9】模拟彩票号码。
其基本步骤如下所述。
1 打开Excel 2010。
2 切换到VBE编程环境,在创建的模块中输入下面的函数代码。
Function lottery() Dim shuzi(1 To 6) As Integer '定 义数组,用于存放随机数 Dim i As Integer Randomize For i = 1 To 6 shuzi(i) = Int(Rnd() * 10) '随机生 成数值 Next i lottery = shuzi '将生成的随机数值 赋值给lottery End Function
在程序中,首先定义一个数组,用来存放生成的随机数值,然后使用随机函数生成每个数值,再赋值给函数。
3 切换到Excel界面,选中一行中的6个单元格区域,在编辑栏中输入公式“=lottery()”,如下图所示。
4 输入完函数名后,按【Ctrl+Shift+Enter】快捷组合键完成公式的输入,此时在所选中的单元格中出现随机生成的数值,如下图所示。
3.7 VBA的过程
本节视频教学录像:5分钟
在编写VBA代码过程中,使用过程可以将复杂的VBA程序以不同的功能划分为不同的单元。每一个单元可以完成一个功能,在一定程度上方便用户编写、阅读、调试,以及维护程序。VBA中每一个程序都包含过程,所有的代码都编写在过程中,并且过程不能进行嵌套。录制的宏是一个过程,一个自定义函数也是一个过程。过程主要分为3类:子过程、函数过程和属性过程。函数过程在上一节已经介绍,这一节重点介绍子过程。
3.7.1 过程的定义
Sub过程是VBA编程中使用最频繁的一种,它是一个无返回值的过程。在VBA中,添加Sub过程主要有两种,分别是通过对话框添加和通过编写VBA代码添加。
1. 通过编写VBA代码添加
在代码窗口中,根据Sub过程的语法结构也可以添加一个Sub过程,它既可以含参数,也可以无参数。Sub过程的具体语法格式如下。
[Private | Public | Friend] [Static] Sub 过程名 [(参数列表)] 语句序列 End Sub
其中各参数的功能如下表所示。
过程保存在模块里,所以编写过程中应先插入一个模块,然后在代码窗口输入过程即可。前面步骤和手工插入函数的方法一样。下面给出一个简单插入过程的例子,如图所示,在代码窗口中输入过程代码即可。
2. 通过对话框添加
和前面介绍的插入函数的方法相似,在代码窗口中定位文本插入点,选择【插入】【过程】命令,在打开的【添加过程】对话框的【名称】文本框中输入过程的名称,在【类型】栏中选中【子程序】单选项,在【范围】栏中设置过程的级别,单击【确定】按钮添加一个Sub过程,如图所示。
3.7.2 过程的执行
在VBA中,通过调用定义好的过程来执行程序,常见的调用过程的方法如下。
方法一:使用call语句调用sub过程。
用call语句可将程序执行控制权转移到sub进程,在过程中遇到End sub或Exit sub语句后,再将控制权返回到调用程序的下一行。Call语句的基本语法格式如下。
Call过程名(参数列表)
使用的时候,参数列表必须要加上括号,如果没有参数,此时括号可以省略。
方法二:直接使用过程名调用sub过程。
直接输入过程名及参数,此时参数用逗号隔开。注意:此时括号不需要。
3.7.3 过程的作用域
Sub过程与所有变量一样,也区分公有和私有,而在说法上稍有区别。过程分模块级过程和工程级过程。
1. 模块级过程
模块级过程即只能在当前模块调用的过程,它的特征如下所述。
⑴ 声明Sub过程前使用Private。
⑵ 只有当前过程可以调用,例如在“模块1”中有以下代码。
Private Sub过程一() MsgBox 123 End Sub Private Sub过程二() Call过程一 End Sub
执行过程二时可以调用过程一,但如果过程二存放于“模块2”中,则将弹出“子过程未定义”的错误提示。
提示
所有事件的代码都是过程级的,默认状态下只能在当前过程调用。
2. 工程级过程
工程级过程是指在当前工程中的任意地方都可以随意调用的过程。它的特征刚好与模块级过程相反:在“Sub”语句前置标识符“Public”,非当前过程也可以调用,可以出现在“宏”对话框中。
如果一个过程没有使用“Public”和“Private”标识,则默认为工程级过程,任何模块或者窗体中都可以调用。
3.7.4 过程的应用举例
下面通过两个具体实例进一步加深对过程的理解。
【实例3-10】通过一个调用“延时”过程,实现延时的效果。
1 在模块中输入“延时”过程代码。
Sub test2(delaytime As Integer) Dim newtime As Long '定义保存延时的变量 newtime = Timer + delaytime '计算延时后的时间 Do While Timer < newtime '如果没有达到规定的时间,空循环 Loop End Sub
其中使用系统函数Timer获得从午夜开始计算的秒数,把这个时间加上延时的秒数,即延时后的时间,然后通过一个空循环语句判断是不是超过这个时间,超过就退出程序。
2 输入调用过程代码。
Sub test1() Dim i As Integer i = Val(InputBox("开始测试延时程 序,请输入延时的秒数:", "延时测试 ", 1)) test2 i MsgBox "已延时" & i & "秒" End Sub
程序要求用户输入延时的秒数,然后通过“test2 i”来调用test2过程,实现延时效果。整个过程代码如图所示。
3 按快捷键【F5】运行过程,如下图所示。
4 在【延时测试】对话框中输入需要延迟的时间,然后单击【确定】按钮,弹出如下图所示的对话框。实现了延时效果。
3.8 综合实战—数据排序
本节视频教学录像:5分钟
这个综合实例介绍对输入的任意8个整数进行排序,程序不仅使用到了循环,而且使用了函数和过程的调用,中间也涉及变量的定义,通过这个实例可将本章所学知识加以融会贯通。
【实例3-11】数据排序。
1 打开VBE编程环境。
2 插入模块,输入下面的代码。
Public a(8) As Integer '定义全局数 组 Sub test() Dim i As Integer Dim j As Integer Dim min As Integer Dim temp As Integer For i = 1 To 8 a(i) = CInt(InputBox("请输入第" & i & "个整数", "选择排序")) '分别 输入要排序的数值到数组中 Next Debug.Print Debug.Print "你输入了如下8个整 数:" Call output '调用输出过程打印 要排序的数值 paixu '调用排序函数 Debug.Print Debug.Print "完成排序的8个整数: " Call output '调用输出过程打印已 经排序的数值 End Sub 然后再录入函数paixu和过程 output,代码如下: Function paixu() '排序函数 For i = 1 To 7 min = i For j= i + 1 To 8 If a(min) > a(j) Then min =j End If Next temp = a(i) a(i) = a(min) a(min) = temp Next End Function Sub output() '输出过程 For i = 1 To 8 Debug.Print a(i) & ","; Next End Sub
3 按快捷键【F5】运行过程,如下图所示。
然后在文本框中输入要排序的第一个整数,单击【确定】按钮,再输入要排序的第2个整数……直到8个要排序的整数输入完毕,单击【确定】按钮,在【立即窗口】中显示出下图所示的结果。