
こんにちは etau です 🤓
前回の記事 で、『「時間主導型」のトリガーといえば Google Apps Script の真骨頂』と書きましたが、時間主導型トリガーにはいくつかの種類があります。
ただ、お仕事をされるみなさんがいちばん必要としているであろう時間ぴったりに繰り返し実行されるトリガーは、残念ながらありません。
今回は、こちらのトリガーを GAS で自動設定していきます。
時間主導型トリガーの種類
今回 GAS で設定していくトリガーは時間主導型トリガーの「特定の日時」です。
イベントのソースを選択 | 時間ベースのトリガーのタイプを選択 | 備考 |
---|---|---|
時間主導型 | 特定の日時 | YYYY-MM-DD HH:MM の設定が必要 |
時間主導型 | 分ベースのタイマー | 1, 10, 15, 30 分おきの設定が可能 |
時間主導型 | 時間ベースのタイマー | 1, 2, 4, 6, 8, 12 時間おきの設定が可能 |
時間主導型 | 日付ベースのタイマー | 午前 0 時~1 時、午後 1 時~2 時、…、午後 11 時~午前 0 時といった 1 時間おきの設定が可能 |
時間主導型 | 週ベースのタイマー | 曜日の選択 + 日付ベースのタイマーの設定が可能 |
時間主導型 | 月ベースのタイマー | 日付の選択 (1, 2, …, 31 日) + 日付ベースのタイマーの設定が可能 |
確認していただくとわかるように、毎日繰り返しで、いちばん細かく設定できるものが「日付ベースのタイマー」で設定できる 1 時間単位です。
この設定を利用すると毎日 10 – 11 時の間に実行することはできますが、10 時ぴったりに実行する場合には、毎回手動で設定する必要があります。
それでは「特定の日時」のトリガーを設定するコードを書いていきます。
トリガーを設定する関数 setTrigger
「特定の日時」のトリガーを設定するための関数 setTrigger には、仮引数として「設定する関数名」と「日時」を受けるよう設定します。
function setTrigger(functionName, date) { ScriptApp.newTrigger(functionName). timeBased(). at(date). create(); }
トリガーを設定する対象の関数を targetFunctionとして、テスト関数 myFunction から、「関数名」と「当日の 10 時の Date オブジェクト」を setTrigger に渡してあげると、トリガーを設定するコードがこちらです。
function myFunction() { const functionName = 'targetFunction'; const date = new Date(); const time = '10:00'; date.setHours(...time.split(':')); setTrigger(functionName, date); } function setTrigger(functionName, date) { ScriptApp.newTrigger(functionName). timeBased(). at(date). create(); } function targetFunction() { }
関数 myFunction を実行して [トリガー] を確認すると、targetFunction が設定されていることが確認できます。

実際に設定されたトリガーの内容を確認しましょう。

10 時に設定したはずが、おかしなことになっています。
[実行数] から内容を確認してみます。

トリガーを設定させるための関数 myFunction は 2022/02/15/ 15:11:05 にエディタから手動実行されています。
関数 targetFunction のトリガーを設定した時間は 2022/02/15 10:00 です。
そして、なぜかその直後に関数 targetFunction が実行されています。

このことから、「特定の日時」を現在日時より前に設定した場合、トリガーはその直後に設定されることがわかりました。
特定の秒数を越えると 1 分後に設定されるため、必ずしも同時刻 (YYYY-MM-DD HH:MM) に実行されるわけではありませんが、対象の関数は必ず 1 度実行されてしまいますので注意が必要です
というわけで、設定する時刻以前に、トリガーを設定するための関数を実行してあげる必要があります。
今回の例でいうと、関数 myFunction を [時間主導型] – [日付ベースのタイマー] を利用し、[午前 9 時~10 時] 以前の設定をしてあげれば、関数 targetFunction は、毎日 10 時ぴったりに設定、実行されます。

さて、このまま毎日 10 時にトリガーを設定し続けると、ある問題が起こります。
実行済みのトリガーがどんどん溜まっていくのです。

「特定の日時」トリガーで実行時間を過ぎたトリガーは「前回の実行」の項目に「無効」と表示されます
気にしないという選択肢もありますが、トリガー設定数の上限が 1 ユーザーに対して 1 プロジェクト 20 までと決められていますので、このままだと 19 日目にはトリガーが設定できなくなってしまいます。
この問題に対処するために、トリガーを削除するコードを書いていきましょう。
トリガーを削除する関数 deleteTriggers
トリガーを削除するための関数 deleteTriggers に、仮引数として「削除する関数名」を受けるよう設定します。
function deleteTriggers(functionName) { const triggers = ScriptApp.getProjectTriggers(); triggers.forEach(trigger => { if (trigger.getHandlerFunction() !== functionName) return; ScriptApp.deleteTrigger(trigger); }); }
現在設定されているトリガーから仮引数として受けた関数名と同様の関数があった場合には、対象のトリガーすべてを削除するコードです。
トリガーをセットする関数 setTrigger の前に トリガーを削除する deleteTriggers を実行させることで、当日に実行させる 10 時のトリガーのみが残ります。
手続き型の完成したものがこちらです。
function myFunction() { const functionName = 'targetFunction'; deleteTriggers(functionName); const date = new Date(); const time = '10:00'; date.setHours(...time.split(':')); setTrigger(functionName, date); } function deleteTriggers(functionName) { const triggers = ScriptApp.getProjectTriggers(); triggers.forEach(trigger => { if (trigger.getHandlerFunction() !== functionName) return; ScriptApp.deleteTrigger(trigger); }); } function setTrigger(functionName, date) { ScriptApp.newTrigger(functionName). timeBased(). at(date). create(); } function targetFunction() { }
最後に、この手続き型のプログラムをベースにクラスを作成していきます。
クラス化
実装するクラスのメンバー (プロパティとメソッド) について、かんたんに解説します。
メンバーの設定
今回作成した関数を利用して、以下のようなメンバーを設定しました。
メンバー種別 | メンバー名 | メンバーの内容 |
---|---|---|
プロパティ | functionName | トリガー操作の対象となる関数名 |
メソッド | createTimeBased | 「時間主導型」「特定の日時」にトリガーを設定するメソッド |
メソッド | delete | functionName プロパティに設定されている関数名をトリガーから削除するメソッド |
Trigger クラスのコード
前述のメンバーをクラスに設定していきます。
class Trigger { /** * トリガーに関するコンストラクタ * @constructor * @param {string} functionName - 関数名 */ constructor(functionName) { /** @type {string} */ this.functionName = functionName; } /** * 指定日時のトリガーを設定するメソッド * @param {Date} triggerTime - トリガーをセットする指定日時 * @return {Trigger} Trigger オブジェクト */ createTimeBased(triggerTime) { ScriptApp.newTrigger(this.functionName). timeBased(). at(triggerTime). create(); return this; } /** * トリガーを削除するメソッド * @return {Trigger} Trigger オブジェクト */ delete() { const triggers = ScriptApp.getProjectTriggers(); triggers.forEach(trigger => { if (trigger.getHandlerFunction() === this.functionName) ScriptApp.deleteTrigger(trigger); }); return this; } }
クラスを実行する関数として、以下のようなものをご用意ください。
function myFunction() { const functionName = 'targetFunction'; const trigger = new Trigger(functionName); const date = new Date(); const time = '10:00'; date.setHours(...time.split(':')); trigger. delete(). createTimeBased(date); } function targetFunction() { }
スッキリですね。
今回はコード上で日付を設定しましたが、この値をスプレッドシートから取得して設定する方法も便利だと思います。
GitHub リンク
まとめ
今回は、指定した時間ぴったりにトリガーを設定するプログラムをご紹介しました。
こちらのコードは弊社では、かなり利用頻度の高いコードです。
始業時間ぴったりにその日のリマインダー メールを飛ばしたり、休憩時間ぴったりにチャット ツールにメッセージを飛ばしたり、いろんな使い方が考えられますね。
ぜひご活用ください。