Power Automate でシングルクォートを含む文字列で ODATA フィルタークエリを使おうとしてハマった

Power Automate
スポンサーリンク

いやー。解決策が分からずにハマりました。1時間半くらい悩んでしまいました。もうこれ以上悩まないために、メモを残しておきます。

Power Automate のクラウドフロー作成中に、Outlook の予定表から「イベントの取得 (V4)」アクションを利用し、特定のイベントアイテムを取得しようとしました。イベントアイテムを特定するために「フィルタークエリ」の設定を利用して、アイテムの件名を用いて絞り込みを行います。しかしこのとき、取得したいアイテムの件名に「’(シングルクォート)」が含まれていると、どうしても「Invalid filter clause」のエラーになり上手く動きませんでした。

シングルクォートの罠

こうした特殊な記号を含んだフィルターをしようとしたときのエラーは、ほとんどの場合がエンコード絡みです。ネットを検索しても、シングルクォートは「%27」にエンコードできるよという情報があります。そんなわけで次のように修正してみました。

元の ODATA フィルタークエリの指定がこちら。(この例はまったくの間違い)

subject eq 'Masaru's Meeting'

修正後がこちら。

subject eq 'Masaru%27 Meeting'

これでうまく行きそうに思えましたが、まるで解決には至りませんでした。引続き「Invalid filter clause」のエラーが発生します。

シングルクォートはシングルクォート x2 に置換

広大なネットの海をさまよっていると、「Power Automate の ODATA フィルタ―クエリでは、シングルクォートは、2 個のシングルクォートとして扱うんだよ」という情報がありました。

つまりこういうことですね。

subject eq 'Masaru''s Meeting'

なるほど。このように指定した場合は、たしかにエラーが発生せずにイベントアイテムを取得できました。

replace 関数で置換する

さて、フローで自動化するために、replace 関数で置換するように書き換えましょう。と、ここで話がさらにややこしくなってきます。例えば、単純に考えて次のように replace 関数を書きます。

replace('Masaru's Meeting', ''', '''')

しかし、この関数は明らかに正しくないですね。「Masaru’s」に含まれるシングルクォートが、引数の文字列を囲むシングルクォートと競合して、引数の値を正しく識別できないからです。つまり、「Masaru’s」のような引数の文字列では、シングルクォートをエスケープする必要があります。

そしてさらにややこしくさせるのが、シングルクォートをエスケープするためには、シングルクォートを利用するという点です。つまり、「’」は「”」とシングルクォート x2 で表記するわけですね。先ほどの replace 関数は次のようになります。

replace('Masaru''s Meeting', '''', '''''')

これはややこしい…。特に最後の引数は、シングルクォート x6 です。パッと見では何をしているのか分かりませんね……。

最終的に ODATA フィルタークエリに指定した式

と、ここまででシングルクォートの課題は解決できました。しかし、いくつかのパターンで ODATA フィルタークエリを利用していると、フィルター条件の文字列に「&」や「#」が含まれている場合もエラーになることがわかりました。これらの文字列は URL エンコードする必要があり、「&」は「%26」に「#」は「%23」に置換しなければなりません。

Power Automate では、こうした文字列を URL エンコードするための uriComponent 関数があります。シングルクォートをシングルクォート x2 に置き換えた文字列を、uriComponent 関数でエンコードしておくことで、「&」や「#」が含まれた場合にも対応できます。

uriComponent(replace('Masaru''s Meeting', '''', ''''''))

これで完璧。ODATA フィルタークエリには、次のように設定します。replace 関数のひとつめの引数には、フィルター条件に利用したい元の文字列を指定します。変数や動的コンテンツに含まれる文字列ではシングルクォートのエスケープは考える必要がありませんので、そのまま引数に指定するだけです。

uriComponent(replace(variables('フィルター件名'), '''', ''''''))

こんな感じ。

subject eq '@{uriComponent(replace(variables('フィルター件名'), '''', ''''''))}'

こうしておけば、どんな文字列でもエラーにはならずに実行できると思います。

さいごに

ODATA フィルタークエリを利用するときに、条件に文字列を利用するときは注意ですね。特に、シングルクォートの扱いにはハマりました。

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