填充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) 

但请注意, ReDimReDim Preserve都有很高的性能成本。 尽量避免一遍又一遍地在一个循环中进行,如果可能的话; 你的用户会感谢你。


但是,在你的问题中显示的简单例子(如果它不只是一次性样品),你根本不需要ReDim 。 只需声明具有明确维度的数组:

 Dim MyArray(0 To 3) 

第一次海报,长时间的读者。 正如科迪和布雷特所说的,你可以通过合理使用Redim Preserve来减lessVBA的减速。 布雷特build议Mod做这个。

您也可以使用用户定义的TypeSub来执行此操作。 考虑我的代码如下:

 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是

  1. 创build一个足够大的数组来处理任何你认为会被抛出的数组
  2. 明智地使用Redim Preserve

下面的代码提供了一个例程,它将根据lngSizevariables对myArray进行维度lngSize ,然后每当上限即将超过时,使用Modtesting添加其他元素(等于初始数组大小)

 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智慧人类宝藏 …)

嘿,这是我的第一篇文章,相信它是清晰的。