LANG SELRCT

コードを書く場所についてはこちら

2016年6月26日日曜日

スクリプトの処理を途中で止めて、再実行時に続きから実行できるようにする

Google Apps Scriptを書き始めた頃、何もわからずにいろいろなコードを書いていて、ある日かなり時間のかかるコードを実行したところ、処理が最後まで実行できないということが起こりました。
原因を見ると「起動時間の最大値を超えました」というエラーが出ていました。
こんな表示です↓


調べてみると起動時間の最大値は5分(現在は6分)らしいということを知りました。
https://developers.google.com/apps-script/guides/services/quotas

時間内に終わるようにスクリプトを書き直せればそれで良いのですが、時間内に終わらない場合は諦めるか、どうにか制限を越える方法を見つけるか。

そこで「制限を越える方法」について、制限時間を越える前に一度処理を止めて再実行するという方法を試してみました。

設定した時間が経過する前に処理を止めて時間制限を回避して、トリガーで再実行した時に前回実行した続きから処理を再開すようにするということをやってみます。

使用するデータとコードは前回書いたものを再利用します。
スクリプトの実行時間を取得してシートに書き出す


ポイント

1. スクリプトが実行されてからの経過時間を取得します。
var start = new Date();
〜実行する処理がここにあります〜
var end = new Date();
var time_past = (end - start) / 1000;

2. スクリプト実行から特定の時間(秒)が経過したらfor文から抜けて処理を止めます。
6分の場合は360秒ですが、今回の例ではデータが少ないので実行後すぐ止まることを確認できるよう2秒に設定しています。
if (time_past > 2) {
    break;
}

3. トリガーの実行タイミングを設定します。
今回は1分後に設定します。(1分毎に処理が実行される)

4. 再度実行された時に前回の続きから実行できるようする。
今回の例では、B列にデータを入れていく処理なので、「B列でデータが入っている最終行」の行数を取得して、再実行の際にはその次の行から実行されるようにします。


コード.gs
function setFormula_getValue_time_past() {
    var site = 'https://www.google.co.jp/#q=';
    var ss = SpreadsheetApp.getActive();
    var sh = ss.getActiveSheet();
    var row = 1;
    var col = 1;
    var len = sh.getRange("A:A").getValues().filter(String).length;
    var row = sh.getRange("B:B").getValues().filter(String).length;
    var start = new Date();

    for (var i = row + 1; i < len + 1; i++) {
        var text = sh.getRange(i, col).getValue();
        var hyperlink = '=Hyperlink("' + site + text + '","' + text + '")';
        var end = new Date();
        var time_past = (end - start) / 1000;
        if (time_past > 2) {
            break;
        } else {
            sh.getRange(i, col + 1).setFormula(hyperlink);
            sh.getRange(i, col + 2).setValue(time_past);
            row++;
        }
    }
}


コードを実行してみる
1. コード.gsにコードを書いて保存します。

2. 編集メニューから「現在のプロジェクトのトリガー」を選択します。


3. 時間主導型の特定の日時で、分タイマーを選択します。

4. そのまま1分ごとを選択してトリガーを保存します。

5. スプレッドシートに戻って1分待ちます。
すると、スクリプトが自動で実行されて、2秒経過する手前で処理が止まります。

その後も1分毎に処理が実行され、最後の行まで処理が実行されます。

これと同じ要領で、今回2秒に設定した数値を360秒(6分)に設定し、トリガーの分タイマーも今回の1分から5分へ変更すると、時間制限にぶつかることなく最後まで処理を実行することができるようになります。