第8章 模块
●章前导读
通过本章,你可以学习到:
模块的概念及创建方法
◎VBA面向对象设计的基本概念、特点和优点
◎变量与常量的数据类型与定义方式
◎VBA程序流程控制语句
◎VBA程序的调试与错误处理的方法
本章学习流程图
8.1 模块的基本概念
模块是Access中的一个重要对象,它是以VBA声明、语句和过程作为一个独立单元的结合。每个模块独立保存并对应于其中的VBA代码。模块分为两大类:类模块和标准模块。本节主要简述模块的概念及创建模块的方法。
8.1.1 类模块
学习提示
【熟记】类模块的概念
【熟记】标准模块的概念
当用户新建一个类的实例的同时,也就创建了新的对象,在模块定义的任何过程都会变成这个对象的属性和方法。类模块又分为3种:窗体模块、报表模块和独立的类模块。
窗体模块是指与特定的窗体相关联的类模块。当用户向窗体对象中添加代码时,用户将在Access数据库中创建新类。用户为窗体所创建的事件处理过程是这个类的新方法。用户使用事件过程对窗体的行为以及用户操作进行响应。
报表模块是指与特定的报表相关联的类模块,包含响应报表、报表段、页眉和页脚所触发的事件代码,对报表模块的操作与对窗体模块的操作类似。
独立的类模块不依附于窗体和报表而独立存在,它可以为自定义对象创建模块。
8.1.2 标准模块
标准模块包含与任何其他对象都无关的通用过程,以及可以从数据库的任何位置运行的常规过程。
标准模块与类模块的主要区别在于其范围和生命周期方面。在与对象相关的类模块中,声明或存在的任何变量或常量的值都仅在该代码运行时可用,且仅在该对象中可用。
8.1.3 将宏转换为模块
在Access中,用户可以根据需要,将设计好的宏对象转换成模块代码形式。
【例8-1】 在“宏”对象中,将已建好的“学生基本信息”宏转换为模块。
在“宏”对象中单击“学生基本信息”宏。
执行菜单“工具”➝“宏”➝“将宏转换为Visual Basic代码”命令,打开“转换窗体宏”对话框。
单击“转换”按钮,即完成宏到模块的转换。
8.2 创建模块
8.2.1 在模块中加入过程
学习提示
【熟记】过程的概念及格式
进入窗体或报表的设计视图,单击工具栏中的“代码”按钮,即可进入类模块的设计和编辑窗口;单击数据库窗体中的“模块”对象标签,再单击“新建”按钮,即可进入标准模块的设计和编辑窗口。
模块的声明区域用于声明模块使用的变量等项目,每个模块都包含一个声明区域,其中包含一个或几个Sub子过程或Function函数过程。
1.Sub子过程
Sub子过程只执行一系列的操作,不返回任何值。
【格式】
2.Function函数过程
【格式】
请注意
Sub子过程可以用Call关键字调用,Function函数过程则不能用Call关键字调用执行。
8.2.2 在模块中执行宏
在模块中执行宏,可以使用DoCmd对象的RunMacro方法。
【格式】
【说明】
8.3 VBA程序设计基础
VBA是宏语言版本的 Microsoft Visual Basic,它在语言级别上等价于 Microsoft Visual Basic。
Visual Basic是微软公司推出的可视化Basic语言,简称VB,用它来编程非常简单。因为简单,而且功能强大,所以微软公司将它的一部分代码结合到Office中,形成今天的VBA。它的很多语法继承了VB,所以用户可以像编写VB语言那样来编写VBA程序,以实现某个功能。当这段程序编译通过以后,用户将其保存在Access的一个模块中,并通过类似在窗体中激发宏的操作那样来启动这个“模块”,从而实现相应的功能。
在运行机制上,VBA是以伪代码( P-Code )的形式运行的。它的功能主要通过模块来实现,是一种面向对象的编程方法。
8.3.1 面向对象的基本概念
学习提示
【熟记】面向对象的基本概念
1.对象和集合
一个对象就是一个实体,每个实体都有各自的属性,如一辆汽车是一个实体,汽车的颜色、品牌就是它的属性。不同实体的属性是不同的,汽车和自行车是两个不同的实体,它们具有的属性显然是不同的。
集合表示的是某类对象所包含的实例构成。
2.属性和方法
属性的引用方式为:
【格式】
方法的引用方式为:
【格式】
Access数据库提供了表、窗体、报表等7 种对象,还提供了一个DoCmd对象。其主要功能是通过调用内部方法来实现VBA对Access中的操作。调用格式如下:
【格式】
在Access中,有两种方式来处理窗体、报表或控件的事件响应,一种是使用宏对象来设置事件属性,另一种是事件过程,即为某个事件编写VBA代码过程。
主要对象事件如表8-1~表8-9所示。
表8-1 窗体的主要事件过程
表8-2 报表的主要事件过程
表8-3 命令按钮控件的主要事件过程
表8-4 标签控件的主要事件过程
表8-5 文本框控件的主要事件过程
表8-6 组合框控件的主要事件过程
表8-7 选项组控件的主要事件过程
表8-8 单选按钮的主要事件过程
表8-9 复选框控件的主要事件过程
【例8-2】 在新建窗体中添加一个命令按钮,并创建“单击”事件响应过程。
在“设计”视图中新建一个窗体,向窗体中添加一个命令按钮“单击事件”,如图8-1所示。
图8-1 “设计”视图
选择“单击事件”命令按钮,单击鼠标右键,在弹出的快捷菜单中选择“属性”命令,如图8-2所示,打开“属性”对话框。
图8-2 快捷菜单
在“属性”对话框中选择“事件”选项卡,设置“单击”属性为“(事件过程)”,如图8-3所示。
图8-3 “事件”选项卡
单击 按钮,进入新建窗体类模块代码编辑区,如图8-4所示。
图8-4 类模块代码编辑区
如图8-5所示,输入VBA程序代码。
图8-5 输入VBA程序代码
关闭类模块编辑区,切换到“窗体”视图,如图8-6所示。
图8-6 “窗体”视图
单击“单击事件”按钮,运行窗体结果如图8-7所示。
图8-7 运行窗体
8.3.2 Visual Basic编辑环境
VBE(Visual Basic Editor)是Access提供的编程界面,本节将介绍几种不同的进入和使用VBE的方式。
1.Visual Basic编辑环境
Visual Basic编辑器(VBE,Visual Basic Editor)是编辑VBA代码时使用的界面。VBE窗口主要由工具栏、工程窗口、属性窗口和代码窗口组成,各部分说明如表8-10所示。
表8-10 VBE 窗口
标准工具栏如图8-8所示,相应说明如表8-11所示。
图8-8 工具栏
表8-11 工具栏
2.进入VBE编程环境
Access模块分为类模块和标准模块,它们进入VBE编程环境的方式也是不同的。
【例8-3】 类模块进入VBE环境的方法。
单击窗体“属性”窗口的“事件”选项卡,如图8-9所示。
图8-9 “事件”选项卡
单击任一“事件过程”右侧的 按钮,进入“选择生成器”窗体,如图8-10所示。
图8-10 “选择生成器”窗体
选择“代码生成器”项,单击“确定”按钮,进入VBE编程环境,如图8-11所示。
图8-11 VBE编程环境
图8-12 菜单命令
请注意
使用<Alt+F11>组合键可以在数据库窗口和VBE之间切换。
3.VBE环境中编写VBA代码
VBA代码是由语句组成的,一条语句就是一行代码,例如:
intCount =3 '将3赋值给变量 intCount
Debug.Print intCount '在立即窗口打印变量 intCount的值3
VBA模块中不能存储单独的语句,一定要将语句组织起来形成过程,即VBA程序是块结构,主体是事件过程或自定义过程。
在VBE的代码窗口,将上面的两条语句写入一个自定义的子过程Proce1 ,代码如下:
Sub Proce 1 ()
Dim intCount As Integer
intCount=3
Debug.Print intCount
End Sub
将光标定位在子过程Proce1的代码中,按<F5>键,运行子过程代码,在立即窗口会看到程序运行结果:3。
编写事件过程的代码,只要双击工程窗口中任何类或对象,都可以在代码窗口中打开相应代码并进行编辑处理。操作时,在代码窗口左边组合框选定一个对象后,右边过程组合框中会列出该对象的所有事件过程,再从该对象事件过程列表选项中选择某个事件名称,系统会自动生成相应的事件过程模板,用户添加代码即可,如图8-13所示。
代码编辑区上部的通用声明段主要编写模块级以上的变量声明、对选项的设置等,控制结构等语句要写在过程块结构中,过程块的先后次序与程序执行的先后次序无关。
图8-13 自动显示提示信息
4.程序语句书写原则
(1)语句书写规定。
通常一个语句写一行。语句较长,一行写不下时,可使用续行符(_),将语句连续写在下一行。
可以使用冒号(:),将几个语句分隔写在一行中。
当输入一行语句并按下回车键后,若该行代码以红色显示(有时伴有错误信息出现),则表明该行语句有错误,应更正。
(2)注释语句。
一个好的程序一般都有注释,这对程序的维护有好处。
在VBA程序中,注释可以通过以下两种方式实现。
①使用Rem语句,格式为:Rem注释语句
②用单引号“'”,格式为:'注释语句
【例8-4】 定义变量并赋值。
Rem定义两个变量
Dim Strl,Str2
Strl="Beijing":Rem注释在语句之后要用冒号隔开
Str2 ="Shanghai" '这也是一条注释。这时无须使用冒号
注释可添加到程序模块的任何位置,并且默认以绿色文本显示。用户还可以利用“编辑”工具栏中的“设置注释块”按钮和“解除注释块”按钮,对大块代码进行注释或解除注释。
(3)采用缩进格式书写程序。
采取正确的缩进格式,以显示出流程中的结构。也可以利用“编辑”菜单下的“缩进”或“凸出”命令进行设置。
(4)F1帮助信息。
用户可以将键盘光标停留在某个语句命令上,按下<F1 >键,系统会立刻提供相关的帮助信息。
8.3.3 数据类型和数据库对象
1.标准数据类型
传统的BASIC语言使用类型说明标点符号来定义数据类型,除此之外, VBA还可以使用类型说明字符来定义数据类型,表8-12 所示为VBA类型标识、符号、字段类型及取值范围。在使用VB代码中的字节、整数、长整数、自动编号、单精度和双精度数等的常量和变量与Ac-cess的其他对象进行数据交换时,必须符合数据表、查询、窗体和报表中相应的字段属性。
表8-12 VBA 数据类型列表
2.用户定义的数据类型
应用过程中,可以建立包含一个或多个VBA标准数据类型的数据类型,这就是用户定义数据类型。它不仅包含VBA的标准数据类型,还可以包含前面已经说明的其他用户定义数据类型。
用户定义数据类型可以在Type...End Type关键字间定义,定义格式如下:
Type [数据类型名]
<域名>As<数据类型>
<域名>As<数据类型>
……
End Type
3.数据库对象
如数据库、表、查询、窗体和报表等,也有对应的VBA对象数据类型,这些对象数据类型由引用的对象库定义,常用VBA对象数据类型和对象库中所包括的对象如表8-13所示。
表8-13 VBA 支持的数据库对象类型
8.3.4 变量与常量
变量是指程序运行时值会发生变化的数据。变量名的命名同字段命名一样,变量命名不能包含有空格或除了下划线字符(_)外的任何其他的标点符号,其长度不能超过255个字符。
常量是在程序中可以直接引用的实际值,其值在程序运行中不变。不同的数据类型,常量的表现形式也不同,VBA中有3种常量:直接常量、符号常量和系统常量。
1.变量的声明
(1)显示声明。
【格式】
【说明】
【例如】
Dim number As Integer
(2)隐含声明。
【格式】
【例如】
Data=123
【说明】
2.强制声明
在默认情况下,VBA允许在代码中使用未声明的变量。若在模块设计窗口顶部的“通用- 声明”区域中,加入语句:
Option Explicit
则强制要求所有变量必须定义才能使用。这种方法只能为当前模块设置自动变量声明功能,如果想让所有新模块都启用此功能,可以单击“工具”→“选项”菜单命令,在弹出的“选项”对话框中选中“要求变量声明”选项。
3.变量的作用域
在VBA中,定义变量的位置和方式不同,其存在的时间和作用范围也不同,也就是它的生命周期和作用域不同。
根据作用范围不同,可以将变量分为3个层次,如表8-14所示。
表8-14 变量
请注意
可以用Static关键字代替Dim定义静态变量,静态变量的持续时间是在整个模块的时间,但它的有效范围由其定义位置决定。
4.数据库对象变量
可以引用Access中的窗体对象。
【格式】
也可以引用Access中的报表对象。
【格式】
【说明】
【例如】
Forms! 学生! 姓名="张域"
如果要多次引用某一值,则可以用一个变量名代替窗体控件对象。
【例如】
DimName As Control '定义控件类型变量
Set Name =Forms! 学生! 姓名 '指定引用窗体控件对象
Name ="张域" '操作对象变量
5.数组
数组变量由变量名和数组下标组成。
【格式】
缺省状态下,下标下限为0。
【例如】
Dim Array(5) As String
定义了由6个字符串构成的数组,数组元素为Array(0) ,…,Array(5)。
Dim Array(1 to 5) As String
定义了由5个字符串构成的数组,数组元素为Array(1) ,…,Array(5)。
Dim Array(5 ,5 ,5) As Integer
定义了一个多维数组,包含6 ×6 ×6个数组元素。
Dim Array( ) As Integer
定义了一个动态数组。在使用动态数组时,先不指明数组元素数目,需要时再用ReDim关键字定义。当不需要使用时,可以用ReDim将其设置为0 ,释放内存空间。如我们将上面定义的动态数组设置为6 ×6 ×6个元素:
ReDim Array(5 ,5 ,5) As Integer
6.变量命名规则
VB和VBA推崇使用匈牙利(Hungarian)法命名,该方法也广泛使用在C和C++等其他程序设计中。匈牙利法一般用小写字母作为变量名的第一个字符。
【例如】定义一个人的英文名字,如下所示:
Dim sName As String
此外,还有一些其他规则。
长度小于255个字符。
变量名是字母、数字与下划线(_)的组合,并且必须以字母开头,不区分大小写,不能包含其他字符。
不能使用VBA关键字。
在同一作用域内,变量名必须是唯一的。
【例如】
Dim sNum As String*3
Dim sName As String
Dim iScore As Integer
7.符号常量
对一些使用较为频繁的常量,可以用符号常量表示。
【格式】
【例如】 定义圆周率:
Const PI=3 .1415926
请注意
符号常量一般要求大写命名。
8.系统常量
Access中的系统常量是可以直接使用的,如True、False、Yes、No、On、Off等。
8.3.5 常用标准函数
标准函数一般用于表达式中。
【格式】
【说明】
1.算术函数
表8-15 算术函数
续表
2.字符串函数
表8-16 字符串函数
3.日期/时间函数
表8-17 日期/时间函数
4.类型转换函数
表8-18 类型转换函数
8.3.6 运算符和表达式
1.运算符
VBA中的运算符分为4种:算术运算符、关系运算符、逻辑运算符和连接运算符。
表8-19 算术运算符
请注意
对于整数除法(\)运算,如果操作数有小数,系统会舍去后再运算,如果结果中有小数也将舍去;对于求模(Mod)运算,如果操作数有小数,系统会四舍五入后再运算;如果被除数是负数,余数也是负数。
表8-20 关系运算符
表8-21 逻辑运算符
表8-22 逻辑运算举例
表8-23 连接运算符
2.表达式和优先级
当一个表达式由多个运算符连接在一起时,运算的先后顺序是按优先级来决定的,优先级高的先运算,优先级等同,按照从左向右顺序进行,运算符优先级规则如下。
算术运算符>连接运算符>关系运算符>逻辑运算符。
优先级相同,按从左向右顺序进行。
括号优先级最高。
各种运算符的优先级情况如表8-24所示。
表8-24 运算符优先级
8.4 VBA流程控制语句
计算机程序的执行控制流程有3种基本结构:顺序结构、条件判断结构和循环结构。
顺序结构:顺序执行程序语句。
条件判断结构:按照给定的条件进行判断,再按判断结果分别执行程序中不同部分的代码。
循环结构:按照条件反复执行一系列语句。
8.4.1 赋值语句
赋值语句主要用于为变量指定一个值或者表达式,通常以“ =”连接。
【格式】
【例如】 定义一个单精度数值,并赋值为1 .23456。
Dim i as single
i=1 .23456
8.4.2 条件语句
1.单分支结构( If...Then语句)
If 测试指定的条件,如果条件为真(True),则执行Then后面的语句。
【格式1】
【格式2】
请注意
If...Then的单行格式不用End If语句。但如果条件表达式的值为真(True)时,要执行多行代码,则必须使用多行If...Then...End If语法。
【例8-5】 用If...Then语句结构编程计算表达式y的值。
当x<0时,y=x+1
2.双分支结构( If...Then...Else)
If...Then语句的变形是If...Then...Else语句,它在条件为True时,执行一段语句,而在条件为False时,执行另一段语句。If...Then...Else语句的格式如下:
【格式】
IF语句的嵌套:多重选择。
【例8-6】 用If...Then语句结构编程计算表达式y的值。
当x>0时,y=x+1
当x<0时,y=x-1
当x=0时,y=0
3.多分支结构( If...Then...Elself语句)
【格式】
【例8-7】 用If...Then...ElseIf语句结构编程计算表达式y的值。
当x>0时,y=x+1
当x<0时,y=x-1
当x=0时,y=0
4.Select语句
Select Case选择结构:根据表达式求值结果,选择执行几个分支中的一个。
【格式】
【说明】
只要测试表达式的值与Case子句中列出的某一个值相同,条件就成立,系统就会执行该Case后面的语句块。
If和Select Case 语句的应用:If 语句适合执行多个条件都执行的情况,如【例8-8】,而Select Case在多个条件式中只能执行一个满足条件的语句块。
【例8-8】 根据计算机成绩和英语成绩,将成绩优秀的输出,程序只能使用If语句。
【例8-9】 用Select语句结构编程,计算表达式y的值。
当x>0时,y=x+1
当x<0时,y=x-1
当x=0时,y=0
5.条件函数
除上述条件语句结构外,VBA还提供了3个函数来完成相应操作。
(1) IIf 语句。
【格式】
【说明】
【例8-10】 取变量A、B中较小的值,并将值赋给Min。
Min=IIf( A<B,A,B)
(2) Switch语句。
【格式】
【说明】
【例8-11】 根据x的值,为变量y赋值。
Y=Switch( x>1 ,7 ,x< -1 ,5 ,-1<x<1 ,9 )
(3) Choose语句。
【格式】
【说明】
【例8-12】 根据x的值,为变量Y赋值。
Y=Choose(x,7,5,9)
下面的例题说明条件语句的使用。
【例8-13】 设计一个“登录”窗体,输入用户名和密码,若用户名和密码为空,给出提示,要求重新输入;若用户名和密码不正确,也给出错误提示,并结束程序运行;若用户名和密码均正确,则显示欢迎信息。
如图8-14所示,设计一个“登录”窗体。文本框名称分别为:txtUser、txtPwd,设置txtPwd文本框的“输入掩码”属性为“密码”。命令按钮名称为“CmdOK”,标题为“确定”。
图8-14 设计“登录”窗体
保存窗体,命名为“登录”;单击“代码”工具按钮,切换至代码窗口,如图 8-15 所示,选择“CmdOK”。
图8-15 代码窗口
在代码窗口中输入下列程序。
单击“保存”按钮,关闭代码窗口。
在Access数据库中运行“登录”窗体,如图8-16~图8-19所示。
图8-16 “登录”窗体
图8-17 用户名错误提示
图8-18 密码错误提示
图8-19 登录成功
8.4.3 循环语句
根据循环的条件,可以把循环结构分为两种:一种是“当型”循环结构,当条件成立时,反复执行语句,For...Next 语句和While...Wend语句属于“当型”循环结构;另一种是“直到型”循环结构,即反复执行语句,直到条件成立为止,Do While...Loop语句和Do...Loop While语句属于“直到型”循环结构。
1.For...Next语句
For...Next循环结构:将一段程序重复执行指定的次数,其中使用一个计数变量,统计执行的次数。
【格式】
【功能】执行For语句时,“循环变量”设为“初值”,执行到Next语句时,步长加(减)到循环变量上,再执行Fo r语句时,若“循环变量”超过“终值”,则循环结束。
【说明】
【例8-14】 计算整数1~10的和。
2.Do While...Loop语句和Do...Loop While语句
【格式】
Do While...Loop循环结构:先判断后执行,有可能一次也不执行。While关键字用于指明条件为真时执行循环体内语句;Until 当条件为假时,执行循环体内语句。“|”表示选择括号内任意一个。
【例8-15】 当i 不为0时,执行Sum=Sum+i。
【格式】
Do...Loop While循环结构:先执行后判断,循环语句至少执行一次;While 关键字用于指明条件为真时执行循环体内语句;Until 当条件为假时,执行循环体内语句。
请注意
在循环体中必须有修改循环变量的语句,如n=n+1,否则循环条件始终不发生改变,循环将永远不会结束,即死循环。
3.While...Wend语句
【格式】
While...Wend语句与Do While...Loop结构类似,当条件满足时执行循环体,只是在循环体内不能使用Exit Do语句。
8.4.4 GoTo语句
GoTo语句用于实现无条件跳转。
【格式】
请注意
标号名字从代码行的最左列开始写。GoTo语句是早期Basic语言中常用的流程控制语句,现在的语言不提倡使用,因为过多会导致程序控制和调试都比较困难,VBA中主要用于错误处理。一般不建议用GoTo语句。
8.5 过程调用和参数传递
在VBA中,过程是由一系列可以完成某项指定的操作、计算语句和方法组成。根据过程是否返回值,分为Sub过程和Function函数。
8.5.1 过程调用
1.过程的定义和调用
用Sub语句声明一个新的过程。
【格式】
使用Public关键字可以使该过程适用于所有模块中的所有其他过程;用Private关键字则使该程序只适用于同一模块中的其他过程。
过程调用形式有以下两种。
Call 过程名([实参])
过程名([实参])
【例8-16】 先编写一个子过程“MsgBox”,然后写出调用该子过程的语句。
调用名为“登录”的窗体,可以用下列语句。
2.函数的定义和调用
过程使用起来很方便,但如果需要返回参数,就要用到函数了。VBA中提供了大量的内置函数。例如字符串函数 Mid ()、统计函数 Max ()等,在编程时直接引用就可以了,非常方便。
有时用户需要按自己的要求定制函数,例如计算半径为R的圆的面积S,则S=3 .14*R^2。但圆的半径R是不确定的,不可能为每一个不同半径的圆来写上相似的一段代码。这时就需要使用函数。
用Function语句可以声明一个新函数,它接收参数、返回变量类型及运行该函数过程的代码,格式如下:
【格式】
【说明】
【例8-17】 编写一个逆向指标标准化的函数过程NXZBJS() ,逆向指标标准化的函数计算方法如下。
假定某一指标的5级指标原始阈值分别为Xi(X1、X2、X3、X4、X5),阈值得分为Ai(90、70、50、30、10) ,X为指标的原始值。
当X<X 1 时,X j = 90 + 10 ( X 1 -X)/X 1 ;
当X j >100时,取X j = 100;
当X i <X<X i-1 时,X j = A i-1 + 20 ( X-X i )/( X i-1 -X i );
当X>X 5 时,X j = 10 ( X-X 5 )/X 5 。
8.5.2 参数传递
过程或函数定义可以设置一个或多个参数,这个参数称为形参,多个参数之间用逗号分隔。
【格式】
各参数的含义如表8-25所示。
表8-25 参数含义
续表
含参数的过程被调用时,主调用过程中的调用式必须提供相应的实参(实际参数的简称),并通过实参向形参传递的方式完成过程操作。
关于实参向形参的数据传递,还需了解以下内容。
实参可以是常量、变量或表达式。
实参数目和类型应该与形参数目和类型相匹配。除非形参定义含 Optional 和 Param Array选项,则参数、类型可能不一致。
传值调用(ByVal 选项)的“单向”作用形式与传址调用(ByRef 选项)的“双向”作用形式。
过程定义时,如果形式参数被说明为传值(ByVal项) ,则过程调用只是相应位置实参的值“单向”传递给形参处理,而被调用过程内部对形参的任何操作引起的形参值的变化均不会反馈、影响实参的值。由于这个过程,数据的传递具有单向性,故称为“传值调用”的“单向”作用形式。反之,如果形式参数被说明为传址(ByRef项) ,则过程调用是将相应位置实参的地址传递给形参处理,而被调用过程内部对形参的任何操作引起的形参值的变化又会反向影响实参的值。在这个过程中,数据的传递具有双向性,故称为“传址调用”的“双向”作用形式。
请注意
实参提供可以是常量、变量或表达式3种方式之一。如果实参为常量或表达式时,形参即便是传址(ByRef项)说明,实际传递的也只是常量或表达式的值,这种情况下,过程参数“传址调用”的“双向”作用形式就不起作用。但实参是变量、形参是传址(ByRef项)说明时,可以将实参变量的地址传递给形参,这时,过程参数“传址调用”的“双向”作用形式就会产生影响。
8.6 VBA程序的错误处理
立即窗口实时跟踪程序的执行过程,将程序执行情况立即显示出来,通过使用Debug.Print语句,把所要显示的内容输出到立即窗口中。
本地窗口显示程序运行到断点处的各变量的值。监视窗口监视的是VBA程序挂起时表达式的值。本节将以实例讲解VBA程序的调试与错误处理。
【例8-18】 在模块中编写一段求和代码并进行调试。
在“模块”对象中单击“新建”按钮,打开VBA编辑器。
在代码窗口中编写程序,功能为计算从1加到100的总和,如图8-20所示。
图8-20 VBA编辑窗口
执行菜单“视图”➝“立即窗口”命令,打开立即窗口。
将光标放在End Sub后面,执行菜单“调试”➝“运行到光标处”命令,如图8-21所示,立即窗口出现显示结果,如图8-21所示。
图8-21 菜单命令
图8-22 在立即窗口调试
单击工具栏上的“保存”按钮,将模块保存为“求和”。
执行菜单“视图”➝“本地窗口”命令,打开本地窗口,如图8-23所示。
图8-23 菜单命令
在代码窗口中单击“Next”语句左边的灰色条处,即在该语句处设置断点,如图8-24所示。
图8-24 设置断点
执行菜单“运行”➝“重新设置”命令,中断上次未完成的程序,如图8-25所示。
图8-25 菜单命令
执行菜单“运行”➝“运行子过程/用户窗体”命令,如图8-26所示。
图8-26 在本地窗口调试
执行菜单“视图”➝“监视窗口”命令,打开监视窗口。
执行菜单“运行”➝“重新设置”命令,中断上次未完成的程序。
执行菜单“调试”➝“添加监视”命令,打开“添加监视”对话框,在“表达式”文本框中输入“i<50”,如图8-27所示。
图8-27 “添加监视”对话框
单击“确定”按钮,在代码窗口中的“Next”处设置断点,单击工具栏上的“运行”按钮,监视窗口如图8-28所示。
图8-28 在监视窗口调试
在模块中,编写的程序会出现错误,常见的错误有3种。
(1)语法错误,如变量没有定义直接使用、语句前后不匹配等。
错误处理:在Access代码窗口中逐行检查,一般的语法错误都能被检查出来。对于复杂的错误,则通过执行菜单“调试”→“编译”命令查找,在编译过程中,模块中的所有语法错误都将被查出。
(2)运行错误,如数据参数传递类型不匹配、数据发生异常等。
错误处理:在出现运行错误时,Access系统会中断程序的执行,显示错误信息,并将代码窗口打开,指定出错代码的位置,根据出错位置进行调试。
(3)逻辑错误,如应用程序没有按照希望的结果执行、运算结果不合逻辑等。
错误处理:出现逻辑错误,则需要修改程序的算法来排除。
8.7 VBA程序的调试
1.断点概念
图8-29所示为设置好的“断点”行。
图8-29 设置断点
2.调试工具的使用
调试工具如图8-30所示,相应说明如表8-26所示。
图8-30 调试工具
表8-26 调试工具
续表
图8-31 本地窗口
图8-32 立即窗口
图8-33 监视窗口
图8-34 快速监视
课后总复习
一、选择题
1.在下列关于宏和模块的叙述中,正确的是( )。
A)模块是能够被程序调用的函数 B)通过定义宏可以选择或更新数据
C)宏或模块都不能是窗体或报表上的事件代码 D)宏可以是独立的数据库对象,可以提供独立的操作动作
2.如果在C盘当前文件夹下已存在名为StuData.dat的顺序文件, 那么执行语句Open "C:StuData.dat"For Append As #1 之后将( )。
A)删除文件中原有内容
B)保留文件中原有内容,可在文件尾添加新内容
C)保留文件中原有内容,在文件头开始添加新内容
D)保留文件中原有内容,在文件中间开始添加新内容
3.下列只能读不能写的文件打开方式是( )。
A) Input B) Output C) Random D) Append
4.VBA中构成对象的三要素是( )。
A)属性、事件、方法 B)控件、属性、事件
C)窗体、控件、过程 D)窗体、控件、模块
5.在VBA中要打开名为“学生信息录入”的窗体,应使用的语句是( )。
A) DoCmd.OpenForm"学生信息录入" B) OpenForm"学生信息录入"
C) DoCmd.OpenWindow"学生信息录入" D) OpenWindow"学生信息录入"
6.在VBA中按文件的访问方式不同,可以将文件分为( )。
A)顺序文件、随机文件和二进制文件 B)文本文件和数据文件
C)数据文件和可执行文件 D) ASCII文件和二进制文件
7.下列表达式计算结果为数值类型的是( )。
A)#5/5/2010# - #5/1/2010# B)"102" > "11"
C)102 = 98 + 4 D)#5/1/2010# + 5
8.下列给出的选项中,非法的变量名是( )。
A) Sum B) Integer_2 C) Rem D) Form1
9.下列变量名中,合法的是( )。
A)4A B)A-1 C)ABC_1 D)private
10.下列能够交换变量X和Y值的程序段是( )。
A) Y=X : X=Y B) Z=X :Y=Z:X=Y C) Z=X : X=Y: Y=Z D) Z=X :W=Y:Y=Z: X=Y
11.有下列命令按钮控件test的单击事件过程:
Private Sub test_click()
Dim I,R
R=0
For I=1 To 5 Step 1
R=R+I
Next I
bResult.Caption=Str(R)
End Sub
当运行窗体,单击命令按钮时,在名为 bResult的窗体标签内将显示的是( )。
A)字符串15 B)字符串5 C)整数15 D)整数5
12.在模块的声明部分使用“Option Base 1”语句,然后定义二维数组A(2 to 5,5),则该数组的元素个数为( )。
A)20 B)24 C)25 D)36
13.如有数组声明语句Dim a(2,-3 to 2,4),则数组 a包含元素的个数是( )。
A)40 B)75 C)12 D)90
14.VBA中定义符号常量使用的关键字是( )。
A) Const B) Dim C) Public D) Static
15.对不同类型的运算符,优先级的规定是( )。
A)字符运算符 > 算术运算符 > 关系运算符 > 逻辑运算符
B)算术运算符 > 字符运算符 > 关系运算符 > 逻辑运算符
C)算术运算符 > 字符运算符 > 逻辑运算符 > 关系运算符
D)字符运算符 > 关系运算符 > 逻辑运算符 > 算术运算符
16.在窗体上有一个命令按钮Command1,编写事件代码如下:
Private Sub Command1_Click()
Dim d1 As Date
Dim d2 As Date
d1 = #12/25/2009#
d2 = #1/5/2010#
MsgBox DateDiff("ww", d1, d2)
End Sub
打开窗体运行后,单击命令按钮,消息框中输出的结果是( )。
A)1 B)2 C)10 D)11
17.窗体中有命令按钮run34,对应的事件代码如下:
Private Sub run34_Enter()
Dim num As Integer, a As Integer, b As Integer, i As Integer
For i = 1 To 10
num = InputBox("请输入数据:","输入")
If Int(num/2)= num/2 Then
a = a + 1
Else
b = b + 1
End If
Next i
MsgBox("运行结果:a="& Str(a)&",b="&Str(b))
End Sub
运行以上事件过程,所完成的功能是( )。
A)对输入的10个数据求累加和 B)对输入的10个数据求各自的余数,然后再进行累加
C)对输入的10个数据分别统计奇数和偶数的个数 D)对输入的10个数据分别统计整数和非整数的个数
18.有如下事件程序,运行该程序后输出结果是( )。
Private Sub Command33_Click()
Dim x As Integer, y As Integer
x = 1:y = 0
Do Until y < = 25
y = y + x* x
x = x + 1
Loop
MsgBox "x="&x & ", y="&y
End Sub
A)x=1, y=0 B)x=4, y=25 C)x=5, y=30 D)输出其他结果
19.在窗体上有一个命令按钮Commandl和一个文本框Textl,编写事件代码如下:
Private Sub Command1_Click()
Dim i,j,x
For i = l To 20 step 2
x = 0
For j = i To 20 step 3
x = x + 1
Next j
Next i
Text1.Value = Str(x)
End Sub
打开窗体运行后,单击命令按钮,文本框中显示的结果是( )。
A)1 B)7 C)17 D)400
20.有以下程序段:
k=5
For I=1 to 10 step 0
k=k+2
Next I
执行该程序段后,结果是( )。
A)语法错误 B)形成无限循环
C)循环体不执行直接结束循环 D)循环体执行一次后结束循环
21.在VBA中,下列关于过程的描述中正确的是( )。
A)过程的定义可以嵌套,但过程的调用不能嵌套 B)过程的定义不可以嵌套,但过程的调用可以嵌套
C)过程的定义和过程的调用均可以嵌套 D)过程的定义和过程的调用均不能嵌套
22.若有如下Sub过程:
Sub sfun(x As Single, y As Single )
t = x
x = t /y
y = t Mod y
End Sub
在窗体中添加一个命令按钮Command33,对应的事件过程如下:
Private Sub Command33_Click()
Dim a As Single
Dim b As Single
a = 5 :b = 4
sfun a, b
MsgBox a & chr(10)+ chr(13)& b
End Sub
打开窗体运行后,单击命令按钮,消息框中有两行输出,内容分别为( )。
A)1和1 B)1.25和1 C)1.25和4 D)5和4
23.在定义过程时,系统将形式参数类型默认为( )。
A)值参 B)变参 C)数组 D)无参
24.可以用InputBox函数产生“输入对话框”。执行语句:
st = InputBox("请输入字符串","字符串对话框","aaaa")
当用户输入字符串“bbbb”,按OK按钮后,变量 st的内容是( )。
A) aaaa B)请输入字符串 C)字符串对话框 D) bbbb
25.要显示当前过程中的所有变量及对象的取值,可以利用的调试窗口是( )。
A)监视窗口 B)调用堆栈 C)立即窗口 D)本地窗口
二、操作题
1.考生文件夹下有一个数据库文件“samp3.mdb”,其中存在已经设计好的表对象“tAddr”和“tUser”,同时还有窗体对象“fEdit”和“fEuser”。请在此基础上按照以下要求补充“fEdit”窗体的设计。
(1)将窗体中名称为“LRemark”的标签控件上的文字颜色改为红色(红色代码为255),字体粗细改为“加粗”。
(2)将窗体标题设置为“修改用户信息”。
(3)将窗体边框改为“对话框边框”样式,取消窗体中的水平和垂直滚动条、记录选定器、浏览按钮和分隔线。
(4)将窗体中“退出”命令按钮(名称为“cmdquit”)上的文字颜色改为深红(深红代码为128),字体粗细改为“加粗”,并给文字加上下划线。
(5)在窗体中还有“修改”和“保存”两个命令按钮,名称分别为“CmdEdit”和“CmdSave”,其中“保存”命令按钮在初始状态为不可用,当单击“修改”按钮后,应使“保存”按钮变为可用。现已编写了部分VBA代码,请按照VBA代码中的指示将代码补充完整。
要求:修改后运行该窗体,并查看修改结果。
注意:不能修改窗体对象“fEdit”和“fEuser”中未涉及的控件、属性;不能修改表对象“tAddr”和“tUser”。
程序代码只允许在“* * * * * * * * * * ”与“* * * * * * * * * * ”之间的空行内补充一行语句、完成设计,不允许增删和修改其他位置已存在的语句。
Private Sub CmdEdit_Click()
用户名_1.Enabled = True
Me! Lremark.Visible = True
Me! 口令_1.Visible = True
Me! 备注_1.Visible = True
Me! tEnter.Visible = True
'* * * * * * * * * * * * * * * * 请在下面添加一条语句 * * * * * * * * * * * * * * * * '
'* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * '
End Sub
2.在考生文件夹下有一个数据库文件“samp3.mdb”,里面已经设计好表对象“tStudent”,同时还设计出窗体对象“fQuery”和“fStudent”。请在此基础上按照以下要求补充“fQuery”窗体的设计。
(1)在距主体节上边0.4cm、左边0.4cm位置添加一个矩形控件,其名称为“rRim”,矩形宽度为16.6cm、高度为1.2cm,“特殊效果”为“凿痕”。
(2)将窗体中“退出”命令按钮上显示的文字颜色改为“深红”(深红代码为128),字体粗细改为“加粗”。
(3)将窗体标题改为“显示查询信息”。
(4)将窗体边框改为“对话框边框”样式,取消窗体中的水平和垂直滚动条、记录选定器、浏览按钮和分隔线。
(5)在窗体中有一个“显示全部记录”命令按钮(名称为“bList”),单击该按钮后,应实现将“tStudent”表中的全部记录显示出来的功能。现已编写了部分VBA代码,请按照VBA代码中的指示将代码补充完整。
要求:修改后运行该窗体,并查看修改结果。
注意:不要修改窗体对象“fQuery”和“fStudent”中未涉及的控件、属性;不要修改表对象“tStudent”。
程序代码只能在“* * * * * * * * * ”与“* * * * * * * * * ”之间的空行内补充一行语句、完成设计,不允许增删和修改其他位置已存在的语句。
Private Sub bList_Click()
'* * * * * * * * 请在下面双引号内添入适当的SELECT语句 * * * * * * * * * '
BBB.Form.RecordSource = ""
'* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * '
[Text2] = ""
End Sub
学习效果自评
本章主要介绍了模块的概念及VBA编程基础。要求考生理解模块及面向对象的基本概念,熟练掌握VBA流程控制,会进行简单的VBA编程及使用常用的操作方法来操作Access数据库。