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倍 = 元の値 * 2in 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 SourceQ_料理
料理IDに、表示用の料理名と分類を対応させるTableです。
let Source = #table( type table [ 料理ID = text, 料理名 = text, 分類 = text ], { {"D01", "麻婆豆腐", "主菜"}, {"D02", "青椒肉絲", "主菜"}, {"D03", "海老のチリソース", "主菜"}, {"D04", "五目炒飯", "飯・麺"} } )in SourceQ_店舗
店舗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を「データを組み立てる言語処理系」として紹介するための順番です。
