填充VBAdynamic数组
下面的代码给我错误9“下标超出范围”。 我的意思是声明一个dynamic数组,以便维度随着元素的添加而改变。 在我像JS一样存储内容之前,是否必须在数组上创build一个“点”?
Sub test_array() Dim test() As Integer Dim i As Integer For i = 0 To 3 test(i) = 3 + i Next i End Sub
在for循环中使用像这样的数组上的Redim:
For i = 0 to 3 ReDim Preserve test(i) test(i) = 3 + i Next i
是的,您正在查找ReDim
语句,该语句dynamic分配数组中所需的空间量。
以下声明
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)
第一次海报,长时间的读者。 正如科迪和布雷特所说的,你可以通过合理使用Redim Preserve
来减lessVBA的减速。 布雷特build议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
。 成员variableseSize
跟踪eSize
的实际数据大小。 直到运行时才知道最终的数组长度,这种方法帮助我提高了性能。
希望这也能帮助别人。
除了科迪的有用的评论,值得注意的是,有时你不会知道你的arrays应该有多大。 在这种情况下的两种select是
- 创build一个足够大的数组来处理任何你认为会被抛出的数组
- 明智地使用
Redim Preserve
下面的代码提供了一个例程,它将根据lngSize
variables对myArray
进行维度lngSize
,然后每当上限即将超过时,使用Mod
testing添加其他元素(等于初始数组大小)
Option Base 1 Sub ArraySample() Dim myArray() As String Dim lngCnt As Long Dim lngSize As Long lngSize = 10 ReDim myArray(1 To lngSize) For lngCnt = 1 To lngSize*5 If lngCnt Mod lngSize = 0 Then ReDim Preserve myArray(1 To UBound(myArray) + lngSize) myArray(lngCnt) = "I am record number " & lngCnt Next End Sub
我看到很多(所有)上面依靠LBound
/ UBound
调用的post,但尚未初始化VBAdynamic数组,什么原因导致应用程序不可避免的死亡…
不稳定的代码:
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)
调用,之间没有ReDim arr1(...)
,崩溃之后。 回旋是采用On Error Resume Next
并在LBound(arr1)
/ UBound(arr1)
调用后检查Err.Number
– 如果数组初始化,它应该为0,否则为非零。 由于存在一些VBA内置的不当行为,需要进一步检查数组的限制。 每个人都可以在Chip Pearson的网站上看到详细的解释(应该被称为VBA智慧的人类宝藏 …)
嘿,这是我的第一篇文章,相信它是清晰的。