1.2VBA语法(及Access的对象结构)VBA程序是VBA语言语句代码以及注释的集合。一条语句是一个完整的命令,语句之间用换行符分割,大多数情况下,一条语句就是一行代码。VBA语句是由规定的保留字(也称为关键字,在本书的范例中,关键字都以大写字母开头)与其他被赋予意义的单词组合而成,每条语句都具有明确意义,在VBA语句分为三种类型:声明语句。定义变量、常数,或定义一段程序。赋值语句。为变量或常数指定一个值或表达式。可执行语句。它可以执行一个方法或是函数。我们往往把实现特定功能的程序段用特定的方式单独封装起来,以便反复调用运行,或者提高程序可读性。这种程序段的最小单元我们称之为过程,一个Access模块中可包含一个或者多个过程。1.2.1过程与函数先看一个简单的过程:SubsubPromptMessage()MsgBox这是一个最简单的过程。EndSub这是一个Sub过程,把光标定位在过程的任意位置,按下F5即可运行。这个过程的执行结果是弹出一个提示对话框,如图8-2所示。也可以单击菜单【运行】,选择【运行子过程/用户窗体】或单击工具栏中【运行子过程/用户窗体】按钮回来立即运行光标位置所在的过程。第一行的“Sub”语句与最后一行的“EndSub”语句标志过程的开始和结束。“Sub”后紧跟的“subPromptMessage”是这个过程的名字。过程名后面的一对小括号是必须的。“Sub”所在行与“EndSub”行之间所有的行就是这个过程的语句。如果要从一个过程返回结果值,就需要定义为一个Function过程,通常称为函数。函数与Sub过程的定义形式稍有不同。FunctionPI()AsSinglePI=3.14159EndFunction“Function”与“EndFunction”标志函数的开始和结束。在代码的第一行,定义了函数的返回值PI的数据类型为Single。在函数过程的代码中有赋值语句来赋予这个函数的返回值。函数过程定义后,就可以在其他过程或者函数中调用该函数返回的结果。例如:SubfunctionReturnTest()MsgBox函数PI()的运行结果是:&PI()EndSub我们可以把这个过程接着再输入到PI()函数的下方,这个过程调用了函数PI(),我们执行这样的一个过程,可以在提示对话框中看到函数PI()的值为3.14159。我们也可以在立即窗口中输入图8-2运行过程printPi()或者?Pi()然后敲回车键,将在立即窗口的下一行输出函数PI()的返回值“3.14159”,通过这种方式,我们可以快速地检查函数的结果是否正确。VBA自带了大量的函数过程,这些函数可以直接在VBA程序中使用,不需要自己定义。它们称为内置函数,比如求绝对值函数Abs()。内置函数非常丰富,它分为数学运算函数、字符串处理函数、日期函数、类型转换函数等几大类。我们不但可以从函数返回一个值,也可以向过程或者函数传入值,我们把它叫做参数。在定义过程时,需要同时定义传入的参数的名称和类型,例如:SubprocInput(strPromptTextAsString)MsgBox参数strPromptText的值是:&strPromptTextEndSub在第一行代码的括号中,定义了传入的参数的名称strPromptText和数据类型String。这样,在过程中就可以通过这个参数的名称使用这个传入过程的参数值。由于在不同场合调用这个过程的时候,传入的参数实际值是不同的,本例中参数strPromptText实际上是一个可变的量,这跟数学方程中定义的变量x、y、z有些类似,变量的值不同,可使同一方程得到不同的结果。定义了参数的过程或者函数,需要由其他过程调用而不能直接运行,因为它需要传入它所规定的参数值。当然我们也可以在立即窗口中快速执行:procInput第一个参数在立即窗口输入上述代码,敲回车。这是典型的过程调用方法,“ProcInput”是调用的过程名,“第一个参数”是传入的参数,这里用英文双引号表示传入的是一个字符串数据类型数据,与函数定义的参数数据类型必须相匹配。可以同时向过程传入多个参数。如果要传递多个参数给一个过程或函数,注意在每一个参数定义之间用英文逗号分隔。1.2.2常量与变量常量有时候也称为常数,它是一个始终保持不变的量,常量值自始至终不能被修改,例如数值5。定义和使用常量也非常简单,例如:FunctionCCL(intRAsInteger)asSingleConstPI=2.14+1MsgBox半径为&intR&的圆周长是&intR*PI*2CCL=intR*PI*2EndFunction本例中定义了一个常量PI,可以在该过程中的任意地方使用,它的值始终为数值3.14。常量的值当然也可以是字符串、日期等其他类型。本例中,英文双引号括起来的“半径为”和“的圆周长是”这两个字符串以及数值2也都是常量。注意定义常量时,其值也可一个表达式。如果常量值是一个字符串或者日期,那么需要用双引号或#号括起来。ConstC=字符ConstC=#2003/1/1#变量是其值可以被改变的一组存储单元,我们给这一组存储单元起一个好记的名字,并通过名字即变量名来实现对内存单元的存取。在同一范围内,变量的值是惟一的、确定的。我们通过一个例子,来看看如何定义变量、如何给变量赋值,以及如何使用变量。SubCCL2()DimintRAsIntegerDimsglLAsSingleintR=2sglL=intR*PI()*2MsgBox半径为&intR&的圆周长是&sglLintR=5sglL=CCL(intR)MsgBox半径为&intR&的圆周长是&sglLEndSub本例中过程CCL2()用语句Dim定义了两个变量intR和sglL,其数据类型分别是Integer和Single。类似这样的两条语句:intR=2sglL=intR*PI()*2属于前面提到的赋值语句,就是把语句等号右边的表达式的结果存储到表达式左边的变量名代表的内存单元中。这两条语句执行以后,intR和sglL的值分别是2和12.56636,赋值语句intR=5执行后intR的值被重新设定为5。赋值语句左边变量的数据类型必须和右边的表达式结果的数据类型相一致,否则程序将出错而无法运行。过程执行结束以后,过程中为变量指定的值会自动被释放而不再存在。注意VBA允许不通过声明语句显式定义变量,而在使用变量时自动定义它,看起来这使变量定义更加灵活,但实际上这是一个非常糟糕的功能。当一个变量被拼写错误的时候程序会把它当作一个新的变量。强烈建议在每个模块的开始使用OptionExplicit语句来强制显式定义变量。(怎么用啊?给出请参见***部分吧)PI()和CCL()是我们刚才定义的函数,注意由于函数的定义不同,在过程中调用时格式也会稍有不同。过程CCL2()中虽然只有两条MsgBox语句,但在执行时我们却看到3次提示,这是因为CCL()函数中也有一条MsgBox语句,当其被执行时出现了第二次的提示。传入到过程的参数也是变量。变量与常量的声明语句往往放在模块后者过程的最开始。快捷键F8可一步一步的执行过程,我们可以用此来查看过程中各条语句执行的顺序,调用函数或者子过程的执行顺序。我们在调试程序的时候经常用到F8。1.2.3数据类型如同字段的数据类型一样,VBA中也为变量和表达式规定了丰富的数据类型:Byte、Boolean、Integer、Long、Single、Double、Currency、Decimal、Date、Object、String、Variant以及用户自定义类型。不同的数据类型,所占用的存储空间不同,所表示的数据范围也有些差异,一般来说在能够表达事务的情况下,采用占用存储空间较少的数据类型会使程序运算速度加快。关于数据类型的详细资料,请参阅【MicrosoftVisualBasic帮助】的“数据类型概述”。1.2.4续行与注释编写程序时,有时候一条语句会比较长,以至于超过屏幕的宽度,需要左右滚动编辑区才能把一条语句看完。这给阅读带来了一定的不便。此时我们可以使用续行符“-”来把较长的语句写在多行上,使得程序看起来更加美观,阅读和调试程序也更加方便。如下例所示:SubProcInput2(strPromptTextAsString)MsgBox参数strPromptText的值是:&strPromptText&vbNewLine_&数据类型是:&TypeName(strPromptText),_vbInformation+vbOKOnly,_提示EndSub本例中使用续行符号将一条MsgBox语句分成了4行书写。注意使用续行符不能把一个独立的关键字、变量名等拆分到不同的行。续行符前必须有至少一个空格。Rem语句中Rem关键字和注释之间也必须有至少一个空格。我们还可以为程序加上一些注释,来说明这一条语句的作用,或者函数的功能、调用方法、注意事项等,以提高程序的可读性,方便自己或第三方阅读程序。写入注释通常以英文单引号开头('),接着写注释的内容,直到一行结束。也可以用Rem语句加入注释,Rem语句和其他语句一样必须独占一行,或在一行的结尾使用续行符“_”写成多行。一般情况下,在MicrosoftVisualBasic代码编辑器中注释语句内容显示为绿色。图8-3所示的程序片段就使用了注释的这几种形式。图1-3程序注释实际上,如同前面第二章所讲到的,虽然有没有注释并不影响程序的运行结果,但注释是程序不可分割的一部分,好的程序同样应该有好的注释。1.2.5数组数组是一组具有相同数据类型的元素的集合,数组中各元素的存取不影响其他元素,组成数组的每个元素都可以通过索引进行访问。当需要使用大量的同类型的变量时,定义和使用数组比逐个定义变量简便。通常我们这样来定义数组:DimintArray(9)AsInteger这条语句定义了一个数组,它包含数据类型为Integer的10个元素,从intArray(0)到intArray(9)。比如我们写一个过程,实现让用户输入三个数字,最后输出这三个数的平均值:SubAvgValue()DimsglNum(2)AsSingle'定义一个数组包含3个元素DimsglAvgAsSingle'定义一个变量用来存储平均值'提示用户输入3次实验数据sglNum(0)=Val(InputBox(请输入第1次实验数据:))sglNum(1)=Val(InputBox(请输入第2次实验数据:))sglNum(2)=Val(InputBox(请输入第3次实验数据:))'求出平均结果,存入变量sglAvg中sglAvg=(sglNum(0)+sglNum(1)+sglNum(2))/3'显示结果MsgBox3次实验的平均结果是:&sglAvgEndSub数组中的元素是通过数组下标来访问的,数组下标默认从0开始。我们也可以自行定义它的起始下标数值,如下例:DimintArrayTest(7To10)AsInteger那么这条声明语句定义了一个类型为Interger的包含4个元素的数组intArrayTest(),这4个元素分别是intArrayTest(7),intArrayTest(8),intArrayTest(9)和intArrayTest(10)。上述定义的数组都属于一维数组,VBA中也可以定义二维和多维数组。一个二维数组有点类似于一个二维矩阵。比如:DimintArray(1,3)AsInteger这条声明语句定义了一个2行4列共8个元素,它们分别是:intArray(0,0),intArray(0,1),intArray(0,2),intArray(0,3)intArray(1,0),intArray(1,1),intArray(1,2),intArray(1,3)关于数组的详细知识,会在后续的小节示例中陆续讲解。1.2.6VBA控制结构本章前面所讲到的示例都是一条一条语句按照顺序执行的,这是顺序结构的程序。在VBA中还有条件、分支和循环控制流语句