下面的代碼給我錯誤9「下標超出範圍」。我的意思是聲明一個動態數組,以便在添加元素時維度發生變化。在我像JS一樣存儲內容之前,是否必須在數組上創建一個「點」?填充VBA動態數組
Sub test_array()
Dim test() As Integer
Dim i As Integer
For i = 0 To 3
test(i) = 3 + i
Next i
End Sub
下面的代碼給我錯誤9「下標超出範圍」。我的意思是聲明一個動態數組,以便在添加元素時維度發生變化。在我像JS一樣存儲內容之前,是否必須在數組上創建一個「點」?填充VBA動態數組
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
語句,動態地分配在陣列中所需的空間量。
下面的語句
Dim MyArray()
聲明沒有維數組,所以編譯器不知道它是多麼大,不能存儲它裏面什麼。
但是你可以使用ReDim
語句來調整數組:
ReDim MyArray(0 To 3)
如果你需要調整的陣列,同時在保持它的內容,你可以用ReDim
語句一起使用Preserve
關鍵字:
ReDim Preserve MyArray(0 To 3)
但是千萬注意,這兩個ReDim
特別ReDim Preserve
有一個沉重的性能代價。如果可能的話,儘量避免一遍又一遍地循環播放;你的用戶會感謝你。
然而,在你的問題中所示(如果它不只是一個一次性的樣品)的簡單的例子,你不需要ReDim
可言。只要有明確的尺寸聲明數組:
Dim MyArray(0 To 3)
+1雖然我想補充的是,下界可以,在我看來應該是被明確指定:'使用ReDim MYARRAY(0-3)' – 2012-01-13 13:22:15
@Jean:這是很好的建議。很多人都被VB(A)支持0以外的下界這一事實所困擾。明確表示總是很好的做法。 – 2012-01-13 13:24:01
除了科迪的有益的意見值得注意的是,有時你不會知道你的陣列應該多大。在這種情況下,這兩個選項是
Redim Preserve
下面的代碼提供了一個例子被拋出將在線路維度myArray
與lngSize
可變的例程,然後通過使用Mod
測試的添加附加元素(等於初始數組大小),只要上限是要被超過
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
第一次海報,長時間讀者。作爲科迪和Brett提到的,你可以減少VBA放緩與合理利用的Redim Preserve
。佈雷特建議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
的實際數據大小。直到運行時才知道最終數組長度,這種方法幫助我提高了性能。
希望這會幫助別人了。
你意識到這個問題在18個月前被問及(並回答)了吧? – 2013-08-21 19:07:25
是的!也想爲其他讀者提供替代方案。我意識到這個操作已經接受了以前的答案。謝謝。 – a505999 2013-08-21 19:08:39
那麼這裏有一個爲你+1,有趣的替代! :) – 2013-08-21 19:13:15
我見上面後但可能未初始化VBA動態數組依靠LBound
/UBound
電話很多(都有)職位,是什麼原因導致應用程序的必然死亡......
不穩定代碼:
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(...)
之間,崩潰immediatelly隨後的任何代碼。迴旋是採用一個On Error Resume Next
和LBound(arr1)
/UBound(arr1)
呼叫後檢查Err.Number
右 - 它應該是0,如果該陣列被初始化,否則非零。由於存在一些VBA內置錯誤行爲,因此需要進一步檢查陣列的限制。詳細的解釋可能大家閱讀Chip Pearson's website(應當慶賀作爲人類寶VBA智慧 ...)
嘿,那是我的第一篇文章,認爲這是清晰可辨。
該評論重新編碼上面依賴ubound/lbound是不正確的 – brettdj 2015-04-27 11:08:07
你爲什麼會做* *中環? 'ReDim',特別是當你添加'Preserve'時,是一個潛在的性能殺手。你知道循環要迭代多少次,所以一定要在循環之外做。然後你只調整一次數組的大小,並且你不需要'Preserve'。 – 2012-01-13 13:10:04
@CodyGray如果在進入循環時已經定義了最終的數組大小,那麼你是絕對正確的。將Redim放在循環中會是一個性能殺手。但是,我認爲數組的大小在進入循環時沒有確定。否則,整個樣本根本沒有意義... – Fluffi1974 2012-01-13 13:29:58
它*具有*在進入循環時被定義。你必須定義循環的範圍。即使它是一個變量而不是像'3'這樣的常量,您仍然在'For'語句中指定了一個上限。使用它來動態初始化數組的大小。 – 2012-01-13 13:30:57