VBA中,数组(Array) 和集合(Collection) 是用于批量存储数据的容器。
数组(Array):相同类型数据的有序集合
数组是相同数据类型的元素组成的有序列表,每个元素通过「索引」(位置编号)访问。
特点:大小可固定(静态)或动态调整,访问速度快,适合存储同类型数据(如多个数字、多个字符串)。
静态数组(大小固定)
声明时直接指定大小,一旦创建不能改变长度。
语法:
Dim 数组名(起始索引 To 结束索引) As 数据类型
VBA默认索引从0开始,但建议显式写
1 To n(更符合日常习惯,比如对应Excel的行号)。
示例:用静态数组存储5个学生的成绩并计算平均分
Sub 静态数组示例()
' 声明一个存储整数的静态数组,包含5个元素(索引1到5)
Dim 成绩(1 To 5) As Integer
Dim 总和 As Integer
Dim 平均分 As Single
Dim i As Integer
' 给数组赋值(模拟5个学生的成绩)
成绩(1) = 85
成绩(2) = 92
成绩(3) = 78
成绩(4) = 90
成绩(5) = 88
' 循环计算总和
总和 = 0
For i = 1 To 5
总和 = 总和 + 成绩(i)
Next i
' 计算平均分
平均分 = 总和 / 5
MsgBox "5个学生的平均分是:" & 平均分 ' 输出:86.6
End Sub
2. 动态数组(大小可变)
声明时不指定大小,后续根据需要用ReDim调整长度(可多次调整)。
语法:
- 先声明:
Dim 数组名() As 数据类型 - 再定义大小:
ReDim 数组名(起始索引 To 结束索引)
示例:动态数组存储不确定数量的姓名
Sub 动态数组示例()
' 声明动态数组(不指定大小)
Dim 姓名() As String
Dim 人数 As Integer
Dim i As Integer
' 让用户输入人数(动态确定数组大小)
人数 = InputBox("请输入人数:")
' 定义数组大小(1到输入的人数)
ReDim 姓名(1 To 人数)
' 循环输入每个人的姓名
For i = 1 To 人数
姓名(i) = InputBox("请输入第" & i & "个人的姓名:")
Next i
' 循环输出所有姓名
For i = 1 To 人数
MsgBox "第" & i & "个人的姓名是:" & 姓名(i)
Next i
End Sub
数组的关键要点:
- 元素类型必须一致(如全是
Integer或全是String); - 索引是“位置编号”,必须在声明的范围内(否则会报错“下标越界”);
- 适合存储数量固定或可预测的数据(如Excel表格的某一列数据)。
集合(Collection):灵活的多类型数据容器
集合是一种更灵活的容器,可存储不同类型的数据(如同时存数字、字符串、对象),大小自动调整,支持用“键”(类似名字)快速访问元素。
特点:无需预先定义大小,支持键值对,适合存储类型复杂、数量不确定的数据。
集合的基本操作
- 声明集合:
Dim 集合名 As New Collection(New表示创建集合对象); - 添加元素:
集合名.Add 元素值, 键(键是可选的,相当于给元素起个唯一的名字); - 访问元素:
集合名.Item(索引或键)(索引从1开始,键必须唯一); - 删除元素:
集合名.Remove(索引或键); - 获取元素数量:
集合名.Count(返回集合中元素的总数)。
示例:用集合管理学生信息(姓名+年龄,支持按姓名访问)
Sub 集合示例()
' 声明一个集合(用于存储学生信息)
Dim 学生集合 As New Collection
Dim 学生信息 As String ' 临时存储单个学生的信息
Dim i As Integer
' 1. 向集合添加3个学生(元素是“姓名-年龄”字符串,键是姓名)
学生集合.Add "张三-18", "张三" ' 键为“张三”,方便后续直接用姓名访问
学生集合.Add "李四-19", "李四"
学生集合.Add "王五-20", "王五"
' 2. 用“键”访问指定学生(比如访问“李四”)
MsgBox "李四的信息:" & 学生集合.Item("李四") ' 输出:李四-19
' 3. 用“索引”遍历所有学生(索引从1开始)
For i = 1 To 学生集合.Count
MsgBox "第" & i & "个学生:" & 学生集合.Item(i)
Next i
' 4. 删除“王五”(用键删除)
学生集合.Remove ("王五")
MsgBox "删除王五后,剩余人数:" & 学生集合.Count ' 输出:2
End Sub
集合的关键要点:
- 元素类型可以不同(比如同时存
Integer、String、Range对象); - 键必须唯一(重复键会报错),索引从1开始;
- 适合存储类型复杂、数量动态变化的数据(如临时管理多个不同类型的对象)。
数组 vs 集合:怎么选?
| 场景 | 选数组 | 选集合 |
|---|---|---|
| 数据类型 | 所有元素类型相同 | 元素类型可不同 |
| 大小是否固定 | 静态数组固定,动态数组可调整 | 自动调整,无需预先定义 |
| 访问方式 | 只能用索引 | 可用索引或键(更灵活) |
| 效率 | 访问速度快(适合大量数据) | 效率稍低(适合少量/复杂数据) |
建议:
- 若数据是同类型(如全是成绩、全是姓名),优先用数组;
- 若数据类型复杂(如混合数字、字符串、对象),或需要用“名字”快速访问,优先用集合。
变量类型
| 变量类型 | 内存占用(字节) | 描述 | 优化建议 |
|---|---|---|---|
| Byte | 1 | 无符号整数,范围 0~255 | 处理二进制数据或小范围整数时优先使用,减少内存占用 |
| Boolean | 2 | 布尔值,True(-1)或 False(0) | 避免用Variant存储布尔值,直接声明为Boolean,节省内存 |
| Integer | 2 | 有符号整数,范围 -32,768~32,767 | 仅当确定数值在此范围内时使用;现代系统中优先考虑Long(减少溢出风险) |
| Long | 4 | 有符号整数,范围 -2,147,483,648~2,147,483,647 | 大多数整数计算优先使用,平衡内存和溢出风险,效率优于Integer |
| Single | 4 | 单精度浮点数,精度约6-7位,范围 ±1.401298E-45~±3.402823E38 | 不需要高精度时使用(如科学计算),避免用于财务等需精确值的场景 |
| Double | 8 | 双精度浮点数,精度约15-17位,范围 ±4.94065645841247E-324~±1.79769313486232E308 | 需较高精度的浮点数计算使用,比Single精度高但内存增加 |
| Currency | 8 | 货币类型,精度到小数点后4位,范围 -922,337,203,685,477.5808~922,337,203,685,477.5807 | 财务/货币计算优先使用,避免浮点数误差(如Single/Double的精度问题) |
| Decimal | 14 | 高精度小数,精度28-29位,需通过Variant声明(如 Dim x As Variant: x = CDec(0)) |
仅在需要极高精度时使用(如精密测量),因内存占用高,避免常规场景 |
| String(定长) | 等于指定长度(每个字符1字节,ANSI编码) | 固定长度字符串,声明方式 Dim s As String * n(n为长度) |
已知字符串长度固定时使用,比变长String更节省内存(无指针开销) |
| String(变长) | 4(指针) + 字符数(每个字符1字节,ANSI) | 长度可变的字符串,默认声明方式 Dim s As String |
字符串长度不固定时使用;避免用字符串存储日期/数值(改用Date/数值类型) |
| Date | 8 | 日期时间类型,范围 100-1-1~9999-12-31,内部存储为双精度浮点数 | 存储日期时间必须用Date类型,比字符串存储更高效(节省内存且便于计算) |
| Object | 4(32位系统)/ 8(64位系统) | 对象引用,指向具体对象(如Worksheet、Range) | 及时用 Set obj = Nothing 释放未使用的对象,减少内存泄漏;避免未初始化对象 |
| Variant | 16(空/数值);更多(字符串/对象等) | 可变类型,可存储任何数据,默认未声明变量的类型 | 尽量避免使用,必须用时明确存储类型;优先用具体类型代替(大幅减少内存) |