【ExcelVBA・マクロ】2次元配列(多次元配列)の使い方完全ガイド|Range⇔配列変換とジャグ配列の代用方法【コピペOK】

ExcelVBA

ExcelVBAで表形式のデータを扱っていると、「1次元配列だけでは行と列の情報を管理しきれない」と感じる場面が出てきます。そんなときに便利なのが2次元配列(多次元配列)です。

この記事では、2次元配列の宣言方法から、セル範囲(Range)と配列を一括変換するテクニック、行数・列数が異なる「ジャグ配列」の代用方法まで、実務でそのまま使えるコード例を交えて解説します。

スポンサーリンク
スポンサーリンク

2次元配列とは何か

1次元配列が「1列のリスト」だとすると、2次元配列は「行×列の表」をそのままメモリ上に持てるデータ構造です。Excelのセル範囲は本質的に「行×列」の表なので、2次元配列と非常に相性が良いのが特徴です。

Sub Sample2DArray()
    Dim arr(1 To 3, 1 To 2) As String

    arr(1, 1) = "田中": arr(1, 2) = "営業部"
    arr(2, 1) = "佐藤": arr(2, 2) = "経理部"
    arr(3, 1) = "鈴木": arr(3, 2) = "開発部"

    Dim i As Long
    For i = 1 To 3
        Debug.Print arr(i, 1) & " / " & arr(i, 2)
    Next i
End Sub

Dim arr(1 To 3, 1 To 2) のように、カンマ区切りで2つの次元を指定します。1つ目が「行」、2つ目が「列」に対応すると考えると、セル範囲との対応関係がイメージしやすくなります。

Range⇔配列の一括変換

2次元配列が最も威力を発揮するのが、セル範囲との一括変換です。セルを1つずつループで読み書きするより、配列に一括変換してから処理するほうが圧倒的に高速です。

セル範囲を配列に読み込む

Sub RangeToArray()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("Sheet1")

    Dim dataArr As Variant
    dataArr = ws.Range("A1:C100").Value

    ' dataArr(1, 1) が A1、dataArr(1, 2) が B1 に対応する
    Dim i As Long
    For i = 1 To UBound(dataArr, 1)
        If dataArr(i, 1) <> "" Then
            Debug.Print dataArr(i, 1) & " : " & dataArr(i, 3)
        End If
    Next i
End Sub

Range.Value を Variant 型の変数に代入するだけで、自動的に2次元配列に変換されます。UBound(dataArr, 1) は行数の上限、UBound(dataArr, 2) は列数の上限を取得します。

配列をセル範囲に書き戻す

Sub ArrayToRange()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("Sheet2")

    Dim resultArr(1 To 5, 1 To 2) As Variant
    Dim i As Long

    For i = 1 To 5
        resultArr(i, 1) = "商品" & i
        resultArr(i, 2) = i * 1000
    Next i

    ws.Range("A1:B5").Value = resultArr
End Sub

配列のサイズとセル範囲のサイズ(行数・列数)を一致させておく必要がある点に注意してください。サイズが一致しないとエラーになったり、意図しない範囲にデータが入ったりします。

動的な2次元配列とReDim Preserve

行数が実行時にしか分からない場合は、動的配列を使います。ただし2次元配列で ReDim Preserve を使う際は、最後の次元しかサイズ変更できないという制約があるため注意が必要です。

Sub DynamicArrayCaution()
    Dim arr() As Variant
    ReDim arr(1 To 10, 1 To 3)

    ' OK:最後の次元(列側)は変更できる
    ReDim Preserve arr(1 To 10, 1 To 5)

    ' NG:最初の次元(行側)を変更しようとするとエラーになる
    ' ReDim Preserve arr(1 To 20, 1 To 5)
End Sub

行数も可変にしたい場合は、あらかじめ最大件数で配列を確保しておき、使わない部分は無視する方法や、Collectionやコレクションを併用する方法が現実的です。

Sub CountBeforeRedim()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("Sheet1")

    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row

    Dim arr() As Variant
    ReDim arr(1 To lastRow, 1 To 3)

    Dim i As Long
    For i = 1 To lastRow
        arr(i, 1) = ws.Cells(i, "A").Value
        arr(i, 2) = ws.Cells(i, "B").Value
        arr(i, 3) = ws.Cells(i, "C").Value
    Next i
End Sub

先に最終行を取得してから配列サイズを確定させることで、ReDim Preserve の制約を回避できます。

ジャグ配列(配列の配列)の代用方法

VBAには他言語のような「ジャグ配列(各行の要素数が異なる配列)」を直接宣言する構文がありません。しかし、配列の中にVariant型の配列を入れることで同じことが実現できます。

Sub JaggedArraySample()
    Dim jagged(1 To 3) As Variant

    jagged(1) = Array("A", "B")
    jagged(2) = Array("C", "D", "E", "F")
    jagged(3) = Array("G")

    Dim i As Long, j As Long
    For i = 1 To 3
        For j = LBound(jagged(i)) To UBound(jagged(i))
            Debug.Print "行" & i & ": " & jagged(i)(j)
        Next j
    Next i
End Sub

jagged(i) に1次元配列を格納し、jagged(i)(j) の形で内側の要素にアクセスします。行ごとに項目数がバラバラな集計結果などを扱うときに便利なテクニックです。

実践例:2次元配列で高速に重複チェックする

最後に、2次元配列とDictionaryを組み合わせて、大量データの重複チェックを高速に行う例を紹介します。

Sub FastDuplicateCheck()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("Sheet1")

    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row

    Dim dataArr As Variant
    dataArr = ws.Range("A1:B" & lastRow).Value

    Dim dict As Object
    Set dict = CreateObject("Scripting.Dictionary")

    Dim i As Long
    For i = 1 To UBound(dataArr, 1)
        Dim key As String
        key = dataArr(i, 1)

        If dict.Exists(key) Then
            dataArr(i, 2) = "重複"
        Else
            dict.Add key, True
            dataArr(i, 2) = "OK"
        End If
    Next i

    ws.Range("A1:B" & lastRow).Value = dataArr
End Sub

セルを1つずつ読み書きせず、配列上で判定処理を完結させてから最後に一括で書き戻すことで、数万行規模のデータでも高速に処理できます。

まとめ

2次元配列は、Excelのセル範囲を扱ううえで非常に相性の良いデータ構造です。

  • Dim arr(1 To 行数, 1 To 列数) で宣言し、arr(行, 列) でアクセスする
  • Range.Value への代入・取得で、セル範囲と2次元配列を一括変換できる
  • ReDim Preserve は最後の次元しかサイズ変更できないため、行数は事前に確定させる
  • 行ごとの要素数が異なる場合は、配列の中に配列を入れる「ジャグ配列」の代用テクニックが使える

セルを1件ずつループする処理を2次元配列に置き換えるだけで、マクロの実行速度が大きく改善することがあります。ぜひ実務のコードにも取り入れてみてください。

スポンサーリンク
スポンサーリンク
ExcelVBA
シェアする
いがぴをフォローする

コメント

タイトルとURLをコピーしました