実務で使えるPower Query小技・テクニック | レコードを作る

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

レコードを作るとは何か

Power Query(M言語)で「レコードを作る」とは、複数の項目(フィールド)をひとまとめにした“名前付きの箱”を作ることです。 Excelでいう「1行分のデータ」に近いイメージで、「顧客コード」「顧客名」「金額」などを1つのセットとして扱えるようにするのがレコードです。

実務では、レコードは次のような場面でよく使われます。

  • 設定値のまとまり(例:税率・閾値・フラグを1つの塊にする)
  • 関数の戻り値として複数の値を返す
  • テーブルの1行を直接扱う
  • ログやメタ情報をまとめて持つ

ここでは、初心者向けに「レコードの作り方・使い方」をステップバイステップで解説していきます。

M言語でのレコードの基本構文

[ フィールド名 = 値, … ] でレコードを作る

最も基本的なレコードの作り方は次のようになります。

let
    Customer =
        [
            顧客コード = "C001",
            顧客名 = "山田商事",
            売上金額 = 120000
        ]
in
    Customer
Power Query

ここでは、Customer という変数にレコードを入れています。 レコードは、[フィールド名 = 値, フィールド名 = 値, ...] という形で作るのが基本ルールです。

フィールド名は「列名」に近いイメージで、 後から Customer[顧客名] のようにして取り出すことができます。

レコードをステップバイステップで作る

ステップ1:何をひとまとめにしたいかを決める

レコードに入れるものは、次のようなものが多いです。

  • 設定値(例:税率・割引率・閾値)
  • 1行分のデータ(例:顧客情報1件)
  • 関数の戻り値(例:合計・平均・件数)
  • ログ情報(例:処理名・対象ファイル・実行時刻)

例:設定値をレコードにまとめる

let
    Settings =
        [
            TaxRate = 0.1,
            DiscountRate = 0.05,
            HighAmountThreshold = 1000
        ]
in
    Settings
Power Query

ステップ2:レコードから値を取り出す

レコードから特定のフィールドを取り出すには、 レコード[フィールド名] という書き方をします。

let
    Settings =
        [
            TaxRate = 0.1,
            DiscountRate = 0.05,
            HighAmountThreshold = 1000
        ],

    TaxRateValue = Settings[TaxRate],
    ThresholdValue = Settings[HighAmountThreshold]
in
    [税率 = TaxRateValue, 閾値 = ThresholdValue]
Power Query

ここでは、

  • Settings[TaxRate] で税率を取り出し
  • Settings[HighAmountThreshold] で閾値を取り出しています。

このように、レコードは「名前付きの値の集合」として扱えるのが特徴です。

ステップ3:レコードを関数の戻り値として使う

複数の値をまとめて返したいとき、レコードは非常に便利です。

let
    GetSalesSummary =
        (SalesTable as table) as record =>
            let
                AmountList = SalesTable[金額],
                CleanAmountList = List.RemoveNulls(AmountList),

                TotalAmount = List.Sum(CleanAmountList),
                RowCount = List.Count(CleanAmountList),
                AverageAmount =
                    if RowCount = 0 then
                        null
                    else
                        TotalAmount / RowCount
            in
                [
                    合計金額 = TotalAmount,
                    件数 = RowCount,
                    平均金額 = AverageAmount
                ]
in
    GetSalesSummary
Power Query

この関数は、

  • 合計金額
  • 件数
  • 平均金額

を1つのレコードとして返します。

呼び出し側では次のように使えます。

let
    SalesTable = Excel.CurrentWorkbook(){[Name="売上"]}[Content],

    Summary = GetSalesSummary(SalesTable),

    Total = Summary[合計金額],
    Avg = Summary[平均金額]
in
    [Total = Total, Avg = Avg]
Power Query

レコードを戻り値に使うことで、「複数の結果をまとめて返す」設計がしやすくなるのがポイントです。

テーブルとレコードの関係

テーブルの1行は「レコード」として扱える

M言語では、テーブルの1行はレコードとして扱われます。

例:先頭行をレコードとして取り出す

let
    SalesTable = Excel.CurrentWorkbook(){[Name="売上"]}[Content],

    FirstRowRecord = SalesTable{0}
in
    FirstRowRecord
Power Query

ここでの SalesTable{0} は、 「インデックス0番目の行(先頭行)をレコードとして取り出す」という意味です。

取り出したレコードから、特定の列の値を参照することもできます。

let
    SalesTable = Excel.CurrentWorkbook(){[Name="売上"]}[Content],

    FirstRowRecord = SalesTable{0},

    FirstCustomerCode = FirstRowRecord[顧客コード],
    FirstAmount = FirstRowRecord[金額]
in
    [顧客コード = FirstCustomerCode, 金額 = FirstAmount]
Power Query

このように、テーブルの行とレコードは密接に結びついているため、 「1行だけを詳しく扱いたい」ときにレコードが役立ちます。

レコードを扱うときの重要な注意点

1. フィールド名は「識別子」であり、型の一部

レコードのフィールド名は、

  • スペルミスすると別のフィールド扱いになる
  • 後から名前を変えると、参照している箇所すべてを直す必要がある

という性質があります。

悪い例:

Settings = [Taxrate = 0.1]   // TaxRate と書きたかったのに…
Tax = Settings[TaxRate]      // ここはエラー
Power Query

良い例:

Settings = [TaxRate = 0.1]
Tax = Settings[TaxRate]
Power Query

フィールド名は、一貫した命名とスペルの正確さが非常に重要です。

2. 存在しないフィールドを参照するとエラーになる

レコードに存在しないフィールド名を参照すると、エラーになります。

Settings = [TaxRate = 0.1],
Value = Settings[DiscountRate]   // DiscountRate は存在しない → エラー
Power Query

そのため、

  • レコードの構造を変更したときは、参照箇所も必ず見直す
  • 必要なら Record.HasFields で存在チェックを行う

といった工夫が重要です。

let
    Settings = [TaxRate = 0.1],

    HasDiscount =
        Record.HasFields(Settings, "DiscountRate")
in
    HasDiscount
Power Query

3. null を含むフィールドの扱いに注意する

レコードのフィールドに null が入っている場合、 そのまま計算や判定に使うと意図しない結果になることがあります。

let
    Info =
        [
            顧客コード = null,
            顧客名 = "山田商事"
        ],

    IsCustomerCodeMissing =
        (Info[顧客コード] = null)
in
    IsCustomerCodeMissing
Power Query

このように、レコードの中でも null を明示的に扱うことが重要です。

4. セキュリティの観点からのレコード

レコードは「設定値のまとまり」「権限情報」「接続情報」など、 セキュリティに関わる情報を持つこともあります。

例:

let
    UserInfo =
        [
            UserId = "U001",
            Role = "Admin",
            IsActive = true
        ],

    IsAdminUser = (UserInfo[Role] = "Admin")
in
    IsAdminUser
Power Query

このようなロジックを使う場合は、

  • 誰がこのコードを編集できるか
  • ロール名や権限情報を変更できる権限が適切か

を意識しておくことが重要です。

誤ってレコードの内容を変更すると、 本来許可されていない操作が可能になってしまうリスクがあります。

実務で使える「レコード作成テンプレート」

テンプレ1:設定値レコード

let
    Settings =
        [
            TaxRate = 0.1,              // 消費税率10%
            DiscountRate = 0.05,        // 割引率5%
            HighAmountThreshold = 1000  // 高額判定の閾値
        ],

    TaxRateValue = Settings[TaxRate],
    DiscountRateValue = Settings[DiscountRate]
in
    Settings
Power Query

テンプレ2:集計結果をレコードで返す

let
    SalesTable = Excel.CurrentWorkbook(){[Name="売上"]}[Content],

    AmountList = List.RemoveNulls(SalesTable[金額]),

    TotalAmount = List.Sum(AmountList),
    RowCount = List.Count(AmountList),
    AverageAmount =
        if RowCount = 0 then
            null
        else
            TotalAmount / RowCount,

    Summary =
        [
            合計金額 = TotalAmount,
            件数 = RowCount,
            平均金額 = AverageAmount
        ]
in
    Summary
Power Query

テンプレ3:ログ情報をレコードで持つ

let
    ProcessName = "売上クレンジング",
    FileName = "売上_2024-01.xlsx",
    RunAt = DateTime.LocalNow(),

    LogRecord =
        [
            処理名 = ProcessName,
            対象ファイル = FileName,
            実行日時 = RunAt
        ]
in
    LogRecord
Power Query

まとめ:レコードを作ることは「意味のあるまとまりに名前を付けること」

M言語でレコードを作るというのは、 「複数の値をひとまとめにして、意味のある単位として扱うこと」です。

これによって、

  • 設定値や集計結果を構造化して管理できる
  • 関数の戻り値として複数の値を安全に返せる
  • テーブルの1行を柔軟に扱える
  • セキュリティや業務ルールをコードとして明示できる

というメリットが得られます。

レコードは、実務の Power Query で「設計の質」を左右する重要な要素ですので、 ぜひ「[フィールド名 = 値] で作る」「レコードからフィールドを取り出す」感覚を身につけていただきたいです。

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