Power Automateで差し込みメールを高速化!splitを2回使う裏ワザ

Power Automate
この記事は約6分で読めます。

Power Automateで「{{name}} 様」のようなテンプレートに値を差し込んでメールを送りたい、と思ったことはありませんか?よくあるやり方だと、変数を用意して Apply to each で1件ずつ置換していくことになりますが、これ、項目が増えてくると意外と遅くて困ってしまうんですよね。

実は、変数もループも一切使わずに、しかもほぼ0秒でテンプレート置換ができる方法があります。今回紹介するのは「split を2回使う」というちょっと変わったテクニック。仕組みさえわかればとてもシンプルなので、順番に見ていきましょう。

やりたいこと

まずはゴールを整理しておきます。こんな穴あきテンプレートを用意して、

{{name}} 様

いつもお世話になっております。
{{期限}}までに下記のURLよりお手続きをお願いいたします。

{{url}}

ご不明な点がございましたらご返信ください。
よろしくお願いいたします。

{{name}}{{url}} の部分を、対応表(辞書)に従って差し替えたい、というのが今回のテーマです。

name → 山田太郎
url  → https://example.com/portal/abc123

普通に考えると「変数を使ってループで置換」となりますが、ここをあえて使わずにやってみます。

最終的には以下のようなフローになります。

なぜループや変数を避けるのか

ここで重要なのは、Apply to each は1件ずつ順番に処理するため、差し込む項目や対象データが増えるほど時間がかかってしまう、という点です。数件なら気になりませんが、数百件のメールを一括で処理するような場面では、この差がじわじわ効いてきます。アクションの実行回数も増えますしね。

そんな時に便利なのが、配列操作で一気に処理してしまう考え方です。split をうまく使うと、ループを回さずに置換が実現できてしまうんですね。

仕組み:なぜsplitを2回するのか

実装前に仕組みを整理します。このテクニックの肝は、その名のとおり split を2回かけるところにあります。ここからは置き換え文字のことを「トークン」と説明していきます。

1回目:{{ で分割する

まず、テンプレート文字列を {{ で分割します。すると、こんな配列になります。

["", "name}} 様 …", "url}} …"]

ここで注目したいのは、分割後の各かたまりが「トークン名 + }} + 後ろの文章」という形になっていることです(先頭だけは例外で、トークンを含まない素のテキストになります)。

2回目:それぞれを }} で分割する

次に、各かたまりをさらに }} で分割します。

""           → [""]                  ← 要素1個
"name}} 様 …" → ["name", " 様 …"]     ← 要素2個
"url}} …"    → ["url", " …"]          ← 要素2個

ここがポイント:要素の数で見分ける

ここで気をつけたいのが、2回目の分割で要素がいくつになったかです。これを見るだけで、そのかたまりがトークンかどうかを判定できます。

  • 要素が2個なら、1番目がトークン名、残りが後ろの文章
  • 要素が1個なら、ただの素のテキストなのでそのまま返す

つまり、要素2個のものだけ「1番目の要素で辞書を引いて値に差し替え、後ろの文章をくっつける」という処理をすればいいわけです。条件分岐ひとつで済んでしまうのが、この方法のうまいところですね。

実際のアクション構成

では、実際にPower Automateで組んでみましょう。今回は3つのアクションで完成します。テンプレート文は テンプレート、辞書は 辞書 という Compose に入っている前提で進めます。

テンプレートには以下のようなメールテンプレートを設定しています。

{{name}} 様

いつもお世話になっております。
{{期限}}までに下記のURLよりお手続きをお願いいたします。

{{url}}

ご不明な点がございましたらご返信ください。
よろしくお願いいたします。

辞書はこんなJSONを入れておきます。

{
  "name": "山田太郎",
  "url": "https://example.com/portal/abc123"
}

1つ目:Select(splitを2回)

1つ目の Select アクションで、2段階の分割をまとめて行います。

From(分割元の配列を作る)には、以下のように記述します。

split(outputs('テンプレート'), '{{')

Map(各かたまりをさらに分割)には、こう書きます。

split(item(), '}}')

これで、出力は「配列の配列」になります。

実行結果

2つ目:Select(辞書で置換)

2つ目の Select で、辞書を引いて置換します。From には1つ目のSelectの出力を指定し、Map には次の式を入れます。

if(
  greater(length(item()), 1),
  concat(
    coalesce(outputs('辞書')?[item()[0]], item()[0]),
    join(skip(item(), 1), '}}')
  ),
  item()[0]
)

少しだけ読み解いておきましょう。greater(length(item()), 1) でトークンかどうかを判定し、トークンなら item()[0](トークン名)で辞書を引きます。coalesce を使っているので、辞書に値がなければ元のトークン名をそのまま残します。そこに後ろの文章を concat で連結する、という流れです。

ここで気をつけたいのは、後ろの文章を item()[1] ではなく join(skip(item(), 1), '}}') で取っている点です。こうしておくと、万が一本文に }} という文字が紛れていても文章が欠けません。要素がちょうど2個のときは item()[1] とまったく同じ結果になるので、こちらの書き方にしておくと安心ですね。

実行するとこのような形になります。

3つ目:Join(つなげる)

最後に、2つ目のSelectの結果を Join アクションで連結します。Join with には何も入れず、空文字にしておきます。

join(body('選択_1'),'')

このJoinの出力を、そのままメール送信アクションの本文に渡せば完成です。

テストから実行すると正しく置換できていることが確認できます。

全体の流れ

実際に動かしてみると、文字列がこんなふうに変化していきます。

テンプレート文字列
   ↓  ① split('{{') → split('}}')
[ [""], ["name", " 様 …"], ["url", " …"] ]
   ↓  ② if で辞書引き&連結
[ "", "山田太郎 様 …", "https://… …" ]
   ↓  ③ join('')
完成したメール本文

①で「形を整える」、②で「中身を差し替える」、③で「元に戻す」という流れです。

使うときの注意点

いくつか気をつけたい点があります。

ただし、トークンは {{name}} のように詰めて書いてください。{{ name }} のように空白を入れてしまうと、辞書のキーに空白が混ざってうまく引けなくなってしまいます。

また、大文字小文字を区別したくない場合は、辞書のキーを小文字でそろえておき、item()[0]toLower(item()[0]) で包んであげるとよいでしょう。

なお、トークンの数に上限はありません。2個でも10個でも、{{ で分割されたかたまりが増えるだけなので、同じロジックでそのまま処理できます。差し込み項目が増えても速度がほとんど変わらないのは、ループを使っていないこの方法ならではの強みですね。

また、今回は {{}}ですが、【】とかでもスペースを挟まないのであれば可能です。もちろん式の対象となる個所は適宜置き換える必要があります。

まとめ

いかがでしたでしょうか。「split を2回かけて、要素数でトークンを見分ける」というシンプルな発想で、変数もループも使わない軽量なテンプレートエンジンが作れるようになりました。

Apply to each で1件ずつ回すやり方に比べて圧倒的に速いので、差し込みメールや動的なドキュメント生成など、活躍する場面はたくさんあります。ぜひ一度、ご自身のフローで試してみてください。参考になれば幸いです。

コメント

タイトルとURLをコピーしました