PowerAutomateのワークフローでExcelファイルのテーブルを更新することはしばしばあると思います。
そして時として多数の行を一括削除したいときがあると思います(私はあります)。
2023/02/03にもう1つの方法を紹介する記事を投稿しました。こちらも参考にしていただければ幸いです。
→ PowerAutomateでExcelテーブルの行を一括削除する - Range.delete()編
Problem
PowerAutomateの標準アクションには、1行ずつ削除するものはありますが、多数をまとめてというものはありません。。
この「行の削除」を使う場合、おそらく「Apply to each」アクションと併用することになるでしょう。
しかしご存知の通りこのアクションはとても遅い。
所要時間の観点で許容できない場合は他の選択肢を探す必要があります。
Solution
以前別の記事でお話したとおりこのようなちょっと難しいタスクをこなすならばOffice Scriptsです。
次のようなスクリプトを作成してExcelファイルに追加します:
function main(workbook: ExcelScript.Workbook, tableName: string) {
const table = workbook.getTable(tableName);
const skip = 1;
const chunk = 10000;
while (table.getRowCount() > skip) {
const n = Math.min(table.getRowCount() - skip, chunk);
table.deleteRowsAt(skip, n);
}
}
今回例に使用したスクリプトの役割が「1行目以外はすべて削除する」なので skip
定数を宣言してロジック内で参照しています。
もう1つ chunk
という定数もありますが、こちらは後述します。
あとはこのスクリプトをPowerAutomateのワークフローから呼び出すだけです:
注意点1:それでも数十秒はかかる
「Apply to each」よりはマシだと思いますが、結構な時間待機が発生します。
これはもう仕方ないかなと。
注意点2:対象件数が増えるとdeleteRowsAt関数がタイムアウトする
削除対象となる行の数が増えてくると、deleteRowsAt
関数レベルでタイムアウトが発生します:
どうやらこの関数は内部的にExcelファイルを操作するWebAPIに要求をしているようで、そのWebAPI側なのか待機する関数側なのか、どこかでタイムアウトになるようです。
公式リファレンスを見ると、「注: 同時に 1,000 行を超える行を削除すると、Power Automateタイムアウトになる可能性があります。」とあります。
が、実際には400件くらいでもエラーになるときはなります。
逆に1,000件以上でもエラーにならないこともあります。
400件でエラーになるテーブルは、何度スクリプトを実行しても必ずエラーになるので、おそらくテーブルの横幅なども関係しているのだと推測していますが、何にしても明確な基準はありません。
注意点3で述べるもう1つのタイムアウトとも無関係です。
先程例示したスクリプトに chunk
定数が宣言されているのは、この「経験知」をロジックに反映させるためのものです。。
注意点3:さらに対象件数が増えると(おそらく)スクリプト全体がタイムアウトする
公式リファレンスによると、「実行時間の長いスクリプトがある場合は、同期的 Power Automate 操作における 120 秒のタイムアウトに注意してください。 スクリプトを最適化するか、Excel の自動化を複数のスクリプトに分割する必要があります。」とのこと。
注意点2の問題を乗り越えたあとは、スクリプト全体の所要時間が問題になります。
繰り返しになりますが、deleteRowsAt関数のタイムアウトとこのスクリプト全体のタイムアウトは別物です。
スクリプト全体が33秒で終わる場合でも、deleteRowsAt関数はタイムアウトするリスクがあります。