资源描述
Access 基础教程(第三版),第10章 VBA应用实例,第10章 VBA应用实例,10.1 程序流程控制 10.2 文件 10.3 过程调用 10.4 计时器Timer 10.5 ADO数据库编程实例,10.1 程序流程控制,10.1.1 选择结构 例1:窗体中有一名为Command1的命令按钮,其单击事件过程如下所示,试分析单击该命令按钮后消息框中的显示内容。 实例:10_1 Private Sub Command1_Click() a=75 If a60 Then k=1 ElseIf a70 Then k=2 ElseIf a80 Then k=3 ElseIf a90 Then k=4 End If MsgBox k End Sub,本例是块If语句的应用,执行的过程是:按条件出现的顺序依次判断每一个条件,发现第一个成立的条件后,则立即执行与该条件相对应的语句组,然后跳出该条件语句,去执行End If后的第一条语句。因为a=75,满足a60的条件,所以k=1,End If后的第一条语句为MsgBox k,所以消息框中显示的结果为1。,10.1 程序流程控制,例2:窗体中有一名为Command1的命令按钮,其单击事件过程如下所示,试分析单击该命令按钮后消息框中的显示内容。 实例:10_2 Private Sub Command1_Click() A=75 If A60 Then I=1 If A70 Then I=2 If A80 Then I=3 If A90 Then I=4 MsgBox I End Sub,本例是四个行If语句的顺序结构。与标准的IfThenEnd If结构相比较,缺少了End If,但这在VBA中是允许的,所以判断的过程也应该是顺序的,执行过程应该是A=75,A大于60所以I=1;A大于70所以I=2;A不大于80,所以I值不发生变化;A值不大于90,所以I值不发生变化;最终消息框中显示的结果应为I的最后值2。,10.1 程序流程控制,例3:分析如下窗体单击事件过程的显示结果。 实例:10_3 Private Sub Form_Click() a=1 For i=3 To 1 Step -1 Select Case i Case 1,3 a=a+1 Case 2,4 a=a+2 End Select Next i MsgBox a End Sub,本例是Select Case选择结构和For循环结构的应用集合,分析的重点在于Select Case的选择分支,分支一Case 1,3,也就是说当i值为1或3时执行的操作为a=a+1;分支二Case 2,4,也就是说当i值为2或4时执行的操作为a=a+2。a的初值为1,循环变量i的变化过程是由3到1,那么在整个循环过程中,要执行两次a=a+1的操作和一次a=a+2的操作,所以最终消息框显示的结果为5。,10.1 程序流程控制,例4:试用IfThenEnd If选择结构实现三个数由大到小的顺序排列。要求在如图10.1所示的“排序”窗体中名为“text1”、“text2”和“text3”的三个文本框中输入三个数,单击“排序”(名为Command1)按钮后,三个数按由大到小的顺序排列;单击“重新输入”(Command2)按钮后,清空文本框,以便于重新输入。结果如图10.2所示。 图10.1-10.2 实例:10_4 解题思路:要想将三个数进行排序,首先要将这三个数中任意两个数进行比较,如果比较过程中较大数在较小数之前,则不需要改变它们的顺序,否则需要将两个数的位置进行交换。对于三个数排序要进行(32)/(21)次比较。 本例中使用了去掉前导空格函数LTrim()、类型转换函数Val()和Str()及对象获得焦点的方法SetFocus;同时在做较大数和较小数的置换过程使用了中间变量t,这是本例中需要注意的。三个IfThenEnd If之间是顺序结构,实现了三次比较的过程。,10.1 程序流程控制,例5:试用Select Case选择结构实现一个收取货物运费的程序。要求:在固定两地之间,收取货物运费的原则是:10吨以内(不含10吨)的货物,每吨收取运费100元;10吨至50吨(不含50吨)的货物,每吨收取运费70元;50吨以上的货物,每吨收取运费50元。在如图10.3所示的“计算运输费用”窗体中“Weight”文本框(关联标签为“货物重量”)内输入货物重量后,单击Command1(标题为“计算”)按钮,在“Cost”文本框(关联标签为“运输费用”)中显示出运输费用;单击Command2(标题为“清除”)按钮,清空两个文本框。结果如图10.4所示。 图10.3-10.4 实例:10_5 解题思路:这是一个最为简单的多路分支选择结构实例,只需要根据货物重量的不同,选择不同运费计算公式即可。 本例中使用了去掉前导空格函数LTrim()、类型转换函数Val()和Str()及对象获得焦点的方法SetFocus;同时在显示计算结果的过程中使用了连接运算符“+”(实现字符串的连接),这是本例中需要注意的。Select Case选择结构的执行过程是在找到满足条件的第一分支并执行其后的语句组,然后End Select。,10.1 程序流程控制,10.1.2 循环结构 例6:窗体中有一名为Command1的命令按钮,其单击事件过程如下所示,试分析单击该命令按钮后sum的值。 实例:10_6 Private Sub Command1_Click() Dim sum As Double,j As Double sum=0 n=0 For i=1 To 5 j=n/i n=n+1 sum=sum+j Next i End Sub 为显示结果,实例中稍有变化。,本例是For循环语句的应用,循环变量i的取值为1到5。当i值为1时,x的值为0,n值1,sum值为0(注意赋值语句的顺序结构);当i值为2时,x值为1/2,n值为2,sum值为1/2;当i值为3时,x值为2/3,n值为3,sum值为1/2+2/3;以此类推,当循环结束之后sum的值为1/2+2/3+3/4+4/5。,10.1 程序流程控制,例7:窗体中有一名为Command1的命令按钮,其单击事件过程如下所示,试分析单击该命令按钮后消息框中的显示内容。 实例:10_7 Private Sub Command1_Cllick() Dim M(10) As Integer For k=1 to 10 M(k)=12-k Next k x=6 MsgBox M(2+M(x) End Sub,本例是For循环语句和数组的集合应用,一维数组M的下限为0、上限为10,循环变量k的取值为1到10。For循环的作用在本例中是为数据M中的元素赋值,下标为k的元素其值为12-k,如:M(1)值为11,M(10)值为2。消息框中显示的消息为M(2+M(x),首先要计算出M(x)的值,x=6,所以M(x)=6;因此M(2+M(x)实际上是M(8),所以最终消息框的显示结果为4。,10.1 程序流程控制,例8:试分析如下程序运行结束之后变量J的值。 实例:10_8 Private Sub Fun() Dim J As Integer J=10 Do J=J+3 Loop While J19 End Sub 为显示结果,实例中稍有变化。,本例是DoLoop While循环结构的应用,分析的重点在于条件式J19和其位置。当J19时执行循环体中的语句;另外需要注意的是条件式在Loop后,循环体至少要执行一次,它决定了是否回到循环体起始处。循环体中的语句为J=J+3,也就是说每执行一次循环J的值要加3。当执行两次循环体操作后J=16,仍然满足J19的条件,所以还要执行第三次循环;而当第三次循环结束后J=19,已经不满足J19的条件,所以循环终止。最终J的值为19。,10.1 程序流程控制,例9:试分析内层n循环的执行次数。 实例:10_9 For m=0 To 7 Step 3 For n=m-2 To m+2 Next n Next m 为显示结果,实例中稍有变化。,本例是For循环的嵌套,分析的重点在于内层循环变量n的初始值和终止值。无论m的值为多少,内层循环变量n的值都只有五个m-2、m-1、m、m+1和m+2,也就是说每执行一次m循环就要执行五次n循环。而m=0 To 7 Step 3,外层m循环要执行3次,所以内层n循环的次数为15。,10.1 程序流程控制,例10:试分析如下程序运行结束之后变量K的值。 实例:10_10 K=0 For I=1 To 3 For J=1 To I K=K+J Next J Next I 为显示结果,实例中稍有变化。,本例是For循环的嵌套,分析的重点在于内层J循环的终止值为I,由于外层循环变量I值的变化,使得内层J循环的次数是不固定。当I=1时,J=1 To 1,K=K+1=1;当I=2时,J=1 To 2,K=K+1+2=4;当I=3时,J=1 To 3,K=K+1+2+3=10。所以当程序运行结束之后K的值为10。(注意K值的累加过程),10.1 程序流程控制,例11:试分析如下程序运行结束之后变量x的值。 实例:10_11 x=1 y=1 z=1 For j=1 To 3 If j=1 Then x=x+y+z Else If j=2 Then x=2*x+2*y+2*z Else x=3*x+3*y+3*z End If Next j 书稿有误,请参照更正。 为显示结果,实例中稍有变化。,本例是For循环结构和块If语句的应用集合,分析的重点在于块If的选择分支,分支一为当j=1时,x=x+y+z;分支二为当j=2时,x=2*x+2*y+2*z;分支三为当j=3时,x=3*x+3*y+3*z。与选择结构的例3相比较,本例中赋值语句右端的变化是在变量参与运算后才进行赋值的。 循环共执行3次,当j=1时,x=1+1+1=3;当j=2时,x=2*3+2*1+2*1=10;当j=3时,x=3*10+3*1+3*1=36。所以当程序运行结束之后x的值为36。,10.1 程序流程控制,例12:窗体中有一名为Command1的命令按钮,其单击事件过程如下所示,试分析单击该命令按钮后消息框中的显示内容。 实例:10_12 Private sub Command1_Click() For i=1 To 4 x=3 For j=1 To 3 x=4 For k=1 To 2 x=x+5 Next k Next j Next i MsgBox x End Sub,本例是For循环的嵌套,分析的重点在于i循环中的赋值语句x=3和j循环中的赋值语句x=4。它们的位置决定了,只要进入i循环,那么x的值就为3;而进入j循环后,x又被重新赋值为4。所以最终的结果由以下语句决定: x=4 For k=1 To 2 x=x+5 Next k 当程序运行结束之后,x的值为14。,10.1 程序流程控制,例13:试分析如下程序运行结束之后变量k的值。 实例:10_13 Dim i,j,k As Integer i=1 Do For j=1 To i Step 2 k=k+j Next j i=i+2 Loop Until i8 为显示结果,实例中稍有变化。,本例是DoLoop Until循环结构和For循环的嵌套,分析的重点在于变量i值的变化过程,它即是For循环的终止值,又控制了DoLoop Until循环的条件。i值的变化在DoLoop Until循环中由i=i+2赋值语句来进行,当i8时程序运行结束,所以i可能的值为1、3、5、7。For循环中步长为2,当i=1时,k=k+1=1;当i=3时,k=k+1+3=5;当i=5时,k=k+1+3+5=14;当i=7时,k=k+1+3+5+7=30。当循环结束之后k的值为30。,10.1 程序流程控制,例14:试分析如下程序运行结束之后消息框中显示的内容. 实例:10_14 Dim str1,str2 As String Dim I As Integer str1=”abcdef” For i=1 To Len(str1) Step 2 str2=UCase(Mid(str1,i,1)+str2 Next i MsgBox str2 为显示结果,实例中稍有变化。,本例中使用了字符串函数Len()、Mid()和大小写转换函数Ucase()。由于字符串str1的值不发生变化,所以Len(str1)的值固定为6。因此For循环变量i的取值为1、3和5(步长为2),Ucase(Mid(str1,i,1)实际上就是取str1中第i个字符然后再转换为大写字母,当i=1时,str2=A;当i=3时,str2=CA;当i=5时,str2=ECA。当程序运行结束之后,消息框中显示的内容为ECA。,10.1 程序流程控制,例15:窗体中有一名为Command1的命令按钮,其单击事件过程如下所示,试分析当单击该命令按钮后消息框中显示的内容。 实例:10_15 Private Sub Command1_Click() Dim a(10,10) For m=2 To 4 For n=4 To 5 a(m,n)=m*n Next n Next m MsgBox a(2,5)+a(3,4)+a(4,5) End Sub,本例是For循环嵌套和二维数组的应用。For循环的作用在于为数组元素赋值a(m,n)=m*n,因此需要考虑的是循环过程中,数组元素a(2,5)、a(3,4)和a(4,5)是否已经赋值,由于m为24,n为45,三者都在范围内,所以a(2,5)=10、a(3,4)=12、a(4,5)=20,因此a(2,5)+a(3,4)+a(4,5)=42。当程序运行结束之后消息框中显示的内容为42。,10.1 程序流程控制,例16:计算 要求:在如图10.5所示的“计算”窗体中有一名为Text1(关联标签为“请输入N值”)的文本框和一名为Command1(标题为“计算”)的命令按钮,在文本框中输入一个正整数,单击Comman1后在消息框中显示计算结果。 解题思路:该表达式每一项均是一个求 的多项式。每个多项式有相同的特点:从1不断除到某一个数。(或者理解为:分母都是从1一直累乘到某一个数)这样,表达式中的每一项就都可以通过一个相同的求值过程来完成。需要注意的是终止值是不断变化到n的。 在Text1中输入5,单击Command1命令按钮后的结果如图10.6所示。 图10.5-10.6 实例:10_16,10.1 程序流程控制,例17:在如图10.7所示的“质数”窗体中有一标题为“筛选”的命令按钮(名称为Command1)和一名为Label1的标签控件。要求:单击“筛选”按钮后,在标签框中显示出50100之间的所有质数。试用循环结构和IfThenElseEnd If选择结构实现。 解题思路:首先,应该清楚怎样判断一个数是否是质数。作为质数,除了1和它本身之外,不能再被其他数整除。那么只需判断该数是否存在1和它本身之外的因子,如果存在,这两个因子必然是一个大于或等于该数的平方根,另一个小于或等于该数的平方根,并且这两个因子是成对出现的。所以只要找出其中较小的一个因子即可认为该数不是质数,否则,该数就是质数。然后,依次判断其他的数是否是质数。 图10.7 实例:10_17,10.1 程序流程控制,例18:试用For循环结构实现一个用“*”在消息框中打印矩形的程序。 要求:在如图10.8所示的“打印矩形”窗体中关联标签为“个数”(名称为Text1)的文本框内输入一个数字N,单击标题为“显示结果”(名称为Command1)的命令按钮后,在消息框中显示由“*”构成的N行N列矩形。 解题思路:首先,应该考虑由“*”组成的矩形是由行和列构成的,行数和列数由用户输入的数字N(取值于文本框控件Text1)来决定,因此要用For循环的嵌套来实现,并且终止值都为N;其次,结果要在循环结束之后显示,因此在每行结束之后都要加上回车符Chr(13)和换行符Chr(10)。 单击“显示结果”按钮后的结果如图10.9所示。 图10.8-10.9 实例:10_18,10.2 文件,例19:通过文件的应用破解Access密码。 解题思路:Access在加密中引入了该文件的创建日期。所以,第一步,调整系统时间后新建一个Access文件,使得新建的文件和要破解密码的文件,在创建日期上是相同的。第二步,需要知道Access密码存放在文件的什么位置。对一个Access文件,它的密码存放的位置的偏移地址是H43。第三步,需要知道的是,Access文件的密码在存储中与实际输入的密码字符之间的关系是什么。实际上,Access密码在存储中是经过异或运算得到的。异或运算具有如下特点:如果A Xor B = C,那么A Xor C = B 和C Xor B = A都成立。由上述已知条件,就不难编写该解密程序。,10.3 过程调用,例20:在窗体有一名为Command1的命令按钮和一名为Text1文本框,命令按钮的单击事件过程如下所示,试分析单击Command1命令按钮后文本框Text1中的显示内容。 实例:10_20 Private Sub Command1_Click() Dim x As Integer,y As Integer,z As Integer x=5:y=7:z=0 Me!Text1=” p1(x,y,z) Me!Text1=z End Sub Sub p1(a As Integer,b As Integer,c As Integer) c=a+b End Sub 为显示结果,实例中稍有变化。,本例是过程调用的应用,要求形参和实参的数据类型及数量一致。子过程pl定义了整型形参a、b和c,命令按钮Command1的单击事件过程中定义了整型实参x、y和z,也就是说a、b、c分别对应x、y、z。缺省的参数传递方式为ByRef,为“双向作用”,实参和形参可以互相影响。因此,单击Command1命令按钮后文本框Text1中的显示内容为12。,10.3 过程调用,例21:窗体中有一名称为Command1的命令按钮,其单击事件过程如下所示,试分析单击Command1命令按钮后消息框中的显示内容。 实例:10_21 Private Sub s(ByVal p As Integer) p=p*3 End Sub Private Sub Command1_Click() Dim I As Integer i=3 s(i) If i10 Then i=i3 End If MsgBox i End Sub,本例是过程调用的应用,分析的重点在于参数的传递方式:ByVal为“单向作用”,形参的值不会影响实参。因此,调用前实参i的值为3,调用后实参i的值仍然为3,所以单击Command1命令按钮后文本框Text1中的显示内容为3。,10.3 过程调用,例22:窗体有一名称为Command1的命令按钮,其单击事件过程如下所示,试分析单击Command1命令按钮后消息框中的显示内容。 实例:10_22 Public x As Integer Private Sub Command1_Click() x=10 Call s1 Call s2 MsgBox x End Sub Private Sub s1() Dim x As Integer x=x*2 End Sub Private Sub s2() x=x*3 End Sub,本例是过程调用的应用,分析的重点在于变量x的作用域。Public x As Integer声明在所有过程之外的起始位置,作用域为模块范围,运行时在模块所包含的所有子过程和函数过程中可见;而子过程s1中的Dim x As Integer,定义在过程内部,其作用域为局部范围,只有执行该过程时才可见,并且其值不会传回。命令按钮的单击事件过程中调用了子过程s1和s2,实际上影响最终显示结果的只有s2,所以结果为30。,10.3 过程调用,例23:求表达式(1+2+3)+(1+2+3+4)+ +(1+2+3+n)之和。(n4) 图:10.10-10.11 实例:10_23 要求:编写一个计算1+2+n的子过程a,并在命令按钮Command1的单击事件过程中调用,根据用户输入的n值求解(1+2+3)+(1+2+3+4)+ +(1+2+3+n)。 说明:在如图10.10所示的“计算结果”窗体中有一名为Command1(标题为“计算”)的命令按钮和名为Text1(关联标签为“请输入N值”)、Text2(关联标签为“结果”)的两个文本框控件,要求在Text1中输入n值,单击“计算”命令按钮后,在Text2中显示计算结果,如图10.11所示。 解题思路:该表达式每一项均是一个完成累加求和的多项式。每个多项式有相同的特点:都是从1一直累加到某一个数。这样,表达式中的每一项就都可以通过一个相同的求值过程来完成。通过调用Sub子程序可以完成这一过程,当然终止值要考虑是不断变化到n的。,10.3 过程调用,例24:在如图10.12所示的“判定奇偶数”窗体中有一个名为Command1(标题为“判定”)的命令按钮和一个名为Text1(关联标签为“请输入一个数字”)的文本框,且文本框的内容为空,要求:编写一个判定奇偶数的函数过程,并在命令按钮的单击事件过程中作为IIf函数的条件式引用,最终在消息框中显示判定结果,如图10.13所示。 解题思路:奇偶数的判定可以通过求模(Mod)2来实现,结果为0是偶数,否则是奇数。IIf函数有三个参数,第一个参数为条件表达式,第二、三个参数是返回值,如果条件式为真返回第二个参数;条件式为假返回第三个参数。 图10.12-10.13 实例:10_24,10.4 计时器Timer,例25:试用窗体的计时器触发事件设计一个如图10.14所示的登录窗体,要求:打开该窗体后输入用户名和密码,登录操作要求在20秒内完成(以单击“登录”命令按钮为截止时间),如果在20秒内没有完成登录操作则倒计时达到0秒时自动关闭登录窗体。 说明:登录窗体中有名为Text1(关联标签为“用户名”)和Text2(关联标签为“密码”)的两个文本框,名为Login(标题为“登录”)的一个命令按钮,名为Label1(用来显示倒计时时间)的一个标签。 解题思路:VBA中通过设置窗体的“计时器间隔”(TimerInterval)属性与添加“计时器触发”(Timer)事件来完成“定时”功能,“计时器间隔”属性值以毫秒为单位,1000表示间隔为1秒。另外,需要考虑定义一个逻辑变量,用它来控制当单击“登录”命令按钮后停止倒计时。 实例:10_25,10.5 ADO数据库编程实例,例26:试用ADO实现在表中添加记录的应用。 实例:10_26 要求:当前工程数据库中表“Stud”用来存储学生的基本信息,包括:学号、姓名、性别和院系,在如图10.15所示的“学生”窗体中有名为tNo、tName、tSex和tDept四个文本框分别与之相对应。当单击窗体中的“添加”命令按钮(名称为Command1)时,首先判断学号是否存在,如果不存在则向“Stud”表中添加学生记录;如果学号存在,则给出提示信息。 解题思路:ADO是基于组件的数据库编程接口,包含了Connection、Command、RecordSet、Field和Error五个对象,执行SQL语句要用到Connection对象的Execute方法;获取记录集要用到RecordSet对象的Open方法。本例应先以用户输入的学号为条件使用RecordSet对象的Open方法在数据源表中查找相关记录,如果找到表示学号存在,给出错误提示;否则,使用Connection对象的Execute方法将用户输入的内容添加到Stud表中。,10.5 ADO数据库编程实例,例27:试用ADO实现商品打折的应用。 实例:10_27 要求:当前工程数据库中表“商品”用来存储商品的基本信息,包括:商品编号、名称、规格和销售价格,在如图10.16所示的“商品”窗体中有名为tNo、tName、tType和tCost四个文本框分别与之相对应。当在窗体中名为Text1(关联标签为“折扣”)的文本框中输入折扣(值为小数),单击“计算打折后价格”命令按钮(名称为Command1)后在窗体中显示商品打折后的价格。(注意:打折是对所有商品进行的,可通过导航按钮查看其它商品信息) 解题思路:ADO是基于组件的数据库编程接口,包含了Connection、Command、RecordSet、Field和Error五个对象,执行SQL语句要用到Connection对象的Execute方法;获取记录集要用到RecordSet对象的Open方法;操作字段数据信息要用到Field。本例应先使用RecordSet对象的Open方法在数据源表中获取所有商品记录;然后设置Field对象的值为“销售价格”;最后使用循环遍历整个记录集,并对每条记录的“销售价格”做调整。,本章小结,本章主要通过丰富的实例对VBA在应用过程中的难点和重点加以解释说明,针对给定问题详细地说明了程序分析的重点和程序设计的思路,这一点读者在今后学习和使用过程可以参考借鉴。通过实例分析和设计是熟练掌握VBA程序设计的一种方法,只有日常的不断积累才能够有助于我们实际应用水平的提高。,
展开阅读全文