部屋数を変えられる動的配列


配列は、いわば集合住宅のようなものです。1棟の建物に複数の世帯が同時に住むことが可能です。配列を使用するときは、配列の宣言時に部屋数(要素数)を指定します。

では、プログラムの実行中に、要素が増加するような場合はどうでしょう。あるいは、プログラムを作成する時点では、いくつの要素を格納するかわからないときは、どうしたらいいでしょう。そんなケースで役立つのが動的配列という使い方です。

動的配列は、宣言時に要素数を指定しません

Sub Sample33()
    Dim Member() As String
End Sub

一般的な配列では「Member(5)」などと要素数を指定するところを、「Member()」と括弧だけを指定します。これで、変数Memeberは配列として使用できます。ただし、この宣言時点では要素数が確定していませんので、実際には使えません。そこで、プログラムのコード中で要素数を再定義します。そのとき使うのがReDimステートメントです。

次のコードは、要素数を決めない動的配列Memberを宣言し、後で要素数に3を定義しています。

Sub Sample34()
    Dim Member() As String
    MsgBox "要素数を再定義します"
    ReDim Member(3)
    Member(1) = "tanaka"
    Member(2) = "yamada"
    Member(3) = "sato"
    MsgBox "1人目は" & Member(1)
End Sub

ReDimステートメントは、何度でも実行できます。

Sub Sample35()
    Dim Member() As String
    MsgBox "要素数を再定義します"
    ReDim Member(2)
    Member(1) = "tanaka"
    Member(2) = "yamada"
    ReDim Member(3)
    Member(3) = "sato"
    MsgBox "3人目は" & Member(3)
End Sub

上のコードは、一度「ReDim Member(2)」と要素数を再定義した配列に対して、再度「ReDim Member(3)」と要素数を変更しています。ただし、上のコードには重要な問題があります。最後のMsgBoxで「最後に定義した要素」を取り出しています。ここではMember(3の"sato"ですね。これは問題ありません。では、先頭の要素Member(1)を取り出したらどうでしょう。

Sub Sample36()
    Dim Member() As String
    MsgBox "要素数を再定義します"
    ReDim Member(2)
    Member(1) = "tanaka"
    Member(2) = "yamada"
    ReDim Member(3)
    Member(3) = "sato"
    MsgBox "1人目は" & Member(1)
End Sub

結果は空欄です。最初に代入した"tanaka"が消えてしまいました。実は、消えたのは"tanaka"だけではありません。"suzuki"も"yamada"も消えています。そう、ReDimステートメントによる要素数の再定義では、それまで格納されていたデータがクリアされてしまうのです。

それでは困る場合もあります。そこで、すでに格納されているデータを消さずに、要素数を再定義する方法もあります。それには、ReDimステートメントにPreserveというキーワードを付けます。次のコードは、すでに格納されているデータを保持したままで配列の要素数を再定義します。

Sub Sample37()
    Dim Member() As String
    MsgBox "要素数を再定義します"
    ReDim Member(2)
    Member(1) = "tanaka"
    Member(2) = "yamada"
    ReDim Preserve Member(3)
    Member(3) = "sato"
    MsgBox "1人目は" & Member(1)
End Sub

配列の要素数を調べる関数

動的配列は、配列の要素数が変化します。配列の要素数を調べるにはLBound関数UBound関数を使います。LBound関数は、引数で指定した配列で使用できる最も小さいインデックス番号を返します。一方のUBound関数は、引数で指定した配列で使用できる最も大きいインデックス番号を返します。

Sub Sample38()
    Dim Member() As String
    MsgBox "要素数を再定義します"
    ReDim Member(2)
    Member(1) = "tanaka"
    Member(2) = "yamada"
    ReDim Preserve Member(3)
    Member(3) = "sato"
    MsgBox LBound(Member) & vbCrLf & _
           UBound(Member)
End Sub

UBound関数は、バリアント型変数に配列を格納したときにもよく使います。詳しくは、下記のページをご覧ください。

バリアント型を配列として使う