GASが「最大実行時間を超えました」で止まるときの直し方

記事
IT・テクノロジー
行が増えてきたら、GAS(Google Apps Script)が途中で止まり「Exceeded maximum execution time(最大実行時間を超えました)」と出るようになった。よくある相談です。GAS は 1 回の実行に時間の上限(無料の Google アカウントでは 6 分)があり、それを超えると途中で止まります。直し方を、効きやすい順にまとめます。

■ 1. セルの読み書きを「まとめて」にする(いちばん効きます)
1 行ずつ getValue / setValue を呼ぶと、そのたびに通信が起きて遅くなります。

遅い書き方:
for (let i = 2; i <= last; i++) {
  const v = sheet.getRange(i, 1).getValue();
  sheet.getRange(i, 2).setValue(v * 2);
}

速い書き方:
const values = sheet.getRange(2, 1, last - 1, 1).getValues();
const out = values.map(function (r) { return [r[0] * 2]; });
sheet.getRange(2, 2, out.length, 1).setValues(out);

読むのも書くのも 1 回ずつにするだけで、数千行でも数秒で終わることが多いです。

■ 2. ループの中で重い処理をしない
・SpreadsheetApp.flush() や Utilities.sleep() をループの中で毎回呼んでいないか
・メール送信やカレンダー登録など、外のサービスを 1 件ずつ呼んでいないか(件数が多いと時間も回数の上限も使います)
・同じシートを何度も getSheetByName していないか(最初に 1 回だけ取る)

■ 3. それでも終わらないときは「分けて」動かす
処理済みの行の番号を保存しておき、時間が来たら一度止めて、次の回で続きから始めます。

function run() {
  const props = PropertiesService.getScriptProperties();
  const start = Number(props.getProperty('next') || 2);
  const began = Date.now();
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('データ');
  const last = sheet.getLastRow();
  let row = start;
  for (; row <= last; row++) {
    if (Date.now() - began > 4.5 * 60 * 1000) break; // 4分半で区切る
    // ここに 1 行ぶんの処理
  }
  props.setProperty('next', String(row > last ? 2 : row));
}

これを時間主導型のトリガーで 5〜10 分ごとに動かすと、少しずつ最後まで進みます。トリガーの設定はこちらにまとめています。
・GASを毎朝決まった時間に自動で動かす方法:https://coconala.com/blogs/6357864/829488

■ どこが遅いかを見つけるには
Apps Script の画面の左の「実行数」から、止まった実行のログを開けます。処理の前後に console.log で時刻を出しておくと、どこで時間を使っているかがわかります。

自分で直すのが難しいとき、止まったスクリプトを見てほしいときは、こちらでお受けしています。
・GAS・Python・VBAのエラーを直します:https://coconala.com/services/4455210
・スプレッドシートの面倒な作業をGASで自動化します:https://coconala.com/services/4455227

※この記事は AI(Claude)の助けを借りて書いています。
サービス数100万件のスキルマーケット、あなたにぴったりのサービスを探す