Excel高级教程:VBA创建Sub过程和案例教程(VBA调用SUB实例)
yuyutoo 2024-10-20 13:06 7 浏览 0 评论
过程是组织和运行一组VBA代码的逻辑单元。VBA中包括Sub过程(子过程)、Function过程(函数过程)、事件过程和属性过程。事件过程实际上属于Sub过程,只不过它依附于特定的对象。下面我们一起来看看VBA创建Sub过程和案例教程吧!
一、声明Sub过程
Sub过程是VBA中最常使用的一类过程,在Excel中录制的宏就是Sub过程。使用过程的主要原因之一是为了简化大量代码堆积在一起导致的复杂程度。可以将实现一个程序中每个独立小功能的代码分别放入不同的过程中,确保每个过程只实现单一的简单功能,最后在一个过程中依次调用包含独立小功能的各个过程。这种利用过程来组织程序的方式使编写和调试代码变得更加简单高效。
一个Sub过程由Sub语句开始,End Sub语句结束,在这两个语句之间放置所需的VBA代码。声明Sub过程的语法格式如下:
[Private | Public] [Static] Sub name [(arglist)]
[statements]
[Exit Sub]
[statements]
End Sub
Private:可选,表示声明的是一个私有的Sub过程,只有在该过程所在的模块中的其他过程可以访问该过程,其他模块中的过程无法访问该过程。
Public:可选,表示声明的是一个公共的Sub过程,所有模块中的所有其他过程都可以访问该过程。如果在包含Option Private Module语句的模块中声明该过程,即使该过程使用了Public关键字,也仍然会变为私有过程。
Static:可选,Sub过程运行结束后保留过程中所使用的变量的值。
Sub:必选,表示Sub过程的开始。
name:必选,Sub过程的名称,与变量的命名规则相同。
arglist:可选,一对圆括号中可以包含一个或多个参数,这些参数用于向Sub过程传递数据以供Sub过程处理,各参数之间以逗号分隔。如果过程不包含任何参数,则必须保留一对空括号。
statements:可选,Sub过程中包含的VBA代码。
Exit Sub:可选,中途退出Sub过程。
End Sub:必选,表示Sub过程的结束。
模块中可以包含任意多个Sub过程,在每个Sub过程中放置用于完成不同功能的VBA代码。一些代码需要放置到模块顶部的声明部分中,即位于所有过程的最上方,这些代码包括模块级变量的声明、用户自定义数据类型、Option Base语句等。
我们可以使用两种方法声明一个Sub过程:手动输入和“添加过程”对话框,下面将分别进行介绍。
1.手动输入法声明Sub过程
打开VBE窗口,在指定的VBA工程中插入一个模块,打开该模块的代码窗口,然后输入关键字Sub和过程的名称如test,按Enter键后Excel会自动添加End Sub语句。创建好的Sub过程如下所示,接下来可以在Sub和End Sub之间添加所需的VBA代码。
Sub test()
End Sub
2.“添加过程”对话框法声明Sub过程
除了手动输入Sub和End Sub语句之外,还可以使用“添加过程”对话框来声明Sub过程,而且该方法还可用于创建Function过程和属性过程。单击VBE窗口菜单栏中的“插入”|“过程”命令,打开“添加过程”对话框,如下图所示。在“名称”文本框中输入Sub过程的名称,然后在“类型”区域中选择“子程序”以创建Sub过程,最后单击“确定”按钮。
二、Sub过程的作用域
Sub过程的作用域与变量类似,但是只分为模块级和工程级两种。对于Sub过程而言,可以将模块级的Sub过程称为私有过程,将工程级的Sub过程称为公有过程。区分Sub过程是私有过程还是公有过程的最直接方法,是在Sub语句之前是否包含Public或Private关键字,以Public关键字开头的Sub过程是公有过程,以Private关键字开头的Sub过程是私有过程。如果既没有Public关键字也没有Private关键字,而是直接以Sub关键字开头,那么该过程是公有过程。
在下面的三个过程中,前两个过程是公有过程,第三个过程是私有过程。
Public Sub 公有过程()
MsgBox “这是一个公有过程”
End Sub
Sub 公有过程2()MsgBox “这也是一个公有过程”
End SubPrivate Sub 私有过程()
MsgBox “这是一个私有过程”
End Sub
如果使用前面介绍的第二种方法声明Sub过程,则可以在“添加过程”对话框的“范围”区域中选择过程的作用域。在该对话框中选择“把所有局部变量声明为静态变量”选项相当于使用Static关键字声明过程,“局部变量”指的就是过程级变量。
VBA中的大多数过程都是公有过程,用户在标准模块中创建的Sub过程通常都是公有过程,录制的宏也是公有过程,而在诸如ThisWorkbook、Sheet等类模块中的工作簿和工作表的事件过程都是私有过程。公有过程可以被其所在的工程中的任何模块中的任何过程调用,私有过程只能被其所在的模块中的其他过程调用,而不能被其他模块中的过程调用。提示:如果不希望让创建的Sub过程显示在“宏”对话框中,而只想在VBA代码中进行调用,则需要将该Sub过程创建为私有过程,或者在创建该Sub过程时为其提供参数。
三、在VBA中调用Sub过程
将功能复杂的程序分解成包含多个功能相对独立的Sub过程,可使程序的结构更清晰,也会使代码的编写和维护更容易。可能会有这样一些Sub过程,它们完成的是一些通用的操作,这些操作会在其他多个Sub过程所完成的任务中用到,比如打开文件的操作。此时在这些Sub过程中只要调用包含打开文件这一操作的Sub过程,就可以实现打开文件的操作,而不必重复编写打开文件的VBA代码。可以使用以下几种方法调用Sub过程:
直接输入过程的名称。如果过程包含参数,则需要输入过程的名称及其参数。如果过程包含多个参数,则需要在参数之间使用逗号进行分隔。
输入Call关键字,然后输入过程的名称。如果过程包含参数,则需要输入过程的名称及其参数,并将所有参数放置到一对圆括号中,参数之间以逗号分隔。
使用Excel中的Application对象的Run方法运行过程,过程的名称以字符串的形式作为Run方法的参数,过程的参数与过程的名称之间需要使用逗号进行分隔,所有参数不需要放置到一对圆括号中。
为了避免表述混乱,可以将调用某个Sub过程的过程称为主调过程,将被其他过程调用的Sub过程称为被调过程。
案例一:调用过程
下面的代码使用第一种方法调用名为“确认退出”的Sub过程,其中名为“主过程”的Sub过程是主调过程,名为“确认退出”的Sub过程是被调过程。
Sub 主过程()
确认退出
End Sub
Sub 确认退出()
MsgBox “是否退出程序?”, vbYesNo + vbQuestion, “退出程序”
End Sub
可以使用Call语句来调用Sub过程,与直接使用过程名的调用方法具有相同的效果,如下所示:
Call 确认退出
案例2:调用包含参数的过程
下面的代码说明了调用包含参数的Sub过程的方法。假设前面案例中的“确认退出”过程包含两个参数,分别用于指定对话框的标题和内容,而对话框中的按钮类型已在名为“确认退出”的被调过程中指定。可以看出,为Sub过程提供参数可以为用户提供更大的灵活性,在本例中可以让用户自定义在对话框中显示的提示消息和标题的具体内容。
Sub 主过程()
确认退出 “退出吗?”, “退出”
End SubSub 主过程2()
Call 确认退出(“退出吗?”, “退出”)
End SubSub 确认退出(varPrompt, varTitle)
MsgBox varPrompt, vbYesNo + vbQuestion, varTitle
End Sub
案例3:使用Application.Run方法调用过程
下面的代码使用Application.Run方法代替Call语句调用Sub过程:
Sub 主过程()
Application.Run “确认退出”, “退出吗?”, “退出”
End SubSub 确认退出(varPrompt, varTitle)
MsgBox varPrompt, vbYesNo + vbQuestion, varTitle
End Sub
前面介绍的过程调用方式都是主调过程与被调过程位于同一个模块的情况,这种调用方式同样适用于它们位于不同模块的情况。但是以下两种例外情况需要注意。
(1)主调过程与被调过程位于同一个模块中,在另一个模块中还存在一个同名的被调过程。
在这种情况下,如果使用前面介绍的方法调用被调过程,那么调用的是与主调过程在同一个模块中的被调过程。如果想要调用的是位于另一个模块中具有相同名称的被调过程,则需要在调用时输入模块名以限定被调过程的来源。
案例4:调用位于不同模块中的过程
工程中包含名为“模块1”和“模块2”的两个模块,在模块1和模块2中都有一个名为“确认退出”的被调过程,模块1中还有一个名为“主过程”的主调过程。如果要在主调过程中调用模块2中的被调过程,则需要先输入被调过程所在的模块名,然后输入一个句点,再输入被调过程的名称或从自动弹出列表中选择被调过程。也可以使用Call语句进行调用,但是后续输入方法相同。如下图所示显示了代码窗口中的过程调用情况。
Sub 主过程()
模块2.确认退出
End Sub
(2)主调过程与被调过程位于不同的模块中,但它们具有相同的名称。
在这种情况下调用被调过程将会出现运行时错误,此时需要使用与第(1)种情况相同的方法来处理,即在调用被调过程时为其添加模块名以明确指定其来源。
以上介绍的方法调用的都是位于同一个工程中的Sub过程。也可以调用位于其他工程中的过程,此时可以添加对包含被调过程的工作簿的引用。通过VBE窗口菜单栏中的“工具”|“选项”命令,在打开的“引用”对话框中选择包含被调过程的工程,工程名称默认会显示为VBAProject,可以在工程属性对话框中修改工程名称。如果工程对应的工作簿当前未被打开,则需要单击“浏览”按钮打开这个工作簿。
建立引用后就可以调用所引用的工程中的Sub过程了。为了可以准确调用指定的过程,应该使用下面的格式:
工程名.模块名.过程名
如下图所示显示了一个实际调用外部工作簿的案例。外部工作簿使用的是上一个例子用到的工作簿。在当前工作簿中建立对该外部工作簿的引用后,在当前工作簿的模块1中的test过程中使用了下面的代码来调用位于外部工作簿中的模块1中名为“主过程”的过程。外部工作簿对应的工程被命名为MyPorject而没有使用默认的VBAProject,在工程资源管理器中可以看到该名称。
MyProject.模块1.主过程
四、向Sub过程传递参数
所有录制的宏都是公有的Sub过程,这些过程不包含任何参数。为了让Sub过程具有更大的灵活性,可以通过向Sub过程传递参数,从而允许用户为过程提供需要处理的数据,而不是将要处理的数据固定写入到过程内部。包含参数的Sub过程只能被其他过程调用,而不能直接运行,也不会显示在“宏”对话框中。
可以将变量、常量、对象等不同类型的内容作为参数传递给过程,一个过程可以包含一个或多个参数,这些参数可以是必选参数,也可以是可选参数。必选参数是指在调用过程时必须要为该参数提供值,可选参数是指在调用过程时不一定非要为该参数提供值。还可以指定参数的数据类型,方法与为变量指定数据类型相同。
在声明Sub过程时,在过程名右侧的圆括号中输入所需的一个或多个参数,各参数之间以逗号分隔。如果需要,可以使用As关键字为参数指定数据类型。
案例5:在欢迎信息中显示指定的用户名
下面的代码声明的Sub过程(名为Greeting)包含一个参数(名为UserName),该参数的数据类型是String,该参数用于指定要在问候消息中显示的用户名。然后在另一个过程中调用Greeting过程,并使用具体的人名作为参数值提供给该过程。
Sub Greeting(UserName As String)
MsgBox “你好” & UserName & “,欢迎登录”
End SubSub 主过程()
Greeting “John”
End Sub
在上面的主调过程中,也可以声明一个变量,然后为变量赋值,再在调用过程时使用变量作为参数的值进行传递,如下所示:
Sub 主过程2()
Dim strMyName As String
strMyName = “John”
Greeting strMyName
End Sub
在向过程传递参数时可以采用传址和传值两种方式,默认为传址。参数的传址或传值是通过在声明过程时使用ByRef或ByVal关键字指定的,使用ByRef或省略该关键字表示参数是传址的,使用ByVal关键字表示参数是传值的。传址是指传递到过程内部的是变量本身,过程中的代码对变量的修改不只局限于过程内,而且还会影响过程外的代码,相当于过程内、过程外共享这个变量。传值是指传递到过程内部的是变量的副本,过程中的代码对变量的修改只限于过程内,而不会对过程外的其他过程有任何影响。
案例6:参数的传址与传值
下面的代码说明了参数的传址与传值的区别。在“求和”过程中使用ByRef将Number1指定为传址,使用ByVal将Number2指定为传值,因此在主调过程中将声明的两个变量intNum1和intNum2赋值后传递给“求和”过程时,intNum1是传址的,intNum2是传值的。“求和”过程对传递进来的两个变量都执行加1运算,由于第一个变量是传址的,因此加1后的变量结果会改变原变量intNum1的值。而第二个变量由于是传值的,因此加1后的变量结果不会改变原变量intNum2的值。可以在主调过程中使用MsgBox函数在对话框中验证两个变量的值,第一个变量的值为2,第二个变量的值仍为1,如下图所示。
可以在立即窗口中随时验证过程的运行结果。首先需要在VBE窗口中通过单击菜单栏中的“视图”|“立即窗口”命令显示出立即窗口,然后需要在代码中使用Debug.Print语句代替MsgBox函数,以便将变量的值输出到立即窗口中。接下来只需在立即窗口中输入过程名称并按Enter键,即可显示变量的结果,如下图所示。
提示:通常会在Function过程中更频繁地使用参数。
五、Sub过程的递归
递归是指过程调用其自身。任何一个过程都可以递归,但是递归可能会导致内存耗尽而产生运行时错误。在某些情况下也可以利用递归来完成任务。
案例7:验证用户登录
下面的代码运行后会显示一个输入对话框让用户输入用户名,然后检测用户名是否正确,如果不正确则会再次显示该对话框,直到用户输入正确的用户名为止。如果正确则会显示登录成功的消息并立刻结束该过程。由于使用If语句设置了终止递归的判断条件,因此本例中的过程递归不会陷入无限循环。
Sub 用户登录()
Dim strUserName As String
strUserName = InputBox(“请输入用户名:”)
If strUserName = “admin” Then
MsgBox “登录成功!”
Exit Sub
Else
MsgBox “用户名错误,请重新输入!”
用户登录
End If
End Sub
点击关注我们不迷路!
相关推荐
- 如何在HTML中使用JavaScript:从基础到高级的全面指南!
-
“这里是云端源想IT,帮你...
- 推荐9个Github上热门的CSS开源框架
-
大家好,我是Echa。...
- 硬核!知网首篇被引过万的论文讲了啥?作者什么来头?
-
整理|袁小华近日,知网首篇被引量破万的中文论文及其作者备受关注。知网中心网站数据显示,截至2021年7月23日,由华南师范大学教授温忠麟等人发表在《心理学报》2004年05期上的学术论文“中介效应检验...
- 为什么我推荐使用JSX开发Vue3_为什么用vue不用jquery
-
在很长的一段时间中,Vue官方都以简单上手作为其推广的重点。这确实给Vue带来了非常大的用户量,尤其是最追求需求开发效率,往往不那么在意工程代码质量的国内中小企业中,Vue占据的份额极速增长...
-
- 【干货】一文详解html和css,前端开发需要哪些技术?
-
网站开发简介...
-
2025-02-20 18:34 yuyutoo
- 分享几个css实用技巧_cssli
-
本篇将介绍几个css小技巧,目录如下:自定义引用标签的符号重置所有标签样式...
- 如何在浏览器中运行 .NET_怎么用浏览器运行代码
-
概述:...
- 前端-干货分享:更牛逼的CSS管理方法-层(CSS Layers)
-
使用CSS最困难的部分之一是处理CSS的权重值,它可以决定到底哪条规则会最终被应用,尤其是如果你想在Bootstrap这样的框架中覆盖其已有样式,更加显得麻烦。不过随着CSS层的引入,这一...
-
- HTML 基础标签库_html标签基本结构
-
HTML标题HTML标题(Heading)是通过-...
-
2025-02-20 18:34 yuyutoo
- 前端css面试20道常见考题_高级前端css面试题
-
1.请解释一下CSS3的flexbox(弹性盒布局模型),以及适用场景?display:flex;在父元素设置,子元素受弹性盒影响,默认排成一行,如果超出一行,按比例压缩flex:1;子元素设置...
- vue引入外部js文件并使用_vue3 引入外部js
-
要在Vue中引入外部的JavaScript文件,可以使用以下几种方法:1.使用``标签引入外部的JavaScript文件。在Vue的HTML模板中,可以直接使用``标签来引入外部的JavaScrip...
- 网页设计得懂css的规范_html+css网页设计
-
在初级的前端工作人员,刚入职的时候,可能在学习前端技术,写代码不是否那么的规范,而在工作中,命名的规范的尤为重要,它直接与你的代码质量挂钩。网上也受很多,但比较杂乱,在加上每年的命名都会发生一变化。...
- Google在Chrome中引入HTML 5.1标记
-
虽然负责制定Web标准的WorldWideWebConsortium(W3C)尚未宣布HTML5正式推荐规格,而Google已经迁移到了HTML5.1。即将发布的Chrome38将引入H...
- HTML DOM 引用( ) 对象_html中如何引用js
-
引用对象引用对象定义了一个同内联元素的HTML引用。标签定义短的引用。元素经常在引用的内容周围添加引号。HTML文档中的每一个标签,都会创建一个引用对象。...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)