GASの特定時間定期実行を真剣に考えてみた
はじめに
Google Apps Script(以下、GAS)は非常に便利ですね😁
弊社もGoogle Work Space(以下、GWS)を導入しており、GWSの様々なリソースを活用するのに大変便利で、頻繁に使用しています。
今回は、特定の時間にGASを定期的に実行したいというニーズに応えるためのちょっとしたコツをお教えします。
最後までお読みください。
なにがしたいの?
GASのあるスクリプトを特定の時間に定期実行したいと考えています。
かみ砕いて言うと、「特定時刻ピッタリに関数を実行させる」というのが今回の主題。
例えば、以下のようなケースが考えられます。
- 平日、10時から18時の間、毎時00分に実行したい
- 毎日、10時00分に実行したい
- and more…
GASのUI上でトリガーを設定して、特定時間に繰り返して関数を実行することはできます。
ですが、「時間ベースのタイマー」というのを選択したとしても、1時間の間のいつに実行かをユーザーが設定することはできません。(「毎時00分に実行」という風な設定はできません。)
AWS Lambdaでは、トリガーをcron形式でシンプルに設定できますが、GASでの最適な方法は何でしょうか?🤔
実現方法の概要
以下のようにGASを用いて処理を記述すれば、期待する動作を実現できます。
ドミノ倒しをイメージしてください。
最初のトリガーが、関数を呼び出します。
まず、自分が起動されたトリガーを削除して、処理を開始。
最後に、特定の時間に実行される次のトリガーを生成します。
実現方法
Step1: トリガーを生成する関数
次のような関数を作成します。
/**
* トリガーをGASに設定する関数
*
* @param String: functionName
* @param DateTime: time
*
*/
function setTrigger(functionName, time) {
ScriptApp.newTrigger(functionName)
.timeBased()
.at(time)
.create();
}
Step2: 正規表現を利用して、特定の時間を指定する関数
Step1で作成した関数を使用して、特定の時間にトリガーを設定します。
特定の時間を汎用的に設定できるように、今回は正規表現を利用しています。
ただし、下の例のように特定期間にトリガーを絞り込む場合は、日を跨ぐトリガー生成に注意です。
この場合、GASのGUI上から設定できる時間駆動型のトリガーと上手く組み合わせると良いでしょう。
/**
* 特定の時間でトリガーを設定する関数
*
*/
function setFixedIntervalTrigger() {
const functionName = 'mainHandler';
// 現在時刻を取得
const time = new Date();
// 月曜~金曜を判定する正規表現
const regWeekDay = /[1-5]/;
// 9時~17時の間を判定する正規表現
const regWorkHours = /^(1[0-7]|9)$/;
// トリガーを設定する分
const minutes = 45;
// 曜日と時間の条件を満たした場合にトリガーを設定
if (regWorkHours.test(time.getHours()) && regWeekDay.test(time.getDay())) {
// 次の時間 (hour) の固定分(minutes)でトリガーを設定
time.setHours(time.getHours() + 1);
time.setMinutes(minutes);
setTrigger(functionName, time);
}
}
Step3: トリガーを削除する関数
特定の関数を呼び出すトリガーがGAS上に蓄積してしまうので、これらを削除する関数も用意します。
/**
* トリガーを削除する関数
*
* @param String: functionName
*
*/
function deleteTrigger(functionName){
const triggers = ScriptApp.getProjectTriggers();
for (const trigger of triggers) {
if (trigger.getHandlerFunction() === functionName) {
ScriptApp.deleteTrigger(trigger);
}
}
}
これをせずにでも動作はします。
しかし、トリガーが溜まってしまうと予期せぬ動作になってしまう恐れがあるので、
使用済みトリガーは削除しておくことを推奨します。
Step4: これらを組み合わせる
/**
* メインの処理を実行する関数
*
*/
function mainHandler() {
// 自身が呼び出されたトリガーを削除
deleteTrigger('mainHandler');
// メインの処理を記述
console.log('Hello world')
// 次のトリガーを設定
setFixedIntervalTrigger();
}
// その他の関数は上記の通り
一番最初のトリガーが必要になりますが、適当にGASのエディタで mainHandler
を実行して下さい。
最後に
特定の時間にGASを定期実行するという要件は意外と多いです。
この記事が実装の参考になれば幸いです。