MENU

【GAS】指定した時間ぴったりにトリガーを設定する方法

  • URLをコピーしました!

こんにちは 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

トリガーを設定させるための関数 myFunction は 2022/02/15/ 15:11:05 にエディタから手動実行されています。

関数 targetFunction のトリガーを設定した時間は 2022/02/15 10:00 です。

そして、なぜかその直後に関数 targetFunction が実行されています。

実行ログ 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「時間主導型」「特定の日時」にトリガーを設定するメソッド
メソッドdeletefunctionName プロパティに設定されている関数名をトリガーから削除するメソッド
Trigger クラスのメンバーの内容

 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 リンク

GitHub
GitHub - FrontWorks-Inc/blog_gas-set-triggers-on-time: create repository create repository. Contribute to FrontWorks-Inc/blog_gas-set-triggers-on-time development by creating an account on GitHub.

まとめ

今回は、指定した時間ぴったりにトリガーを設定するプログラムをご紹介しました。

こちらのコードは弊社では、かなり利用頻度の高いコードです。

始業時間ぴったりにその日のリマインダー メールを飛ばしたり、休憩時間ぴったりにチャット ツールにメッセージを飛ばしたり、いろんな使い方が考えられますね。

ぜひご活用ください。

gas-set-triggers-on-time_featured-image

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

株式会社フロント・ワークス代表取締役の etau です 🤓
へーしゃは「ノンプロ協会」に、個人では「ノンプロ研」所属しています。
趣味は「マンガ」「料理 (特にスパイス カレー)」「お酒」「コーヒー」「コーチング」「マネジメント」です。

目次