質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

タイムアウト

タイムアウトはイベント発生から完了までに掛かる経過時間に対する一定の待ち時間を指します。また、特定の時間が経過された場合に発生するイベントを指すこともあります。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

3回答

6784閲覧

GoogleAppsScriptのタイムアウト回避処理について

TakanoriOki

総合スコア16

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

タイムアウト

タイムアウトはイベント発生から完了までに掛かる経過時間に対する一定の待ち時間を指します。また、特定の時間が経過された場合に発生するイベントを指すこともあります。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

2クリップ

投稿2016/03/31 03:19

Google App Scriptのタイムアウトを回避する処理を実装したいのですが、処理経過の保存やトリガーの設置・削除の仕方がいまいちわかりません。どのようにすればよいのでしょうか?
moment.jsを使用して実装しようと考えています。

javascript

1function deleteRows() { 2 var ss = SpreadsheetApp.getActiveSpreadsheet(); 3 var objSheet = ss.getSheetByName("シート1"); 4 ss.setActiveSheet(objSheet); 5 var end = ss.getLastRow(); 6 var start = Moment.moment(); 7 TiggerUtil.deleteTrigger(); 8 9 Browser.msgBox("E列の最終行 - " + end + "までの空白行を削除します。"); 10 11 //E列の空白行を削除(下から) 12 for (var counta = end; counta > 0; --counta) { 13 cell = ss.getRange("E" + counta) 14 data = cell.getValue(); 15 16 if (data == "") { 17 ss.deleteRow(counta); 18 } 19 20 var now = Moment.moment(); 21 if (now.diff(start, "minutes") >= 5) { 22 23 var triggerId = ScriptApp.newTrigger("deleteRows5").timeBased().at(Moment.moment().add("minutes", 1).toDate()).create().getUniqueId(); 24 25 ScriptProperties.setProperty("triggerId", triggerId); 26 } 27 } 28}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ご質問の内容とは直接関係はないのですが、Google Apps Script の API 呼び出しは超絶遅いので、できるだけ呼び出し回数を減らした方がよいです。もしかすると、呼び出し回数を減らすことで、タイムアウト前に実行が完了するようになるかもしれません。

今回提示されているコードで言えば、「ss.getRange('E').getValues() で E 列の値全部を一度に取得」、「取得した値を下からチェックし、連続する空白行の開始行、終了行を特定して ss.deleteRows(startRow, rowCount) で削除、を繰り返す」とやるといいと思います。
シートの内容によっては、次のようにすることも可能で、それであればもっと API 呼び出しを減らせ、早く処理が終了すると思います。

javascript

1var range = ss.getDataRange(); 2var values = range.getValues(); 3/* 4 * values の中身を見て空白行があれば上に詰めていく 5 * 詰め終わったら、有効な最終行番号を lastRow に保存 6 * この間、API 呼び出しはなくて全部メモリ上での処理 7 */ 8range.setValues(values); 9ss.deleteRows(lastRow, values[length] - lastRow + 1); 10// 先に deleteRows してから setValues するのも可。ちょっと面倒だけど

投稿2016/03/31 08:03

unau

総合スコア2468

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TakanoriOki

2016/04/01 05:25

ありがとうございます。 getValues()を使うと良いのですね。 データが9000行くらいあるので時間がかかっていたので、早速やってみます。
guest

0

下記ページにあるテンプレートは便利です。
私は moment.js を使用していないので、時間周りを改造して使用しています。

【よく使うTime Triggerのテンプレ - Qiita】
http://qiita.com/soundTricker/items/fd997cdf0825c6b2a146

投稿2016/03/31 05:59

kei344

総合スコア69364

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TakanoriOki

2016/04/01 05:23

ありがとうございます。 そのテンプレート、私も見つけて利用しようとしてみたのですが、初心者なものでどうやって自分のコードに適用すればよいかわからず諦めておりました… もう少し勉強してみます。
guest

0

ベストアンサー

どうやって自分のコードに適用すればよいかわからず諦めておりました…

多分こういう感じではないかと(未テストです)。example_func_run_tasks は適当に while で実行できる形にしておけばよい感じです。

JavaScript

1var ScriptProperties = PropertiesService.getScriptProperties(); 2function loop () { 3 var start = Moment.moment(); // タイムアウトカウント用 4 var error_count = 0; 5 var current = ScriptProperties.getProperty( 'current' ) || 'First!'; // 処理中ならcurrentが入っている。入っていないなら取りあえず文字列を入れておく 6 // タスク登録解除(あれば) 7 TriggerUtil.deleteTrigger(); 8 // 初回ならタスクを取り出す 9 if ( current === 'First!' ) { 10 current = example_func_get_tasks(); // 初回データを取り出す 11 }; 12 while ( current > 0 ) { 13 14 try { // 重い処理 15 example_func_run_tasks( current ); // なんか処理。ちなみにgetActiveSpreadsheetはタイムベーストリガーでは参照できないので注意 16 } catch( e ) { 17 Logger.log( e ); 18 error_count++; 19 if ( error_count > 5) { 20 //レジューム処理 21 ScriptProperties.setProperty( current ); // 状態を保存 22 TriggerUtil.resumeTrigger( aruments.callee.name ); 23 return; // 終了してしまう 24 }; 25 }; // End try 26 27 current--; // whileをまわす 28 29 // タイムアウト処理 30 if ( TriggerUtil.isNearlyTimeOut( start ) ) { 31 //レジューム処理 32 ScriptProperties.setProperty( current ); // 状態を保存 33 TriggerUtil.resumeTrigger( aruments.callee.name ); 34 return; // 終了してしまう 35 }; 36 }; // End while 37 38 // タスク完了処理 39 40 ScriptProperties.deleteProperty( 'current' ); // 状態の初期化 41 TriggerUtil.deleteTrigger(); 42 43 // タスク完了!! 44} 45

current に配列を保存して while のたびに1個ずつ削除していく書き方もできます。配列などは直接 setProperty 出来ないので、JSONにして保存します。

JavaScript

1ScriptProperties.setProperty( 'prop_array', JSON.stringify( [ 'a', 'b' ] ) ); 2prop_array = JSON.parse( ScriptProperties.getProperty( 'prop_array' ) ) || [];

流れを示しているだけなので省略していますが、Propertyに while で使用する変数を保存しておいたりします。current の書かれている場所で同じように追加したり消したりします。

JavaScript

1 var current = ScriptProperties.getProperty( 'current' ) || 'First!'; 2 var my_prop = ScriptProperties.getProperty( 'my_prop' ) || 'My Prop';

投稿2016/04/01 14:59

kei344

総合スコア69364

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問