関数を作るとは何か
Power Query(M言語)で「関数を作る」とは、よく使う処理に“名前”と“引数”を付けて、何度でも呼び出せるようにすることです。 同じような計算や変換を、クエリのあちこちにコピペしていると、修正が大変になり、バグやセキュリティ上の問題も起きやすくなります。 そこで「関数」としてまとめておくことで、再利用性・保守性・安全性が一気に高まるのがポイントです。
M言語の関数は、
- 「入力(引数)」を受け取って
- 「処理」を行い
- 「結果(戻り値)」を返す
という、シンプルな仕組みで動きます。
M言語の関数の基本構文
(引数) => 式 という形で書きます
最も基本的な関数の形は次のようになります。
let
Double =
(x as number) as number =>
x * 2
in
Double
Power Queryここでのポイントは次の通りです。
Double:関数の名前(x as number):引数(x)とその型(number)as number:戻り値の型=> x * 2:処理内容(x を2倍にする)
この関数は「数値を受け取って、その2倍を返す関数」です。
呼び出すときは次のように書きます。
let
Double =
(x as number) as number =>
x * 2,
Result = Double(10)
in
Result // 20
Power Query関数をステップバイステップで作る
ステップ1:何を“ひとまとまりの処理”にしたいか決める
関数に向いている処理は、次のようなものです。
- よく使う計算(例:税込金額の計算)
- よく使う変換(例:顧客コードのクレンジング)
- テーブルに対する共通処理(例:必須項目チェック)
- セキュリティチェック(例:ロール判定)
例:税込金額を計算する関数を作りたい場合
let
CalcTaxIncluded =
(price as number, taxRate as number) as number =>
price * (1 + taxRate)
in
CalcTaxIncluded
Power Queryステップ2:引数と戻り値の型をきちんと書く
M言語では、引数や戻り値に型を付けることができます。
(price as number, taxRate as number) as number =>
...
Power Query型を付けるメリットは次の通りです。
- 間違った型の値が渡されたときに早期に気づける
- 関数の意図が読みやすくなる
- セキュリティ・品質の観点からも安全になる
例えば、顧客コードのクレンジング関数なら次のように書けます。
let
CleanCustomerCode =
(code as nullable text) as nullable text =>
if code = null then
null
else
Text.Upper(Text.Trim(code))
in
CleanCustomerCode
Power Queryここでは、
code as nullable text:null を許容するテキストas nullable text:戻り値も null を許容するテキスト
と明示しています。
ステップ3:関数をテーブル処理に組み込む
関数は「Table.AddColumn や Table.TransformColumns の中で使う」ときに真価を発揮します。
let
CleanCustomerCode =
(code as nullable text) as nullable text =>
if code = null then
null
else
Text.Upper(Text.Trim(code)),
SalesTable = Excel.CurrentWorkbook(){[Name="売上"]}[Content],
CleanedTable =
Table.TransformColumns(
SalesTable,
{{"顧客コード", CleanCustomerCode, type text}}
)
in
CleanedTable
Power Queryここでは、
- 顧客コード列に対して
CleanCustomerCode関数を適用し - トリム+大文字化+null対応を一括で行っています。
同じロジックを複数のクエリで使いたい場合、 関数として切り出しておくことで、コピペではなく“呼び出し”で再利用できるようになります。
実務でよく使う関数のパターン
1. 計算系関数(税・割引・スコアなど)
let
CalcFinalAmount =
(price as number, taxRate as number, discountRate as number) as number =>
let
discount = price * discountRate,
taxed = (price - discount) * (1 + taxRate)
in
taxed
in
CalcFinalAmount
Power Queryこの関数は、
- 価格
- 税率
- 割引率
を受け取り、最終的な税込金額を返します。
テーブルに適用する例:
let
CalcFinalAmount =
(price as number, taxRate as number, discountRate as number) as number =>
let
discount = price * discountRate,
taxed = (price - discount) * (1 + taxRate)
in
taxed,
TaxRate = 0.1,
DiscountRate = 0.05,
SalesTable = Excel.CurrentWorkbook(){[Name="売上"]}[Content],
AddedFinalAmount =
Table.AddColumn(
SalesTable,
"最終金額",
each CalcFinalAmount([金額], TaxRate, DiscountRate),
type number
)
in
AddedFinalAmount
Power Query2. クレンジング系関数
let
CleanText =
(value as nullable text) as nullable text =>
if value = null then
null
else
Text.Trim(value),
CleanCustomerCode =
(code as nullable text) as nullable text =>
if code = null then
null
else
Text.Upper(CleanText(code))
in
CleanCustomerCode
Power Queryこのように、関数の中で別の関数を呼び出すこともできます。 クレンジングロジックを関数としてまとめておくと、 複数のテーブルで同じルールを簡単に適用できます。
3. チェック系関数(品質・セキュリティ)
m
let
IsValidSalesRow =
(row as record) as logical =>
let
hasCustomer =
(row[顧客コード] <> null and row[顧客コード] <> ""),
hasPositiveAmount =
(row[金額] <> null and row[金額] > 0)
in
hasCustomer and hasPositiveAmount
in
IsValidSalesRow
Power Queryこの関数は「1行分のレコード」を受け取り、
- 顧客コードが入っているか
- 金額が正の値か
をチェックして、true / false を返します。
テーブルに適用する例:
let
IsValidSalesRow =
(row as record) as logical =>
let
hasCustomer =
(row[顧客コード] <> null and row[顧客コード] <> ""),
hasPositiveAmount =
(row[金額] <> null and row[金額] > 0)
in
hasCustomer and hasPositiveAmount,
SalesTable = Excel.CurrentWorkbook(){[Name="売上"]}[Content],
AddedValidFlag =
Table.AddColumn(
SalesTable,
"有効行",
each IsValidSalesRow(_),
type logical
)
in
AddedValidFlag
Power Queryここでの each IsValidSalesRow(_) の _ は「行全体(レコード)」を表します。
品質チェックやセキュリティチェックを関数としてまとめておくことで、 「どの行が有効か」を一貫したルールで判定できるようになります。
関数を作るときの重要な注意点
1. 引数の型と戻り値の型を意識する
型を付けないこともできますが、 実務では 必ず型を付けることを強くおすすめします。
悪い例:
MyFunc = (x) => x * 2
Power Query良い例:
MyFunc = (x as number) as number => x * 2
Power Query型を付けることで、
- 間違った値が渡されたときに早期に検知できる
- 関数の意図が明確になる
- セキュリティ・品質の観点からも安心できる
というメリットがあります。
2. null をどう扱うかを必ず決める
引数や戻り値に null が入りうる場合、 null をどう扱うかを関数内で明示的に決めることが重要です。
let
SafeDivide =
(x as nullable number, y as nullable number) as nullable number =>
if x = null or y = null or y = 0 then
null
else
x / y
in
SafeDivide
Power Queryこのように、
- null の場合
- 0で割る場合
などを事前に処理しておくことで、 予期せぬエラーや不正な結果を防げます。
3. セキュリティに関わる関数は特に慎重に設計する
次のような関数は、セキュリティ上重要です。
- 権限判定(例:
IsAdminUser) - 外部システムへの送信可否(例:
IsReadyToSend) - データ品質判定(例:
IsTrustedData)
例:
let
IsAdminUser =
(role as text) as logical =>
role = "Admin"
in
IsAdminUser
Power Queryこのような関数を使う場合、
- ロール名の管理方法
- 誰が関数を編集できるか
- 誤ってロジックを緩くしてしまわないか
を意識しておく必要があります。
セキュリティに関わる関数は、 コメントで意図を明確にし、変更時にはレビューを行うなどの運用も重要です。
実務で使える「関数作成テンプレート」
テンプレ1:税込金額計算関数
let
CalcTaxIncluded =
(price as number, taxRate as number) as number =>
price * (1 + taxRate)
in
CalcTaxIncluded
Power Queryテンプレ2:顧客コードクレンジング関数
let
CleanCustomerCode =
(code as nullable text) as nullable text =>
if code = null then
null
else
Text.Upper(Text.Trim(code))
in
CleanCustomerCode
Power Queryテンプレ3:売上行の有効判定関数
let
IsValidSalesRow =
(row as record) as logical =>
let
hasCustomer =
(row[顧客コード] <> null and row[顧客コード] <> ""),
hasPositiveAmount =
(row[金額] <> null and row[金額] > 0)
in
hasCustomer and hasPositiveAmount
in
IsValidSalesRow
Power Queryまとめ:関数を作ることは「ロジックに名前を付けて再利用すること」
M言語で関数を作るというのは、 「よく使う処理に名前を付けて、引数と戻り値を決め、何度でも安全に再利用できるようにすること」です。
これによって、
- コピペではなく“呼び出し”でロジックを共有できる
- 修正が1か所で済むようになり、保守性が高まる
- 型やnullの扱いを統一でき、品質・セキュリティが向上する
- テーブル処理やクレンジング・チェックをスマートに書ける
というメリットが得られます。
関数は、実務の Power Query を「ただ動くコード」から「設計されたコード」に進化させる鍵ですので、 ぜひ「(引数) => 式」「型を付ける」「nullを意識する」という基本を押さえつつ、 自分の現場でよく使うロジックを関数として育てていっていただきたいです。
