总结
添加新模块到 Excel VBA 项目中是一个简单的过程,可以通过 VBA 编辑器的菜单或快捷菜单来完成。模块是组织 VBA 代码的有效方式,可以包含声明、子过程、和函数过程。合理组织模块是编写高效、可维护 VBA 代码的关键。
代码书写一共是以下几个步骤:
- 定义子过程(第一行)
- 声明变量(Dim语句)
- 为变量赋值(Msg和Ans)
- 连接两个字符串(用&操作符)
- 使用内置的VBA函数(MsgBox)
- 使用内置的VBA常量(vbYesNo、vbNo和vbYes)
- 使用If-Then结构(两次)结束子过程(最后一行)
0.8. 添加新的 VBA 模块
当开始录制宏时,Excel 会根据选择的宏存储位置自动创建一个新的模块。如果选择将宏保存在“个人宏工作簿”中,那么模块将被添加到这个隐藏的工作簿中。如果选择将宏保存在当前工作簿,那么模块将被添加到当前工作簿的 VBA 项目中。
手动添加新模块的步骤如下:
- 打开 VBA 编辑器 (
Alt+F11)。 - 在“工程资源管理器”窗口中,选择想要添加模块的工作簿的名称。
- 在菜单栏中选择“插入(Insert)” > “模块(Module)”。
- 或者,可以右击工作簿的名称,在弹出的快捷菜单中选择“插入(Insert)” > “模块(Module)”。
新添加的模块将出现在“工程资源管理器”窗口中的“模块(Modules)”文件夹下,这时可以开始在其中编写或粘贴 VBA 代码。

0.9. VBA 模块中的基本语法
- 声明(Declarations): 在模块的顶部,通常用于声明全局变量或常量,这些变量或常量在整个模块中都可以访问。声明还可以包括编译指令,如
Option Explicit,它要求所有变量在使用前必须显式声明。
Dim count As Integer
这里 count 是变量名,Integer 是数据类型,表示 count 可以存储整数。
-
子过程(Sub Procedures): 是执行一系列操作的代码块,以
Sub关键字开始,以End Sub结束。录制的宏以及自己编写的过程通常都是子过程。它们可以被用户调用,但不返回任何值。 -
函数过程(Function Procedures): 是返回单个值的代码块,以
Function关键字开始,以End Function结束。它们可以在其他 VBA 代码中被调用,也可以像工作表函数一样在 Excel 单元格中使用。
0.10. 变量范围和数据类型
0.10.1 变量范围
- 局部变量: 在过程(如 Sub 或 Function)内部声明的变量,只在该过程内有效。
- 模块级变量: 在过程外部但在模块内部使用
Dim或Private关键字声明的变量,对该模块内的所有过程都是可见的。 - 全局变量: 使用
Global或Public关键字在模块的顶层(所有过程外部)声明的变量,对整个项目都是可见的。
0.10.2 数据类型
变量可以有不同的数据类型,比如 Integer, String, Double, Boolean 等:
Integer: 一个存储整数的数据类型,可以存储的范围通常是 -32,768 到 32,767。Long: 类似于Integer,但范围更大,从 -2,147,483,648 到 2,147,483,647。Single: 单精度浮点数据类型,用于存储较大范围的数值,具有7位精度。Double: 双精度浮点数据类型,范围和精度都大于Single,具有15位精度。Currency: 用于存储货币值,精确到小数点后四位。String: 用于存储文本。Boolean: 可以存储True或False。Date: 用于存储日期和时间。Variant: 特殊的数据类型,可以存储任何类型的数据,包括数字、字符串和日期。如果不声明变量类型,则默认为Variant。
Dim age As Integer ' 声明整数变量
Dim salary As Currency ' 声明货币变量
Dim firstName As String ' 声明字符串变量
Dim isEmployee As Boolean ' 声明布尔变量
Dim startDate As Date ' 声明日期变量
Dim score As Double ' 声明双精度浮点变量
在声明变量时,也可以在一个语句中声明多个同类型的变量:
Dim x, y, z As Integer ' 注意:只有 z 被声明为 Integer,x 和 y 将默认为 Variant
为了避免混淆,推荐每行声明一个变量,这样可以清晰地指定每个变量的类型:
Dim x As Integer
Dim y As Integer
Dim z As Integer
0.11. 控制结构语法
0.11.1 条件结构
If…Then…Else:
这是最基本的条件控制结构。它允许基于一个或多个条件执行不同的代码块。
If condition Then
' 执行这些语句如果条件为真
Else
' 执行这些语句如果条件为假
End If
如果需要基于多个条件执行不同的语句,可以使用 ElseIf:
If condition1 Then
' 条件1为真时执行
ElseIf condition2 Then
' 条件2为真时执行
Else
' 如果以上条件都不满足时执行
End If
Select Case:
当有多个条件需要检查时,Select Case 语句比多个 If...ElseIf 语句更为清晰和易于管理。
Select Case testExpression
Case condition1
' 条件1满足时执行
Case condition2
' 条件2满足时执行
Case Else
' 以上条件都不满足时执行
End Select
0.11.2 循环结构
For…Next:
For...Next 循环对于执行一定次数的重复操作非常有用。
For counter = start To end [Step step]
' 循环体中的语句
Next counter
For Each…Next:
用于循环遍历集合中的每个元素,如数组或 Excel 范围。
For Each element In group
' 循环体中的语句
Next element
While…Wend:
当不知道循环需要执行多少次时,While...Wend 循环很有用。循环将继续执行,直到条件不再为真。
While condition
' 循环体中的语句
Wend
Do…Loop:
Do...Loop 循环是 VBA 中最灵活的循环结构,它可以在循环的开始或结束检查条件。
Do While condition
' 循环体中的语句
Loop
或者在循环的结束处检查条件:
Do
' 循环体中的语句
Loop Until condition
0.11.2 跳转语句
Exit:
在任何类型的循环中,可以使用 Exit For 或 Exit Do 来提前退出循环。
For i = 1 To 10
If i = 5 Then Exit For ' 当 i 等于 5 时退出循环
' 循环体中的其他语句
Next i
GoTo:
虽然通常不建议使用(因为它可能会导致代码难以理解和维护),但 GoTo 语句可以无条件地跳转到程序中的另一个点。
If condition Then
GoTo LineLabel ' 跳转到 LineLabel 标记的代码行
End If
' 程序的其他部分
LineLabel:
' 一些代码
0.12. 对象和成员
对象是类的实例。类可以看作是对象的蓝图,它定义了对象的结构和行为。在 VBA 中,有许多内建对象,比如:
- Application: 代表整个应用程序(比如 Excel),是所有对象的根。
- Workbook: 代表一个 Excel 工作簿。
- Worksheet: 代表工作簿中的一个工作表。
- Range: 代表工作表上的一个单元格或一系列单元格。
- Chart: 代表一个图表。
这些对象构成了一个对象模型,可以通过它们访问和控制应用程序的各个部分。
对象的成员包括属性、方法和事件:
-
属性 (Properties): 描述了一个对象的特征,如大小、颜色或其他特定于该对象的数据。在 VBA 中,可以读取和设置对象的属性。例如,
Range对象的Value属性表示单元格的内容。Dim cellValue As String cellValue = Range("A1").Value ' 读取属性 Range("A1").Value = "Hello" ' 设置属性 -
方法 (Methods): 是对象能执行的动作或操作。比如,
Worksheet对象的Copy方法可以用来复制一个工作表。Worksheets("Sheet1").Copy After:=Worksheets("Sheet3") ' 调用方法 -
事件 (Events): 是由对象触发的动作,响应这些事件可以执行代码。例如,
Worksheet对象的Change事件在工作表的单元格内容被修改时触发。Private Sub Worksheet_Change(ByVal Target As Range) MsgBox "Cell " & Target.Address & " has changed!" End Sub
在 VBA 中创建对象可以使用 New 关键字,或者使用工厂方法(如 Workbooks.Add 创建新的 Workbook 对象)。
Dim mySheet As Worksheet
Set mySheet = ThisWorkbook.Worksheets.Add ' 使用工厂方法
或者使用 New 关键字创建一个新的对象实例:
Dim myObject As New SomeClass ' 创建一个新的对象实例
在使用对象时需要注意的是,它们通常需要被设置为 Nothing 以释放内存,尤其是在处理大量的或者复杂的对象时。
Set mySheet = Nothing ' 释放对象
0.13. 错误处理
VBA 提供了内置的 Err 对象,其中包含有关当前错误的信息。一些常用的 Err 对象的属性和方法包括:
Number: 错误的编号Description: 错误的描述Source: 错误来源(哪个应用程序或对象产生的错误)Clear: 清除当前错误Raise: 产生一个运行时错误
错误处理用于捕获和处理运行时错误。
On Error Resume Next ' 跳过错误
On Error GoTo ErrorHandler ' 跳转到错误处理代码
On Error Resume Next 使程序在发生错误后立即恢复执行,跳过错误的那一行代码:
Sub ResumeNextExample()
On Error Resume Next
' 可能会产生错误的代码
Workbooks.Open "nonexistentfile.xlsx"
' 即使上面的代码产生了错误,下面的代码仍会继续执行
MsgBox "Execution continues here"
End Sub
使用 On Error Resume Next 需要谨慎,因为它会忽略所有的错误,可能会导致难以追踪的问题。
On Error GoTo 语句允许程序在遇到错误时跳转到指定的错误处理代码行:
Sub ErrorHandlerExample()
On Error GoTo ErrHandler
' 正常的代码执行区域
Workbooks.Open "nonexistentfile.xlsx" ' 这里会产生一个错误
' 如果没有错误发生,代码将继续执行
Exit Sub
ErrHandler:
' 错误处理代码
MsgBox "An error occurred: " & Err.Description
Resume Next ' 继续执行下一行代码
End Sub
在这个例子中,如果 Workbooks.Open 导致错误,执行将跳转到 ErrHandler 标签下的代码。Err 对象包含错误的详细信息,Err.Description 提供了错误的描述。
On Error GoTo 语句允许程序在遇到错误时跳转到指定的错误处理代码行:
Sub ErrorHandlerExample()
On Error GoTo ErrHandler
' 正常的代码执行区域
Workbooks.Open "nonexistentfile.xlsx" ' 这里会产生一个错误
' 如果没有错误发生,代码将继续执行
Exit Sub
ErrHandler:
' 错误处理代码
MsgBox "An error occurred: " & Err.Description
Resume Next ' 继续执行下一行代码
End Sub
在这个例子中,如果 Workbooks.Open 导致错误,执行将跳转到 ErrHandler 标签下的代码。Err 对象包含错误的详细信息,Err.Description 提供了错误的描述。
0.14. 向模块中放置VBA代码
在进行实质性操作前,首先必须保证VBA模块中要有一些VBA代码。有三种方式可以实现:
- 用Excel宏录制器录制用户的动作,将它们转变成VBA代码。
- 直接输入这些代码。
- 从一个模块中复制VBA代码,将这些代码粘贴到另一个模块中。
不过,录制宏后,不是所有的任务都可以被转换成VBA 代码。经常会出现需要直接在模块中输入代码的情况。直接输入代码主要是指用户手动输入一行行代码或者从其他地方将代码复制粘贴过来。
VBA中的一条指令可以要多长有多长。但是,考虑到可读性,可以用续行符把一条很长的指令分解成长度适中的多行。因此,在代码行的末尾加上一个空格和一个下划线字符_,然后按回车键并继续在下一行输入这条指令(又称为语句)。
注意:
-
单个VBA模块可以存储任意数量的子过程、函数过程和声明。如何编写VBA模块完全取决于个人。
有些人更倾向于将一个应用的所有VBA代码都保存在单个 VBA模块中;也有些人喜欢将代码分散到多个不同的模块中。这都是个人选择,跟摆放自己家里的家具差不多。 -
在 Excel 中使用 VBA(Visual Basic for Applications)时,模块是存储和组织代码的容器。录制的宏以及手动编写的代码都可以保存在模块中。
-
可以删除VBA模块,但是不能删除与工作簿关联的模块(如ThisWorkbook模块)和与表对象相关联的模块(如Sheet模块)。
-
如何组织模块完全取决于个人偏好和项目的需求。有些开发者喜欢将相关功能的代码放在同一个模块中,以便于管理和维护;而有些开发者则可能根据逻辑功能将代码分散到不同的模块中,以提高代码的可读性和重用性。例如,一个模块可能包含与用户界面相关的所有子过程,而另一个模块则包含处理数据的函数。这样划分可以使代码更加模块化,当项目变得复杂时,也更易于理解和维护。
使用代码窗口的小tips
1. 使用快捷键
快捷键可以加快编码速度并提高效率:
F5:运行程序。F8:逐行执行代码。Ctrl+Space:自动完成和显示智能提示列表。Ctrl+Shift+I:跳到声明的变量或过程。Ctrl+Y:删除当前行。Ctrl+G:打开“立即窗口”以查看输出或运行表达式。Ctrl+R:显示或隐藏“工程资源管理器”。
2. 使用代码折叠
如果代码窗口支持代码折叠(某些 VBA 版本可能不支持),可以折叠或展开不同的代码段,这有助于专注于当前正在处理的部分。
3. 利用拖放
可以通过拖放文本来重新组织代码行,这样可以快速移动代码块。
4. 使用断点
在代码中设置断点可以调试程序。只需点击代码边缘或按 F9,就可以设置或清除断点。
5. 使用注释
通过添加注释来记录代码的功能和操作思路。使用 ' 符号开始注释。
6. 查找和替换
使用 Ctrl + F 可以快速查找代码中的特定文本,使用 Ctrl + H 可以替换文本。
7. 代码格式化
保持代码整洁和一致的格式化有助于可读性。使用缩进 (Tab 键) 和空行来组织代码块。
8. 使用模块级和程序级代码分隔符
在模块中使用分隔符可以帮助逻辑上分隔不同的代码段。例如,可以在不同的函数或子过程之间插入一行由等号或连字符组成的注释行。
9. 利用立即窗口
立即窗口 (Immediate Window) 可以用来测试和调试代码片段。可以在其中运行任意代码行或查询变量值。
10. 使用条件编译
在不同的部署阶段,可能需要编译不同的代码块。使用 #If...Then...#Else 可以根据条件来包含或排除代码块。
11. 代码模块化
将常用的代码片段封装到单独的过程或函数中,这样可以提高代码的重用性并减少冗余。
12. 错误处理
在代码中加入错误处理,如 On Error GoTo 语句,这样可以在发生错误时提供更清晰的指导。
13. 监视窗口
通过监视窗口 (Watch Window),可以监视变量的值或表达式的结果,而不必在代码中添加额外的输出语句。
14. 定期备份代码
不定期地将VBA 代码导出到一个文件中,以备不时之需。
参考资料:
Alexander, M., & Kusleika, D. (2016). Excel® 2016 power programming with VBA. John Wiley & Sons. https://doi.org/10.1002/9781119415503
:基础知识——VB语言&spm=1001.2101.3001.5002&articleId=135774239&d=1&t=3&u=73b72ba2b73b4fe3a084f06b474a65c4)
2715

被折叠的 条评论
为什么被折叠?



