#46 トリガーの「編集時」と「変更時」の違いは?
今回の記事は、記事の内容が直接役立つものではなく、この内容によって GAS がより理解できるようになる、もしくは GAS でのプログラムを作成するためのアイディアとなるものです。
そのため、ちょっと小難しい内容となっています…
トリガー設定時のイベントは 4種類?
Google スプレッドシートで GAS(Google Apps Script)のトリガーを設定しようとすると、選択肢には下図のように 4つ表示されています。
起動時
編集時
変更時
フォーム送信時
この 4つに加えて、「Time-driven (clock):時間駆動型 (クロック)」を含めたトリガーが、「Installable Triggers :インストール可能なトリガー」と呼ばれるようで、以下の URL で説明されています。
トリガーには、「Installable Triggers :インストール可能なトリガー」の他に「Simple Triggers:シンプルなトリガー」があり、この分類については「Simple Triggers」→「Available types of triggers」に説明されています。
この表の右側「Installable Triggers」に「Sheets(スプレッドシート)」のアイコンが 4つ並んでいます。これが冒頭のイベントの種類として表示されていた 4つに対応するものです。
Open → 起動時
Edit → 編集時
Change → 変更時
Form submit → フォーム送信時
Installable Triggers と Simple Triggers の違い
前述の表を見ていて感じるのは、
Installable Triggers と Simple Triggers は何が違うの?
スプレッドシートのアイコンが Open と Edit の両方に表示されているのはなぜ?
といったところです。前述のリファレンスに書かれている内容から解釈するに、以下のような感じのようです。
Simple Triggers
onOpen() や onEdit() のように、あらかじめ決められた名前でトリガー関数を記述する。→ トリガー関数の関数名は予約済みとなっている。
関数名として予約されているので、設定しなくてもトリガー関数として動作する。
Installable Triggers
任意の名前でトリガー関数を記述できる。
手作業もしくはプログラムによってトリガー関数として設定しなければ、トリガー関数として動作しない。
すなわち、前述の Open と Edit のトリガーは、Installable Triggers としても、Simple Triggers としても動作させられます。
Open を例にすれば、onOpen() という関数名でトリガー関数を記述すれば、冒頭の画像のようにトリガー関数を設定しなくても、トリガー関数として実行されます。別の関数名でトリガー関数を記述した場合には、トリガー関数として設定すれば、トリガー関数として動作します。この設定が、「インストール」ということなのでしょう。
スプレッドシートにオリジナルのメニューを追加するときに、onOpen() をトリガー関数として登録しなくても、スプレッドシートを開いたときに自動的に実行され、メニューが追加されていたのは Simple Triggers として動作していたからです。 ※これまで意識していませんでしたが、何だかすっきりした感じです。
Simple Triggers の制限
ただし、「Restrictions:制限」でも説明されているように、Simple Triggers として動作する場合には、ユーザーに承認を求めることなく自動的に起動されるものの、いくつかの制限が設けられています。
注意が必要なのは、承認(ユーザー認証)が必要な処理は、Simple Triggers としては実行できないことです。
そのため、onOpen や onEdit のように Simple Triggers として動作可能なものであっても、承認が必要な処理を行う場合には、Installable Triggers として動作させなければならないのです。
わかりやすくするなら、以下のような感じで考えてもいいのかもしれません。
どちらでもいい場合には Simple Triggers ではなく、Installable Triggers として設定する。 明示的にトリガー関数として設定する。
onOpen 以外は、Installable Triggers として設定する。
Edit と Change の違い
冒頭の図にもある、イベントの種類として設定できる Edit(編集時)と Change(変更時)にはどのような違いがあるのかを確認してみました。
具体的には、以下 URL のようにトリガー関数に引数として渡される「Event Objects」が、それぞれのトリガー関数によって異なる内容になっているようで、その内容を比較すれば違いがわかりそうです。
Change(変更時)
authMode
A value from the ScriptApp.AuthMode enum.changeType
The type of change (EDIT, INSERT_ROW, INSERT_COLUMN, REMOVE_ROW, REMOVE_COLUMN, INSERT_GRID, REMOVE_GRID, FORMAT, or OTHER).triggerUid
ID of trigger that produced this event.user
A User object, representing the active user, if available (depending on a complex set of security restrictions).
Edit(編集時)
authMode
A value from the ScriptApp.AuthMode enum.oldValue
Cell value prior to the edit, if any. Only available if the edited range is a single cell. Will be undefined if the cell had no previous content.range
A Range object, representing the cell or range of cells that were edited.source
A Spreadsheet object, representing the Google Sheets file to which the script is bound.triggerUid
ID of trigger that produced this event (installable triggers only).user
A User object, representing the active user, if available (depending on a complex set of security restrictions).value
New cell value after the edit. Only available if the edited range is a single cell.
似たような名前のトリガー関数でありながら、「Event Objects」の内容はずいぶん違います。
authMode、triggerUid、user、の 3つはどちらにもある。
Edit には、編集された前後の oldValue と value がある。
Change には、 changeType があり、どのような変更を加えられたかがわかる。Edit には range があり、どこが編集されたかがわかる。
Change にはない。
実際に確認してみた!
以下のようなプログラムを作成してみました。それぞれのトリガー関数が実行されたら、対応するセル(B1 か B2)に実行された日時と、状況を記録します。
onEdit() の方は、Simple Triggers として動作させられるので、トリガーとして設定しなくても動作しました。onChange() の方は、Installable Triggers なので手作業でトリガー関数として設定しています。
function onEdit(e) {
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var answerSheet = spreadSheet.getSheets();
answerSheet[0].getRange('B1').setValue('Last modified: ' + new Date() + ' / ' + e.range.getA1Notation() + ' (' + e.oldValue + '→' + e.value + ')');
}
function onChange(e) {
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var answerSheet = spreadSheet.getSheets();
answerSheet[0].getRange('B2').setValue('Last modified: ' + new Date() + ' / ' + e.changeType);
}
上記の GAS のプログラムを、「拡張機能」→「Apps Script」でエディタを開いて、貼り付けます。前述したように onChange() の方は、手作業でトリガー関数として設定します。 ※A1 には「onEdit(event)」、A2には「onChange(event)」と入力してあります。
そして、スプレッドシートで適当に入力を行うと、プログラムで記述されているように B1 と B2 にトリガー関数が実行された状況が記録されます。
実際に実行してみて気付いたことは…
同じようなプログラムなのに、Simple Triggers として実行されている onEdit() では「日本標準時」と表示されていますが、Installable Triggers として実行されている onChange() では「Japan Standard Time」と英語表記になっている。
onEdit() を Installable Triggers として登録すると、「日本標準時」ではなく、「Japan Standard Time」と英語表記になった。
onEdit() を Installable Triggers として登録すると、Simple Triggers として実行された後に、Installable Triggers としても実行され、2回実行されることになる。 ※Simple Triggers を Installable Triggers として登録するなら、関数名は変更するべき!
「Event Objects」の内容が違うように、トリガー関数が動作するタイミングと得られる情報には違いがある。
という感じでした。
まとめ
似たような名称の「Edit(編集時)」と「Change(変更時)」という 2種類のトリガー関数は、名前が違うように動作も異なっていました。
「Edit(編集時)」のトリガー関数は、Simple Triggers と Installable Triggers のどちらとしても動作できる。
onEdit() という関数名であれば、Simple Triggers として動作するが、Installable Triggers としても登録すると二重に動作してしまうので注意!「Edit(編集時)」は、セルの中身が変更されたことを確認、「Change(変更時)」は、シートに対して行われた変更を確認、という感じ。
この二つをうまく使い分けて、いい感じのプログラムを作れればいいな、と思います。 ということで、トリガー関数について詳しくなれたものの、実質的な成果物はありません。
この記事が気に入ったらサポートをしてみませんか?