行が増えてきたら、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 分ごとに動かすと、少しずつ最後まで進みます。トリガーの設定はこちらにまとめています。
■ どこが遅いかを見つけるには
Apps Script の画面の左の「実行数」から、止まった実行のログを開けます。処理の前後に console.log で時刻を出しておくと、どこで時間を使っているかがわかります。
自分で直すのが難しいとき、止まったスクリプトを見てほしいときは、こちらでお受けしています。
※この記事は AI(Claude)の助けを借りて書いています。