Power Query 実務テンプレ | クレンジング(前処理)系:日付文字列を日付型変換

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

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

今回のテーマは「2024/10/012024-10-01 のような“日付っぽい文字列”を、Power Query で ちゃんと日付型(type date)に変換する実務テンプレ」です。

見た目は日付なのに、実は text のままで、
並べ替えが文字順になる・期間集計ができない・他テーブルの日付と JOIN できない——こういう“日付あるある事故”を防ぐのが目的です。

キーワードは「文字列のパターンをそろえる」「ロケール(日付の読み方)を意識する」「エラーを出さないように変換する」です。


まず「なぜ日付になってくれないのか」を理解する

Power Query が日付として認識できるかどうかは“書式次第”

Power Query は、2024-10-012024/10/01 のような、
「その環境のロケールで“日付として読める形”」なら、自動で date 型に変換できます。

逆に、次のようなパターンは、そのままだと失敗しがちです。

2024.10.01(ドット区切り)
2024年10月1日(日本語入り)
20241001(区切りなし8桁)
01/10/2024(日付と月の順番がロケールと違う)

なので、やるべきことはこうです。

文字列を「Power Query が読める日付書式」にそろえる。
そのうえで、date 型に変換する(または Date.FromText を使う)。

この2ステップをテンプレ化しておけば、ほとんどの“日付文字列”は怖くなくなります。


例題の前提データをイメージする

次のようなテーブルを想像してください。

受注番号受注日納品予定日
1001“2024/10/01”“2024-10-05”
1002“2024年10月2日”“2024/10/10”
1003“20241003”“”
1004null“2024.10.15”

ポイントはこうです。

受注日・納品予定日が、どちらも text として入っている。
書式がバラバラ(スラッシュ、ハイフン、日本語、8桁、ドット)。
空文字や NULL も混ざっている。

このままでは、期間フィルタ・月別集計・日付差分(納期遅延日数など)がまともに計算できません。
ここに「日付文字列を日付型に変換」テンプレをかけていきます。


一番シンプルな型:すでに「YYYY/MM/DD」ならそのまま型変換

受注日がきれいな 2024/10/01 形式の場合

まずは、書式がすでに「YYYY/MM/DD」でそろっている、いちばんラクなパターンです。

let
    Source = ・・・前のステップ・・・,

    ChangedType =
        Table.TransformColumnTypes(
            Source,
            {{"受注日", type date}}
        )
in
    ChangedType
Power Query

これだけで、"2024/10/01"#date(2024, 10, 1) という date 型になります。
日本語環境(ロケールが日本)なら、YYYY/MM/DDYYYY-MM-DD は素直に読んでくれます。

「まずは型変換だけ試してみて、ダメなら前処理を足す」という順番で考えると、シンプルに進められます。


パターン1:YYYY年MM月DD日 を日付型に変換する

日本語入りの日付文字列をどう扱うか

"2024年10月2日" のような文字列は、そのまま type date に変換しようとすると、たいていエラーになります。
なので、いったん「数字と区切りだけの形」に変換してから、日付型にします。

例えば、"2024年10月2日""2024/10/2" に変えてから date にする、というイメージです。

受注日列に対しての変換テンプレ

let
    Source = ・・・前のステップ・・・,

    // 1) 日本語を取り除き、スラッシュ区切りにそろえる
    Normalized =
        Table.TransformColumns(
            Source,
            {
                {
                    "受注日",
                    each
                        if _ = null then
                            null
                        else
                            let
                                t = Text.From(_),
                                noYear = Text.Replace(t, "年", "/"),
                                noMonth = Text.Replace(noYear, "月", "/"),
                                noDay = Text.Replace(noMonth, "日", "")
                            in
                                noDay,
                    type nullable text
                }
            }
        ),

    // 2) 日付型に変換
    ChangedType =
        Table.TransformColumnTypes(
            Normalized,
            {{"受注日", type date}}
        )
in
    ChangedType
Power Query

ここでやっていることを言葉で整理します。

"2024年10月2日""2024/10/2/""2024/10/2/""2024/10/2" のように、
「年」「月」「日」をスラッシュや空文字に置き換えて、YYYY/MM/DD 形式に寄せている。
そのうえで type date に変換している。

これで、日本語入りの日付文字列も、きれいに date 型にできます。


パターン2:YYYYMMDD(8桁)を日付型に変換する

区切りなし8桁の日付文字列

"20241003" のような「区切りなし8桁」は、
そのままでは日付として認識されませんが、
YYYY/MM/DD に変形してしまえば、あとは同じです。

8桁日付を YYYY/MM/DD に変換するテンプレ

let
    Source = ・・・前のステップ・・・,

    // 1) 8桁文字列を YYYY/MM/DD に整形
    Normalized =
        Table.TransformColumns(
            Source,
            {
                {
                    "受注日",
                    each
                        if _ = null or _ = "" then
                            null
                        else
                            let
                                t = Text.From(_),
                                y = Text.Start(t, 4),
                                m = Text.Middle(t, 4, 2),
                                d = Text.End(t, 2),
                                result = y & "/" & m & "/" & d
                            in
                                result,
                    type nullable text
                }
            }
        ),

    // 2) 日付型に変換
    ChangedType =
        Table.TransformColumnTypes(
            Normalized,
            {{"受注日", type date}}
        )
in
    ChangedType
Power Query

"20241003""2024"(年)+ "10"(月)+ "03"(日) → "2024/10/03"
という形にしてから、date 型に変換しています。

空文字や NULL はそのまま NULL にしているので、変換エラーも出ません。


パターン3:ドット区切り YYYY.MM.DD を日付型に変換する

"2024.10.15" のようなパターン

"2024.10.15" は、そのままだとロケールによっては日付として認識されません。
これも、「ドットをスラッシュに変える」だけで、かなり素直に変換できるようになります。

let
    Source = ・・・前のステップ・・・,

    Normalized =
        Table.TransformColumns(
            Source,
            {
                {
                    "納品予定日",
                    each
                        if _ = null then
                            null
                        else
                            Text.Replace(Text.From(_), ".", "/"),
                    type nullable text
                }
            }
        ),

    ChangedType =
        Table.TransformColumnTypes(
            Normalized,
            {{"納品予定日", type date}}
        )
in
    ChangedType
Power Query

"2024.10.15""2024/10/15"#date(2024, 10, 15)
という流れです。


もう一歩進んだ実務テンプレ:関数化して再利用する

「日付文字列を日付型に変換する関数」を1つ持っておく

書式が混在している現場では、
「日本語入り」「8桁」「スラッシュ」「ハイフン」「ドット」などをまとめて面倒見たいことが多いです。

そこで、「日付文字列をいい感じに日付型にしてくれる関数」を一つ作っておくと便利です。

// クエリ名:fn_TextToDateJP
let
    TextToDateJP = (value as nullable any) as nullable date =>
        let
            // null はそのまま
            v =
                if value = null then
                    null
                else
                    Text.Trim(Text.From(value)),

            // 空文字は null
            v1 =
                if v = "" then
                    null
                else
                    v,

            // 日本語をスラッシュに
            v2 =
                if v1 = null then
                    null
                else
                    let
                        s1 = Text.Replace(v1, "年", "/"),
                        s2 = Text.Replace(s1, "月", "/"),
                        s3 = Text.Replace(s2, "日", "")
                    in
                        s3,

            // ドットをスラッシュに
            v3 =
                if v2 = null then
                    null
                else
                    Text.Replace(v2, ".", "/"),

            // 8桁(YYYYMMDD)の場合はスラッシュを挿入
            v4 =
                if v3 = null then
                    null
                else if Text.Length(v3) = 8 and Text.Select(v3, {"0".."9"}) = v3 then
                    let
                        y = Text.Start(v3, 4),
                        m = Text.Middle(v3, 4, 2),
                        d = Text.End(v3, 2)
                    in
                        y & "/" & m & "/" & d
                else
                    v3,

            // 最後に Date.FromText で日付化(失敗したら null)
            result =
                if v4 = null then
                    null
                else
                    try Date.FromText(v4) otherwise null
        in
            result
in
    TextToDateJP
Power Query

この関数は、ざっくり言うとこういう動きをします。

NULL や空文字はそのまま NULL。
「年」「月」「日」をスラッシュに変える。
ドットをスラッシュに変える。
8桁数字なら YYYY/MM/DD に整形する。
最後に Date.FromText で日付に変換し、失敗したら NULL にする。

これを作っておけば、クエリ側はかなりスッキリ書けます。

let
    Source = ・・・前のステップ・・・,

    Converted =
        Table.TransformColumns(
            Source,
            {
                {"受注日", fn_TextToDateJP, type nullable date},
                {"納品予定日", fn_TextToDateJP, type nullable date}
            }
        )
in
    Converted
Power Query

「日付文字列を日付型に変換する」という意図が、コードから一目で分かるようになります。


実務での“ハマりポイント”と回避のコツ

ロケール(日付の読み方)に注意する

01/10/2024 が「2024年1月10日」なのか「2024年10月1日」なのかは、
ロケール(地域設定)によって解釈が変わります。

日本ロケールでは、基本的に YYYY/MM/DD を想定しているので、
DD/MM/YYYY 形式のデータを扱うときは、
「日」「月」を入れ替える前処理を自分で書く必要があります。

「どの列がどの書式で来るか」を最初に決めておくと、クレンジングの設計が一気に楽になります。

日付型にしておくと何が嬉しいか

日付型にしておくと、次のようなことが“当たり前に”できるようになります。

期間フィルタ(2024/10/01〜2024/10/31 だけ抽出)。
月別・年別の集計(Date.Year、Date.Month など)。
日付差分(納期遅延日数、在庫滞留日数など)の計算。

逆に、text のまま放置すると、
「文字列としての大小比較」になってしまい、
"2024/2/1""2024/10/1" の順番が崩れたりします。


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

「日付文字列を日付型変換」の本質は、次の二つです。

Power Query が読める書式(たとえば YYYY/MM/DD)に、文字列をまずそろえる。
そのうえで、type date への型変換、または Date.FromText を使って日付型にする。

これをテンプレとして持っておけば、
受注日・出荷日・請求日・入金日・有効期限など、
あらゆる“日付っぽい文字列”を、迷わず“ちゃんと日付”として扱えるようになります。

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