VBAの2次元配列でUBoundを使う方法|行数・列数の取得から動的配列まで解説

当ページのリンクには広告 (Amazonアソシエイト含む) が含まれています。
2次元配列について
サクッと結論

VBAで2次元配列を扱うとき、UBound でまず覚えるのは、UBound(arr, 1) が1つ目の次元、UBound(arr, 2) が2つ目の次元を見るということです。

2次元配列をExcelの表として扱うなら、基本は arr(行, 列) と考えます。ただし配列の開始番号は0とは限らないため、正確な行数・列数は UBound(arr, 次元) - LBound(arr, 次元) + 1 で取得します。

セル範囲を Range.Value で読み込むと、複数セルの場合は値を2次元配列として扱えます。加工後は Range("E1").Resize(行数, 列数).Value = arr の形でまとめて貼り付けます。

ReDim Preserve は最後の次元しかサイズ変更できません。arr(行, 列) のまま行を増やしたい場合は、先に必要な行数を数えてから ReDim するのが安全です。

VBAの2次元配列は、最初に見るとかなり難しく感じます。

理由は、同時に考えることが多いからです。DimReDimUBoundLBoundRange.ValueResize が一気に出てきますし、さらに「配列は0から始まるのか、1から始まるのか」という混乱もあります。

この記事では、現行記事で扱っていた2次元配列の基礎、動的宣言、CurrentRegion、セルへの貼り付け、1行ずつ処理する使い方、ReDim Preserveの注意点を残したまま、UBoundで2次元配列の行数・列数を確認する方法を軸に整理し直します。

初心者の方は、先に「UBoundで2次元配列の行数と列数を取る」ところだけ押さえてください。そこが分かると、動的配列、貼り付け、1行ずつの処理まで一気につながります。

また、実際に手を動かす場面では「2次元の動的配列をどう宣言するか」「配列をセルへ貼り付けるにはどうするか」「ReDim Preserveで行数を増やせないのはなぜか」まで一緒に理解する必要があります。この記事では、それらを別々の断片ではなく、2次元配列を使う一連の流れとして扱います。

【 この記事の概要 】

よく使う度
難しさ
覚えておくと安心度
この記事の探し方
スクロールできます
知りたいこと読む場所
UBound(arr, 1)UBound(arr, 2) の違いUBoundの次元指定を見る
2次元配列の行数・列数を安全に取得したい行数・列数の計算を見る
動的な2次元配列を宣言したい動的配列の宣言を見る
2次元配列の考え方を初心者向けに知りたい2次元配列の考え方を見る
セル範囲を配列に入れて、別のセルへ貼り付けたいセルへの貼り付けを見る
2次元配列を1行ずつ処理したい1行ずつ処理する例を見る
ReDim Preserve でエラーになる理由を知りたいReDim Preserveの制限を見る
目次

VBAのUBoundで2次元配列の行数・列数を取得する基本

2次元配列を実務で使うとき、最初に必要になるのは「この配列は何行・何列あるのか」を知ることです。

セル範囲を配列に入れたあと、行数や列数が分からないまま処理を書くと、最後の行を読み飛ばしたり、貼り付け先のセル範囲がずれたりします。

ここでは、2次元配列でUBoundをどう使うか知りたい方に向けて、UBoundLBound の使い方から確認します。

UBound(arr, 1)とUBound(arr, 2)の違い

UBound は、配列の上限番号を返す関数です。

2次元配列の場合は、2つ目の引数に「どの次元を見るか」を指定します。

Sub Check2DArraySize()
    Dim arr As Variant

    arr = Worksheets("Sheet1").Range("A1:C4").Value

    Debug.Print "行の下限: " & LBound(arr, 1)
    Debug.Print "行の上限: " & UBound(arr, 1)
    Debug.Print "列の下限: " & LBound(arr, 2)
    Debug.Print "列の上限: " & UBound(arr, 2)
End Sub

Excelの表として考えるなら、基本は次のように読みます。

スクロールできます
書き方見ているものExcel表のイメージ
UBound(arr, 1)1つ目の次元の上限行方向
UBound(arr, 2)2つ目の次元の上限列方向
LBound(arr, 1)1つ目の次元の下限最初の行番号
LBound(arr, 2)2つ目の次元の下限最初の列番号

Microsoft LearnのUBound関数でも、UBound(arrayname, [dimension])dimension は、1なら第1次元、2なら第2次元を返すものとして説明されています。

つまり、2次元配列で「行数を見たい」のに UBound(arr) だけで書くと、意図が伝わりにくくなります。省略すると第1次元が対象になりますが、2次元配列では UBound(arr, 1) と明示した方が読みやすいです。

Excelの表を2次元配列としてVBEのローカルウィンドウで確認した例
Excelの表を2次元配列としてVBEのローカルウィンドウで確認した例

UBoundとLBoundそのものを先に整理したい場合は、関連記事の LBound、UBound (配列のサイズを知る) もあわせて確認すると理解しやすいです。

行数・列数を変数に入れて使い回す

実務では、上限番号そのものよりも「何行あるか」「何列あるか」を使う場面が多いです。

そのため、上限だけを見るのではなく、下限を返す Microsoft LearnのLBound関数 も含めて行数・列数を計算しておくと安全です。

Sub GetRowAndColumnCount()
    Dim arr As Variant
    Dim rowCount As Long
    Dim colCount As Long

    arr = Worksheets("Sheet1").Range("A1:C4").Value

    rowCount = UBound(arr, 1) - LBound(arr, 1) + 1
    colCount = UBound(arr, 2) - LBound(arr, 2) + 1

    Debug.Print "行数: " & rowCount
    Debug.Print "列数: " & colCount
End Sub

Range.Value で取得した複数セルの配列は、実務上は 1 To 行数, 1 To 列数 の感覚で扱う場面が多いです。ただし、すべての配列が1始まりとは限りません。

たとえば、Dim arr(0 To 2, 0 To 3) のように自分で宣言した配列なら0始まりです。Option Baseステートメント を使っているモジュールもあります。だからこそ、初心者のうちから UBound - LBound + 1 で行数・列数を出す癖をつけると、後で詰まりにくくなります。

動的な2次元配列を宣言して必要サイズだけ確保する

2次元配列の宣言には、最初からサイズを決める方法と、あとからサイズを決める方法があります。

最初からサイズを決める配列を、ここでは固定サイズの配列として扱います。

Sub Static2DArraySample()
    Dim data(1 To 4, 1 To 3) As Variant

    data(1, 1) = "名前"
    data(1, 2) = "点数"
    data(1, 3) = "判定"
End Sub

行数や列数が処理のたびに変わるなら、動的配列にします。

Sub Dynamic2DArraySample()
    Dim rowCount As Long
    Dim colCount As Long
    Dim data() As Variant

    rowCount = 4
    colCount = 3

    ReDim data(1 To rowCount, 1 To colCount)

    data(1, 1) = "名前"
    data(1, 2) = "点数"
    data(1, 3) = "判定"
End Sub

Microsoft LearnのDimステートメントでも、空の括弧で動的配列を宣言し、あとから ReDim で要素数を定義できるとされています。

配列の宣言、固定サイズの配列、動的配列の全体像を先に押さえたい場合は、関連記事の VBA 配列の使い方徹底解説 を先に読むと、このあとのコードが追いやすくなります。

初心者の方は、まず次の形をテンプレートとして覚えるのがおすすめです。

Dim arr() As Variant
ReDim arr(1 To rowCount, 1 To colCount)

この形にしておくと、UBound(arr, 1) で行方向、UBound(arr, 2) で列方向を見られるため、Excelの表と対応させやすくなります。

2次元配列とは?初心者向けにExcel表で考える

2次元配列は、Excelの表をVBAの中に一時的に持つための入れ物です。

1つの値だけを変数に入れるのではなく、複数行・複数列の値をまとめて扱えます。

VBAの2次元配列は「Excel表」をメモリに持つ仕組み
VBAの2次元配列はExcel表をメモリ上に持つ箱

1次元配列と2次元配列の違い

1次元配列は、横一列または縦一列のリストとして考えると分かりやすいです。

Dim names(1 To 3) As String

names(1) = "佐藤"
names(2) = "田中"
names(3) = "鈴木"

一方、2次元配列は「行」と「列」の2つの番号で値を指定します。

Dim data(1 To 3, 1 To 2) As Variant

data(1, 1) = "佐藤"
data(1, 2) = 85
data(2, 1) = "田中"
data(2, 2) = 58
data(3, 1) = "鈴木"
data(3, 2) = 72

data(2, 1) は2行目・1列目です。Excelのセル番地でいう A2 と似た感覚ですが、完全に同じではありません。

配列の中では、あくまで「配列内の何行目・何列目か」を見ています。ここをExcelのセル番地と混同すると、arr(2, 3)B3 なのか C2 なのか分からなくなります。

この記事では、初心者向けに arr(行, 列) の順番で統一して説明します。

Range.Valueでセル範囲を2次元配列に入れる

Excel VBAで2次元配列がよく使われる理由は、セル範囲と相性がよいからです。

Microsoft LearnのRange.Valueプロパティでは、複数セル範囲の値は2次元配列を含む Variant として返されると説明されています。また、2次元配列を Value に代入すると、範囲へ一括でコピーできます。

Sub GetArrayFromRange()
    Dim arr As Variant

    arr = Range("A1").CurrentRegion.Value

End Sub
指定したセル範囲を2次元配列としてVBEで確認した例
指定したセル範囲を2次元配列としてVBEで確認した例

範囲が毎回変わるなら、CurrentRegion を使う方法もあります。CurrentRegionの基本を別記事で確認したい場合は、VBA CurrentRegionでセル範囲を自動取得・最終行やセル操作を解説 も参考になります。

Sub ReadCurrentRegionAsArray()
    Dim arr As Variant
    Dim targetRange As Range

    Set targetRange = Worksheets("Sheet1").Range("A1").CurrentRegion
    arr = targetRange.Value

    Debug.Print "行数: " & UBound(arr, 1) - LBound(arr, 1) + 1
    Debug.Print "列数: " & UBound(arr, 2) - LBound(arr, 2) + 1
End Sub

Microsoft LearnのRange.CurrentRegionプロパティでは、CurrentRegion は空白行や空白列で囲まれた範囲を返すものとして説明されています。表の途中に空白行・空白列があると、想定より狭い範囲になることがあります。また、保護されたワークシートでは使えない点も公式ドキュメントに明記されています。

添字は0始まり・1始まりが混ざるのでLBoundも見る

VBAの配列で初心者が混乱しやすいのが、開始番号です。

たとえば、次の配列は0始まりです。

Dim arr(0 To 2, 0 To 3) As Variant

次の配列は1始まりです。

Dim arr(1 To 3, 1 To 4) As Variant

さらに、Option Base 1 が書かれたモジュールでは、下限を明示しない配列の開始番号が変わります。

そのため、2次元配列を安全に扱うなら、UBound だけでなく LBound も見ます。

rowCount = UBound(arr, 1) - LBound(arr, 1) + 1
colCount = UBound(arr, 2) - LBound(arr, 2) + 1

この書き方なら、0始まりでも1始まりでも行数・列数を正しく取得できます。

2次元配列を貼り付ける・1行ずつ処理する・ReDim Preserveで増やす

ここからは、現行記事でも扱っていた実務寄りの使い方を、UBound を中心に整理します。

2次元配列は「読み込む」だけではあまり価値がありません。実務では、読み込んだ値を加工し、必要な形で貼り付けるところまで使います。

2次元配列の実務フロー読み込み→加工→一括貼り付け
2次元配列の実務パターンは読み込み、加工、まとめて貼り付け

2次元配列をセルにまとめて貼り付ける

配列をセルへ貼り付けるときは、貼り付け先の範囲サイズを配列サイズに合わせます。

Sub Paste2DArrayToSheet()
    Dim arr(1 To 4, 1 To 3) As Variant
    Dim rowCount As Long
    Dim colCount As Long

    arr(1, 1) = "名前"
    arr(1, 2) = "点数"
    arr(1, 3) = "判定"

    arr(2, 1) = "佐藤"
    arr(2, 2) = 85
    arr(2, 3) = "合格"

    arr(3, 1) = "田中"
    arr(3, 2) = 58
    arr(3, 3) = "確認"

    arr(4, 1) = "鈴木"
    arr(4, 2) = 72
    arr(4, 3) = "合格"

    rowCount = UBound(arr, 1) - LBound(arr, 1) + 1
    colCount = UBound(arr, 2) - LBound(arr, 2) + 1

    Worksheets("Sheet1").Range("B1").Resize(rowCount, colCount).Value = arr
End Sub
2次元配列貼り付け結果

ポイントは、Resize(rowCount, colCount) です。

貼り付け先が小さいと、配列の一部しか貼り付けられません。貼り付け先が大きすぎると、余ったセルにエラー値が入ることがあります。Range.Valueの公式説明でも、対象範囲が配列より大きい場合、残りのセルにエラー値が入るとされています。

そのため、配列を貼り付けるときは、先に UBoundLBound で行数・列数を出してから Resize します。

RangeCells の指定がまだあいまいな場合は VBA RangeとCellsの使い方 を、Resize の考え方を深掘りしたい場合は VBA Resizeの使い方 を先に確認すると、貼り付け先の範囲指定で迷いにくくなります。

2次元配列を1行ずつ処理する

次は、セル範囲を配列に入れて、1行ずつ判定してから別の場所に貼り付ける例です。

例として、点数が70点以上なら「合格」、70点未満なら「確認」と入れます。

Sub JudgeScoresBy2DArray()
    Dim ws As Worksheet
    Dim arr As Variant
    Dim i As Long
    Dim rowCount As Long
    Dim colCount As Long

    Set ws = Worksheets("Sheet1")

    arr = ws.Range("A1").CurrentRegion.Value

    For i = LBound(arr, 1) + 1 To UBound(arr, 1)
        If Val(arr(i, 2)) >= 70 Then
            arr(i, 3) = "合格"
        Else
            arr(i, 3) = "確認"
        End If
    Next i

    rowCount = UBound(arr, 1) - LBound(arr, 1) + 1
    colCount = UBound(arr, 2) - LBound(arr, 2) + 1

    ws.Range("E1").Resize(rowCount, colCount).Value = arr
End Sub
このようにE1を開始位置として貼り付けることができます。

For i = LBound(arr, 1) + 1 To UBound(arr, 1) としているのは、1行目を見出し行として扱っているためです。

For 文の基本構文に不安がある場合は、関連記事の VBA For文の使い方 で先に流れを確認しておくと、この処理の意味が追いやすくなります。

もし見出し行がない表なら、LBound(arr, 1) から開始します。

For i = LBound(arr, 1) To UBound(arr, 1)
    ' 見出し行がない場合の処理
Next i

2次元配列を1行ずつ処理するときは、次の3点をセットで見ると安全です。

スクロールできます
確認すること
何行目から処理するか見出しありなら LBound(arr, 1) + 1
何列目を判定に使うか点数列なら arr(i, 2)
どの列へ結果を書くか判定列なら arr(i, 3)

セルを1つずつ読み書きするコードでも同じ処理はできます。ただ、行数が増えるほど処理が遅くなりやすく、コードも散らばります。

配列に入れてから処理し、最後にまとめて貼り付ける形にすると、処理の流れが「読み込み → 加工 → 出力」に分かれるため、あとから見返しやすくなります。

ReDim Preserveは最後の次元だけ

2次元配列でよくあるつまずきが、ReDim Preserve です。

ReDim Preserve は、配列の中身を残したままサイズを変更したいときに使います。ただし、Microsoft LearnのReDimステートメントでは、Preserve を使う場合は最後の次元だけを変更できると説明されています。

ReDim Preserveは最後の次元だけサイズ変更できる

たとえば、次のコードは「列方向」を増やしているため考え方としては問題ありません。

Sub PreserveColumnSample()
    Dim arr() As Variant

    ReDim arr(1 To 3, 1 To 3)
    arr(1, 1) = "A"

    ReDim Preserve arr(1 To 3, 1 To 5)
End Sub

一方、次のように「行方向」を増やそうとすると、Preserve の制限に引っかかります。

Sub PreserveRowErrorSample()
    Dim arr() As Variant

    ReDim arr(1 To 3, 1 To 3)
    arr(1, 1) = "A"

    ReDim Preserve arr(1 To 5, 1 To 3)
End Sub
ReDim Preserveで行方向を増やそうとしたときの実行時エラー
ReDim Preserveで行方向を増やそうとしたときの実行時エラー

実務では、次の順番にすると安全です。

  1. 先に対象行数を数える
  2. 必要なサイズで ReDim する
  3. 配列へ値を入れる
  4. 最後にセルへまとめて貼り付ける

次の例では、点数が70点以上の行だけを抽出して別の場所へ貼り付けます。

Sub ExtractPassedRows()
    Dim ws As Worksheet
    Dim source As Variant
    Dim result() As Variant
    Dim i As Long
    Dim j As Long
    Dim outRow As Long
    Dim passCount As Long
    Dim colCount As Long

    Set ws = Worksheets("Sheet1")
    source = ws.Range("A1").CurrentRegion.Value

    colCount = UBound(source, 2) - LBound(source, 2) + 1

    For i = LBound(source, 1) + 1 To UBound(source, 1)
        If Val(source(i, 2)) >= 70 Then
            passCount = passCount + 1
        End If
    Next i

    If passCount = 0 Then
        MsgBox "抽出対象がありません。"
        Exit Sub
    End If

    ReDim result(1 To passCount + 1, 1 To colCount)

    For j = 1 To colCount
        result(1, j) = source(LBound(source, 1), LBound(source, 2) + j - 1)
    Next j

    outRow = 1
    For i = LBound(source, 1) + 1 To UBound(source, 1)
        If Val(source(i, 2)) >= 70 Then
            outRow = outRow + 1
            For j = 1 To colCount
                result(outRow, j) = source(i, LBound(source, 2) + j - 1)
            Next j
        End If
    Next i

    ws.Range("E1").Resize(UBound(result, 1), UBound(result, 2)).Value = result
End Sub
2次元配列で条件分岐を行い貼り付け

このコードは少し長く見えますが、やっていることは単純です。

最初に対象行数を数え、必要な分だけ result を確保し、そのあとで値を入れています。ReDim Preserve で行を増やし続けるより、初心者にとってもエラーの原因を追いやすいです。

動画で学ぶなら PR・アフィリエイト

2次元配列だけでなく、Range・UBound・動的配列まで理解したい方は、VBA講座も確認しておくと迷いにくいです

この記事のコードだけでも、arr(行, 列)UBound(arr, 1)UBound(arr, 2) は試せます。ただ、実務では Range で読み込み、ReDim でサイズを変え、Excelへまとめて貼り付ける流れまでつながります。画面を見ながら学びたい場合は、動画講座も候補になります。

見るべきポイント 配列・Range・ループ処理をまとめて扱っているか
失敗しにくい選び方 更新日・無料プレビュー・返金条件を確認
向いている人 コピペだけでなく、自分の表に合わせて直したい人

※価格・割引・返金条件・講座内容は変わる場合があります。購入前にUdemy上で最新情報をご確認ください。

よくある質問とまとめ:UBoundから2次元配列を理解する

最後に、2次元配列とUBoundでつまずきやすい点をFAQ形式で整理します。

よくある質問

UBound(arr, 1)は行数ですか?

厳密には、UBound(arr, 1) は第1次元の上限番号です。

配列が1始まりなら、結果的に行数と同じになることが多いです。ただし、0始まりの配列では行数とは一致しません。

安全に行数を取得するなら、次の形にします。

rowCount = UBound(arr, 1) - LBound(arr, 1) + 1
UBound(arr, 2)は列数ですか?

UBound(arr, 2) は第2次元の上限番号です。

Excelの表を arr(行, 列) として扱うなら、第2次元は列方向です。ただし、行数と同じく、正確な列数は LBound も使って計算します。

colCount = UBound(arr, 2) - LBound(arr, 2) + 1
VBAで2次元配列を動的に宣言するには?

次の形が基本です。

Dim arr() As Variant
ReDim arr(1 To rowCount, 1 To colCount)

Dim arr() でサイズ未定の配列を宣言し、ReDim であとから行数・列数を決めます。

表の行数が毎回変わる処理では、固定サイズよりも動的配列の方が扱いやすいです。

ReDim Preserveで2次元配列の行数を増やせないのはなぜですか?

ReDim Preserve では、最後の次元しかサイズ変更できないためです。

arr(行, 列) の形で2次元配列を作っている場合、最後の次元は列です。そのため、列数は増やせても、行数を増やそうとするとエラーになります。

行方向に増やしたい場合は、先に行数を数えてから ReDim する、または別の配列へコピーする設計にします。

Range.Valueで取得した値は必ず2次元配列ですか?

複数セルの範囲なら、2次元配列として扱えます。

一方、単一セルだけを Range("A1").Value で取得すると、配列ではなく1つの値として扱う場面があります。

2次元配列として処理したいなら、Range("A1:C4").ValueRange("A1").CurrentRegion.Value のように、複数セルの範囲を対象にします。

CurrentRegionを使えばいつでも表全体を取得できますか?

いつでもではありません。

CurrentRegion は、空白行や空白列で囲まれた範囲を返します。表の途中に空白行や空白列があると、そこで範囲が切れることがあります。

また、Range.CurrentRegionの公式説明では、保護されたワークシートでは CurrentRegion を使えないと説明されています。

業務ファイルで使う場合は、表の途中に空白行・空白列がないか確認してから使うのが安全です。

まとめ

2次元配列は、最初は難しく見えます。

ただ、軸を UBound に置くと理解しやすくなります。

  • UBound(arr, 1) は第1次元、Excel表のイメージでは行方向
  • UBound(arr, 2) は第2次元、Excel表のイメージでは列方向
  • 正確な行数・列数は UBound - LBound + 1 で取得する
  • 複数セルの Range.Value は2次元配列として扱える
  • セルへ戻すときは Resize(行数, 列数).Value = arr
  • ReDim Preserve は最後の次元だけサイズ変更できる
  • 行方向に増やしたいなら、先に必要行数を数えてから ReDim する

初心者の方は、いきなり複雑な抽出処理を書くよりも、まず次の3つを手元で動かすのがおすすめです。

  1. Range.Value でセル範囲を配列に入れる
  2. UBound(arr, 1)UBound(arr, 2)Debug.Print で確認する
  3. Resize(rowCount, colCount).Value = arr で別の場所に貼り付ける

この3つがつながると、2次元配列は「難しい概念」ではなく、「Excelの表を一時的にVBAの中へ持つ方法」として使えるようになります。

無料Liteあり 買い切りStandard PR・自社製品

配列で一覧を作れるようになったら、次は「会議メモをExcelへ戻せる形」で整理しませんか?

TsunaGraphは、箇条書きからマインドマップを作り、JSON・CSV・PNGで保存できるローカルアプリです。会議の論点やタスクを1枚で整理し、CSVでExcelへ戻せるので、WBSや進捗表の下書きにもつなげやすくなります。

箇条書きからマップ化 会議メモや作業メモを、左から右へ展開するマインドマップにできます。
Excelへ戻しやすい CSV保存に対応。Standard版はExcel補助ブックも使えます。
外部通信なし HTMLをPCブラウザで開いて使うローカルアプリです。
TsunaGraphの画面と無料Lite版を見る TsunaGraph紹介ページをスマホで開くためのQRコード あとでスマホで確認したい方へ 会社PCで見ている場合は、QRコードからスマホで紹介ページを確認できます。

※TsunaGraphは筆者が作成した自社製品です。無料Lite版、Standard版の違い、動作環境、価格はリンク先で確認できます。

次に読むと理解しやすい記事

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次