VBAには動的配列(可変長配列)というものが存在していて、色々なサイトで説明がされています。
Dim strs() As String
動的配列が生きる場面としてはsplit関数の戻り値を格納する場合や、array関数で初期値を与えてあげたりする場合ですね。
ただ、動的配列は要素数を持っていないため、配列に値を追加していくことができません。
Redimで初期化をすれば追加できるようになるのですが初期化をするということは配列を作り直すということなので、動的配列として宣言する意味が薄いです。
配列の使い方として一番多いのが値を次々に追加していく使い方になるので、VBAでは配列がかなり使いにくいです。JavaとかならArrayListとかで次々に追加できるのに…。
そこで配列を使いやすくするために、自分はいつも配列を拡張しながら値を格納する関数を作成しています。その方法を紹介します。
Redimで1要素増やして、値も格納する
配列と値を受け取り、値を配列に格納するという関数を作成します。
単純にRedimをしてしまうと配列が初期化されてしまうのでPreserveオプションを使用します。
'第一引数で渡した配列に、第二引数で渡した文字列を格納する
Sub addToArray(ByRef s() As String, ByVal v As String)
If isEmptyArray(s) Then
'最初は配列の0番目に値を格納
ReDim s(0)
s(0) = v
Else
'配列の要素数を1増やす
ReDim Preserve s(UBound(s) + 1)
'増やした要素に値を格納する
s(UBound(s)) = v
End If
End Sub
'配列が初期化前であるか判定する
Function isEmptyArray(s() As String) As Boolean
If (Not s) = -1 Then
isEmptyArray = True
Else
isEmptyArray = (UBound(s) = 0 And s(0) = "")
End If
End Function
呼び出し方のサンプルは以下のような感じです。
Sub test()
Dim s() As String
Call addToArray(s, "あ")
Call addToArray(s, "い")
Call addToArray(s, "う")
End Sub
上記を実行すると、以下のように順番に値が格納されていきます。

ReDim Preserveの欠点としては二次元配列の要素数は増やせないということがあります。
この場合は、配列を使うのを諦めることが多いですね。
配列同士を結合する
前述した「要素増やして、値も格納する」の発展形で配列を結合する関数も作ってみたいと思います。
'第一引数と第二引数の配列を結合して返却する
Function pushArray(s1() As String, s2() As String)
Dim i As Long
For i = LBound(s2) To UBound(s2)
Call addToArray(s1, s2(i))
Next i
pushArray = s1
End Function
※addToArrayは前項で作成した関数を呼び出しています。
呼び出し方のサンプルは以下のような感じです。
Sub test()
Dim s() As String
Call addToArray(s, "あ")
Call addToArray(s, "い")
Call addToArray(s, "う")
Dim s2() As String
Call addToArray(s2, "え")
Dim s3() As String
s3 = pushArray(s, s2)
End Sub
配列を結合する前には、sに{”あ”、”い”、”う”}が格納されており、S2に{”え”}が格納されています。
そしてそれを結合するので実行結果は以下のようになります。

そもそも配列よりCollectionとか使えばよくね?
ぶっちゃけ値を動的に追加していくだけであればcollectionを使えばいいと思います。
Dim col As New Collection
col.Add ("あ")
col.Add ("い")
col.Add ("う")
keyを指定せずに上記のように追加していけば、「配列の要素数を増やしながら値を追加していく」ことと同じ動作になります。
しかしcollectionを使わずに配列で対応するメリットもあります。
- collectionより配列のほうが処理速度が早い
- collectionを使うと可読性が下がる
まずcollectionは連想配列なので、大量に値を格納すると遅くなってくることがあります。
遅くなるのは配列の値を参照をする時です。大量というのは要素数10万以上くらいですかね。
(まあ、こんなに大量に入れるケースは稀なので普段は気にすることはない気もします。)
次のデメリットはcollectionは何が入っているかわからないので、可読性が下がるということです。
Dim s() As String
Dim col As New Collection
上記で配列の変数の方は、Stringが格納されるとすぐに分かりますが、Collectionの方はソースを読んでいかないと正体が判明しません。
また、Collectionは連想配列で使われること多いので、そもそもIndexではなくKeyでアクセスする前提で使われているかもしれません。
いずれにしても配列を使ったほうがソースを読みやすいと思うので、特に理由がない場合には配列の方を使うことをおすすめします。
コメントを残す