次のコードは、エラー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
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)
また、preservingのコンテンツの間に配列のサイズを変更する必要がある場合は、Preserve
キーワードとともにReDim
ステートメントを使用できます。
ReDim Preserve MyArray(0 To 3)
ただし、ReDim
と特にReDim Preserve
の両方のパフォーマンスコストが高いことに注意してください。ループ内でこれを繰り返し行うことは、可能な限り避けてください。ユーザーに感謝します。
ただし、質問に示されている単純な例(単なる使い捨てのサンプルではない場合)では、ReDim
はまったく必要ありません。明示的な次元で配列を宣言するだけです:
Dim MyArray(0 To 3)
CodyとBrettが述べたように、Redim Preserve
を適切に使用することでVBAのスローダウンを減らすことができます。 Brettは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
これは、サイズが2倍になったときにのみReDim Preserve
を呼び出します。メンバー変数eSize
は、eElems
の実際のデータサイズを追跡します。このアプローチは、実行時まで最終的な配列の長さがわからない場合のパフォーマンスの向上に役立ちました。
これが他の人にも役立つことを願っています。
Codyの便利なコメントに加えて、配列の大きさがわからない場合があることに注意してください。この状況での2つのオプションは次のとおりです。
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
上記の多くの(すべての)投稿が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)
呼び出しがReDim arr1(...)
の間にないコードはクラッシュします。回り道は、On Error Resume Next
を使用し、LBound(arr1)
/UBound(arr1)
呼び出しの直後にErr.Number
をチェックすることです。配列が初期化されている場合は0、そうでない場合は0でなければなりません。 VBAには組み込みの不正な動作があるため、アレイの制限をさらに確認する必要があります。詳細な説明は、誰でも Chip PearsonのWebサイト (Mankind Treasure Of VBA Wisdom ...)
へー、それは私の最初の投稿で、読みやすいと信じています。