以下代码给出了错误9“下标超出范围”。我的意思是声明一个动态数组,以便在我向其添加元素时更改维度。在我将数据存储在JS中之前,我是否必须在数组上创建一个“点”?
Sub test_array()
Dim test() As Integer
Dim i As Integer
For i = 0 To 3
test(i) = 3 + i
Next i
End Sub
答案 0 :(得分:54)
在这个数组上使用Redim:
For i = 0 to 3
ReDim Preserve test(i)
test(i) = 3 + i
Next i
答案 1 :(得分:24)
是的,您正在寻找ReDim
语句,该语句动态分配数组中所需的空间量。
以下陈述
Dim MyArray()
声明一个没有维度的数组,因此编译器不知道它有多大,也不能在其中存储任何内容。
但您可以使用ReDim
语句来调整数组的大小:
ReDim MyArray(0 To 3)
如果您需要在保留其内容时调整数组大小,可以使用Preserve
关键字和ReDim
语句:
ReDim Preserve MyArray(0 To 3)
但请注意,ReDim
和特别是ReDim Preserve
都会产生很高的性能成本。尽量避免在循环中反复这样做;您的用户会感谢您。
但是,在您的问题中显示的简单示例中(如果它不仅仅是一次性样本),您根本不需要ReDim
。只需使用显式尺寸声明数组:
Dim MyArray(0 To 3)
答案 2 :(得分:21)
正如Cody和Brett所说,你可以通过合理使用Redim Preserve
来减少VBA的减速。布雷特建议Mod
这样做。
您还可以使用用户定义的Type
和Sub
来执行此操作。请考虑下面的代码:
Public Type dsIntArrayType
eElems() As Integer
eSize As Integer
End Type
Public Sub PushBackIntArray( _
ByRef dsIntArray As dsIntArrayType, _
ByVal intValue As Integer)
With dsIntArray
If UBound(.eElems) < (.eSize + 1) Then
ReDim Preserve .eElems(.eSize * 2 + 1)
End If
.eSize = .eSize + 1
.eElems(.eSize) = intValue
End With
End Sub
仅在尺寸加倍时调用ReDim Preserve
。成员变量eSize
会跟踪eElems
的实际数据大小。这种方法帮助我提高了性能,直到运行时才能知道最终的数组长度。
希望这也有助于其他人。
答案 3 :(得分:11)
除了Cody的有用评论之外,值得注意的是,有时你不会知道你的阵列有多大。这种情况下的两个选项是
Redim Preserve
下面的代码提供了一个例程,它将myArray
维度与lngSize
变量一致,然后使用{{1}添加其他元素(等于初始数组大小)每当要超过上限时测试
Mod
答案 4 :(得分:9)
我看到上面有很多(所有)帖子依赖于LBound
/ UBound
调用尚未初始化的VBA动态数组,导致应用程序不可避免的死亡......
不稳定的代码:
Dim x As Long
Dim arr1() As SomeType
...
x = UBound(arr1) 'crashes
正确的代码:
Dim x As Long
Dim arr1() As SomeType
...
ReDim Preserve arr1(0 To 0)
...
x = UBound(arr1)
...即,Dim arr1()
/ LBound(arr1)
之间没有UBound(arr1)
的{{1}} / ReDim arr1(...)
次呼叫紧急跟踪On Error Resume Next
的任何代码,崩溃。环形交叉口将使用Err.Number
并在LBound(arr1)
/ UBound(arr1)
调用后立即检查{{1}} - 如果数组已初始化,则应为0,否则为非零。由于存在一些VBA内置的不当行为,因此需要进一步检查数组的限制。详细解释可能每个人都在Chip Pearson's website阅读(应该作为人类对VBA智慧的宝藏来庆祝......)