3

在我的项目中,我经常使用锯齿状数组,即元素也是数组的数组。

直到知道我才设法像这样定义这些数组:

dim subarray(1 to 3) as Integer
dim MyArray(1 to 5) as Variant
subarray(1) = 40
subarray(2) = 50
subarray(3) = 60

MyArray(1) = subarray

但我想做这样的事情:

dim MyArray(1 to 5)(1 to 3) as Variant/Integer
MyArray(1)(1) = 40

上面的示例无法编译。是否有类似的有效方法可以直接声明嵌套数组?

编辑:正确的术语是“锯齿状数组”而不是“嵌套数组”。

EDIT2:编辑了示例值,以防止索引和值之间的混淆。

4

3 回答 3

13

在 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

锯齿状阵列

好的:

  • 灵活的

坏的:

  • 你失去了编译时类型安全
  • 由于嵌套结构,它们有点棘手/混乱
  • 调整内部数组的大小既尴尬又昂贵

您可以创建交错数组,声明一个外部数组 type 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

您必须重新分配tempIntsouter数组的原因是数组在 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
于 2013-10-29T14:03:15.590 回答
1

数组数组:

Dim aa(), ax(),  dd,  x(), xx(), x2()  ' all are " As Variant"

' Array of Arrays - Variant(0 To 2) with 3 Variant(0 To 2) ( 3 Variant/Integer each )
aa = Array( Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9) )
aa(0)(0) = 0

' Array of "Excel" arrays - Variant(0 To 2) with 3 Variant(1 To 3) (3 Variant/Integer each)
ax = Array([{1,2,3}], [{4,5,6}], [{7,8,9}])
ax(0)(1) = 0

另一种选择是 Collection of Collections 或 Dictionary of Dictionaries:

Set dd = CreateObject("Scripting.Dictionary")
Set dd(2) = CreateObject("Scripting.Dictionary")
dd(2)(4) = 24


一些“Excel”矩形数组示例(因为不是 VBA 类型并且也适用于 Excel 公式):

' "row" array starts at 1 - Variant(1 To 3) with 3 Variant/Integer each
x = [{1,2,3}]
x(1) = 0

' "column" array starts at 1, 1 - Variant(1 To 3, 1 To 1)
xx = [{1;2;3}]
xx(1, 1) = 0

' "Excel" rectangular array - Variant(1 To 3, 1 To 3)
x2 = [{1,2,3;4,5,6;7,8,9}]
x2(1, 1) = 0

Stop ' pause to check the types in the Locals window
于 2016-07-25T13:01:29.613 回答
0

正如 Joshua 所说:没有用于直接声明锯齿状数组的特定 VBA 语法。
但是锯齿状数组遵循正常的 VBA 规则进行赋值:例如

Dim a as integer
dim v as variant
a=17
v=a
a=19

您不会期望 V 现在等于 19!

于 2013-10-28T23:17:25.433 回答