要素数を逐次拡大する動的配列 : 1次元・2次元

動的配列とは、要素数(長さ)を後から変更できる配列です。対象が検出される度に配列の要素を追加して値を格納していく使い方について説明します。条件に合致するものだけを配列に格納するなど、格納する値の数が特定できない場合に利用します。

動的配列での Dim と ReDim

Dimでの宣言は 配列名() で

動的配列にするには、要素数を指定しないで「Dim 配列変数名() As データ型」と宣言します。

Dim 配列名(10)」や「Dim 配列名(1 To 10)」のように要素数を指定すると 固定配列 になります。要素数を変更しようとするとエラーになります。

配列の固定・ロックエラー

ReDim Preserve: 要素を追加して値を格納する

ReDim は配列の要素数を変更するステートメントです。ReDim のみでは、要素数の変更と同時に格納済みの値がリセットされます。

格納済みの値を保持したまま配列の要素数を変更するには、ReDim Preserve とセットにします。なお、配列の開始インデックスは変更できません。

Dim aryVal(0 To 10)
→ OK : ReDim Preserve AryVal(0 To 100)
NG : ReDim Preserve AryVal(1 To 10)

1次元の動的配列のコード例

Dim aryName() As String '要素数を指定しない
Dim aSty As Style
Dim cnt As Long

' Excelの場合はActiveWorkbook.Styles
For Each aSty In ActiveDocument.Styles
  If aSty.BuiltIn = False Then
    cnt = cnt + 1
    '動的配列 値を保持して要素数を追加
    ReDim Preserve aryName(1 To cnt)
    aryName(cnt) = aSty.NameLocal
  End If
Next aSty

2次元の動的配列 : 行・列に注意

2次元の動的配列となると少しややこしくなります。

2次元配列内の値は「変数名(1, 3)」のように取り出せるので、「Cells(, )」をイメージして扱えます。問題は動的に値を追加する場合の次の規則です。

多次元配列では ReDim Preserve で変更できる要素数は最終次元のみ

つまりテーブルでいえば、列は追加できるが行は追加できないということです。

Dim aryVal(10, 10)
OK : ReDim Preserve aryVal(10, 100)
NG : ReDim Preserve aryVal(100, 10)

このため、2次元の動的配列を扱う際には、テーブルの行・列関係を入れ替えて考えなくてはなりません。

2次元の動的配列のコード例

ユーザー定義のスタイルのリストを配列に格納する例です。スタイル名、フォント種類、文字色の3行に対し、該当するスタイル数に応じて列が追加されます。

Dim aryStyle()
Dim aSty As Style
Dim cnt As Long

' Excelの場合はActiveWorkbook.Styles
For Each aSty In ActiveDocument.Styles
  If aSty.BuiltIn = False Then
    cnt = cnt + 1
    '動的配列 値を保持して要素数を追加
    ReDim Preserve aryStyle(1 To 3, 1 To cnt)
    aryStyle(1, cnt) = aSty.NameLocal
    aryStyle(2, cnt) = aSty.Font.Name
    aryStyle(3, cnt) = aSty.Font.Color
  End If
Next aSty

2次元配列の行・列(1次元・2次元)を入れ替えるマクロ

配列をExcelに貼り付ける場合や行・列を脳内で入れ替えるのが煩雑な場合には、マクロで入れ替えてしまいましょう。

Function 行列入れ替え(arySou()) As Variant

    Dim r As Long, c As Long
    Dim aryBuf

    ReDim aryBuf(LBound(arySou, 2) To UBound(arySou, 2), _
              LBound(arySou, 1) To UBound(arySou, 1))
    For r = LBound(aryBuf, 1) To UBound(aryBuf, 1)
        For c = LBound(aryBuf, 2) To UBound(aryBuf, 2)
            aryBuf(r, c) = arySou(c, r)
        Next c
    Next r

    行列入れ替え = aryBuf
End Function
タイトルとURLをコピーしました