Power Query 実務テンプレ | データ取込・更新系:ファイル名日付で抽出

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

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

今回のテーマは「ファイル名の中に埋め込まれた日付(例:売上_2024-10-01.csv)を Power Query で読み取り、その日付を使って“欲しい期間だけ抽出する”実務テンプレ」を身につけることです。

ポイントはこの3つです。
ファイル名から日付部分だけを文字列として切り出す。
その文字列を Date 型に変換して“ちゃんとした日付”にする。
その日付を条件にして、欲しいファイルだけを残す。

ここさえ押さえれば、「特定年月だけ」「今日の分だけ」「最新日付だけ」など、いろんなパターンに応用できます。


基本の考え方:ファイル名 → 日付文字列 → Date 型

まずは Folder.Files で「ファイル一覧の表」を作る

入口はいつも Folder.Files です。

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

これで、「フォルダ内のファイル一覧」がテーブルとして返ってきます。
ここには Name(ファイル名)、Extension(拡張子)、Date modified(更新日時)、Content(中身)などが入っています。

今回の主役は Name 列です。
ここから「日付部分だけ」を切り出していきます。

ファイル名のパターンを決めておく

例として、こんなファイル名を想定します。

売上_2024-10-01.csv

この場合、日付部分は "2024-10-01" です。
「どこからどこまでが日付か」を自分で決めて、それに合わせて切り出します。

例えば、
売上_YYYY-MM-DD.csv という固定パターンなら、
売上_ が 3文字+1文字(アンダースコア)で合計4文字、
その後ろから 10文字分が日付(2024-10-01)です。

つまり、「4文字目から 10文字切り出す」というルールになります。


例題1:ファイル名の日付を列に追加するテンプレ

Text.Middle で日付部分を切り出す

まずは「日付を列として持たせる」ところまでやります。

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

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

    // 1) ファイル名から日付文字列を切り出す
    AddedDateText =
        Table.AddColumn(
            OnlyCsv,
            "日付文字列",
            each Text.Middle([Name], 3 + 1, 10),
            type text
        ),

    // 2) 文字列を Date 型に変換する
    AddedDate =
        Table.AddColumn(
            AddedDateText,
            "ファイル日付",
            each Date.FromText([日付文字列]),
            type date
        )
in
    AddedDate
Power Query

ここでのポイントを分解します。

Text.Middle(テキスト, 開始位置, 文字数) は「指定位置から指定文字数だけ切り出す」関数。
開始位置は 0 始まり(0 が1文字目)なので、売上_(4文字)の次は位置 4。
Text.Middle([Name], 4, 10) と書いてもいいし、意味を残したければ 3 + 1 としてもよい。
Date.FromText("2024-10-01") は、その文字列を Date 型に変換する。

これで、「ファイル名から日付を読み取って、Date 型の列として持たせる」ことができます。
この「ファイル日付」列を使って、次に抽出条件を書いていきます。


例題2:ファイル名日付で「特定年月だけ」を抽出

想定する状況

C:\Data\DailyCsv に、1年分のファイルが溜まっているとします。

売上_2024-09-30.csv
売上_2024-10-01.csv
売上_2024-10-02.csv

この中から、「2024年10月分だけ」を取り込みたい、というケースです。

実務テンプレ M コード(2024-10 のみ)

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

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

    // ファイル名から日付文字列を切り出す
    AddedDateText =
        Table.AddColumn(
            OnlyCsv,
            "日付文字列",
            each Text.Middle([Name], 4, 10),
            type text
        ),

    // 文字列を Date 型に変換
    AddedDate =
        Table.AddColumn(
            AddedDateText,
            "ファイル日付",
            each Date.FromText([日付文字列]),
            type date
        ),

    // 2024-10-01 〜 2024-10-31 の範囲だけに絞り込む
    Filtered =
        Table.SelectRows(
            AddedDate,
            each
                [ファイル日付]
                    >= #date(2024, 10, 1)
                    and [ファイル日付]
                    <= #date(2024, 10, 31)
        )
in
    Filtered
Power Query

ここでの重要ポイントは、「日付を文字列のまま比較しない」ことです。
"2024-10-01""2024-9-30" を文字列として比較すると、順番がおかしくなることがあります。

必ず Date.FromText で Date 型に変換してから、#date(年, 月, 日) と比較する——これが実務テンプレです。


例題3:ファイル名日付で「最新日付のファイルだけ」を抽出

「更新日時ではなく、ファイル名の日付で最新を決めたい」ケース

さっきまでの「最新ファイルのみ取得」は Date modified(更新日時)で決めていました。
でも、現場によっては「ファイル名の日付が正義」ということも多いです。

例えば、こんな状況です。

log_2024-10-01.csv(後から修正されて更新日時が新しい)
log_2024-10-02.csv(更新日時は古いまま)

「一番新しいログ日付」は 2024-10-02 ですが、更新日時だけ見ると逆転することがあります。
この場合は、「ファイル名の日付で最大値を取る」方が自然です。

実務テンプレ M コード(ファイル名日付で最新1件)

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

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

    // ファイル名から日付文字列を切り出す
    AddedDateText =
        Table.AddColumn(
            OnlyCsv,
            "日付文字列",
            each Text.Middle([Name], 4, 10),
            type text
        ),

    // 文字列を Date 型に変換
    AddedDate =
        Table.AddColumn(
            AddedDateText,
            "ファイル日付",
            each Date.FromText([日付文字列]),
            type date
        ),

    // 日付で降順ソート(新しい日付が先頭)
    Sorted =
        Table.Sort(
            AddedDate,
            {{"ファイル日付", Order.Descending}}
        ),

    // 先頭 1 行だけ残す(最新日付のファイル)
    LatestOne = Table.FirstN(Sorted, 1)
in
    LatestOne
Power Query

この LatestOne から Content を取り出して Csv.Document に渡せば、
「ファイル名の日付が一番新しいファイルだけを読む」クエリになります。


重要ポイントの深掘り

Text.Middle の「開始位置」と「文字数」をどう決めるか

ここが一番“職人っぽく”見えるところですが、やっていることは単純です。

例:売上_2024-10-01.csv

文字ごとに番号を振るとこうなります(0 始まり)。

0: 売
1: 上
2: _
3: 2
4: 0
5: 2
6: 4
7: –
8: 1
9: 0
10: –
11: 0
12: 1

日付部分は「3〜12」の10文字です。
なので、Text.Middle([Name], 3, 10) でも OK ですし、
売上 が2文字+_ が1文字=3文字、その次から10文字」と考えてもいいです。

パターンが変われば、ここを変えるだけです。

sales_20241001.csv(YYYYMMDD の8文字)なら、
sales_ が6文字なので、Text.Middle([Name], 6, 8) になります。

日付形式が違う場合の扱い

Date.FromText は、基本的に YYYY-MM-DDYYYY/MM/DD のような標準的な形式を想定しています。
もしファイル名の日付が 20241001 のような「区切りなし」の場合は、一度整形してから Date に変換します。

例:sales_20241001.csv から 2024-10-01 を作る

let
    DateRaw = Text.Middle([Name], 6, 8),      // "20241001"
    yyyy = Text.Start(DateRaw, 4),           // "2024"
    mm = Text.Middle(DateRaw, 4, 2),         // "10"
    dd = Text.End(DateRaw, 2),               // "01"
    DateText = yyyy & "-" & mm & "-" & dd    // "2024-10-01"
in
    Date.FromText(DateText)
Power Query

こうやって「一度きれいな日付文字列を作ってから Date にする」というのが、
“変則的なファイル名日付”への王道パターンです。


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

「ファイル名日付で抽出」の型は、次の流れに集約できます。

Folder.Files でファイル一覧をテーブルにする。
Name から日付部分を Text.Middle などで切り出し、Date.FromText で Date 型にする。
その Date 列を使って、範囲フィルタ・特定年月・最大値(最新)・最小値(最古)などを判定する。

一度この型を体に入れてしまえば、
「ファイル名に日付が入っているフォルダ」は、ほぼ全部“手なずけられる”ようになります。

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