• ベストアンサー

Google Apps Scriptのトリガー

Google Apps Scriptnの時間主導型トリガーがうまく機能してくれません。 あるプロジェクトを1分毎に自動実行するようにしたいのですが、全く実行されません。 単体のプロジェクトとしては、エラーもなく、手動では問題なく実行できます。 ためしに、別のサンプルコード(特定のセルに1分毎に現在時刻を表示させる)を使ってみたところ、こちらは問題なく自動実行してくれます。 自動実行を有効にするためには何らかの条件が必要なのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
noname#247307
noname#247307
回答No.3

>しかし、そこで新たに疑問に思うのは、最初のコードでトリガーを設定せずに端末からの手動実行した場合に、処理結果に変化がない(数値等の変化がない)にも関わらず、何故アクティブセルが移動するような挙動が端末に表示されるのかということです。 このへんは情報がないので、私も推測するしかないんですが……。おそらくシートを開いてスクリプトを実行させる場合、「シートの画面(ブラウザ内)」「サーバー内のデータ」「スクリプト(の実行エンジン)」の間でAjaxでやりとりがされていると思うのです。トリガーの場合、そのシートが実際に画面に表示されている必要はないわけで、そことの間のやりとりは必ずしも保証されていないのでは……という気がします。(シートを閉じていてもちゃんと動かなければトリガーとして役に立たないわけですから) 私もそのへんになるとはっきりした情報を持っていないので、これは推測として参考程度に考えて下さい。ただ、いずれにしても、トリガーを「現在開いているシートの表示を操作する」という目的で利用するのはやめたほうがいいように思えます。 設定したトリガーは、そのシートを閉じても、またブラウザを終了しても、パソコンを落としても、ずっとGoogleのサーバーで実行され続けている、ということを頭に入れておいたほうが良いです。そうした動きをするという前提で使い方を考えたほうがいいでしょう。

nighty
質問者

お礼

分かりやすく説明していただき、ありがとうございました。

その他の回答 (2)

noname#247307
noname#247307
回答No.2

スクリプトを見ました。こちらで試してみましたが、スクリプト自体はちゃんと動いています。ただ、動いていますが表示は変わりません。activateしてもそのセルが選択されないからです。 おそらく、時間主導型トリガーの働きを勘違いされているのだと思います。これは時間が来ると、(スプレッドシートがブラウザで開かているかどうかには関係なく)スクリプトを実行するものです。開いているシートを操作するものではなくて、どちらかといえ「Googleドライブに保存されているデータにアクセスして操作するもの」ととらえたほうがよいでしょう。 例えば、セルに値を表示する処理は、トリガーで問題なく動きます。トリガーにより指定のセルの値が変更され、開いているシートは内部で変更されたデータと同期をとるので変更が画面に反映されるのです。つまり、画面を操作しているのではなく、「データを変更する→開いたシートがデータと同期される→結果的に表示が変わる」ということです。 activateのようにセルを選択するといった動作は、データとして保存されているシートに命令しても無意味です(エラーにはなりません)。ですからトリガーで操作しても表示には何も反映されません。

nighty
質問者

お礼

shylock様、ありがとうございました。 先程のコードを少し変えて以下のようにしてみると、トリガーが機能して空白行を1で埋めていく結果が表示されました。 function onTmeEdit() { var mySheet=SpreadsheetApp.getActiveSheet(); mySheet.getRange("k200").activate(); var myRange=SpreadsheetApp.getActiveRange(); while(myRange.getValue()=="") { myRange.setValue(1); mySheet.setActiveRange(myRange.offset(-1,0)).activate(); var myRange=SpreadsheetApp.getActiveRange(); } } クラウドで処理しているのだから、処理結果(数値の変化等)だけが端末に表示され、処理結果に変化がなければ端末での表示にも変化はない、ということですね。勘違いしておりました。 しかし、そこで新たに疑問に思うのは、最初のコードでトリガーを設定せずに端末からの手動実行した場合に、処理結果に変化がない(数値等の変化がない)にも関わらず、何故アクティブセルが移動するような挙動が端末に表示されるのかということです。 時間主導型トリガーで自動実行する場合には、「Google Drive上でのトリガー起動」→「クラウドでの処理」→「処理結果がGoogle Driveに戻る」→「端末での同期」という経路を辿る為、処理結果に変化がなければ端末表示も変化しないということだと思いますが、端末から手動実行する場合も、「端末からの実行命令」→「クラウドでの処理」→「処理結果がGoogle Driveに戻る」→「端末での同期」という経路になるのなら、端末上でアクティブセルが勝手に移動する理屈が分かりません。少し話は違いますが、複数のPCで同じアカウントで同じスプレッドシートを開いた際、各端末でのアクティブセルがひとつの画面に色分けして表示される仕組みも理解できません。所詮私のような素人には難しすぎですね…

noname#247307
noname#247307
回答No.1

具体的に、どういうコードを実行させようとしていますか。実行されないのではなく、実行しようとしたがエラーになって動かない、という可能性はありませんか。 よくあるのは、例えばスプレッドシートに何か操作をするようなとき、ActiveSheetなどでSheetを取得し操作しようとしてエラーになっているといったものですね。 時間主導型のトリガーは、そのシートが閉じられている間も実行され続けます。ですから、シートを開いていなくても設定した関数は実行されるのです。結果、ActiveSheetが取得できずにエラーになってしまう、ということが多々あります。 エラーが出ている場合、1日経過後に、前の日に発生したエラー情報がどさっとメールで届くので気がつくはずです。 これ以上は、トリガーで呼び出される関数を見ないとなんともいえません……。

nighty
質問者

補足

すいません。 1分毎に自動実行させたいプロジェクトは、セルk200から、そのセルが空白行である限り1行ずつ上に上げていく以下のようなコードです。特にシートを閉じたりしていないので問題ないと思うのですが… function onTmeEdit() { var mySheet=SpreadsheetApp.getActiveSheet(); mySheet.getRange("k200").activate(); var myRange=SpreadsheetApp.getActiveRange(); while(myRange.getValue()=="") { mySheet.setActiveRange(myRange.offset(-1,0)).activate(); var myRange=SpreadsheetApp.getActiveRange(); } }

関連するQ&A