スプレッドシートのGASを使用して、
「起動時間の最大値を超えました」というエラー
ありますよね。
実行時間が6分を超えると
出てしまうエラーなので
割とすぐ出てしまうエラーです。
前回は、トリガーを使って回避する方法を書いたので、
今回は並列起動で回避する方法を忘備録として書き残しています。
前回と同じく、
私の環境は、1つのコピー元の共有シートがあって、
その共有シートから使い人がそれぞれコピーして、
使用しているという状態で、
その元の共有シートを更新したときに、
同じようにコピーされたシートにも更新を反映させるために、
処理を実行しています。
GASのタイムアウト回避方法
私がタイムアウト回避するにあたって、
行なった施策は2つです。
1、タイムアウトのエラーが出る前にトリガーセット
2、並列起動して一気に処理をする
今回は、並列起動して一気に処理をする方法となります。
トリガーセットで回避する方法はこちら
2、並列起動して一気に処理をする
トリガーセットをするコードは、
ひとつひとつ、ブックIDを読み込んで、シートを順番に処理していって、
終わったらチェックをして、次のブックへ
という感じで、上から順番に処理を行なっていますが、
並列で実行できるように起動すると、
ブックIDを一気に読み込んで、
同時並行で並列処理をすることが可能になります。
GASの同時実行の上限は30らしいので、
私は20ブックずつくらいで処理をするようにしています。
私の場合は、大体、1つのブックあたり2分くらいで処理が終わるので、
順番に行うと10ブックで20分ほどかかってしまいますが、
並列で行うと一気に処理をして2分で完了するので、
時間効率もすごくいいです。
並列で行う場合も、同じようにメンテナンス用のブックを用意します。
※トリガーのところで使ったのと同じブックです
今回は、並列実行を起動するために、
HTMLを作成して、
HTMLでブックIDをGASの実際の処理に渡して実行させるという方法です。
なので、まずはブックIDを読み込んでGASを起動させるHTMLを作成します。
ファイル名は「heiretu.html」
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
for(let n = 10; n < 13; n++) {
google.script.run
.withSuccessHandler(onSuccess)
.mente(n)
}
function onSuccess() {
google.script.host.close()
}
</script>
</head>
</html>
for文の中の変数「n」は実行回数なので、
状況に応じて変更してください。
function実行時に、変数を渡すことでできます。
「mente(n)」の「n」の部分です。
変数を渡す必要がなければ「()」だけでOKです。
「hmente」は起動するfunction名なので、
実行したい任意の名前に変更してください。
HTMLが作成できたら、次はGASスクリプトのコーディングをしていきます。
以下のコードをコピペして、
新規作成、もしくは既にあるコードの上か下に追加してください。
function openDialog() {
const html = HtmlService.createTemplateFromFile("heiretu.html").evaluate()
SpreadsheetApp.getUi().showModalDialog(html, "並列メンテ処理実行中...")
}
function onOpen() {
SpreadsheetApp
.getActiveSpreadsheet()
.addMenu('メンテナンス', [
{ name: '並列メンテ実行', functionName: 'openDialog' },
]);
}
ここまで出来たら、
該当のスプレッドシートを開いたら「メンテナンス」というメニューが出ているはずなので、
そこから「並列メンテ実行」を選ぶだけで、処理が実行されるようになります。
ダイアログが出ている間は処理中で、処理が終わればダイアログが閉じるようになっています。
処理中のログは、GASのログで追うことができます。
タイムアウト回避に応用で使用できるコード
ここからは、改変して使用しやすくコードをまとめて置いています。
コピペで使用できるので、好きな方をコピペして使用してみてください。
GASタイムアウト回避、並列処理コピペ用
並列処理は、HTMLとGASの2つのコードが必要になりますが、
一度作ってしまえば、処理時間も圧倒的に少なく終えることができるので、
おすすめの方法です!
並列処理を行うためには、
まずはGASスクリプトのコーティング画面でHTMLを作成します。
ファイル名は「heiretu.html」としています。
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
for(let n = 10; n < 13; n++) {
google.script.run
.withSuccessHandler(onSuccess)
.mente(n)
}
function onSuccess() {
google.script.host.close()
}
</script>
</head>
</html>
for文の中の変数「n」は実行回数なので、
状況に応じて変更してください。
function実行時に、変数を渡すことでできます。
「mente(n)」の「n」の部分です。
変数を渡す必要がなければ「()」だけでOKです。
「hmente」は起動するfunction名なので、
実行したい任意の名前に変更してください。
HTMLが作成できたら、次はGASスクリプトのコーディングをしていきます。
以下のコードをコピペして、
新規作成、もしくは既にあるコードの上か下に追加してください。
function openDialog() {
const html = HtmlService.createTemplateFromFile("heiretu.html").evaluate()
SpreadsheetApp.getUi().showModalDialog(html, "並列メンテ処理実行中...")
}
function onOpen() {
SpreadsheetApp
.getActiveSpreadsheet()
.addMenu('メンテナンス', [
{ name: '並列メンテ実行', functionName: 'openDialog' },
]);
}
ここまで出来たら、
該当のスプレッドシートを開いたら「メンテナンス」というメニューが出ているはずなので、
そこから「並列メンテ実行」を選ぶだけで、処理が実行されるようになります。
ダイアログが出ている間は処理中で、処理が終わればダイアログが閉じるようになっています。
応用でコピペするには、ある程度GASの知識が必要にはなりますが、
そんなに難しくはないので、ぜひ取り入れて見てください!
コメント
時間指定でのイベントトリガーで実行すると、
Exception: このコンテキストから SpreadsheetApp.getUi() を呼び出せません
というエラーが表示されるのですが、イベント実行では並列で実行できないのでしょうか。
コメントありがとうございます!
SpreadsheetApp.getUi()はダイアログ等のインターフェイスを表示させるメソッドです。
スプレッドシートを表示して起動する必要があるため、イベントトリガーでは正常に動かないと思います。
ダイアログ不要でトリガーで起動したいとのことでしたら、
function openDialogにある、「SpreadsheetApp.getUi().showModalDialog(html, “並列メンテ処理実行中…”)」の箇所を削除してみてください。
トリガー実行の場合、読み取り専用のファイルや承認が必要な実行はエラーになってしまうため、
この辺りにも注意してコードを組んでみてください!
よろしくお願いいたします。