見出し画像

【GAS】中級の復習 その4(トリガー)

▼こちらの続きです。

前回の復習をnoteに書いてから2週間も経ってしまった。今いる会社は業務の特性上、7月の後半から8月前半が繁忙期になる。しかも子供も夏休みでずっと家にいるし、3食ごはん作らないといけないし、、恐怖の夏休み。

GASは全く触っていなかったわけではないけど、仕事優先でGAS復習の優先度は下げていた。仕事が忙しい上に、副業も立て込んでしまい(断れない性格)、かなり忙しかった。久しぶりにゆっくりできる週末がきたので、ノンプロ研のGAS中級講座の復習を再開。

▼こちらで学んでます。9月にも開講される予定みたいですよ。ご興味がある方はぜひ申し込んでみてください!

本日の復習テーマはトリガー。

シンプルトリガー

シンプルトリガーは決められた関数名を使用して設置するもので、関数名は固定で決まっている。起動時に発火するonOpenや編集時に発火するonEdit。

私はオリジナルメニューを作って、それをonOpen関数で起動時に毎度開くようにするという使い方が多いかな。

onOpen()

function onOpen() {
 Browser.msgBox(`スプレッドシートが開きました`);
}

画像1

スプレッドシートが開いたときにメッセージボックスが出る。

onEdit()

function onEdit(){
 Browser.msgBox(`セルが編集されました`);
}

画像2

編集されたときにメッセージボックスが出る。

インストーラブルトリガー

スクリプトエディタ上でトリガーを設置するのがインストーラブルトリガー。時計マークのところを押します。↓

画像3

実行する関数を指定して、スプレッドシートの起動時・編集時やフォーム送信時、カレンダーの更新時などを選べる以外に、分・時間・日付・週・月ベースの好きなタイミングで実行させることもできる。日本語で書いてあるし(英語苦手人材)、とてもとても便利。インストーラブルトリガー最高。

画像4

イベントオブジェクト

トリガーで関数を実行した際に関数に引数として渡されるオブジェクトのこと。シンプルトリガー・インストーラブルトリガーともに使用可能で、仮引数eを使う。よく見る"e"はこれだったのかー!ってヤツです。

スプレッドシートの編集時をトリガーとして動作し、編集したセルに最終更新日時と前回の値をメモとして残すスクリプトを作成しましょう。
function myFunction4_05(e) {
 const d = new Date();
 const lastUpdatedTime = Utilities.formatDate(d, `JST`, `MM/dd hh:mm:ss`);
 const oldValue = e.oldValue;
 const range = e.range;
 let msg = ``;
 msg += `最終更新日時:${lastUpdatedTime}\n`;
 msg += `前回の値:${oldValue}`;

 range.setNote(msg);
}

↑この関数で、スプレッドシートの編集時に発火するトリガーを設置する。

画像5

「あああ」と入っていて、「いいい」と上書きすると・・・

画像6

更新した日時と、更新前の値(oldValue)をメモに残してくれる。

スプレッドシートは履歴が残っていて、バージョンを遡ることもできるけれど、勝手に上書きされると困るシートなどに実装しておくと良いかも。ただし、よく編集するシートに入れるとメモだらけになるので注意です。w

Scriptサービス

ScriptサービスはScript Servicesに含まれていて、インストーラブルトリガーの操作(設置や削除)を行うことができる。

頭の整理のために、Script Servicesのリファレンスを見てみる。Scriptサービスの他によく使うのはプロパティストアを取り扱うPropertiesサービスや、日時をフォーマットするためのUtilitiesサービス、メニューやダイアログを取り扱うBaseサービスなど。ふむふむ。

画像7

ScriptAppクラスがScriptサービスのトップレベルオブジェクトで、以下のようなメンバーがある。

newTrigger(functionName) 新しいトリガービルダーを作成して返す
deleteTrigger(trigger) トリガーを削除する
getProjectTriggers() プロジェクトのトリガーを配列で取得する


インストーラブルトリガーの設置

GAS本によると、①汎用のトリガービルダーを生成→②各種のトリガービルダの設定・作成という手順を踏むとのこと。

function myFunction4_06(){

 const setTime = new Date();
 const functionName = `**ここに実行したい関数名を入れる**`;
 setTime.setMinutes(setTime.getMinutes() + 1);

 const triggerBuilderObj = ScriptApp.newTrigger(functionName); //汎用のトリガービルダーオブジェクトを設置する(①)
 triggerBuilderObj.timeBased().at(setTime).create(); //時間主導型のトリガービルダーを設置する(②)
}

特定の時刻にピンポイントでトリガーを設置したいときになどに使える。

↑実際に実行すると、インストーラブルトリガーが時計マークのところで設定されたことがわかる。

インストーラブルトリガーの削除

function myFunction4_07(){

 const triggers = ScriptApp.getProjectTriggers(); //トリガーを配列で返す
 const functionName = `**ここに削除したい関数名を入れる**`;

 for (const trigger of triggers){
   if(trigger.getHandlerFunction() === functionName){
     ScriptApp.deleteTrigger(trigger);
   }
 }
}

こちらの関数はトリガーの削除。getProjectTriggers()メソッドでトリガーが配列で返ってくるので、for..of文でトリガーを1つずつ取り出して、関数名が一致したものを削除する、というスクリプト。


「肉の日です!」とスプレッドシートの任意のセルに入力する関数を作ります。日付に「2」と「9」の数字が含まれる日にのみ、その関数が午前10時ぴったりに実行されるように、トリガーの設置をするスクリプトを作成しましょう。また、スプレッドシートへの入力が完了したら、トリガーを忘れずに削除するようにしましょう。

1回講座の宿題で提出したはずだけど、ちょっと苦戦した。

function setNiku() {
 const msg = `肉の日です!`;
 const range = SpreadsheetApp.getActiveSheet().getRange(`A1`);
 const d = new Date();
 const today = Utilities.formatDate(d, `JST`, `d`);

 if (today.includes(`2`) || today.includes(`9`)) {
   range.setValue(msg);
 }

 const functionName = `setNiku`;
 const triggers = ScriptApp.getProjectTriggers();
 if(range !==``){
   for (const trigger of triggers){
     if(trigger.getHandlerFunction() === functionName){
       ScriptApp.deleteTrigger(trigger);
     }
   }
 }
}

function myFunction4_08() {
 const functionName = `setNiku`;

 const d = new Date();
 d.setHours(10);

 const triggerObj = ScriptApp.newTrigger(functionName);
 triggerObj.timeBased().at(d).create();
}

実務で2か9が付く日に「肉の日です!」とスプレッドシートに書き込む機会はおそらく一生ないと思うけど、例えば営業日を判定して、最終営業日に何らかの予定をカレンダーに入れるとか、Slackでリマインドをする、、というような応用はできそう。

時間主導型のインストーラブルトリガーは便利なのだけど、土日や祝日が判定できないのが唯一つらみなのよね。私は気にしないけど、チームの他メンバーにSlackの通知がいってしまう・・とかはやっぱり避けたいので。

次回の復習へ続く。

この記事が気に入ったらサポートをしてみませんか?