Power Queryのボタンの向こう側へ

LWP TECHNICAL ARTICLE | 187

Power Queryのボタンの向こう側へ

M式でデータを組み立てる ― 登壇用セミナーテキスト

ほえほえ研究所 Power Query LT会|2026年8月22日

Copyright © 2026 LWP 山中 一弘

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

記事要約

ExcelシートやCSVを教材として使わず、3本の #table クエリをM式で直接作ります。以降の章は、そのクエリを入力として上から順に進めます。

このセミナーの進め方

各章は、一つのトピックだけを扱います。受講者に個別演習をさせる講義資料ではありません。登壇者が詳細エディターと結果プレビューを切り替えながら、Power Queryの考え方を順番に見せるためのテキストです。

最初に見せること Power Queryは、ボタン操作の集合ではなく、値を入力し、値を変換し、最後の値を返す仕組みです。

最後に残したいこと 詳細エディターを怖がらず、入力・変換・出力をM式として読めるようになることです。

本日の合言葉 ボタンを押したらコードを見る。コードを見たら、何の値が入り、何の値が出るかを考える。

登壇順

第1章 初期設定を、安心して試すための前提として置く

第2章 詳細エディターで let / in を読む

第3章 M式の中に三つのサンプルテーブルを作る

第4章 クエリを、値を返す式として読む

第5章 Tableに列を加える

第6章 二つのTableを結合する

第7章 Tableを集計して別のTableにする

第8章 List・Record・Tableをアクセス記法で見分ける

第9章 eachを短い関数として読む

第10章 関数を作り、変換を名前で呼ぶ

第11章 クロージャーで条件を覚えた関数を作る

第12章 依存関係を見て、データの流れとして捉え直す

登壇メモ 時間が短いときは、第1章から第7章を本線にします。第8章から第11章は、GUIの裏側にあるM言語の考え方を見せる発展パートです。

第1章 初期設定は、試すための安全装置である

このトピックの核 Power Queryの設定は、便利にするためだけのものではありません。何と何を結合してよいかをPower Queryへ伝える境界です。

画面で見せるもの Excelの[データ]タブから[クエリ オプション]を開き、プライバシーの設定と型検出の設定を確認する画面です。

プライバシー設定

プライバシーレベルは、異なるデータソースの間で情報が意図せず渡ることを防ぐ仕組みです。講義で使うデータがローカルの既知データだけであっても、実務で設定を無条件に無効化してよい、という話ではありません。

型の自動検出

Power Queryは、列の内容を見て型を推測できます。便利な一方で、いつ型が付いたのか分からなくなることがあります。今日の画面では、[変更された型]ステップがどこで作られたかだけを確認します。

この章の着地 設定はM式の外側にある前提条件です。M式そのものは、次章から同じ形で読めます。

登壇メモ 設定画面の説明を長くしません。「安全に試すための入口」と置き、すぐに詳細エディターへ移ります。

第2章 詳細エディターでクエリの骨格を見る

このトピックの核 Power Queryのクエリは、letで途中の名前を定義し、inで最後に返す値を指定する式です。

画面で見せるもの 空のクエリを詳細エディターで開いた画面です。最初から表を操作するのではなく、短いM式を見せます。

let と in

letの中では、途中の値に名前を付けます。名前と式をイコールで結び、複数の定義をコンマで区切ります。inの右側には、最後に返す値の名前を書きます。

let
    元の値 = 10,
    2倍 = 元の値 * 2
in
    2倍

この式は、numberという値から別のnumberを作り、最後に20を返します。以降は返す値がTableになるだけで、let / inの骨格は変わりません。

この章の着地 GUIの「適用したステップ」は、M式では途中の値に付けた名前として見えます。

登壇メモ 「命令を上から実行する」と断定せず、前の名前が持つ値を次の式が参照する、と説明します。ここがデータの流れとして見る入口です。

第3章 M式の中に三つのサンプルテーブルを作る

このトピックの核 講義用の入力データをExcelシートに置かず、#tableで直接作ります。これにより、ファイルやシートの状態から切り離して、M式だけを見せられます。

画面で見せるもの 詳細エディターとクエリ一覧です。次の三つを、それぞれ別の空のクエリとして作ります。以降の章では、この三つを入力として参照します。

Q_注文

注文という出来事を表すTableです。数量と実売単価は、この後の金額計算に使います。

let
    Source =
        #table(
            type table [
                注文ID = text,
                店舗ID = text,
                料理ID = text,
                数量 = number,
                実売単価 = number
            ],
            {
                {"O001", "S01", "D01", 2, 900},
                {"O002", "S01", "D03", 1, 1200},
                {"O003", "S02", "D02", 3, 780},
                {"O004", "S03", "D04", 1, 1050},
                {"O005", "S02", "D01", 1, 900},
                {"O006", "S03", "D03", 2, 1200}
            }
        )
in
    Source

Q_料理

料理IDに、表示用の料理名と分類を対応させるTableです。

let
    Source =
        #table(
            type table [
                料理ID = text,
                料理名 = text,
                分類 = text
            ],
            {
                {"D01", "麻婆豆腐", "主菜"},
                {"D02", "青椒肉絲", "主菜"},
                {"D03", "海老のチリソース", "主菜"},
                {"D04", "五目炒飯", "飯・麺"}
            }
        )
in
    Source

Q_店舗

店舗IDに、店舗名と地域を対応させるTableです。

let
    Source =
        #table(
            type table [
                店舗ID = text,
                店舗名 = text,
                地域 = text
            ],
            {
                {"S01", "神田店", "東京東"},
                {"S02", "新宿店", "東京西"},
                {"S03", "横浜店", "神奈川"}
            }
        )
in
    Source

この章の着地 三つともTableを返すクエリです。#tableの中身を変えれば結果は変わりますが、以降の変換の考え方は変わりません。

登壇メモ 全データを読み上げません。列名、行のまとまり、そして「シートがなくてもTableを作れる」という一点に集中します。

第4章 クエリを、値を返す式として読む

このトピックの核 一つのクエリは、前の名前が持つ値を次の式に渡し、最後にinで選んだ値を返します。クエリ名はファイル名ではなく、値に付けた入口の名前です。

画面で見せるもの Q_注文を参照する新しい空のクエリです。クエリ一覧にQ_注文とQ_金額付き注文が並ぶ状態を見せます。

let
    Source = Q_注文,
    金額付き =
        Table.AddColumn(
            Source,
            "金額",
            each [数量] * [実売単価],
            type number
        )
in
    金額付き

Sourceも金額付きもTableです。途中の名前を変えても、値の型を意識して読めば流れを追えます。

この章の着地 Q_金額付き注文はQ_注文を入力にしています。Q_注文の値が変われば、その先も再評価されます。

登壇メモ ここでは「更新順」より「依存関係」という言葉を使います。Power Queryをデータの流れとして見るためです。

第5章 Tableに列を加える

このトピックの核 Table.AddColumnは、Tableと「1行を受け取って値を返す関数」を受け取り、新しい列を持つTableを返します。

画面で見せるもの Q_金額付き注文の結果プレビューです。数量2、実売単価900の行に、金額1800が現れることを指します。

let
    Source = Q_注文,
    金額付き =
        Table.AddColumn(
            Source,
            "金額",
            each [数量] * [実売単価],
            type number
        )
in
    金額付き

元のQ_注文を書き換えたのではありません。Q_注文を材料にして、金額列を持つ別のTableを作りました。

この章の着地 列の追加は、各行を入力にして新しい列の値を返す変換です。

登壇メモ eachは「1行を受け取る短い関数」だと予告します。ここではeachの文法を掘り下げず、第9章へつなぎます。

第6章 二つのTableを結合する

このトピックの核 Table.NestedJoinで対応する行を入れ子のTableとして結び、Table.ExpandTableColumnで必要な列だけを広げます。

画面で見せるもの Q_金額付き注文とQ_料理を料理IDでつなぎ、料理名と分類が注文行の右側へ現れる結果です。

let
    Source = Q_金額付き注文,
    結合 =
        Table.NestedJoin(
            Source,
            {"料理ID"},
            Q_料理,
            {"料理ID"},
            "料理",
            JoinKind.LeftOuter
        ),
    展開 =
        Table.ExpandTableColumn(
            結合,
            "料理",
            {"料理名", "分類"},
            {"料理名", "分類"}
        )
in
    展開

結合の途中にある料理列は、各行の中に入った小さなTableです。次の展開で、その中の列を通常の列として見せます。

この章の着地 結合は「横に付けるボタン」ではなく、対応する行を見つける規則です。

登壇メモ キー列が重複すると結果の行数にも影響します。実務では、結合前に料理IDの一意性を見る習慣が必要だと添えます。

第7章 Tableを集計して別のTableにする

このトピックの核 Table.Groupは、明細Tableをキーごとのグループに分け、集計結果を持つ新しいTableを返します。

画面で見せるもの 料理名ごとの売上を示すQ_料理別売上です。明細が6行から、料理名ごとの数行へ変わる結果を見せます。

let
    Source = Q_料理付き注文,
    集計 =
        Table.Group(
            Source,
            {"料理名", "分類"},
            {
                {
                    "売上",
                    each List.Sum([金額]),
                    type number
                }
            }
        ),
    並べ替え =
        Table.Sort(
            集計,
            {{"売上", Order.Descending}}
        )
in
    並べ替え

第5章の列追加は、一行ずつ値を増やす変換でした。集計は、複数行をまとめて一行に作り直す変換です。

この章の着地 グループの中の[金額]はListとして扱えます。Tableの列を取り出すとListになります。

登壇メモ ここでListを詳しく説明せず、「次章でTableをほどいて中身を見る」と予告します。

第8章 List・Record・Tableをアクセス記法で見分ける

このトピックの核 Tableは行と列の集合、Recordは一行分の名前付き値、Listは順番を持つ値の並びです。同じデータを、別の形として取り出せます。

画面で見せるもの Q_注文の結果と、次の式を順に評価したときのプレビューです。型の名称より、取り出し方の違いを見せます。

let
    注文Table = Q_注文,
    先頭行 = 注文Table{0},
    先頭行の店舗ID = 先頭行[店舗ID],
    料理IDの列 = 注文Table[料理ID],
    最初の料理ID = 料理IDの列{0}
in
    [
        店舗ID = 先頭行の店舗ID,
        料理ID = 最初の料理ID
    ]

Tableから一行を取るとRecordになります。Tableから一列を取るとListになります。波かっこは位置、角かっこは名前で取り出す記法です。

この章の着地 表の見た目に引きずられず、今手元にある値がTable、Record、Listのどれかを考えます。

登壇メモ 記号の完全な文法表は出しません。画面上で一行、列、フィールドを一つずつ取り出し、結果の形を見せます。

第9章 eachを短い関数として読む

このトピックの核 each [数量] * [実売単価] は、各行を受け取り、金額を返す関数の省略記法です。

画面で見せるもの 第5章の金額列追加を、eachありと明示的な関数ありの二つで並べます。結果が同じであることをプレビューで確認します。

// each を使う短い形
each [数量] * [実売単価]
 
// 同じ意味を明示した形
(_) => _[数量] * _[実売単価]

アンダースコアは、その場で渡される一つの値を表します。Table.AddColumnの中では、一行分のRecordが渡されます。

この章の着地 eachは特別な繰り返し命令ではなく、関数を書くための短い記法です。

登壇メモ 省略形を暗記させる必要はありません。読みにくくなったら明示形に戻せることが重要です。

第10章 関数を作り、変換を名前で呼ぶ

このトピックの核 変換に名前を付けると、式の目的が見え、同じ規則を何度でも使えます。関数もM言語では値です。

画面で見せるもの F_金額という名前の空のクエリと、それを列追加から呼び出すクエリです。

F_金額

(行 as record) as number =>
    行[数量] * 行[実売単価]

関数を使う側

let
    Source = Q_注文,
    金額付き =
        Table.AddColumn(
            Source,
            "金額",
            each F_金額(_),
            type number
        )
in
    金額付き

関数を別クエリにした瞬間に、クエリ一覧は「データ」だけでなく、「変換の部品」も並ぶ場所になります。

この章の着地 この計算にはF_金額という名前が付き、計算方法と利用場所を分けて読めるようになりました。

登壇メモ 最初から汎用ライブラリの話へ広げません。一つの短い計算に名前を付ける効果だけを見せます。

第11章 クロージャーで条件を覚えた関数を作る

このトピックの核 関数の外側で受け取った最低金額を、内側の関数が覚えて使います。この形をクロージャーと呼びます。

画面で見せるもの 最低金額1500を渡した結果、金額が1500以上の注文だけが残るプレビューです。Excelセルの設定値は使わず、値を直接渡します。

F_最低金額以上

(最低金額 as number) as function =>
    (行 as record) as logical =>
        行[金額] >= 最低金額

条件を覚えた関数を使う

let
    Source = Q_金額付き注文,
    条件 = F_最低金額以上(1500),
    絞り込み =
        Table.SelectRows(
            Source,
            each 条件(_)
        )
in
    絞り込み

条件は関数を作るときに渡しています。作られた関数は、その条件を覚えたまま各行を判定します。

この章の着地 同じ絞り込みの仕組みを、最低金額だけ変えて再利用できます。

登壇メモ Excelセルを読む設計へ進む前に、まず値をM式へ直接渡します。「入力の場所」と「条件を覚える関数」を分けて見せるためです。

第12章 データの流れとして全体を見直す

このトピックの核 Power Queryのクエリ一覧は、値の依存関係を表す部品表です。最終結果だけでなく、どこから何を受け取り、どの規則で変えたかを追えます。

画面で見せるもの クエリの依存関係画面、またはクエリ一覧です。Q_注文、Q_料理、Q_店舗、F_金額、F_最低金額以上、出力クエリを並べます。

Q_注文 ─┐
        ├─ Q_金額付き注文 ─┬─ Q_料理付き注文 ── Q_料理別売上
F_金額 ─┘                  │
Q_料理 ────────────────────┘
 
F_最低金額以上(1500) ─────── Q_条件付き注文

「ボタンを押した記録」として見ると、手順が増えて見えます。「値の流れ」として見ると、入力、変換部品、最終出力に分かれます。

この章の着地 詳細エディターを開いて、入力・変換・出力の三つを声に出して読めれば、今日の目的は達成です。

登壇メモ 今日見たすべての式を、入力・変換・出力の三層へ戻して終えます。

まとめ ボタンの向こう側を読む

Power Queryでは、すべてのクエリが何らかの値を返します。Tableだけでなく、List、Record、number、functionも同じように値です。

最初の一歩 GUIで操作した後、詳細エディターを開き、letの最初とinの最後を見ます。

次の一歩 M式の中で#tableを一つ作り、外部データを読む前に変換の形だけを試します。

その先 同じ変換に名前を付け、関数として切り出し、条件を引数として渡します。

登壇メモ この資料は演習の答えではありません。登壇者が画面とコードを往復しながら、Power Queryを「データを組み立てる言語処理系」として紹介するための順番です。