【GAS(Google Apps Script)】トリガー実行するメソッドに引数を渡したい

GAS(Google Apps Script) トリガーに引数を渡したい GAS

GASでスクリプトからトリガーを作成する際に、トリガーに設定するメソッドに引数を渡したい場合の対処法です。
結論から書かせていただくと、トリガー実行するメソッドに引数を渡すことはできません。そのため引数を渡して処理を行いたい場合はひと工夫必要になってきます。

やりたいこと

LINE botでリマインダーアプリのようなものを作っていた際に、トリガーに引数を渡したい場面がありました。

下の画像のように、予定と日時を記載したスプレッドシートがあるとします。

予定表

このシートを上から順に読み出してB列に記載されている日時に予定の通知を行う、という機能を実装していきたいです。
通知の文言はA列に記載されている内容とします。

トリガーの作成方法

トリガーは下記のように作成できます。

ScriptApp.newTrigger('hoge').timeBased().at(time).create();

例えば、2022年11月1日の朝8時にトリガーを実行したい場合は下記のようになります。

// 日付を生成
const time = new Date("2022/11/01");
// 時間に「8時」を設定
time.setHours(8);
// トリガー作成
ScriptApp.newTrigger('hoge').timeBased().at(time).create();

'hoge' の部分にはトリガーで実行したいメソッドの名前を指定します。

トリガーを作成するメソッドとトリガーで実行するメソッドを用意

トリガーで実行するメソッドに引数を渡す前に、引数を渡さない状態でトリガー作成のメソッドとトリガーで実行する用のメソッドをある程度作っておきます。

トリガーを作成するメソッド:createRemindTrigger

まずはトリガーを作成するためのメソッドです。
スプレッドシートの上から順に読み出してトリガーを設定していきたいので、for文を使って下記のようにします。
sendRemind」となっているのがトリガーで実行されるメソッドです。

function createRemindTrigger() {
  // スプレッドシートの値を参照するための初期化処理
  const spreadsheet = SpreadsheetApp.openById({sheetId});
  const sheet = spreadsheet.getSheetByName({sheetName});

  for (let i = 1; i <= sheet.getLastRow(); i++) {
    // スプレッドシートのB列から予定日時を取得
    var remindDate = sheet.getRange('B' + i).getValue();
    // トリガー作成
    ScriptApp.newTrigger('sendRemind').timeBased().at(dateTime).create();
  }
}

トリガーに渡すメソッド:sendRemind

通知を送る際はLINE Messaging APIを使いますが、詳しい処理は割愛します。

function sendRemind() {
  const scheduleName = // 引数でもらいたい
  const message = '今日は' + scheduleName + 'の日!!!';
  
  // LINEに通知を送信する処理
  // 引数に渡したメッセージの内容を送信する
  return postPushMessage(message);
}

通知の文言にはスプレッドシートのA列の内容を入れたいですが、現状 sendRemind 側でどの行の内容を使うかを判断する材料がありません。createRemindTrigger メソッドから引数を渡してもらえれば判断できそうですが、冒頭に書いた通りScriptApp.newTrigger に指定したメソッドに引数を渡すことはできません。

そこで、ここからが本題になります。

トリガーIDと引数に渡したい値を紐づける

トリガーを作成する際に戻り値として返ってくるオブジェクトから、トリガーを識別するためのIDが取得できます(以降トリガーIDと呼びます)。このトリガーIDと、通知を行う際に利用したい値の紐付けをどこかに保存しておくことで、sendRemind メソッドが実行される際に値を読み取れるようにすることができます。

createRemindTriggerメソッドの修正

まずは createRemindTrigger メソッドで、トリガーIDと予定名を紐づけて保存しておく処理を追加します。保存場所はプロパティストアに保存、スプレッドシートに書き出す、などが考えられますが、今回はスプレッドシートに書き出す方法を使いたいと思います。

function createRemindTrigger() {
  // スプレッドシートの値を参照するための初期化処理
  const spreadsheet = SpreadsheetApp.openById({sheetId});
  const sheet = spreadsheet.getSheetByName({sheetName});

  // トリガーIDと予定名の紐付けを保存するためのスプレッドシートの初期化処理
  const triggerMappingSpreadSheet = SpreadsheetApp.openById({sheetId});
  const triggerMappingSheet = triggerMappingSpreadSheet.getSheetByName({sheetName});

  for (let i = 1; i <= sheet.getLastRow(); i++) {
    // スプレッドシートのB列から予定日時を取得
    const remindDate = sheet.getRange('B' + i).getValue();
    // トリガー作成
    const trigger = ScriptApp.newTrigger('sendRemind').timeBased().at(dateTime).create();

    // トリガーIDを取得
    const triggerId = trigger.getUniqueId();
    // 予定名を取得
    const scheduleName = sheet.getRange('A' + i).getValue();
    // スプレッドシートのどの行に紐付けを保存するかを取得
    const targetRow = triggerMappingSheet.getLastRow() + 1;

    // A列にトリガーIDを保存
    triggerMappingSheet.getRange('A' + targetRow;).setValue(triggerId);
    // B列に予定名を保存
    triggerMappingSheet.getRange('B' + targetRow;).setValue(scheduleName);
  }
}

これでトリガーIDと予定名の紐付けを保存することができました。

sendRemindメソッドの修正

sendRemind メソッドでは createRemindTrigger メソッドで保存した紐付けを参照できるようにします。目的の予定名を参照するためにはトリガーIDが必要なのでまずはトリガーIDを取得します。

sendRemind メソッド側でトリガーIDを取得する処理は以下の通りです。

function sendRemind(e) {
  // トリガーIDを取得
  const triggerId = e.triggerUid;
  
  // 以下略
}

引数 e ではGASが自動で渡してくれているイベントオブジェクトを受け取っています。このイベントオブジェクトからトリガーIDを取得することができます。

続いて createRemindTrigger メソッドで紐付けの保存を行ったスプレッドシートから、目的の予定名を取得します。

function sendRemind(e) {
  // トリガーIDを取得
  const triggerId = e.triggerUid;
  
  // トリガーIDと予定名の紐付けを保存するためのスプレッドシートの初期化処理
  const triggerMappingSpreadSheet = SpreadsheetApp.openById({sheetId});
  const triggerMappingSheet = triggerMappingSpreadSheet.getSheetByName({sheetName});
  // スプレッドシートの最終行を取得
  const lastRow = triggerMappingSheet.getLastRow();

  // トリガーIDに対応する予定名を取得
  const scheduleName;
  for (let i = 1; i <= lastRow; i++) {
    // トリガーIDが記載されているセル
    const cellTriggerId = 'A' + i;
    // トリガーIDを取得
    const targetTriggerId = this.sheet.getRange(cellTriggerId).getValue();

    if (targetTriggerId === triggerId) {
      // 予定名が記載されているセル
      const cellScheduleRow = 'B' + i;
      // 予定名を取得
      scheduleName = triggerMappingSheet.getRange(cellScheduleRow).getValue();
    }
  }

  // 以下略
}

あとはメッセージの内容を作成して送信を行う処理を追加して完了です。

function sendRemind(e) {
  // トリガーIDを取得
  const triggerId = e.triggerUid;
  
  // トリガーIDと予定名の紐付けを保存するためのスプレッドシートの初期化処理
  const triggerMappingSpreadSheet = SpreadsheetApp.openById({sheetId});
  const triggerMappingSheet = triggerMappingSpreadSheet.getSheetByName({sheetName});
  // スプレッドシートの最終行を取得
  const lastRow = triggerMappingSheet.getLastRow();

  // トリガーIDに対応する予定名を取得
  const scheduleName;
  for (let i = 1; i <= lastRow; i++) {
    // トリガーIDが記載されているセル
    const cellTriggerId = 'A' + i;
    // トリガーIDを取得
    const targetTriggerId = this.sheet.getRange(cellTriggerId).getValue();

    if (targetTriggerId === triggerId) {
      // 予定名が記載されているセル
      const cellScheduleRow = 'B' + i;
      // 予定名を取得
      scheduleName = triggerMappingSheet.getRange(cellScheduleRow).getValue();
    }
  }

  // メッセージ作成
  const message = '今日は' + scheduleName + 'の日!!!';
  
  // LINEに通知を送信する処理
  // 引数に渡したメッセージの内容を送信する
  return postPushMessage(message);
}

これで無事にトリガーで実行されるメソッドに値を渡すことができました!

参考

コメント

タイトルとURLをコピーしました