在 VBA 中有多种方法可以拥有集合的集合。它们都有优点和缺点。
多维数组
好:
- 语法简单(只有一个变量)
- 类型安全。
Integer 矩阵的所有元素都是已知的并强制为Integers。
-
非常快速的数组访问
不好:
- 如果内部数组的大小差异很大,则矩阵会浪费一些空间,因为矩阵中有未使用的“单元格”。
- 您只能使用
ReDim Preserve 更改最后一个维度的边界。所以你不能在不清除所有数据的情况下向矩阵添加“列”。
通过包含多个用逗号分隔的边界来声明多维数组:
Dim intMatrix(0 to 2, 0 to 4) As Integer
如果你首先声明一个没有任何边界的数组,你可以动态增加一个多维数组的最后一个维度:
Dim intMatrix() As Integer ' Uninitialized dynamic array
ReDim intMatrix(0 to 4, 0 to 2) ' Initialize as a matrix
ReDim Preserve intMatrix(0 to 4, 0 to 3) ' Add another "row" to the matrix, preserving existing data
锯齿状数组
好:
不好:
- 您失去了编译时类型安全性
- 由于嵌套结构,它们有点棘手/混乱
- 调整内部数组的大小既麻烦又昂贵
您可以通过声明Variant() 类型的外部数组并将其他数组分配给外部数组的元素来创建交错数组:
Dim outer() As Variant ' Dynamic, so new inner arrays can be added
Dim inner() As Integer ' Dynamic, so new elements can be added
ReDim outer(0 to 3)
ReDim inner(0 to 4)
outer(2) = inner
丢失编译时类型信息
所有编译器“知道”外部数组是它可以包含任何东西。所以下面的代码会编译:
Set objWorksheet = outer(2)(3)
虽然在运行时这会导致错误,因为outer(2) 的内部数组包含Integers,而不是Worksheet 对象。
调整大小很尴尬
交错数组的一个好处是内部数组可以有不同的大小。但是,您不能直接调整内部数组的大小。 VBA 就是无法处理语法;以下内容无法编译:
ReDim Preserve outer(2)(0 to 5)
为了调整内部数组的大小,您首先必须将内部数组分配给一个单独的变量,调整该变量的大小,然后将其分配回锯齿状数组:
Dim tempInts() As Integer
tempInts = outer(2)
ReDim Preserve tempInts(0 to 5)
outer(2) = tempInts
您必须将tempInts 重新分配回outer 数组的原因是数组在VBA 中使用按值语义。这意味着当您将数组分配给变量时(如在tempInts = outer(2) 中,您复制整个数组。如果您的数组很长(例如几千个元素),这可能会非常昂贵,如果您的数组包含字符串则更昂贵,因为每个字符串也必须被复制。
锯齿状集合
好:
- 添加和删除元素的简单语法
- 就像锯齿状数组一样灵活
- 集合使用按引用语义,因此分配成本很低,并且您可以对同一个集合对象有多个引用
不好:
如果您经常向内部数组添加元素,使用Collection 对象而不是数组会容易得多。 Collections 不强制其元素的数据类型,因此这与使用 Variant 数组具有相同的缺点——但无论如何您必须这样做才能使用锯齿状数组。
Dim cAnimals As New Collection
' Let's add stats on the Cheetah
Dim cCheetah As New Collection
' Easy to add inner collections to the outer collection. Also, cCheetah refers
' to the same collection object as cAnimals(1).
cAnimals.Add cCheetah
' Easy to add items to inner collection.
' Working directly with the cCheetah collection:
For Each vMeasurment In GetMeasurements("Cheetah")
cCheetah.Add vMeasurement
Next
' Working on the same collection by indexing into the outer object
For i = 1 To cAnimals.Count
For j = 1 To cAnimals(i).Count
cAnimals(i)(j) = cAnimals(i)(j) * dblNormalizingFactor
Next
Next