必見!2次元配列から1次元配列にする

マクロ講座 動画編 103回
マクロ講座

動画でExcel 必見!2次元配列から1次元配列にする

必見!2次元配列から1次元配列にする

この記事で学べる内容

  • CurrentRegionで取得した2次元配列の構造(行×列)を正しく理解できる
  • WorksheetFunction.Transposeを使って行列を入れ替える必要性とその動作原理
  • WorksheetFunction.Indexを使って、2次元配列の特定行(=1次元)だけを簡単に取り出す方法
  • 取得した1次元配列をDebug.PrintやJoin関数で確認するテクニック
  • Transposeを使わずに、必要な列だけを抽出・整形して1次元配列を作る別アプローチ

動画版「マクロ講座103回」です。

2次元配列で配列を1次元配列に分けたり、取り出したりする方法。
はじめに
この回では、
「シートの表を丸ごと配列に入れたんだけど、1列だけ取り出して使いたい」
という、とてもよくある場面を練習します。
2次元配列(行と列を持つ配列)
1次元配列(縦か横のどちらか一列だけの配列)
の関係を、実際のコードを使いながら確認していきます。
ポイントはこの3つです。

  1. CurrentRegion で表全体を 2次元配列として取り込む
  2. WorksheetFunction.Transpose を使って行列を入れ替える
  3. WorksheetFunction.Index を使って、1次元配列として取り出す



(サンプルファイルは、こちらです。 2次元配列から1次元配列にする。サンプル103回

マクロ動画 必見!2次元配列から1次元配列にする

コードの簡略化のため、Sheetのコード名、およびシート名をshlist に変更しています。

100回から102回までの振り返りとコードの再利用

  1. コードの簡略化のため、Sheetのコード名、
    およびシート名をshlist に変更しています。

    2次元配列から1次元配列を取得する、タイトル05
  2. この103回は、100~102回の内容の続きになっています。かんたんに振り返っておきましょう。
    100回
    ParamArray を使って
    「引数の数が毎回ちがってもいい関数」を作りました。
    動的配列と組み合わせて、文字列の結合を行いました。

    101回
    シートの表を
    Range("A1").CurrentRegion でつかまえて
    そのまま配列に入れる方法を学びました。
    「セル範囲 ⇒ 配列」は、一気に読み込む方が速くて楽、という考え方でした。

    102回
    LBound / UBound で、配列の「最小の番号」と「最大の番号」を調べる
    Option Base 1 や 1 To 10 の書き方で、インデックスを 1 から始める方法
    データ数が分からないときに、動的配列+ReDim でサイズを決める方法
    を練習しました。

    この103回では、これらの知識を使って、
    「2次元配列 ⇒ 1次元配列」 の変換にチャレンジします。

    2次元配列から1次元配列を取得する、タイトル01
  3. それから配列を作成するときに欠かせないウィンドウとしてローカルウィンドウを表示させておくことで、配列がどのように取得されたかを確認することができるということを説明しました。

    2次元配列から1次元配列を取得する、タイトル02
  4. 2次元配列を用意する(復習)
    まずは、シートの表を 2次元配列として取得します。
    ここでは、シートのコード名とシート名をどちらも shlist に変更してある前提で話を進めます。
    (コードの中に shlist.Range(...) と書きたいからです。)
    2次元配列を作るコード

      Sub getoneDimension_fromTwo_1()
        Dim two_arr As Variant ' 2次元配列を入れる箱
        Dim one_arr As Variant ' あとで 1次元配列を入れる箱
    
        ' A1 を起点に、表の「かたまり」を CurrentRegion で取得して 2次元配列に入れる
        two_arr = shlist.Range("A1").CurrentRegion
    End Sub
    
    
  5. ここまでで、
    two_arr(行番号, 列番号)
    という形の 2次元配列 ができました。
    たとえば、A1:B6 の表なら、

    列方向 … 1~2
    というイメージです。

  6. 次の目標は、
    「支店名が入っている列だけ、1次元配列として取り出したい」
    のように「1列だけ欲しい」ケースです。
    ところが、2次元配列のままだと、
    two_arr(1, 1) … 1行1列目
    two_arr(2, 1) … 2行1列目
    というように、
    「行番号+列番号」が必要なので、そのままでは 1次元になりません。
    そこで使うのが、ワークシート関数の
    WorksheetFunction.Transpose
    です。

  7. コードに Transpose を追加する

      Sub getoneDimension_fromTwo_1()
        Dim two_arr As Variant, one_arr As Variant
    
        ' 2次元配列を取得
        two_arr = shlist.Range("A1").CurrentRegion
    
        ' 行と列を入れ替える(転置)
        two_arr = WorksheetFunction.Transpose(two_arr)
    End Sub
    
    
    2次元配列から1次元配列を取得する、タイトル03
  8. 元の two_arr:
    行方向 = 元の表の「行」
    列方向 = 元の表の「列」
    転置後の two_arr:
    行方向 = 元の表の「列」
    列方向 = 元の表の「行」
    というふうに、役割がひっくり返ります

Index 関数で 1次元配列を取り出す

  Sub getoneDimension_fromTwo_1()
    Dim two_arr As Variant, one_arr As Variant

    two_arr = shlist.Range("A1").CurrentRegion
    two_arr = WorksheetFunction.Transpose(two_arr)

    ' 転置後の two_arr から「1行目」を 1次元配列として取得
    one_arr = WorksheetFunction.Index(two_arr, 1)
End Sub

  1. ここで大事なのは、
    転置前:
    two_arr(行, 列) で「行・列」を指定
    転置後:
    「行番号 1」が、「元の表の 1 列目」になっている
    という点です。
    Index(two_arr, 1) は
    「two_arr の 1行目全体 をください」
    という意味になり、その結果が
    「1次元配列(横に並んだ 1列分)」
    として one_arr に入ります。

    2次元配列から1次元配列を取得する、タイトル04
  2. Debug.Print と Join で中身をチェックする
    ちゃんと配列が取れているかどうかは、
    コードのままでは見えないので、確認方法もセットで覚えておくと便利です。
    ここでは、
    Debug.Print
    Join 関数
    を使って、イミディエイトウィンドウに表示させます。

      Sub getoneDimension_fromTwo_1()
        Dim two_arr As Variant, one_arr As Variant
    
        two_arr = shlist.Range("A1").CurrentRegion
        two_arr = WorksheetFunction.Transpose(two_arr)
        one_arr = WorksheetFunction.Index(two_arr, 1)
    
        ' one_arr の中身を「,」でつないで 1行で表示
        Debug.Print "one_arr = " & Join(one_arr, ",")
      End Sub
    
    
    2次元配列から1次元配列を取得する、タイトル05
  3. Join(one_arr, ",")
    → 配列 one_arr の要素を
     「A店,B店,C店,…」のようにカンマで結合して 1つの文字列にします。
    Debug.Print
    → その文字列をイミディエイトウィンドウに出力します。
    こうしておけば、実行するたびに
    one_arr = 東京支店,横浜支店,名古屋支店,…
    のように、配列の中身を一目で確認できます。

  4. シートに書き戻して 1次元配列を確認する
    イミディエイトウィンドウだけでなく、
    シート上にも出して確認したい場合は、次のようなコードにします。

    Sub getoneDimension_fromTwo_1()
        Dim two_arr As Variant
        Dim one_arr As Variant
        Dim r As Long
    
        ' 2次元配列を取得
        two_arr = shlist.Range("A1").CurrentRegion
    
        ' 行列を入れ替え
        two_arr = WorksheetFunction.Transpose(two_arr)
    
        ' 1次元配列(1行目)を取得
        one_arr = WorksheetFunction.Index(two_arr, 1)
    
        ' one_arr の中身を C12 以降のセルに縦に書き出す
        For r = LBound(one_arr) To UBound(one_arr)
            Cells(r + 12, 3).Value = one_arr(r)
        Next r
    End Sub
    

    ここで使っているポイント: LBound(one_arr) … 配列の最初の番号 UBound(one_arr) … 配列の最後の番号 Cells(r + 12, 3) … 3列目(C列)の「12行目から下」に、1つずつ書き出す 実行すると、C12 から下に向かって、 1次元配列の中身が順番に表示されます。

Transpose を使わない別解:欲しい列だけを取り出す

  1. ここまでの方法は、
    表全体を 2次元配列に入れる
    Transpose で行列を入れ替える
    Index で 1行分=1次元配列を取り出す
    という流れでした。
    もう一つの考え方として、
    「最初から 欲しい列だけ 2次元配列にして、
    For 文で 1次元配列にコピーする」
    という方法もあります。
    Resize を使ったコード例

  2. Sub getrange_onearrfromResize()
        Dim two_arr As Variant     ' 2次元配列(1列だけ)
        Dim one_arr() As Variant   ' 1次元配列
        Dim i As Long
    
        ' A1 を起点に表全体を取得し、そのうち 1列だけを two_arr に入れる
        two_arr = shlist.Range("A1").CurrentRegion.Columns(1) ' 1列目だけ
    
        ' two_arr は「行×1列」の2次元配列なので、行数分だけ 1次元配列を用意
        ReDim one_arr(1 To UBound(two_arr, 1))
    
        ' 2次元配列 two_arr(行, 1) から 1次元配列 one_arr(行) にコピー
        For i = LBound(two_arr, 1) To UBound(two_arr, 1)
            one_arr(i) = two_arr(i, 1)
        Next i
    
        ' 確認用:イミディエイトウィンドウに表示
        Debug.Print "one_arr = " & Join(one_arr, ",")
    End Sub
    
  3. ここでのポイント CurrentRegion.Columns(1) → 表全体ではなく、「1列目だけ」の範囲を 2次元配列として取得 UBound(two_arr, 1) → 行数だけ取り出して、1次元配列 one_arr のサイズを決める For 文で two_arr(行, 1) → one_arr(行) にコピー → メモリ上のデータのコピーだけなので、とても高速です。

    2次元配列から1次元配列を取得する、タイトル07
  4. まとめ

  5. この回では、次のような流れで
    2次元配列から 1次元配列を作る 方法を学びました。
    Range("A1").CurrentRegion で、表をまるごと 2次元配列にする
    WorksheetFunction.Transpose で、行と列を入れ替える
    WorksheetFunction.Index(two_arr, 1) で、「1行分」を 1次元配列として取り出す
    Debug.Print と Join で、配列の中身を確認する
    Resize や Columns(1) を使って、「欲しい列だけ」を 2次元→1次元に変換する別解もある
    配列をうまく使えるようになると、
    ループの回数が減ったり、処理がすごく速くなったりして、
    本格的なマクロの世界に一歩近づけます。
    1次元を取得します。