Excelの検索条件をPower QueryのM関数として注入する

Excelの検索条件をPower QueryのM関数として注入する

~検索画面とPower Queryを名前定義セルでつなぐ、構造化条件注入の設計~

Copyright © 2026 LWP 山中 一弘

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

記事要約

 Power Queryの検索条件を利用者ごと、実行ごとに変えたい場合、Mコードを毎回編集させる運用は現実的ではありません。Excelの検索画面で項目名、演算子、値、and / or を選び、その結果をM言語の行判定関数としてPower Queryへ渡せれば、利用者はワークシートだけで検索条件を変更できます。

 この記事では、Excelの構造化された条件をM関数リテラルへ変換し、名前定義セルから Excel.CurrentWorkbook、Expression.Evaluate、Table.SelectRows へ渡す方式を説明します。この方式を「Excel条件UI-M述語関数注入方式」と呼びます。

 結論は、任意のMコードを利用者に書かせるのではなく、許可した項目、演算子、データ型から行判定関数だけを生成することです。これにより、Power Queryの処理本体と検索条件を分離しながら、型違い、文字列の引用、過大な評価権限といった問題も管理できます。

本記事の対象とゴール

想定読者

  • ExcelとPower Queryを組み合わせた業務ブックを作っている人

  • VBAからPower Queryの更新を制御している人

  • 検索画面の条件をMコードへ反映したい人

  • Expression.Evaluate を使うべき範囲と注意点を知りたい人

本記事で得られること

  1. Excelの条件入力から Table.SelectRows までの受け渡し構造を説明できるようになります。

  2. Mの真偽式ではなく、行を受け取るfunctionを渡す理由が分かります。

  3. 項目名、値、演算子、評価環境を安全に扱う設計判断が分かります。

  4. 1セルの名前定義を使った最小例を自分のブックで再現できます。

1. Excel画面からMコードを変えるという考え方

 Power Queryでは、通常は詳細エディターにMコードを書きます。しかし、検索条件が毎回変わる業務では、固定したMコードだけでは対応しにくくなります。

 例えば、利用者がExcel画面で次の条件を指定するとします。

  • 売上年月が202401以上

  • 売上年月が202412以下

  • 金額が100000以上

  • すべての条件を and で結ぶ

 この条件は、M言語では次の行判定関数として表現できます。この文字列は、後で名前定義セルへ書き込む値です。

(_)=>([売上年月] >= 202401 and [売上年月] <= 202412) and ([金額] >= 100000)

 このコードを使う目的は、テーブルの各行について、条件に一致するかをtrueまたはfalseで返すことです。成功時には、該当する期間かつ10万円以上の行だけが残ります。

2. 方式を4つの役割に分ける

 この方式は、Excel、条件生成処理、受け渡し場所、Power Queryの4つに分けて考えると理解しやすくなります。

2.1 Excelは条件入力画面になる

 利用者は、項目名、演算子、値、論理演算子をワークシートへ入力します。項目名と演算子は入力規則のリストから選ばせます。値だけを自由入力にする場合でも、項目ごとに数値、文字列、日付などの型を決めておきます。

2.2 VBAまたはMが条件をコンパイルする

 入力された条件を、そのまま文字列連結するのではなく、許可された規則に従ってMの関数リテラルへ変換します。この変換処理は、画面入力をM言語へ翻訳する小さなコンパイラーです。

2.3 名前定義セルが受け渡し場所になる

 生成したM関数リテラルを、例えば 検索条件_M関数 という名前を付けた1セルへ書き込みます。Power Queryは、セル番地ではなく名前を使って値を取得します。

2.4 Power Queryが評価して実行する

 Power Queryは名前定義セルから文字列を取得し、Expression.Evaluate でfunction値へ変換します。最後に、そのfunctionを Table.SelectRows へ渡します。

3. 最小構成を作る

 ここでは、同じブック内にあるExcelテーブルを検索する最小構成を作ります。対象環境は、Power Queryを利用できるWindows版Excelです。

3.1 Excel側に2つの名前を用意する

 最初に、検索対象データをExcelテーブルにし、テーブル名を 検索対象 とします。例では 売上年月、金額、商品名 の列があるものとします。

 次に、空いているセルを1つ選び、名前ボックスまたは名前の管理から 検索条件_M関数 という名前を付けます。そのセルへ、先ほどの (_)=> で始まる文字列を入力します。

3.2 Power Queryで名前定義セルを読む

 次のコードを新しい空のクエリの詳細エディターへ入力します。クエリ名は 検索結果 とします。このコードは、名前定義セルの文字列をfunctionへ変換し、Excelテーブル 検索対象 を絞り込みます。

let
    条件セル =
        Excel.CurrentWorkbook(){[Name = "検索条件_M関数"]}[Content],
    条件文字列 =
        Text.From(条件セル{0}[Column1]),
    評価環境 =
        Record.SelectFields(
            #shared,
            {"Text.Contains"},
            MissingField.Ignore
        ),
    条件関数 =
        Expression.Evaluate(条件文字列, 評価環境),
    確認済み条件関数 =
        if 条件関数 is function then
            条件関数
        else
            error "検索条件が行判定関数ではありません。",
    検索対象 =
        Excel.CurrentWorkbook(){[Name = "検索対象"]}[Content],
    検索結果 =
        Table.SelectRows(検索対象, 確認済み条件関数)
in
    検索結果

 クエリを更新し、指定期間かつ指定金額以上の行だけが残れば成功です。エラーになった場合は、名前定義の名称、列名、値の型、条件文字列の括弧を確認します。

3.3 VBAから条件を書き込む

 次のVBAは、最小例の条件関数を名前定義セルへ書き込み、検索結果クエリの接続を更新します。接続名はブックによって異なるため、実際の接続名に合わせてください。

Option Explicit
Public Sub 検索条件を注入して更新する()
    Const XM_PREDICATE As String = _
        "(_)=>([売上年月] >= 202401 and [売上年月] <= 202412)" & _
        " and ([金額] >= 100000)"
    ThisWorkbook.Names("検索条件_M関数").RefersToRange.Value = _
        XM_PREDICATE
    ThisWorkbook.Connections("クエリ - 検索結果").Refresh
End Sub

 このマクロの目的は、注入経路の動作確認です。実務版では、定数で条件を書くのではなく、検索画面から読み取った条件を専用の生成関数で組み立てます。マクロ実行後、名前定義セルの文字列と検索結果の両方を確認します。

4. なぜ真偽式ではなくfunctionを渡すのか

 Table.SelectRows の第2引数は、テーブル全体に対する1つのtrueまたはfalseではありません。各行を受け取り、その行を残すかどうかを返すfunctionです。

 そのため、次の条件本体だけでは不足します。

[金額] >= 100000

 行を受け取る関数にすると、Table.SelectRows が各行へ繰り返し適用できます。

(_)=>[金額] >= 100000

 Mでよく使う each [金額] >= 100000 も同じ役割です。動的に文字列として受け渡す場合は、(_)=> の形にすると関数であることが明示されます。

5. 検索画面を構造化する

 実務用の検索画面では、条件を単なる自由記述欄にしません。1条件を「項目名、演算子、値」の組として扱います。

 同じグループ内の条件は and で結びます。複数グループを作る場合は、グループ間の and または or を別の入力欄で指定します。例えば、1行目に期間の下限と上限、2行目に金額条件を置けば、画面のまとまりと生成される括弧のまとまりを対応させられます。

 演算子は、少なくとも次のような許可リストから選択させます。

  • =

  • <>

  • >

  • <

  • >=

  • <=

  • 含む。Mでは Text.Contains に変換する

 VBAの関数名も、実際の役割に合わせます。グループ間が or 固定でないなら、「Or条件生成」ではなく「条件グループ結合」のような名前にしたほうが誤解を防げます。

6. 方式として確立するための安全規則

6.1 項目マスタにデータ型を持たせる

 Excelセルが数値に見えるかどうかだけで、Mの数値リテラルか文字列リテラルかを決めてはいけません。社員番号、商品コード、年月のように、見た目は数字でも文字列として管理する列があります。

 項目マスタには、表示名、M列名、Mデータ型、使用可能な演算子を持たせます。Mデータ型は number、text、date、datetime、logical などです。

6.2 識別子と値を単純連結しない

 列名に空白、演算子、引用符などが含まれる場合は、Mの引用識別子が必要です。文字列値の中に引用符や改行がある場合も、Mの文字列リテラルとして正しく表現しなければなりません。

 条件式をM側で生成できる場合は、Expression.Identifier と Expression.Constant を使うと、識別子と値をMソースとして表現できます。次のコードは、空白を含む列名と引用符を含む文字列から、安全な条件関数文字列を作ります。

let
    項目名 = "商品 名",
    検索値 = "A ""ランク""",
    項目式 =
        "[" & Expression.Identifier(項目名) & "]",
    値式 =
        Expression.Constant(検索値),
    条件文字列 =
        "(_)=>" & 項目式 & " = " & 値式
in
    条件文字列

 VBAでM文字列を生成する場合も、同じ引用規則を実装した専用関数とテストが必要です。画面値を直接 "[" & 項目名 & "]" のように連結するだけでは、汎用方式としては不十分です。

6.3 演算子を対応表から変換する

 利用者が入力した文字列を演算子としてそのまま埋め込まず、許可済みの対応表を使います。特に 含む は二項演算子ではないため、Text.Contains([列], 値) という関数呼出しへ変換します。

6.4 評価環境を限定する

 Expression.Evaluate(条件文字列, #shared) とすると、共有環境にある多くの関数を条件式から参照できます。管理された社内ブックでは動作しますが、方式として公開・再利用するなら、必要な関数だけを含むenvironmentへ限定します。

 この記事の最小例では、文字列の部分一致に必要な Text.Contains だけを選択しています。比較演算子、数値リテラル、文字列リテラル、行フィールド参照はMの構文なので、environmentへ個別登録する必要はありません。

6.5 条件関数は一度だけ評価する

 複数の月次テーブルへ同じ条件を適用する場合、テーブルごとに Expression.Evaluate を呼ぶ必要はありません。最初に一度だけfunctionを生成し、同じfunctionを各 Table.SelectRows へ渡します。

 各テーブルを絞り込んでから Table.Combine すれば、結合後に全件を絞り込むより中間行数を抑えられます。ただし、すべてのテーブルで列名とデータ型が一致していることが前提です。

6.6 エラーを利用者へ返す

 条件が空、項目名が存在しない、値の型が合わない、条件文字列がfunctionではない、更新中に再実行した、といった状態を区別します。Power Queryのエラーをそのまま見せるだけでなく、どの条件を直せばよいかをExcel画面へ返す設計が必要です。

7. この方式が向く範囲

 この方式は、項目、演算子、値、論理演算子で表せる検索に向きます。複数ファイルや複数テーブルに対して、同じ条件を適用する業務検索画面では特に有効です。

 一方で、結合方法、集計方法、追加列、外部データソースまで利用者が自由に変更する用途には向きません。その場合は、用途別のクエリを分ける、条件定義テーブルをM関数が直接解釈する、または専用アプリケーションにするほうが管理しやすくなります。

 判断基準は、動的にする対象を「行を残すかどうか」に限定できるかです。限定できるなら、述語関数だけを注入するこの方式は、Power Query本体を固定したまま検索条件を外出しできます。

8. まとめ

 ExcelからPower Queryへ検索条件を渡すときは、値を1つ渡すだけでなく、行を判定するMのfunctionを渡すことができます。Excel画面を入力層、条件生成処理をコンパイル層、名前定義セルを受け渡し層、Power Queryを実行層として分けると、方式の責任が明確になります。

 ただし、成立の中心は Expression.Evaluate そのものではありません。利用者の入力を構造化し、項目型と演算子を制限し、識別子と値を正しく表現し、評価できる範囲を限定することが中心です。

 この境界を守れば、Power Queryエディターを利用者に触らせず、Excelの検索画面から再利用可能なM条件関数を供給できます。

出典メモ

  • ほえほえ作成の業務用Excelマクロブックを2026-08-01に確認した。顧客名、ブック名、固有の業務項目、実データは掲載していない。

  • Microsoft Learn: Expression.Evaluate - https://learn.microsoft.com/en-us/powerquery-m/expression-evaluate

  • Microsoft Learn: Table.SelectRows - https://learn.microsoft.com/en-us/powerquery-m/table-selectrows

  • Microsoft Learn: Excel.CurrentWorkbook - https://learn.microsoft.com/en-us/powerquery-m/excel-currentworkbook

  • Microsoft Learn: Expression.Identifier - https://learn.microsoft.com/en-us/powerquery-m/expression-identifier

  • Microsoft Learn: Expression.Constant - https://learn.microsoft.com/en-us/powerquery-m/expression-constant

  • Microsoft Learn: Power Query M language specification - https://learn.microsoft.com/en-us/powerquery-m/power-query-m-language-specification

  • 確認範囲: 元ブックは静的に読み戻した。検索ボタンの実行と外部データの再評価は行っていない。記事のコードは、方式説明のために匿名化して作り直した独自例である。