動的配列の初期化と利用方法
VBAで配列を利用することがあります。
その配列に入れる値の数は固定の場合もあれば可変の場合もあります。
配列の要素数が最初に決まるものを「静的配列」や「固定配列」と言い、配列の要素数が変動するものを「動的配列」と言います。
ここでは可変の場合である動的配列の初期化から利用方法について取り上げます。
静的配列と動的配列の違い
静的配列の場合は以下のように変数宣言時に要素数を指定して書きます。
1 |
Dim ary(10) |
しかし動的配列の場合は変数宣言時はサイズの指定を行いません。
そして要素数を変更するRedimステートメントを使って上限値を設定します。
1 2 3 |
Dim ary() '// 途中省略 ReDim ary(3) |
動的配列の初期化と利用と解放
動的配列は初期化、値の設定、値の利用、解放、の流れで使用します。
その流れをまとめたコードが以下になります。
各部分について詳細を後述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
Sub 動的配列() ' ReDim ary(0) '// いきなりRedimで宣言も可能。 Dim ary() '// 配列を宣言。動的配列として使うので()内のサイズ指定は不要 Dim i '// ループカウンタ Dim iCount '// 動的配列としてサイズ0で初期化 ReDim ary(0) '// 1から10までループ i = 0 For i = 0 To 10 '// 動的配列の要素を増やす ReDim Preserve ary(i) '// 増やした動的配列の要素に現在のループカウンタ値を入れる ary(i) = i Next '// 配列の要素数を取得 iCount = UBound(ary) '// 動的配列の内容を出力 For i = 0 To iCount Debug.Print ary(i) Next '// 配列の内容を解放(サイズもなくなるためErase後にUbound関数を使うとエラーになります) Erase ary '// サイズ0に初期化 ReDim ary(0) End Sub |
ソースコードの説明
ソースコードが少し長いので、部分を切り出しながら説明します。
動的配列の宣言は1行でも書けるし、2行でも書ける
2 3 4 5 6 7 8 |
' ReDim ary(0) '// いきなりRedimで宣言も可能。 Dim ary() '// 配列を宣言。動的配列として使うので()内のサイズ指定は不要 Dim i '// ループカウンタ Dim iCount '// 動的配列としてサイズ0で初期化 ReDim ary(0) |
2行目でコメントアウトしているRedim ary(0)ですが、3行目と8行目を1行で書いた内容になります。
動的配列の宣言は2行目のように1行で書いてもいいですし、3行目と8行目のように分けて書いてもいいです。
8行目は動的配列としてのサイズを指定して配列を初期化します。
仮に(3)などで書くと配列は以下のように4つの領域を持ちます。
8 |
Redim ary(3) |
1 2 3 4 |
ary(0) = 1 ary(1) = 2 ary(2) = 3 ary(3) = 4 |
サイズ指定した値と実際の領域の数が異なるため注意が必要です。
動的配列を確保後に、再度違う要素で確保すると、新しい要素数で確保されなおす
12 13 14 15 16 17 18 |
For i = 0 To 10 '// 動的配列の要素を増やす ReDim Preserve ary(i) '// 増やした動的配列の要素に現在のループカウンタ値を入れる ary(i) = i Next |
14行目でRedim Preserveにて動的配列の要素を増やしています。
Redim Preserveは元の要素数より大きい数を指定すれば配列が拡張されますが、それとは逆に、すでに確保済みの領域数より小さい数を設定した場合は、その小さい値以降の領域は削除されます。
そのため、上のコードのループがすべて回り、18行目が終わった時点で動的配列変数のaryは11の領域を持っていますが、その直後にRedim Preserve ary(2)と書くとary(3)を含めて以降の領域は削除され、ary(0)、ary(1)、ary(2)の3つの領域が残ります。
動的配列の解放と再初期化
20 21 22 23 24 25 26 27 28 29 30 31 32 |
'// 配列の要素数を取得 iCount = UBound(ary) '// 動的配列の内容を出力 For i = 0 To iCount Debug.Print ary(i) Next '// 配列の内容を解放(サイズもなくなるためErase後にUbound関数を使うとエラーになります) Erase ary '// サイズ0に初期化 ReDim ary(0) |
21行目で使っているUbound関数は配列の要素数を取得します。
29行目のEraseステートメントは配列の内容を解放します。
解放後は動的配列であったことすらも解放されます。
なお、固定配列の場合は各サイズの内容のクリアされ初期化されます。
ここでは例として書いているだけで、関数終了後に動的配列は解放されるため通常はEraseを書く必要はありません。
32行目で再度動的配列として初期化しています。
Eraseと同様ですが、実際にコーディングする際にはこの初期化を書く必要はありません。