第9章 Sub过程.docx
- 文档编号:25758035
- 上传时间:2023-06-13
- 格式:DOCX
- 页数:13
- 大小:20.74KB
第9章 Sub过程.docx
《第9章 Sub过程.docx》由会员分享,可在线阅读,更多相关《第9章 Sub过程.docx(13页珍藏版)》请在冰豆网上搜索。
第9章Sub过程
第9章 Sub过程
第9章 Sub过程
VBA应用程序是由过程组成的,使用Excel VBA开发应用程序就是在编写过程。
前面各章中已经多次使用到过程。
9.1 过程的分类
过程是指由一组完成指定任务的VBA语句组成的代码集合。
在VBA中,可执行的代码都必须放置在过程中。
VBA中的过程可分为事件过程、属性过程和通用过程。
1. 事件过程
事件过程是当发生某个事件(如单击、双击)时,对该事件做出响应的程序段。
事件过程位于对象所在模块中,例如有关工作簿的事件代码放置在ThisWorkbook对象的代码模块中。
在打开工作簿时将调用的程序代码可放置在Workbook对象的Open事件中,如图9-1所示。
2. 属性过程
在“类模块”中设置类的属性值时,可通过“属性过程”来完成。
3. 通用过程
有时在不同的事件过程中需要执行一段相同的代码,可以把这段代码独立出来,作为一个过程,这样的过程称为“通用过程”。
在VBA中,通用过程又分为两类:
Sub(子程序)过程和Function(函数)过程。
●Sub过程:
这类过程完成指定任务,执行结束后不返回值。
●Function过程:
这类过程完成指定的任务,并返回一个值供调用程序使用。
一般通用过程保存在VBA的“模块”中,一个模块可以包含任意数量的过程,同时,一个VBA工程可以包括任意多个模块。
9.2 定义Sub过程
在使用之前,需要先在模块中定义过程。
VBA中有两种定义过程的方法:
一种方法是使用窗体创建过程的结构,再在过程中编写相应的代码;另一种方法是在模块中直接输入代码来定义过程。
】
9.2.1 添加过程
通用过程一般保存在模块中,在创建过程前可先通过选择“插入”ㄧ“模块”命令向工程中添加一个模块。
VBA开发环境中提供了一个“添加过程”对话框,通过该对话框可方便地向当前模块中添加过程。
具体操作步骤如下。
步骤1 在VBE环境中选择“插入”ㄧ“过程”命令,打开如图9-2所示的“添加过程”对话框。
使用图9-2所示对话框除了可以插入一个新的Sub过程、Function过程或属性过程,还可以设置Public或Private有效范围,并使得过程中所有的局部变量成为静态变量。
步骤2 在“名称”文本框中输入过程的名称。
步骤3 在“类型”中选择“子程序”单选按钮。
它有三种类型可以选择:
●子程序,为Sub过程;
●函数,为Function过程;
●属性,为Property过程。
步骤4 在“范围”中选中“公共的”单选按钮,设置过程为全局的(即在工程的各模块中都可以调用该过程),将在过程前面添加Public关键字。
还可根据需要选中下方的“把所有局部变量声明为静态变量”复选框,如果选中该复选框,将在过程名前面添加Static关键字。
步骤5 设置好以上参数后,单击“确定”按钮,VBA将自动生成过程的结构代码,如图9-3所示。
在该过程结构中编写以下代码:
Public Sub TestSub()
MsgBox "这是使用对话框创建的Sub过程!
"
End Sub
9.2.2 使用代码创建Sub过程
大多数开发人员更习惯于通过手工输入的方式来创建Sub过程,因为这更利于了解创建Sub过程中各元素的作用。
Sub过程的结构如下:
[PrivateㄧPublicㄧFriend][Static]Sub过程名[(参数列表)]
[语句序列1]
[ExitSub]
[语句序列2]
End Sub
过程由Sub和End Sub及之间的VBA代码构成。
其中在Sub前面可加上限制过程作用域的关键字,主要有以下几个:
●Privat,表示只有在包含其声明的模块中的其他过程可以访问该Sub过程。
●Public,表示所有模块的所有其他过程都可访问这个Sub过程。
如果在Sub前面省略关键字,则表示其为Public。
●Friend,只能在类模块中使用,表示该Sub过程在整个工程中都是可见的,但对象实例的控制者是不可见的。
●Static,表示在调用时保留Sub过程的局部变量的值。
Static属性对在Sub之外声明的变量不会产生影响,即使过程中也使用了这些变量。
注意:
每一个过程都必须对应一个名称,通过过程名称可以调用该过程。
过程名称的命名应符合标识符命名规则。
End Sub语句标志着Sub过程的结束。
为了能正确运行,每个Sub过程必须有一个End Sub语句,当程序执行到该语句时就结束该过程的运行。
另外,在过程中可以使用一个或多个Exit Sub语句直接退出过程的执行。
注意:
Sub过程的定义不能嵌套,即不能将过程的定义放在另一个过程中。
在了解了Sub过程结构及各语句的作用后,就可在代码窗口中创建Sub过程了。
具体操作步骤如下。
步骤1 双击“工程资源管理”窗口中的“模块1”,打开代码窗口。
步骤2 在代码窗口中输入“Sub手工创建Sub过程”,并按回车键。
步骤3 系统自动在过程名后面添加一对括号,并自动生成“End Sub”语句,如图9-4所示。
步骤4 在过程结构中输入以下代码:
Sub 手工创建Sub过程()
MsgBox "这是手工输入代码创建的Sub过程!
"
End Sub
9.3 调用Sub过程
使用过程的目的就是将一个应用程序划分为多个小模块,每个小模块完成一个具体的功能,最后通过组合这些过程来完成一个大任务。
在VBA中,通过调用定义好的过程来执行程序。
Sub过程的调用分两种方式:
一种是在VBA代码中调用Sub过程;另一种是在Excel中以调用宏的方式来执行Sub过程。
93.1 调用Sub过程
在程序中调用Sub过程有两种方式:
一是把过程名字放在一个Call语句中,另一种是把过程名作为一个语句来使用。
1. 用Call语句调用Sub过程
用Call语句可将程序执行控制权转移到一个Sub过程或Function过程中,在过程中遇到End Sub或Exit Sub语句后,再将控制权返回到调用程序的下一行。
Call语句的语法格式很简单:
Call 过程名(过程参数列表)
如果使用Call语句来调用一个需要参数的过程,“参数列表”必须要加上括号;如果过程没有参数,可省略过程名后的括号。
例如,以下代码:
Call TestSub
将调用上节定义的过程“TestSub”。
2. 将过程作为一个语句
在调用过程时,如果省略Call关键字,过程也可调用。
与使用Call关键字不同的是,如果过程有参数,这种调用方式必须要省略“参数列表”外面的括号。
例如:
Call Test(a,b)
可改为以下形式:
Test a,b
下面以实例演示Sub过程的定义和调用。
本例首先创建一个名为“延时”的过程,该过程根据传递的参数来决定程序延时的长度;然后再创建一个调用“延时”过程的过程,具体步骤如下。
步骤1 在“模块1”中输入以下代码:
Sub 延时(ByVal DelayTime As Integer)
Dim NewTime As Long '保存延时到达的时刻
NewTime=Timer+DelayTime'计算延时后的时刻
Do While Timer <NewTime'如果未达到规定的时间,空循环
Loop
End Sub
程序中使用Timer函数获得系统从午夜开始计算的秒数(数值较大,需将NewTime变量声明为Long,用Integer类型的话将出现溢出),把这个时间加上需要延时的秒数,得到延时到达时的秒数;然后程序通过一个空循环语句反复检查是不是超过这个时间,超过就退出程序,达到延时的效果。
步骤2 接着输入以下测试过程的代码:
Sub 测试延时()
Dim iAs Integer
i= Val(InputBox("开始测试延时程序,请输入延时的秒数:
","延时测试",1))
延时 i
MsgBox "已延时" & i & "秒。
"
End Sub
该过程要求用户输入需要延时的时长,然后调用“延时”过程,该过程执行完毕后,返回调用过程执行下一条语句(用MsgBox显示一条提示信息)。
程序中使用
延时 i
的方式来调用过程,也可使用Call的方式,代码如下:
Call 延时(i)
使用Call语句,就需要将参数i用括号引起来。
9.3.2 以宏方式调用Sub过程
在Excel中录制宏时,将创建一个Sub过程,所以也可将Sub过程作为一个宏来调用。
具体步骤如下。
步骤1 切换到Excel工作界面(或关闭VBE环境)。
步骤2 在工作表中绘制一个按钮,打开如图9-5所示的“指定宏”对话框。
步骤3 在对话框中选择宏“手工创建Sub过程”,单击“确定”按钮,即可将该宏与插入的按钮绑定在一起。
单击该按钮执行“手工创建Sub过程”过程。
注意:
以宏方式调用Sub过程无法给过程传递参数,所以需用参数的过程不会显示在图9-5所示的宏列表中。
9.4 传递参数
为了使过程更具有通用性,很多过程都需要设置参数。
传递不同的参数给过程,可使执行的结果不同。
对于有参数的过程,在调用时必须将实际参数传递给过程,完成形参与实参的结合,过程再使用实参执行代码。
9.4.1 形参与实参的结合
形参是形式参数的简称,是在Sub过程的定义中出现的变量名。
因其没有具体的值,只是形式上的参数,所以称为形参。
实参是实际参数的简称,是在调用Sub过程时传递给Sub过程的值。
在VBA中实参可为常量、变量、数组或对象类的数据。
在VBA中,形参与实参的结合有两种方式。
1. 按位置结合
大多数程序语言调用子过程时都位置结合形参与实参。
在这种方式下,调用Sub过程时使用的实参次序必须与定义Sub过程时设置的参数次序相对应。
例如,使用以下代码定义Sub子过程:
Sub Test(arglAsInteger,arg2AsLong,arg3AsString)
……
End Sub
子过程中定义了三个参数,可使用以下语句调用该子过程:
Call Test(1,2,"abc")
此时,Test子过程的形参与实参的结合如图9-6所示。
2. 按命名参数方式结合
形参与实参的另一种结合方式是按形参名称来进行,即在调用Sub过程时,输入形参的名称,将形参名称与实参用“:
=”符号连接起来。
与按位置结合方式不同,使用这种方式时,调用过程的参数位置可随意设置。
例如,使用名结合的方式调用上面定义的“Test”子过程:
Call Test(arg1:
=1,arg3:
="abc",arg2:
=2)
或
Call Test(arg3:
="abc",arg1:
=1,arg2:
=2)
都可得到同样的效果。
按命名参数方式结合形参和实参,在输入代码时要增加一些工作量,但其好处也显而易见;通过这种方式可改变过程调用的可读性,减少程序出错的相对性。
9.4.2 传地址
在VBA中,实参可通过两种方式将数据传递给形参,即传地址和传值。
传地址是VBA默认的方式,在定义过程时,如果在形参前面有关键字ByRef,则该参数通过传地址的方式传递。
传地址是指将实参变量的地址传递给形参,这让形参和实参都代表同一个内存区域。
所以,在过程中对形参的值进行了改变,返回到调用程序后,使用实参变量名也可访问到改变后的值。
例如,有以下子过程,形参使用传地址方式进行传递。
Sub 传地址测试(ByRef a As Integer)
a=a+1
Debug.Print"子过程中的变量A="&a
End Sub
使用以下过程调用“传地址测试”子过程。
Sub 调用过程()
Dim b As Integer
b=3
Debug.Print"主程序中变量B="&b
传地址测试 b
Debug.Print"主程序中变量B="&b
End Sub
程序首先给变量b赋初始值,并输出变量b的值(为3),接着调用“传地址测试”子过程,使用传地址方式传递变量,使子过程的形参变量a的地址与调用过程中的实参变量b的地址相同。
在子过程中将变量a增加1,并输出变量a的值(为4),返回调用过程后,因为变量b和为题a是指向同一内存单元的,所以变量b的值也为4。
运行以上程序后,“立即窗口”的显示结果如图9-7所示。
前面说过,Sub过程不能返回运算结果。
如果需要Sub过程返回值时,通过使用ByRef方式来定义形参就可将子过程的运算数据返回到调用程序中。
注意:
当形参定义为ByRef形式时,只有当实参为一个变量时,才能按传地址方式传递参数;如果实参为一个表达式或常量,则不能按地址方式传递参数。
9.4.3 传值
传值就是将实参的值作为一个副本,赋值给形参(相当于执行一次赋值操作),而不是传送实参的地址给形参。
定义过程时,在形参的前面添加ByVal关键字,则该参数就按传值方式传递,否则用传地址方式传递。
使用传值方式传递参数时,传递的只是变量的副本。
如果过程改变了形参的值,所做改变也只在过程内部起作用,不会影响到调用程序中变量的值。
例如,将上例中的代码改写为以下形式:
Sub 传值测试(ByVal a As Integer)
a=a+1
Debug.Print "子过程中的变量A="&a
End Sub
过程中用ByVal关键字将参数传递定义为传值方式:
Sub 调用传值测试()
Dim b As Integer
b=3
Debug。
Print "主程序中变量B="&b
传值测试 b
Debug.Print"主程序中变量B="&b
End Sub
执行以上过程后“立即窗口”显示的内容如图9-8所示。
从图9-8的运行结果可以看出,主程序中的变量b和子过程中的变量a之间是被隔离的,即在子过程中改变了变量a的值的情况下,并不会影响主程序中的变量b的值。
在程序中使用传地址比传值效率高,但是传地址方式中,形参不是一个真正的局部变量,有可能对程序产生不必要的影响。
如果没有特殊要求,应尽量使用传值方式。
9.4.4 传递数组参数
数组作为在内存中的一片连续区域,也可作为一个参数传递给Sub子过程进行处理。
数组一般是通过传地址方式进行传递的。
例如,编写一个求数组中最大数的过程。
Sub 求最大数(a()AsInteger)
Dim i As Integer,maxAsInteger
max=a(LBound(a))
Fori=LBound(a)ToUBound(a)
Ifa(i)>maxThenmax=a(i)
Next
Debug.Print"最大数:
"&max
End Sub
在该过程中,将形参定义为一个数组。
使用数组作为形参时,必须输入数组名并跟上一对空括号。
对传递过程的数组,应使用LBound函数和UBound函数获取其下标的下界和上界,然后程序才能遍历数组,或对数组,进行其他相关的操作。
在本例中,将最大值保存在另一个变量max和每个数组元素进行比较,如果数组元素比max大,则将其值赋给max,确保max中始终保存着最大数。
接下来编写调用“求最大数”的代码:
在程序中,调用“求最大数”子过程,并将数组MyArray作为参数传递到该子过程中进行处理。
9.5 可选参数和可变参数
在创建VBA的过程时,除了可使用前面介绍的方法设置参数按地址或按值传递之外,还可以根据需要为过程设置可选参数和可变参数。
9.5.1 可选参数
通常情况下,一个VBA过程中的形参数量是固定的,调用时提供的实参数量也是固定的。
在有的过程中,可能有必需收集信息和可选信息,如收集顾客的信息时必须提供“姓名”、“性别”,而“身份证号码”则是可选的(可提供,也可不提供)。
VBA的过程可以通过在形参前面加上Optional关键字来设置该形参为可选参数。
在过程内部通过使用IsMissing函数可测试调用程序是否传递了该可选。
例如:
该过程有三个参数,前两个参数为必须使用的,最后一个参数使用了Optional关键字,表示该参数是可选参数。
调用该过程时,可以提供两个参数,也可以提供三个参数:
'可选参数"王小凤","女"
或:
可选参数"王小凤","女","410214198501012345"
注意:
过程中可定义多个可选参数,但可选参数必须放在参数表的最后,而且必须是Variant类型。
9.5.2 可变参数
无论是固定参数还是可选参数,在定义过程时都已经指定了参数的个数。
在VBA中,还可以定义可变参数,即参数的个数在定义时是未知的。
在定义过程的参数表时,在最后一个参数前面加上ParamArray关键字,过程将接受任意个数的参数。
例如,使用可变参数编写求和函数SUM.
科学试验中定义了两个形参,第一个用于返回计算的结果;第二个参数使用ParamArray关键字将其定义为可变参数。
可变参数为一个数组。
程序中使用LBound函数和UBound函数获得数组下标的上下界,然后进行累加,并将累加的结果保存在第一个参数中,用于返回给调用程序。
调用以上子过程的代码如下:
程序中定义了一个变量i,用来获得子过程运算的结果。
参数传递时,将参数i用传地址方式传递给“MySum”子过程的形参intTotal,将后面的“1,2,3,4,5,6,7,8”作为一个数组传递给形参intNum。
注意:
ParamArray只能用于参数列表的最后一个参数,指明最后这个参数是一个Variant元素的Optional数组。
ParamArray关键字不能与ByVal,
ByRef,或Optional一起使用。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第9章 Sub过程 Sub 过程