Power QueryのM言語を10の小さな実験で理解する

LWP | Power QueryのM言語を10の小さな実験で理解する

LWP TECHNICAL ARTICLE | 185

Power QueryのM言語を10の小さな実験で理解する

GUIの裏側にある「値・型・関数」の世界を30分で覗いてみる

Copyright © 2026 LWP 山中 一弘

本資料は、出典を明記いただければ、商用・非商用を問わず、ご自由に複製・改変・再配布していただけます。なお、著作権表示は改変せず、そのまま記載してご利用くださいますようお願いいたします。

記事要約

Power Queryは、Excelの画面から列削除や行抽出を行える便利なデータ変換機能です。しかし、GUIで行った操作の裏側では、M言語の式が作られ、ある値から次の値への変換が組み立てられています。

Mを最初から体系的に暗記する必要はありません。GUIが作った式を観察し、Table・Record・List、letとin、eachと_、関数、Durationといった要素を小さく試すだけでも、Power Queryの見え方は大きく変わります。

この記事では、一つの「中華料理」テーブルを共通データにして、M言語の特徴を10の実験で確認します。結論は、Mを「Excelセルを操作する手順」ではなく、値を受け取り、別の値を返す式の連鎖として読むことです。この見方を持つと、GUIで作ったクエリの読解、修正、再利用がしやすくなります。

本記事の対象とゴール

想定読者

  • Power QueryのGUI操作はできるが、数式バーや詳細エディターをほとんど見たことがない方

  • let、in、each、_、{}、[]の意味を実例でつかみたい方

  • M言語を本格的に学ぶ前に、どのような言語なのか短時間で体験したい方

本記事で得られること

  1. GUI操作とMコードの関係を説明できます。

  2. Table・Record・Listの違いと、値を取り出す記法を確認できます。

  3. each、高階関数、クロージャー、再帰、式評価までを一続きの考え方として捉えられます。

はじめに 共通データを用意する

この記事のコードは、ExcelのPower Queryエディターで空のクエリを作り、[詳細エディター]へ貼り付けて試せます。最初に、共通の実験材料となる「中華料理」クエリを作ります。

クエリ名を 中華料理 とし、次のコードを貼り付けます。

let
    Source =
        #table(
            type table [
                料理名 = text,
                分類 = text,
                単価 = number,
                数量 = number,
                注文日 = date
            ],
            {
                {"麻婆豆腐", "一品料理", 900, 2, #date(2026, 8, 1)},
                {"青椒肉絲", "一品料理", 1100, 1, #date(2026, 8, 5)},
                {"小籠包", "点心", 600, 3, #date(2026, 8, 10)},
                {"担々麺", "麺", 950, 2, #date(2026, 8, 15)},
                {"海老炒飯", "飯", 1000, 1, #date(2026, 8, 20)},
                {"回鍋肉", "一品料理", 850, 3, #date(2026, 8, 22)},
                {"焼売", "点心", 550, 4, #date(2026, 8, 25)}
            }
        )
in
    Source

#tableは、列の定義と行データからTable値を作ります。ここでは列ごとの型も明示しているため、以後の実験で文字列、数値、日付を区別できます。

各実験は、空のクエリへコードを貼り付けて単独で試せます。List、Record、関数など、共通テーブルだけでは説明しにくいものは、その場で小さな値を作ります。

第1章 GUIはMコードを生成している

1.1 列削除の裏側を見る

「中華料理」クエリで[分類]列を選び、GUIから列を削除します。数式バーには、次のような式が生成されます。

Table.RemoveColumns(Source, {"分類"})

GUIは単なる操作画面ではありません。選んだ操作をMの式へ翻訳するフロントエンドでもあります。

1.2 同じ処理を直接実行する

別の空のクエリで、次の式を試します。

Table.RemoveColumns(中華料理, {"分類"})

[分類]列を除いた新しいTableが返れば成功です。元の「中華料理」クエリそのものから列が消えるわけではありません。関数が元のTableを受け取り、列を除いた別のTableを返しています。

Mへの入り口は、白紙からすべて書くことではありません。

  • GUIで処理を作る。

  • 数式バーや詳細エディターで生成されたMを見る。

  • 必要な箇所だけ修正する。

この順序なら、普段の操作とコードを対応づけながら学べます。

第2章 適用したステップは値の連鎖である

2.1 前の値から次の値を作る

次のクエリは、列削除と行抽出を順に行います。

let
    Source = 中華料理,
    RemovedColumns = Table.RemoveColumns(Source, {"分類"}),
    FilteredRows = Table.SelectRows(RemovedColumns, each [単価] >= 1000)
in
    FilteredRows

処理の流れは、次のように読めます。

  • Sourceは「中華料理」と同じTableです。

  • RemovedColumnsは、Sourceから[分類]列を除いたTableです。

  • FilteredRowsは、RemovedColumnsから単価1,000円以上の行を選んだTableです。

  • inは、クエリ全体の結果としてFilteredRowsを返します。

適用したステップは「画面操作の履歴」に見えますが、Mの側から見ると、名前を付けた値どうしの依存関係です。

2.2 inを変えて途中結果を見る

最後だけ次のように変えます。

in
    RemovedColumns

今度は、行を抽出する前のTableが返ります。letの中で途中の値を定義し、inで最終的に返す式を選ぶ。この構造が分かると、複数ステップのクエリを上から順に読みやすくなります。

第3章 Mはセルではなく値を扱う

Excelでは、A1、B5、Sheet1!C10のようにセルを中心に考えることが多くあります。Power QueryのMでは、Table、List、Recordなどの値を受け取り、新しい値を返す考え方が中心です。

次の式は、数量が2以上の行を選びます。

Table.SelectRows(
    中華料理,
    each [数量] >= 2
)

ここで行っているのは、特定のセルを上書きする処理ではありません。

  • 入力は「中華料理」というTableです。

  • 条件は「各行の数量が2以上」です。

  • 出力は、条件を満たす行だけを持つ新しいTableです。

Excelのシート上では最終結果がセルへ読み込まれますが、クエリ内の思考単位はセル番地ではなく値です。

第4章 Table・Record・Listを見分ける

4.1 Listは順序を持つ値の並び

次の式は、4個のnumberを持つListです。

{900, 1100, 600, 950}

Listでは、項目を0から始まる位置で取り出せます。

{900, 1100, 600, 950}{0}

結果は900です。

4.2 Recordはフィールド名と値の組

次の式は、一つの料理を表すRecordです。

[
    料理名 = "麻婆豆腐",
    分類 = "一品料理",
    単価 = 900,
    数量 = 2
]

Recordでは、角括弧を使ってフィールドを取り出せます。

[
    料理名 = "麻婆豆腐",
    分類 = "一品料理",
    単価 = 900,
    数量 = 2
][単価]

結果は900です。

4.3 Tableは行と列を持つ

最初に作った「中華料理」はTableです。各行はRecordとして扱え、同じ列構造を持つRecordが並んでいると捉えると、Tableから値を取り出す記法が理解しやすくなります。

第5章 Tableから1行取るとRecordになる

5.1 0番目の行を取り出す

次の式を実行します。

中華料理{0}

結果はTableではなく、先頭行を表すRecordです。概念的には次の内容です。

[
    料理名 = "麻婆豆腐",
    分類 = "一品料理",
    単価 = 900,
    数量 = 2,
    注文日 = #date(2026, 8, 1)
]

5.2 Recordからフィールドを取り出す

行を取り出した後に、料理名フィールドを選びます。

中華料理{0}[料理名]

結果は文字列の「麻婆豆腐」です。

この式は、左から順に次のように読めます。

  • 中華料理はTableである。

  • {0}で先頭行を選ぶとRecordになる。

  • [料理名]でRecordのフィールドを選ぶとtextになる。

記号を暗記するだけでなく、「式を通過するたびに値の種類が変わる」と見るのがポイントです。

第6章 eachと_の正体は小さな関数である

6.1 金額列を追加する

単価と数量を掛けた[金額]列を追加します。

Table.AddColumn(
    中華料理,
    "金額",
    each [単価] * [数量],
    type number
)

麻婆豆腐の行なら、900×2で1,800になります。第4引数のtype numberは、追加列の型を明示しています。

6.2 eachは関数の省略記法

MicrosoftのM言語解説では、each ...は引数名を_とした関数の省略記法です。

each [単価] * [数量]

この式は、次の関数として読めます。

(_) => _[単価] * _[数量]

Table.AddColumnは各行をRecordとして関数へ渡します。_にはその時点の行が入り、_[単価]と_[数量]でフィールドを取り出します。

eachを「Power Query特有の不思議な予約語」と暗記するより、「引数を一つ受け取る短い関数」と考える方が応用できます。

第7章 関数そのものも値である

7.1 関数を名前へ入れる

次のコードでは、Text.Upperという関数そのものをfへ入れます。

let
    f = Text.Upper
in
    f("mapo tofu")

結果は次の文字列です。

MAPO TOFU

Text.Upperをその場で実行して結果を保存しているのではありません。関数値をfへ束縛し、その後で引数を渡して呼び出しています。

7.2 関数を渡せるから処理を部品化できる

Mでは、数値、文字列、List、Record、Tableだけでなく、関数も値として扱えます。関数を名前へ入れ、別の関数へ渡し、関数から返せます。

この性質が、Table.SelectRowsへ条件関数を渡す処理や、Table.AddColumnへ列の生成関数を渡す処理の土台です。

第8章 ループを書く代わりに関数を渡す

8.1 Listの全要素を10倍する

次の式は、Listの各要素へ同じ変換を適用します。

List.Transform(
    {1, 2, 3},
    each _ * 10
)

結果は次のListです。

{10, 20, 30}

処理順を制御するForループを書くのではなく、「各要素へ適用する変換」を関数として渡しています。

8.2 Tableの行抽出も同じ発想で読む

Table.SelectRows(
    中華料理,
    each [単価] >= 1000
)

Table.SelectRowsへ渡すのは、各行が残るかどうかを判定する関数です。

  • List.Transformは、各要素を別の値へ変換します。

  • Table.SelectRowsは、各行についてtrueまたはfalseを返す条件で行を選びます。

  • Table.AddColumnは、各行から新しい列の値を計算します。

関数名は違っても、「データと、データへ適用する関数を渡す」という形は共通しています。

第9章 日付の差はnumberではなくDurationになる

9.1 二つの注文日の差を求める

先頭行は2026年8月1日、5行目は2026年8月20日です。二つのdateを引きます。

中華料理{4}[注文日] - 中華料理{0}[注文日]

差は19日ですが、結果の型はnumberではなくdurationです。表示上は、次のような期間値になります。

#duration(19, 0, 0, 0)

9.2 日数というnumberへ変換する

日数だけが必要なら、Duration.Daysで日という構成部分を取り出せます。

Duration.Days(
    中華料理{4}[注文日] - 中華料理{0}[注文日]
)

結果はnumberの19です。

dateやdatetimeは「いつか」を表し、durationは「どれだけ離れているか」を表します。Excelでは日付差が数値として見えますが、Mでは時点と時間の長さを別の型にするため、式の意味が明示されます。

時刻まで含む経過時間を小数の日数へ換算したい場合は、日部分だけを返すDuration.Daysではなく、Duration.TotalDaysを検討します。

第10章 Mは自分で関数を作り、関数を返し、式まで評価できる

ここでは詳細な文法を覚える必要はありません。Mがデータ整形専用の簡易記法ではなく、関数を組み立てられる言語であることを確認します。

10.1 自分で関数を作る

次のDoubleは、受け取った値を2倍する関数です。

let
    Double = (x) => x * 2
in
    Double(100)

結果は200です。

10.2 関数から関数を返す

次のAddは、最初の値を受け取ると、もう一つの値を加える関数を返します。

let
    Add = (x) => (y) => x + y,
    Add100 = Add(100)
in
    Add100(20)

結果は120です。Add100は、最初に与えられた100を保持しています。関数が作られた環境の値を保持する仕組みがクロージャーです。

10.3 再帰関数を作る

次の関数は、5の階乗を求めます。

let
    Factorial = (n as number) as number =>
        if n <= 1 then
            1
        else
            n * @Factorial(n - 1)
in
    Factorial(5)

結果は120です。関数の定義内から自分自身を参照する箇所では、スコープ演算子@を付けています。

10.4 文字列に書かれたM式を評価する

Expression.Evaluateは、文字列として渡したM式を評価します。実務では、信頼できない文字列を無条件に渡しません。

Expression.Evaluate(
    "100 + 20"
)

結果は120です。

まとめ Mを全部覚えなくても、Power Queryの見え方は変わる

この記事では、M言語の特徴を10の実験で確認しました。

  • GUI操作はMコードを生成しています。

  • 適用したステップは、前の値から次の値を作る連鎖です。

  • Mはセル操作ではなく、Tableなどの値を変換します。

  • Table・Record・Listは、それぞれ異なる構造を持つ値です。

  • Tableから1行を選ぶとRecordになり、そこからフィールドを取り出せます。

  • eachは、引数名を_とした短い関数の省略記法です。

  • Mでは、関数そのものも値として扱えます。

  • データと処理関数を渡すことで、明示的なForループなしに変換できます。

  • 日付の差は、時間の長さを表すdurationになります。

  • 自作関数、クロージャー、再帰、式評価まで記述できます。

Mを学ぶときに重要なのは、関数名を大量に暗記することではありません。まず、式の入力と出力がどの種類の値なのかを追います。

Table
  ↓ 行を選ぶ
Record
  ↓ フィールドを選ぶ
text / number / date
  ↓ 関数へ渡す
別の値

GUIで処理を作り、生成されたMを覗き、分からない記号を一つずつ実験する。この繰り返しだけでも、Power Queryは「ボタンを押す道具」から「値の変換を設計する道具」へ変わって見えてきます。

参考資料

  • Microsoft Learn「Power Query M formula language introduction」

  • Microsoft Learn「M Language basic concepts」

  • Microsoft Learn「M Language Let」

  • Microsoft Learn「Understanding Power Query M functions」

  • Microsoft Learn「Table.AddColumn」

  • Microsoft Learn「Table.SelectRows」

  • Microsoft Learn「Duration support in Power Query M」

  • Microsoft Learn「Expression.Evaluate」

出典メモ

  • 元原稿: C:\Users\hoehoe\Downloads\記事ネタmd\PowerQuery_M_10の小技_30分講義_記事元ネタ.md

  • 元原稿の「共通の中華料理テーブルを使い、Mの特徴を10個の小実験で見る」という構成を主軸に、対象読者、確認方法、型の遷移、実務上の注意を補って公開記事へ再構成しました。

  • Mの値、let式、ListとRecordのアクセス、関数値、eachと_、再帰の@、Duration、Table.AddColumn、Table.SelectRows、Expression.Evaluateは、2026年8月21日にMicrosoft公式資料で確認しました。

  • 公式資料: https://learn.microsoft.com/en-us/powerquery-m/m-spec-introduction

  • 公式資料: https://learn.microsoft.com/en-us/powerquery-m/m-spec-basic-concepts

  • 公式資料: https://learn.microsoft.com/en-us/powerquery-m/m-spec-let

  • 公式資料: https://learn.microsoft.com/en-us/powerquery-m/understanding-power-query-m-functions

  • 公式資料: https://learn.microsoft.com/en-us/powerquery-m/table-addcolumn

  • 公式資料: https://learn.microsoft.com/en-us/powerquery-m/table-selectrows

  • 公式資料: https://learn.microsoft.com/en-us/powerquery-m/durations

  • 公式資料: https://learn.microsoft.com/en-us/powerquery-m/expression-evaluate