どうも。つじけ(tsujikenzo)です。このシリーズでは、2021年9月から始まりました「ノンプロ研GAS中級講座6期」について、全7回でお届けします。今日はDay4です。
前回のおさらい
前回は、「組み込みオブジェクト」 をお届けしました。
今回は、 「Utilitiy services1」 をお届けします。
今日のアジェンダ
- Utilitiy Servicesになりました
- Script Serviceとトップレベルオブジェクト
- トリガーから作成できないトリガー
GAS中級講座5期の補講ブログでは、以下をお届けしています。
- トリガーの正式名称
- シンプルトリガーの4つのポイント
- シンプルトリガーは認証不要でAPIを呼び出せる
- 与えた認証の削除
- シンプルトリガーはバインドしているファイル以外にアクセスできない
- インストーラブルトリガーの設置アカウントと発火
- トリガーは編集権限を失うと削除される
- イベントオブジェクトの公式リファレンス
- getUi()とaddMenu()メソッド
- Properteiesサービスのデータ量
- UserPropertyの使いどころ
前回の補講ブログは、どちらかというと、スクリプトエディタとトリガーメニューを使ってトリガーを設置する内容でした。
読んでいただければ、講座がさらに理解できる内容になっていると思います。
今回の補講ブログでは、トリガーはオブジェクトであるという視点から、理解を深めたいと思います。
Utility Servicesになりました
2021年10月に、Google Apps Script内で、アップデートが行われ、Script Serviciesの名称が、Utility Servicesになりました
Google Apps Scriptは、以下の3つのServicesと1つのResourcesからなります。
- Google Workspace services
- Other Google services
- Utility services
- Script project resources
Utility Servicesは、以下の4項目で構成されています。
- API & database connections
- Data usability & optimization
- HTML & content
- Script execution & information
とくに、中級講座後半であつかうServiceは、以下の5つです。
- URL Fetch
- Utilities
- Base
- Properties
- Script
どのServicesに所属(分類)するのかは、覚える必要はありません。
なんとなく、これらのServiceはUtility Servicesにあったなぁと思っていただければ十分です。
Script Serviceとトップレベルオブジェクト
Script Serviceは、その名のとおりスクリプトを操作するサービスですが、以下のような項目を取り扱います。
- トリガーの操作
- スクリプトの公開
- イベントに関するプロパティ
今回はトリガーの操作について、お届けします。
さっそく、トップレベルオブジェクトのClass ScriptAppを見てみましょう。
トリガーを扱うさまざまなプロパティやメンバーが登録されています。
**newTrigger()やdeleteTrigger()**などは、これから何度も呼び出すメソッドです。
これらは、ScriptApp(トップレベルオブジェクト)のメソッドであることを理解しましょう。
newTrigger()メソッドとTriggerBuilderオブジェクト
newTrigger()メソッドの戻り値は、TriggerBuilderオブジェクトです。
TriggerBuilderオブジェクトとは、なんでしょうか。クラスを確認しましょう。
クラスを確認すると、5種類のTriggerBuilderオブジェクトがあるようです。
- ドキュメントを開いたときに発火するトリガーを作る
- フォームを開いたり送信したときに発火するトリガーを作る
- スプレッドシートを開いたり編集したりしたときに発火するトリガーを作る
- カレンダーのイベントを更新しときに発火するトリガーを作る
- 時限式トリガーを操作する
つまり、Script Serviceでは、このような流れでトリガーを作成します。
- トップレベルオブジェクトからTriggerBuilderオブジェクトを作成する
- TriggerBuilderオブジェクトから DocumentTriggerBuilderや、SpreadsheetTriggerBuilderなどのサービス名+TriggerBuilderオブジェクトを設定する
- サービス名+TriggerBuilderオブジェクトのcreate()メソッドで、Triggerオブジェクトを作成する
最終的にTriggerオブジェクトは、実行されたり参照されたり設置されたり削除されたりします。
「時間置きに」とか「スプレッドシートが開いたら」などは、あくまでサービス名+TriggerBuilderオブジェクトのcreate()メソッドでTriggerオブジェクトが生成された結果です。
Class SpreadsheetTriggerBuilderから生成されたTriggerオブジェクトを、Class DocumentTriggerBuilderから生成されたTriggerオブジェクトに変更したり、時限式トリガーを設定することはできません。
Class Trigger
Class Triggerを見てみましょう。
get系のメソッド しかありません。
なので、いちど作成されたTriggerオブジェクトに対して、発火時刻を再設定したりできません。
さらに、Triggerオブジェクトは、設置したらプロジェクト内にずっと残ります。
使い終わったTriggerは削除します。その感覚になれていきましょう。
トリガーの作成は変数に格納しない
公式リファレンスにもあるとおり、トリガーは、変数に格納せず作成した方がリーダブルかもしれません。
ScriptApp.newTrigger('main').timeBased().everyMinutes(10).create();
公式リファレンスでは、メソッドごとに改行して書かれています。
この方がチェーン記法だということが伝わりやすい人もいるので、改行については、どっちが正しいというわけではありません。
/**
* Creates two time-driven triggers.
*/
function createTimeDrivenTriggers() {
// Trigger every 6 hours.
ScriptApp.newTrigger('myFunction')
.timeBased()
.everyHours(6)
.create();
// Trigger every Monday at 09:00.
ScriptApp.newTrigger('myFunction')
.timeBased()
.onWeekDay(ScriptApp.WeekDay.MONDAY)
.atHour(9)
.create();
}
トリガーから作成できないトリガー
講座内では、GASからトリガーを作成する方法をお伝えしました。
1分おきに発火する時限式トリガーを手動で設置する
1分ごとに、関数printを発火するトリガーを、関数myFunctionを実行して設置します。
/** 時限式トリガーを作成する関数 */
function myFunction() {
ScriptApp.newTrigger("print").timeBased().everyMinutes(1).create();
}
/** 正常にログ出力しましたと出力する関数 */
function print() {
console.log('正常にログ出力しました');
}
このような時限式トリガーが設置され、1分起きに発火します。問題ありません。
1分後に発火する時限式トリガーを手動で設置する
1分後に、関数printを発火するトリガーを、関数myFunctionを実行して設置します。
/** 時限式トリガーを作成する関数 */
function myFunction() {
const setTime = new Date();
setTime.setMinutes(setTime.getMinutes() + 1);
ScriptApp.newTrigger("print").timeBased().at(setTime).create();
}
/** 正常にログ出力しましたと出力する関数 */
function print() {
console.log('正常にログ出力しました');
}
もちろん、1分後に関数printが実行され、トリガーは有効期限が切れます。
それでは、関数myFunctionを1分ごとに発火する時限式トリガーを手動で設置するとどうなるでしょう。
このように、1分後に「1分後に関数printを発火するトリガー」が設置されます。
実行数を確認すると、関数myFunctionの実行、関数printの実行を1分ごとに繰り返します。
トリガーは、無効になったものが増え続けます。(この後の説明のために一度すべてのトリガーを手動で削除します)
1分後に発火する時限式トリガーをGASで設置する
それでは、関数myFunctionを1分ごとに発火する時限式トリガーを、GASで設置してみます。
関数createMyTrrigerを手動で実行します。
/** 時限式トリガーを作成する関数 */
function createMyTrriger() {
ScriptApp.newTrigger("myFunction").timeBased().everyMinutes(1).create();
}
/** 時限式トリガーを作成する関数 */
function myFunction() {
const setTime = new Date();
setTime.setMinutes(setTime.getMinutes() + 1);
ScriptApp.newTrigger("print").timeBased().at(setTime).create();
}
/** 正常にログ出力しましたと出力する関数 */
function print() {
console.log('正常にログ出力しました');
}
関数myFunctionを発火するトリガーが設置されます。
関数printを発火するトリガーが設置されます。
しかし、関数printを発火するトリガーは無効になってしまいます。
「このトリガーは無効になりました。原因は不明です」とのことです。
実行数を確認しても、関数printは発火していません。
これは、V8のバグです。どうやらRhinoランタイムに戻すと実行されるようです。
結論:『GASで設置した時限式トリガーから、設置された時限式トリガーは、無効になるバグがある』です。
この回避方法は、「GASで6分の壁を乗り越える」という記事を、後日書こうと思います。
ノンプロ研メンバーが書かれているこちらの記事も参考にしてください。
まとめ
以上で、「Utility services1」 をお届けしました。
繰り返しになりますが、GAS中級講座5期の補講ブログでは、講座内で伝えられなかったTipsをたくさん載せてあります。
ぜひご一読ください。
次回は、 「Utility services2」 をお届けします。