Office365(Microsoft365)で、ユーザーオペやスケジュールをトリガーに自動起動する連携処理を実装するのに便利なPowerAutomateですが、実際に業務の中で使おうとするといろいろな制約があります。
そのような制約を克服するため思いついたり調べたりした内容をご紹介していこうと考えています。
Problem
PowerAutomateには配列ソートを行うための組み込みの方法が存在しません。
おそらく、そもそもPowerAutomateの目的は、ユーザーオペ単位で発生するとても小さなトランザクションをこなすことであり、バルク処理を行うことではないとか、まあそういうことなのだろうと推測しています。
そうはいっても、実際問題としてある程度の数(数件~数十件)の要素からなる配列をソートせざるをえない(したくてしかたない)ときがあります。
しかも組織のポリシーなどの関係で、O365からサードパーティの提供するアクションを利用できないということもしばしばあります。
Solution
今回ご紹介する方法は「きれいな方法」とは言い難いですが、比較的シンプルで、ソート問題以外の制約の克服も含めた一般的な課題解決にも応用可能という意味で、気に入っているものです。
1. O365上でExcelファイルを用意
まずはO365上にExcelファイルを用意します。
PowerAutomateから(PowerAutomateのフローを実行するユーザーから)参照可能なところであればどこでも結構です。
2. OfficeScriptでソートを実装
先程作成したExcelファイルを開くとメニューに「自動化」というタブが表示されます(ファイルを開いてから数秒待たないと表示されないことがあります):
ここから「自動化」→「すべてのスクリプト」→「+新しいスクリプト」と進み、表示されたコードエディターで関数を定義します:
function main(
workbook: ExcelScript.Workbook,
array: Array<object>,
key: string,
ascending?: boolean
) : string {
let compare = (a :object, b :object) => {
if (typeof(a) === "number" && typeof(b) === "number") {
return a - b;
}
let a2 = String(a);
let b2 = String(b);
return a2 > b2 ? 1 : (a2 < b2 ? -1 : 0);
};
return JSON.stringify(array.sort((a, b) => (ascending ? 1 : -1) * compare(a[key], b[key])));
}
スクリプト名を「arraySort」ではなく「arraySortThenStringify」としている点に注意してください。
スクリプトは引数で Array<object>
を受け取ることはできますが、戻り値で Array<object>
を返すことができません。これはOfficeScriptの仕様です。幸い、 string
を返すことはできます。
しかたなく、ソート結果を JSON.stringify()
でJSON文字列で返しています。
そういうわけで、この例ではスクリプト名を「...ThenStringify」としていますが、スクリプト名の命名は皆さんの好みに合わせてください。
なお、本来 Array.prototype.sort()
はレシーバーとなる配列オブジェクトそのものを変更する仕様ですが、その変更はPowerAutomate側には反映されません。PowerAutomateからOfficeScriptを呼び出す段階で、引数のオブジェクトのクローンが行われているのでしょう。
したがってやはり戻り値を使う必要があるわけです。
もう1点。他のユーザーのフローからも実行する可能性がある場合は、「すべてのスクリプト」の一覧で「...」→「共有」をクリックしておきましょう:
3. 「スクリプトの実行」アクションをセットアップ
PowerAutomateのフロー側で「スクリプトの実行」アクションをセットアップし、引数としてソート対象の配列やソートに用いるキーを指定します:
4. 実行結果をデシリアライズ
2.でお話した事情があるため、「スクリプトの実行」アクションの出力結果は文字列化されたJSONとなります。これ自体はもうどうしようもないので、受け取った側で工夫をしましょう。つまり、出力結果をデシリアライズします:
json(outputs('スクリプトの実行_2')?['body/result'])
言うまでもないことですが、 outputs()
関数の引数には適切な値を設定してあげてください。
以上で、任意の配列を、任意のキーで、ソートできるようになりました。
Note
Excelファイルは単なるOfficeScriptの保管場所でしかなく、なんとも微妙な使い方になっていますが、そんなことを気にしていてはPowerAutomateを使った業務が楽しくなくなります。
「ちょっとしたことなのにPowerAutomateの制約があってできない!」ということがあったら、こんな解決策もあることを頭の片隅に置いておくと良いかもしれません。