Office VBA从新手到高手
上QQ阅读APP看书,第一时间看更新

第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个要排序的整数输入完毕,单击【确定】按钮,在【立即窗口】中显示出下图所示的结果。