LWP | Excel上のMコードをPower Queryから動的実行する設計
LWP TECHNICAL ARTICLE | 167
Excel上のMコードをPower Queryから動的実行する設計
Expression.Evaluateで固定ランチャーと外部ロジックを安全に分ける
Copyright © 2026 LWP 山中 一弘
本資料は、出典を明記いただければ、商用・非商用を問わず、ご自由に複製・改変・再配布していただけます。なお、著作権表示は改変せず、そのまま記載してご利用くださいますようお願いいたします。
記事要約
Excelの名前定義やテーブルにMコードを文字列として置き、Power Query側の固定ランチャーからExpression.Evaluateで評価すると、クエリ本体を変更せず処理ロジックを差し替えられます。ただし、文字列を評価するだけでは設計として不十分です。評価環境、入力元、戻り値の型、エラー、権限、変更手順を契約として決める必要があります。
本記事では、Excel.CurrentWorkbookでコードを取得し、Name/Value表からRecord.FromTableで環境を作る方法を示します。動的実行が有効な条件と、通常の固定Mコードを選ぶべき条件も明確にします。
本記事の対象とゴール
想定読者
Power Queryの処理ロジックをExcel側で管理したい方
Expression.Evaluateの第2引数を理解したい方
固定クエリと差し替え可能な処理を分離したい設計者
本記事で得られること
Excel上の文字列をM式として評価できます。
必要最小限の評価環境を構成できます。
戻り値と変更権限を含む運用契約を設計できます。
目次
第1章 この方式の基本的な考え方
第2章 条件式だけでなくクエリ全体を書けます
第3章 テーブルを使う最小構成
第4章 名前を統一します
第5章 Power Query側を固定ランチャーにできます
第6章 CSV読込で特に有効です
第7章 共通ライブラリと組み合わせます
第8章 VBAでクエリを書き換える方式との違い
第9章 この方式でもクエリと出力の関係は残ります
第10章 動的コードにもインターフェースを決めます
第11章 コードをデータとして扱う設計です
第12章 管理テーブルを発展させることもできます
第13章 実務上の注意点
第14章 設計上の重要ポイント
第15章 設計判断をまとめます
まとめ コードをデータとして扱うなら契約を先に決める
第1章 この方式の基本的な考え方
第1節 通常のPower Queryとの違い
1. 通常の構成
通常のPower Queryでは、処理本体となるMコードをPower Queryエディター内に記述します。
Power Query
↓
Mコード
↓
実行
この場合、処理内容を変更するにはPower Query側のコードを変更します。
2. 今回の構成
今回の方式では、Power Query側にはMコードを実行するための固定的なランチャーだけを置きます。
実際の処理内容は、Excelシート上のセル、名前定義、またはテーブルに文字列として保持します。
Excel
↓
Mコードを文字列として保持
↓
Power Query
↓
Expression.Evaluate
↓
Mコードとして実行
重要なのは、Excel上の文字列を単なる設定値として読むのではなく、M式として評価する点です。
第2節 Expression.Evaluate の役割
1. 基本形
Expression.Evaluate(
code,
environment
)
第1引数には評価するMコードを文字列で渡します。
第2引数には、そのMコードから参照できる環境を渡します。
2. 最小例
Expression.Evaluate(
"1 + 2",
#shared
)
結果は 3 です。
3. クエリ名も評価できます
文字列として、
Lib
を読み込み、
Expression.Evaluate(
"Lib",
#shared
)
とすると、共有環境に Lib というクエリが存在すれば、そのクエリを参照できます。
つまり、Excel側に「どのクエリを実行するか」という名前だけを置くこともできます。
第2章 条件式だけでなくクエリ全体を書けます
第1節 Mでは let ... in ... 全体が式です
1. 一部分だけではありません
Expression.Evaluate は、次のような短い式だけを評価する機能ではありません。
1 + 2
if x > 10 then "A" else "B"
Mでは、次のような let ... in ... 全体も1つの式です。
let
Source = {1, 2, 3},
Result = List.Transform(Source, each _ * 10)
in
Result
したがって、このコード全体をExcelセルに保存し、その文字列を Expression.Evaluate に渡すことができます。
2. 実質的にクエリ本体を外部化できます
Power Query側には、
Expression.Evaluate(code, env)
だけを残し、実際の処理本体をExcel側に置けます。
概念的には、
Power Query
↓
固定ランチャー
Excel
↓
実際のMコード
という分離になります。
第3章 テーブルを使う最小構成
第1節 Excel側のテーブル
1. サンプルでは短い名前を使います
テーブル名:
Code
列:
| Name | Value |
|---|---|
| CSV1 | let ... in ... |
この場合、CSV1 がコードを識別するキーです。
2. Power Query側
let
tbl = Excel.CurrentWorkbook(){[Name="Code"]}[Content],
rec = Record.FromTable(tbl),
code = rec[CSV1],
out = Expression.Evaluate(code, #shared)
in
out
処理の流れは次のとおりです。
Codeテーブル
↓
CSV1 の Value を取得
↓
Mコード文字列
↓
Expression.Evaluate
↓
実行結果
第2節 Record.FromTable を使う理由
1. Name / Value をキーと値として扱えます
次のテーブル、
| Name | Value |
|---|---|
| CSV1 | let ... in ... |
を、
Record.FromTable(tbl)
でレコード化すると、概念的には、
[
CSV1 = "let ... in ..."
]
となります。
したがって、
rec[CSV1]
で対象コードを直接取得できます。
2. 設定表との相性もよい構造です
Mコードだけでなく、
FILE
ENCODING
VERSION
MODE
なども同じ Name / Value 方式で扱えます。
第4章 名前を統一します
第1節 名前定義を使う場合
1. 原則
Excelの「定義された名前」を使ってMコードを保持する場合は、
定義された名前
=
Power Queryのクエリ名
とします。
2. 例
Excel側の名前定義:
CSV1
Power Query側のクエリ名:
CSV1
このように、同じものには同じ名前を付けます。
3. 利点
Power Query一覧で CSV1 を見たときに、Excel側でも CSV1 を探せばよくなります。
別の対応表を持つ必要がありません。
第2節 テーブルを使う場合
1. 原則
テーブル方式では、テーブル名そのものではなく、
テーブル名_キー名
をPower Queryのクエリ名にします。
2. 例
Excelテーブル名:
Code
キー名:
CSV1
Power Queryのクエリ名:
Code_CSV1
とします。
3. なぜこの形がよいのでしょうか
テーブルは複数のコードを格納する「入れ物」です。
たとえば、
| Name | Value |
|---|---|
| CSV1 | let ... in ... |
| CSV2 | let ... in ... |
| CSV3 | let ... in ... |
という構成なら、Code だけではどのコードか分かりません。
そこで、
Code_CSV1
Code_CSV2
Code_CSV3
とします。
名前だけで、
どのテーブルにあるか
+
どのキーか
が分かります。
4. 命名規則のまとめ
名前定義方式:
名前定義名
=
クエリ名
テーブル方式:
テーブル名_キー名
=
クエリ名
この規則は、動的コードの所在を追跡するための基本ルールとします。
第5章 Power Query側を固定ランチャーにできます
第1節 処理本体を変更しないランチャー
1. 基本形
let
tbl = Excel.CurrentWorkbook(){[Name="Code"]}[Content],
rec = Record.FromTable(tbl),
code = rec[CSV1],
out = Expression.Evaluate(code, #shared)
in
out
このクエリ自体は固定します。
変更するのはExcel側の CSV1 の内容です。
2. Excel側だけで処理を差し替えられます
たとえば最初は、
let
Source = {1, 2, 3}
in
Source
だったものを、
let
Source = {10, 20, 30},
Result = List.Transform(Source, each _ * 2)
in
Result
へ変更できます。
Power Query側のランチャーは変更しません。
第6章 CSV読込で特に有効です
第1節 CSVは「設定値」だけでは吸収できないことがあります
1. 単純な設定値で済む場合
たとえば、
| Name | Value |
|---|---|
| FILE | C:\Data\a.csv |
| ENC | 65001 |
| DELIM | , |
程度なら、通常のパラメーター化で十分です。
2. 処理そのものが違う場合
実務では、CSVごとに次のような違いがあります。
CSV A:
UTF-8
1行目がヘッダー
カンマ区切り
CSV B:
Shift-JIS
先頭5行を削除
タブ区切り
最終列を削除
CSV C:
ヘッダーなし
列数可変
アンピボットが必要
この場合、単なる値の違いではなく、処理ロジックそのものが違います。
第2節 巨大な条件分岐を避けられます
1. 通常の方法
1本のクエリで全部処理すると、
if kind = "A" then
...
else if kind = "B" then
...
else if kind = "C" then
...
となります。
処理が増えるほど保守しにくくなります。
2. コードそのものを切り替えます
Excel側に、
| Name | Value |
|---|---|
| CSV1 | let ... in ... |
| CSV2 | let ... in ... |
| CSV3 | let ... in ... |
と持てば、CSV形式ごとにMコードそのものを分離できます。
つまり、
設定値を変える
だけでなく、
処理ロジックを差し替える
ことができます。
第7章 共通ライブラリと組み合わせます
第1節 共通処理はライブラリに残します
1. Excel側へすべて書く必要はありません
共通処理は Lib のようなライブラリへ置きます。
例:
path_join
table_from
table_lookup
error_replace
2. Excel側には個別処理だけを書きます
たとえば、
このCSVだけ先頭5行を削除する
この会社だけ特殊な列構成を持つ
この帳票だけアンピボットする
といった処理です。
構造は、
共通処理
↓
Lib
個別処理
↓
Excel上のMコード
となります。
第2節 評価環境へライブラリを渡します
1. #shared を使う場合
Expression.Evaluate(
code,
#shared
)
共有環境に Lib が存在すれば、評価コードから参照できます。
2. 明示的に渡す場合
Expression.Evaluate(
code,
Record.Combine({
#shared,
[Lib = Lib]
})
)
評価コード側では、
Lib[path_join](...)
のように利用できます。
第8章 VBAでクエリを書き換える方式との違い
第1節 VBA方式
VBAでは、Power QueryのFormulaそのものを書き換えられます。
概念的には、
Workbook.Queries("Q1").Formula = "let ..."
のような処理です。
構造は、
VBA
↓
クエリ定義を書き換える
↓
Power Query更新
です。
つまり、Power Queryオブジェクトそのものを変更します。
第2節 Expression.Evaluate 方式
今回の方式では、
固定Power Query
↓
Excelからコード文字列を読む
↓
Expression.Evaluate
↓
その場で評価
となります。
Power QueryのFormulaそのものは変更しません。
変わるのは、
固定クエリが実行するコードの内容
です。
第3節 両者は競合ではなく用途が違います
Expression.Evaluate が向く場合
VBAを使いたくない
クエリ数は固定でよい
ロード先も固定でよい
処理内容だけ切り替えたい
CSVごとにロジックを変えたい
Excelを設定画面として使いたい
共通ライブラリと個別処理を分離したい
VBAが向く場合
クエリそのものを生成・削除したい
クエリ名を変更したい
ロード先まで制御したい
多数のクエリを自動生成したい
Excelオブジェクトモデル全体を操作したい
第9章 この方式でもクエリと出力の関係は残ります
第1節 外側のクエリは固定です
1. 中身は変えられます
たとえば Code_CSV1 というクエリがある場合、その内部で評価するMコードは大きく変更できます。
CSV読込A
↓
CSV読込B
という切替もできます。
2. クエリそのものが増減するわけではありません
Expression.Evaluate は、
3個のクエリを生成する
5個のクエリを削除する
という機能ではありません。
外側のPower Queryオブジェクトはそのままです。
第2節 ロード設定も基本的に外側のクエリに属します
外側のクエリに、
ワークシートへロード
接続のみ
データモデルへロード
などの設定があります。
評価するMコードを変更しても、その外側のロード設定自体を切り替える仕組みではありません。
したがって、
処理内容
=
動的
クエリという器
=
固定
ロード先
=
基本的に固定
と考えます。
第10章 動的コードにもインターフェースを決めます
第1節 戻り値の型を統一します
Expression.Evaluate は、M式であれば、
table
list
record
number
text
function
などを返せます。
しかしExcelへテーブルとして出力するクエリなら、動的コードも最終的に table を返すと決めておいた方が安全です。
内部ロジック
=
自由
出力インターフェース
=
固定
という設計にします。
第2節 CSVなら出力列も決められます
たとえば、
出力型:
table
必須列:
日付
商品
数量
金額
と決めておきます。
CSV AとCSV Bで内部処理がまったく違っても、最後は同じテーブル構造を返します。
これにより、後続処理を固定できます。
第11章 コードをデータとして扱う設計です
第1節 通常の考え方
通常は、
Mコード
↓
プログラム
として扱います。
第2節 今回の考え方
今回の方式では、
Mコード
↓
Excelセルの文字列
↓
データ
として一度保持します。
その後、
文字列
↓
Expression.Evaluate
↓
再びMコードとして評価
します。
つまり、
コードをデータとして保持し、必要な環境を与えて実行する
というメタプログラミング的な構造です。
第12章 管理テーブルを発展させることもできます
第1節 単純なName / Value
最小形は、
| Name | Value |
|---|---|
| CSV1 | let ... in ... |
です。
第2節 管理情報を追加します
実用化する場合は、
| Name | Version | Enabled | Note | Code |
|---|---|---|---|---|
| CSV1 | 1.0 | TRUE | A社CSV | let ... in ... |
| CSV2 | 1.1 | TRUE | B社CSV | let ... in ... |
| OLD | 0.9 | FALSE | 旧形式 | let ... in ... |
のような構成も考えられます。
Excel側が小さなMコード管理表になります。
第13章 実務上の注意点
第1節 依存関係が見えにくくなります
通常のPower Queryでは、エディターを開けば処理コードがあります。
今回の方式では、
Power Query
↓
Excelテーブル
↓
Mコード
↓
Lib
と複数段階になります。
そのため、
名前の統一
説明列
バージョン
コードID
が重要になります。
第2節 Excelセルの編集がプログラム変更になります
MコードをExcelへ置くということは、
Excelセルを書き換えることがプログラム変更になる
ということです。
必要に応じて、
シート保護
バックアップ
バージョン管理
Enabled列
Note列
などを用意します。
第3節 評価環境を広げすぎない方がよい場合があります
#shared は便利ですが、評価コードから参照できる範囲も広くなります。
厳格に管理する場合は、必要なものだけを渡す設計もあります。
Expression.Evaluate(
code,
[
Lib = Lib,
Csv = Csv.Document,
File = File.Contents
]
)
つまり、
評価コードに何を見せるか
も設計対象です。
第14章 設計上の重要ポイント
第1節 単なる「設定値の外部化」ではありません
一般的なPower Queryのパラメーター化は、
ファイル名
文字コード
区切り文字
などの値を外部化します。
今回の方式は、
処理ロジックそのものを外部化できる
点が異なります。
第2節 クエリ全体を差し替えられます
let ... in ... 全体をセルへ持てるので、
条件式だけを差し替える
という範囲を超え、
読込
整形
変換
結合
出力
を含む処理本体を差し替えられます。
第3節 CSVのような形式差の大きい入力に向いています
「出力は同じだが、入力ごとに処理方法が大きく違う」という問題に強い構成です。
第4節 VBAとは役割が違います
VBA:
クエリそのものを書き換える
Expression.Evaluate:
固定クエリが評価するコードを差し替える
この違いは記事の主要論点になります。
第5節 命名規則が非常に重要です
名前定義:
名前定義名 = クエリ名
テーブル:
テーブル名_キー名 = クエリ名
例:
Code_CSV1
この規則により、Excel側とPower Query側の対応関係を名前だけで追跡できます。
第15章 設計判断をまとめます
第1節 短い結論
ExcelシートにMコードを文字列として保存し、Expression.Evaluate で実行すると、Power Queryを固定ランチャーとして利用できます。
これにより、Power Query本体を変更せず、処理ロジックそのものをExcel側から差し替えられます。
第2節 技術的な結論
この方式は、
固定Power Query
+
外部化されたMコード
+
評価環境
+
共通ライブラリ
という構成です。
単なる設定値の外部化ではなく、
Mコードそのものをデータとして管理し、実行時に評価する仕組み
と整理できます。
第3節 実務的な結論
特に、
クエリ数は固定
ロード先も固定
しかし入力形式ごとに処理内容を大きく変えたい
という用途に向いています。
CSV読込は、その代表例になり得ます。
まとめ コードをデータとして扱うなら契約を先に決める
Excel上のMコードを動的実行する方式は、固定ランチャー、外部コード、評価環境、戻り値契約の四つで成り立ちます。自由度が高い反面、編集権限を持つ利用者は実行ロジックを変更できます。入力元を限定し、環境レコードを最小化し、変更履歴とテストを残すことが前提です。
単にパスや列名を変えるだけなら、コードではなく設定値を外部化する方が安全です。処理構造そのものを差し替える必要があり、運用責任者と検証手順を定められる場合に、この設計を選びます。
出典メモ
Microsoft Learn『Expression.Evaluate』 https://learn.microsoft.com/en-us/powerquery-m/expression-evaluate
Microsoft Learn『Excel.CurrentWorkbook』 https://learn.microsoft.com/en-us/powerquery-m/excel-currentworkbook
Microsoft Learn『Record.FromTable』 https://learn.microsoft.com/en-us/powerquery-m/record-fromtable
Microsoft Learn『Sections』 https://learn.microsoft.com/en-us/powerquery-m/m-spec-sections
