Power Query 実務テンプレ | データ取込・更新系:最古ファイルのみ取得

Excel VBA Power Query M Formula Language
スポンサーリンク

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

今回のテーマは「フォルダの中に同じ形式のファイルがたくさんあっても、“一番古いファイルだけ”を Power Query で自動的に選んで取り込む実務テンプレ」を身につけることです。
「最古ファイルのみ取得」は、ログの初期日、最初のマスタ版、最初の契約書など、“いちばん古い状態”を基準にしたいときに使えます。

やること自体は「最新ファイルのみ取得」とほぼ同じで、違うのは「並べ替えの向き」だけです。
キーワードは Folder.FilesDate modified(更新日時)、そして「並べ替え+先頭1行」です。


基本の考え方:フォルダ一覧から「一番古い1行」を選ぶ

Folder.Files と Date modified 列をおさらい

まず、フォルダを Power Query で扱う入口はいつも Folder.Files です。

let
    Source = Folder.Files("C:\Data\Logs")
in
    Source
Power Query

これを実行すると、「そのフォルダにあるファイル一覧」がテーブルとして返ってきます。
このテーブルには、次のような列が含まれます。

Name(ファイル名)
Extension(拡張子)
Date modified(更新日時)
Size(サイズ)
Content(中身のバイナリ)

今回の主役は Date modified です。
ここを「昇順(古い順)」に並べ替え、先頭の1行だけ残せば、それが“最古ファイル”になります。

「最古ファイルだけ」を選ぶ流れ

流れはシンプルです。

更新日時で昇順ソート(古い順)。
先頭の1行だけ残す。
その行の Content を使って中身を読み込む。

「最新」との違いは、ソートの向きが Order.Descending ではなく Order.Ascending になるだけです。


例題1:最古の CSV ファイルだけを取り込むテンプレ

想定する状況

C:\Data\DailyCsv フォルダに、毎日こんなファイルが溜まっているとします。

log_2024-10-01.csv
log_2024-10-02.csv
log_2024-10-03.csv

この中から、「一番古い CSV(最初の日のログ)だけを Power Query で読みたい」というケースです。

実務テンプレ M コード(最古 CSV 1つだけ)

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

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

    // 3) 更新日時で昇順ソート(古い順)
    Sorted =
        Table.Sort(
            OnlyCsv,
            {{"Date modified", Order.Ascending}}
        ),

    // 4) 先頭の 1 行だけ残す(最古ファイル)
    OldestOne = Table.FirstN(Sorted, 1),

    // 5) そのファイルの Content を CSV として読み込む
    OldestContent = OldestOne{0}[Content],

    CsvTable =
        Csv.Document(
            OldestContent,
            [
                Delimiter = ",",
                Encoding = 65001,
                QuoteStyle = QuoteStyle.Csv
            ]
        ),

    // 6) 先頭行をヘッダーに昇格
    Promoted =
        Table.PromoteHeaders(
            CsvTable,
            [PromoteAllScalars = true]
        )
in
    Promoted
Power Query

ここで一番大事なのは、次の3行です。

Sorted =
    Table.Sort(OnlyCsv, {{"Date modified", Order.Ascending}})

OldestOne = Table.FirstN(Sorted, 1)

OldestContent = OldestOne{0}[Content]
Power Query

Order.Ascending で「古い順」に並べ替え、Table.FirstN で「先頭1行だけ残し」、
その行の Content を取り出して Csv.Document に渡す——これが“最古ファイルのみ取得”のコアパターンです。


例題2:最古の Excel ファイルだけを取り込むテンプレ

想定する状況

C:\Data\MonthlyBooks に、毎月のマスタブックが溜まっているとします。

マスタ_商品2023-04.xlsx
マスタ
商品2023-05.xlsx
マスタ
商品_2023-06.xlsx

この中から、「一番古いマスタ(最初の版)の1枚目シートだけを読みたい」というケースです。

実務テンプレ M コード(最古 Excel 1つだけ)

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

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

    // 3) 更新日時で昇順ソート(古い順)
    Sorted =
        Table.Sort(
            OnlyXlsx,
            {{"Date modified", Order.Ascending}}
        ),

    // 4) 先頭の 1 行だけ残す(最古ブック)
    OldestOne = Table.FirstN(Sorted, 1),

    // 5) そのブックの Content を取り出す
    OldestContent = OldestOne{0}[Content],

    // 6) Excel.Workbook で中身を一覧化
    Wb =
        Excel.Workbook(
            OldestContent,
            true,
            true
        ),

    // 7) 1 枚目のシートを取得
    FirstSheetRow =
        Table.SelectRows(Wb, each [Kind] = "Sheet"){0},

    FirstSheetTable = FirstSheetRow[Data],

    // 8) 先頭行をヘッダーに昇格
    Promoted =
        Table.PromoteHeaders(
            FirstSheetTable,
            [PromoteAllScalars = true]
        )
in
    Promoted
Power Query

CSV のときと同じく、「Sorted → OldestOne → OldestContent」の3ステップが肝です。
そのあとに Excel.Workbook で中身を読むか、Csv.Document で読むかが違うだけで、型はまったく同じです。


重要ポイントの深掘り

「最古」を何で決めるか:更新日時かファイル名か

ここが実務的にはかなり重要です。

Date modified(更新日時)で最古を決めると、「一番最初に作られて、かつその後あまり更新されていないファイル」が選ばれます。
でも、現場によっては「ファイル名に含まれる日付」で最古を決めたいこともあります。

例えば、こんなケースです。

ファイル名:log_2024-01-01.csv
更新日時:2024-03-01(後から追記された)

この場合、「日付として一番古いログ」は 2024-01-01 ですが、
更新日時だけ見ると、もっと新しいファイルより“新しい”と判定されることがあります。

もし「ファイル名の日付で最古を決めたい」なら、次のような流れになります。

Name から日付部分を切り出す(Text.Middle や Text.Range など)。
それを Date 型に変換して「基準日」列を作る。
その列で昇順ソートして、先頭1行だけ残す。

更新日時で十分な現場も多いので、まずは Date modified 版を押さえ、
必要になったら「ファイル名日付版」に発展させる、という順番が現実的です。

Table.FirstN と {0} の関係をちゃんと理解する

ここは Power Query の“感覚”を作るうえで大事なので、もう一度整理します。

Table.FirstN(Sorted, 1) は、「Sorted テーブルの先頭から 1 行だけ残したテーブル」を返します。
つまり、OldestOne は「1行だけを持つテーブル」です。

OldestOne{0} は、「そのテーブルの 0 番目の行(最初の行)をレコードとして取り出す」操作です。
そのレコードの Content 列を取り出すので、OldestOne{0}[Content] という書き方になります。

テーブル
→ 1行だけのテーブル(Table.FirstN)
→ その1行のレコード({0})
→ そのレコードの特定列([Content] や [Name])

この階段を登る感覚に慣れておくと、フォルダ系のクエリは一気に怖くなくなります。


応用:最古ファイル名を列として残しておく

「どのファイルが最古だったか」を後から確認できるようにする

最古ファイルだけを読んでいると、「今どのファイルを見ているのか」を忘れがちです。
そこで、最古ファイルの Name(ファイル名)を列として一緒に持たせておくと、後から確認しやすくなります。

CSV 版に少しだけ手を加えると、こうなります。

let
    Source = Folder.Files("C:\Data\DailyCsv"),

    OnlyCsv =
        Table.SelectRows(
            Source,
            each Text.Lower([Extension]) = ".csv"
        ),

    Sorted =
        Table.Sort(
            OnlyCsv,
            {{"Date modified", Order.Ascending}}
        ),

    OldestOne = Table.FirstN(Sorted, 1),

    OldestContent = OldestOne{0}[Content],
    OldestName = OldestOne{0}[Name],

    CsvTable =
        Csv.Document(
            OldestContent,
            [
                Delimiter = ",",
                Encoding = 65001,
                QuoteStyle = QuoteStyle.Csv
            ]
        ),

    Promoted =
        Table.PromoteHeaders(
            CsvTable,
            [PromoteAllScalars = true]
        ),

    WithFileName =
        Table.AddColumn(
            Promoted,
            "元ファイル名",
            each OldestName,
            type text
        )
in
    WithFileName
Power Query

これで、最終テーブルのすべての行に「元ファイル名」として最古ファイルの名前が入ります。
「このデータはどのファイル由来か」「最古の基準が変わっていないか」を簡単にチェックできます。


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

“最古ファイルのみ取得”の型は、たった一言で表せます。

「フォルダ一覧を更新日時で昇順ソートして、先頭1行だけ残し、その Content を読む」

これを CSV 版・Excel 版で一度手を動かして体に入れてしまえば、
「一番古いログだけ」「最初のマスタだけ」「最初の契約書だけ」といったニーズに、落ち着いて応えられるようになります。

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