Posted at

PowerQuery のステップをパイプ風に

PowerQueryのエディターで自動的に出来上がるコードはこんな感じです。

let

ソース = ...,
#"変更された型" = Table.TransformColumnTypes(ソース, ...),
#"昇格されたヘッダー数" = Table.PromoteHeaders(#"変更された型", ...),
#"削除された列" = Table.RemoveColumns(#"昇格されたヘッダー数", ...)
#"変更された型1" = Table.TransformColumnTypes(#"削除された列", ...),
...

「変更された型」とか日本語的に不自然だし、ステップ数が多いと後から見たときによく分からなくなります。

自分でコードを書くときには、ステップごとにいちいち名前をつけるなんて面倒なことはしたくないし、そんなことをする必要もありません。

コマンドラインのように、各ステップをパイプでつないで、その中をデータが流れていくようにしたら、分かりやすいし、もっとコーディングが楽しくなるんじゃないでしょうか。

// イメージ

ソース | ステップ1 | ステップ2 | ステップ3 | ...

それに近いことを List.Accumulate という関数を使って、できる方法を紹介します。

// 例

let
Source = 7, // 実際には何かのデータソース (Excel.Workbook() とか) が入る

Transform = Function.Pipe({
// 各ステップを関数として書く
// 前のステップの評価結果が次のステップの引数になる
// これは例なので簡単な四則計算をしているが、
// 実際には table を受け取って table を返すことが多い
each _ * 3, // 7 * 3 = 21
each _ + 4, // 21 + 4 = 25
each Number.Mod(_, 7), // 25 mod 7 = 4
each Power(_, 2) // 4 * 4 = 16
}),

Result = Transform(Source), // (((7 * 3) + 4) mod 7) pow 2 = 16

Function.Pipe = (functions as list) as function =>
(value) => List.Accumulate(functions, value, (s, f) => f(s))
in
Result

Function.Pipe という関数を自作しています。この関数は関数のリストを受け取って、それを順番に適用していく関数を返します。

このパターンをテンプレ的に使い回しています。もう2年以上になりますが、気に入っていて飽きません。