【VBAリファレンス】VBA練習問題解答練習問題30(マトリックス→リスト形式)解答

スポンサーリンク

VBAによるマトリックス形式からリスト形式へのデータ変換:高効率なデータ加工術

Excel業務において、最も頻繁に遭遇する「厄介なデータ構造」の一つが、行と列の両方に項目が並ぶマトリックス形式(クロス集計表)です。この形式は人間が視覚的に確認するには優れていますが、ExcelのピボットテーブルやPower BI、あるいはデータベースでの集計には全く適していません。

本稿では、VBAを用いてマトリックス形式のデータを、分析に適した「フラットなリスト形式(正規化データ)」に変換する手法を詳細に解説します。

詳細解説:なぜマトリックスからリストへの変換が必要なのか

マトリックス形式(例:行に氏名、列に日付、交点に売上金額)は、データの追加や更新が非常に困難です。例えば、新しい日付のデータを追加しようとすると、列を挿入し、書式を整え、既存の数式を修正するという手間が発生します。また、この形式では「日付」という情報の属性が列見出しに埋め込まれているため、Excelのフィルター機能や並び替えが正しく機能しません。

リスト形式(1行1レコード)に変換することで、以下のメリットが生まれます。
1. データの追加・削除が容易(行を増やすだけ)。
2. ピボットテーブルによる多角的な分析が可能になる。
3. 関数(SUMIFS, COUNTIFS等)を用いた集計が直感的になる。
4. Power Queryや他のBIツールへの連携がスムーズになる。

今回の技術的アプローチでは、配列(Array)を活用します。セルを一つずつ読み書きするのは非常に低速であるため、メモリ上にデータを展開し、高速に加工してから一括出力する方法を採用します。

サンプルコード:マトリックスからリストへの変換ロジック

以下は、A列に項目名、1行目に列見出しがあるマトリックスを、別シートに「項目・列見出し・値」の3列リストとして出力する汎用的なコードです。


Sub ConvertMatrixToList()
    Dim wsSource As Worksheet, wsDest As Worksheet
    Dim rngData As Range
    Dim vData As Variant
    Dim vResult As Variant
    Dim i As Long, j As Long, k As Long
    Dim rowCount As Long, colCount As Long

    ' シートの設定
    Set wsSource = ThisWorkbook.Sheets("Matrix")
    Set wsDest = ThisWorkbook.Sheets("List")
    
    ' データ範囲の取得(A1を起点とする連続範囲)
    Set rngData = wsSource.Range("A1").CurrentRegion
    vData = rngData.Value
    
    rowCount = UBound(vData, 1)
    colCount = UBound(vData, 2)
    
    ' 結果用配列の確保(最大行数:(行数-1) * (列数-1))
    ReDim vResult(1 To (rowCount - 1) * (colCount - 1), 1 To 3)
    
    k = 1
    ' マトリックスの走査(1行目と1列目は見出しとして扱う)
    For i = 2 To rowCount
        For j = 2 To colCount
            ' データが空でない場合のみ格納
            If Not IsEmpty(vData(i, j)) Then
                vResult(k, 1) = vData(i, 1)      ' 行見出し
                vResult(k, 2) = vData(1, j)      ' 列見出し
                vResult(k, 3) = vData(i, j)      ' 値
                k = k + 1
            End If
        Next j
    Next i
    
    ' 結果の出力
    With wsDest
        .Cells.Clear
        .Range("A1:C1").Value = Array("項目", "日付/分類", "金額")
        .Range("A2").Resize(k - 1, 3).Value = vResult
        .Columns("A:C").AutoFit
    End With
    
    MsgBox "変換が完了しました。"
End Sub

実務アドバイス:堅牢なVBAコードにするためのポイント

実務でこのコードを使用する際には、いくつかの注意点があります。

1. 空白セルの扱い
上のサンプルコードでは「If Not IsEmpty」で値をチェックしていますが、マトリックス内の「0」と「空白」を厳密に区別する必要がある場合は、条件式を調整してください。場合によっては、すべてのセルをリスト化し、後にオートフィルターで空白を削除する方がコードが簡潔になることもあります。

2. メモリ管理
データ量が数万行を超える場合、配列のサイズを動的に再定義(ReDim Preserve)し続けるとパフォーマンスが著しく低下します。本コードのように、あらかじめ最大サイズでReDimし、最後に結果をトリミングする手法が最も効率的です。

3. エラーハンドリング
データシートが空である場合や、範囲が単一セルである場合にエラーが発生しないよう、`If rngData.Cells.Count = 1 Then Exit Sub` のような事前チェックを入れるのがプロフェッショナルです。

4. 柔軟性の向上
列見出しが日付型の場合、VBA側でシリアル値として認識されます。出力先のセルにあらかじめ書式設定(例:yyyy/mm/dd)を適用しておくことで、出力後の見た目を整える手間が省けます。

応用編:Power Queryとの比較

現代のExcel環境においては、マトリックスからリスト形式への変換は「Power Query」の「列のピボット解除」機能を使うのが最も推奨される手法です。VBAを書く必要すらありません。しかし、VBAが必要となるケースは依然として存在します。それは「ボタン一つで誰でも操作できるようにしたい場合」や「他の複雑な処理と一連の流れで統合したい場合」です。

VBA講師としての見解を述べれば、VBAは「自動化の接着剤」として機能させるのがベストです。Power Queryで作成したクエリをVBAから更新する(ActiveWorkbook.Connections(“Query – テーブル名”).Refresh)という組み合わせは、現代のExcel業務において最強の効率を誇ります。

まとめ

マトリックスからリストへのデータ変換は、データ分析の第一歩です。この変換を自動化することで、人的ミスを排除し、分析に費やす時間を大幅に短縮できます。

今回紹介した配列を用いた処理手法は、VBAの基本である「セルへの直接アクセスを避ける」という原則を体現しています。このコードをベースに、自身の業務に合わせて「列の追加」や「データのクレンジング」といった要件を組み込んでみてください。VBAを単なる「マクロ」ではなく「データ加工エンジン」として活用できるようになれば、あなたのエンジニアとしての市場価値は飛躍的に向上するはずです。

日々のルーチンワークをコードに置き換え、より高次な思考に時間を割くこと。それが、ベテランエンジニアとしての生存戦略です。次のステップとして、この変換ロジックをクラスモジュール化し、より拡張性の高い設計に挑戦してみることを強く推奨します。

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