Power Query 実務テンプレ | データ取込・更新系:フォルダ内Excel一括取込

Excel VBA PowerQuery
スポンサーリンク

ゴールのイメージを先にそろえる

今回のテーマは「フォルダの中にある複数の Excel ブックを、Power Query で一括取込して、毎回[更新]ボタンだけで最新状態に保てる“実務テンプレ”を作ること」です。
毎月の売上ファイル、部署ごとの報告ファイルなどを、手作業コピペではなく「フォルダに入れるだけ」で集約できる状態を目指します。

キーワードは「Folder.Files」と「Excel.Workbook」と「どのシートを読むか」です。
ここを押さえれば、あとはパターンを少し変えるだけで、いろんな現場に持ち込めます。


全体の流れのイメージ

フォルダを“ブックの一覧表”に変える

最初のステップは、フォルダを「ただの箱」ではなく「ブックの一覧表」に変えることです。
Power Query には Folder.Files という関数があり、これを使うと、指定フォルダ内のファイルを行として並べたテーブルが手に入ります。

たとえば、こんなフォルダを想定します。

C:\Data\MonthlyBooks
 売上_2024-01.xlsx
 売上_2024-02.xlsx
 売上_2024-03.xlsx

このフォルダを Folder.Files で読むと、Name(ファイル名)、Extension(拡張子)、Date modified(更新日)、Content(中身のバイナリ)などの列を持つテーブルになります。
この「Content」列が、後で Excel.Workbook に渡す“ブック本体”です。

各ブックの中身を Excel.Workbook でテーブル化する

次のステップは、「各ブックの中身を一覧にして、その中から欲しいシートを選ぶ」ことです。
ここで使うのが Excel.Workbook です。

Excel.Workbook([Content], true, true) とすると、そのブックの中のシート・テーブル・名前付き範囲などが、1行ずつ並んだ“カタログ表”として返ってきます。
各行には Name(シート名など)、Kind(Sheet / Table など)、Data(中身のテーブル)が入っています。

つまり、「フォルダ → ファイル一覧 → 各ファイルの中身一覧 → 欲しいシートの Data を取り出す → 全部縦に結合」という流れになります。


例題:フォルダ内の「1枚目のシート」を全部まとめる

想定する現場の状況

たとえば、こんな運用をしているとします。

毎月、各店舗から「売上店舗A.xlsx」「売上店舗B.xlsx」…のようなブックが届く。
どのブックも「1枚目のシートにだけ売上明細が入っている」。
シート名は人によって「売上」「Sheet1」「店舗A」などバラバラ。

この場合、「シート名で指定する」のは危険なので、「1枚目固定で取る」方が安定します。

M コードの実務テンプレ(1枚目シート版)

let
    // 1) フォルダ内のファイル一覧を取得
    Source = Folder.Files("C:\Data\MonthlyBooks"),

    // 2) .xlsx だけに絞り込む(大文字・小文字を吸収)
    OnlyXlsx =
        Table.SelectRows(
            Source,
            each Text.Lower([Extension]) = ".xlsx"
        ),

    // 3) 必要な列だけ残す(中身とファイル名)
    PickColumns =
        Table.SelectColumns(
            OnlyXlsx,
            {"Content", "Name"}
        ),

    // 4) 各ブックの「1枚目のシート」を読み込む
    WithSheetTable =
        Table.AddColumn(
            PickColumns,
            "SheetData",
            each
                let
                    wb = Excel.Workbook([Content], true, true),
                    // Kind = "Sheet" の行だけに絞ってから、先頭の行を取る
                    firstSheetRow = Table.SelectRows(wb, each [Kind] = "Sheet"){0},
                    firstSheetTable = firstSheetRow[Data],
                    promoted =
                        Table.PromoteHeaders(
                            firstSheetTable,
                            [PromoteAllScalars = true]
                        )
                in
                    promoted,
            type table
        ),

    // 5) 取り出しに失敗した行(シートが無いなど)を除外
    NonNullOnly =
        Table.SelectRows(
            WithSheetTable,
            each [SheetData] <> null
        ),

    // 6) 代表の1テーブルから列名を取得
    SampleTable = NonNullOnly[SheetData]{0},
    ColNames = Table.ColumnNames(SampleTable),

    // 7) SheetData 列を展開して、全ブック分を縦に結合
    Combined =
        Table.ExpandTableColumn(
            NonNullOnly,
            "SheetData",
            ColNames,
            ColNames
        )
in
    Combined

ここまでで、「フォルダ内のすべての Excel ブックの1枚目シートを、1つの大きなテーブルにまとめる」テンプレが完成です。

ポイントを言葉で整理すると、こうなります。

フォルダからファイル一覧を取る。
各ファイルの Content を Excel.Workbook に渡して、中身の一覧を作る。
Kind = “Sheet” の行だけに絞り、その先頭(1枚目)を選ぶ。
その行の Data 列(シートの中身)を取り出し、ヘッダー昇格する。
最後に SheetData 列を展開して、全部縦に結合する。


例題:フォルダ内の「特定シート名」だけを全部まとめる

シート名がきちんと決まっている現場

今度は、どのブックにも必ず「集計」というシートがあり、そこだけを集めたいケースを考えます。
この場合は、「1枚目」ではなく「Name = ‘集計’ かつ Kind = ‘Sheet’」で指定する方が分かりやすいです。

M コードの実務テンプレ(特定シート名版)

let
    // 1) フォルダ内のファイル一覧を取得
    Source = Folder.Files("C:\Data\MonthlyBooks"),

    // 2) .xlsx だけに絞り込む
    OnlyXlsx =
        Table.SelectRows(
            Source,
            each Text.Lower([Extension]) = ".xlsx"
        ),

    // 3) 必要な列だけ残す
    PickColumns =
        Table.SelectColumns(
            OnlyXlsx,
            {"Content", "Name"}
        ),

    // 4) 各ブックから「集計」シートを読み込む
    WithSheetTable =
        Table.AddColumn(
            PickColumns,
            "SheetData",
            each
                let
                    wb = Excel.Workbook([Content], true, true),
                    targetRow = wb{[Name = "集計", Kind = "Sheet"]},
                    targetTable = targetRow[Data],
                    promoted =
                        Table.PromoteHeaders(
                            targetTable,
                            [PromoteAllScalars = true]
                        )
                in
                    promoted,
            type table
        ),

    // 5) 取り出しに失敗した行を除外(集計シートが無いブックなど)
    NonNullOnly =
        Table.SelectRows(
            WithSheetTable,
            each [SheetData] <> null
        ),

    // 6) 列名を取得して展開
    SampleTable = NonNullOnly[SheetData]{0},
    ColNames = Table.ColumnNames(SampleTable),

    Combined =
        Table.ExpandTableColumn(
            NonNullOnly,
            "SheetData",
            ColNames,
            ColNames
        )
in
    Combined

ここでのキモは、この1行です。

targetRow = wb{[Name = "集計", Kind = "Sheet"]},

これは「Excel.Workbook の結果テーブルの中から、Name が ‘集計’ で Kind が ‘Sheet’ の行を1つだけ取り出す」という意味です。
その行の Data 列が、まさに「集計」シートの中身です。


重要ポイントの深掘り

Excel.Workbook の「Data 列」の正体

初心者が一番つまずきやすいのが、「Data 列の中にさらにテーブルが入っている」という構造です。

Excel.Workbook の戻り値は、「ブックの中身のカタログ表」です。
各行は「1つのシート」「1つのテーブル」「1つの名前付き範囲」などを表し、その中身が Data 列に格納されています。

だからこそ、次の三段階が必要になります。

ブック全体を Excel.Workbook で読み込む。
Name / Kind などで欲しい行を1つだけ特定する。
その行の Data 列を取り出すと、中身の表(テーブル)が手に入る。

この構造を一度理解してしまえば、「1枚目シート」「特定シート名」「特定テーブル名」「名前付き範囲」など、いろいろなパターンに応用できます。

なぜ「フォルダ+Power Query」が実務で強いのか

一度このテンプレを作ってしまえば、毎月やることは本当にシンプルになります。

新しい Excel ファイルを、決めたフォルダにコピーする。
Excel 側で[すべて更新]を押す。

これだけで、過去分+新しいファイル分がすべて反映されたテーブルが手に入ります。
「ブックを開いてコピペ」「列の幅を調整」「フィルタをかけ直す」といった作業は、丸ごと不要になります。

さらに、ファイル名や更新日を列として持たせておけば、「どのファイル由来か」「どの月のデータか」を簡単に分析できます。
たとえば、Folder.Files の段階で次のように列を追加しておくと便利です。

WithMeta =
    Table.AddColumn(
        OnlyXlsx,
        "元ファイル名",
        each [Name],
        type text
    )

この列は、最後の Combined テーブルにも引き継がれるので、「店舗別」「月別」「ファイル別」の集計が簡単にできます。


実務テンプレとしてのまとめ

フォルダ内 Excel 一括取込の型は、こう整理できます。

フォルダを Folder.Files で「ファイル一覧テーブル」にする。
各ファイルの Content を Excel.Workbook に渡して「中身のカタログ表」にする。
Name / Kind で欲しいシート(または1枚目)を特定し、その Data を取り出す。
ヘッダー昇格などの整形をしたうえで、全ブック分を縦に結合する。

ここまでが“型”です。
あとは、あなたの現場の

フォルダパス
ブック名のルール
読みたいシートが「1枚目」か「特定名」か

を当てはめれば、そのまま使えるテンプレになります。

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