GAS業務自動化 |

GASの実行時間制限(6分)を回避する5つのテクニック

GASの実行時間制限を回避する方法

GASで大量データを処理しようとしたら、途中で強制終了してしまった——そんな経験をしたことがある方に向けて、この記事では6分制限(無料版)の仕組みと、実際に使える回避テクニックを5つ紹介します。PropertiesServiceを使った進捗保存から、トリガーによる自動再開まで、コードコピーで即使える形で解説します。

GASの実行時間制限とは——6分・30分の仕組み

GASには、1回のスクリプト実行に対して最大実行時間の上限が設けられています。無料のGoogleアカウントでは最大6分、Google Workspace(有料プラン)では最大30分です。この制限を超えると、処理の途中でも強制終了され Exceeded maximum execution time エラーが発生します。

この制限が問題になるのは、主に以下のような処理です。スプレッドシートの全行を1件ずつ処理するループ、大量のメールを順番に送信する処理、外部APIを何百回も呼び出す処理、複数シートを横断してデータを集計する処理——いずれも行数や件数が増えるにつれて実行時間が長くなります。

アカウント種別 最大実行時間 1日のトリガー実行時間
無料Googleアカウント 6分/回 90分/日
Google Workspace(旧G Suite) 30分/回 6時間/日

Workspaceに切り替えると制限が大幅に緩和されますが、それでも30分を超える処理には対策が必要です。以下の5つのテクニックを使えば、どちらのプランでも長時間処理を確実に完走させられます。

無料ダウンロード

業務自動化でできること100選

経理・人事・営業・CS・総務・ITの6部門100事例を収録。各事例に月間削減時間と導入難易度を明記。今日から始められるチェックリスト付き。

無料ダウンロード

テクニック1: 実行時間を監視して処理を安全に中断する

最も基本的な対策は、スクリプト内で現在の実行時間を測定し、制限に近づいたら自分で処理を中断することです。new Date() で開始時刻を記録し、ループの各周で経過時間をチェックします。

function processLargeData() {
  const startTime = new Date();
  const TIME_LIMIT_MS = 5 * 60 * 1000; // 5分(6分制限の1分前に終了)

  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('データ');
  const data = sheet.getDataRange().getValues();

  for (let i = 1; i < data.length; i++) {
    const elapsed = new Date() - startTime;
    if (elapsed >= TIME_LIMIT_MS) {
      Logger.log(`時間制限に近づいたため ${i} 行目で中断しました`);
      break; // 安全に中断
    }

    // ここで実際の処理
    processRow(data[i]);
  }
}

この方法だけでは「中断した続き」を次回実行する仕組みがないため、テクニック2と組み合わせることが必須です。

テクニック2: PropertiesServiceで進捗を保存・再開する

GASの PropertiesService を使うと、スクリプトの実行をまたいで値を保存できます。「次に処理すべき行番号」をPropertiesServiceに保存しておけば、次回実行時にその番号から再開できます。

function processWithResume() {
  const startTime = new Date();
  const TIME_LIMIT_MS = 5 * 60 * 1000;
  const props = PropertiesService.getScriptProperties();

  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('データ');
  const data = sheet.getDataRange().getValues();

  // 前回の続き行を取得(なければ1行目から)
  let startRow = parseInt(props.getProperty('lastProcessedRow') || '1');

  for (let i = startRow; i < data.length; i++) {
    const elapsed = new Date() - startTime;
    if (elapsed >= TIME_LIMIT_MS) {
      // 続きの行番号を保存して中断
      props.setProperty('lastProcessedRow', String(i));
      Logger.log(`${i} 行目で一時中断。次回はここから再開します。`);
      return;
    }

    processRow(data[i]);
  }

  // 全件処理完了したらリセット
  props.deleteProperty('lastProcessedRow');
  Logger.log('全件処理完了');
}

テクニック3: 時間トリガーで自動的に続きから再実行する

テクニック2と組み合わせると最も強力なのが、処理を中断する際に「数分後に自分自身を再実行するトリガー」をGASのコード内から動的に設定する方法です。これにより、担当者が手動でボタンを押し続けなくても、GASが自動的に続きから処理を再開します。

function processWithAutoResume() {
  const startTime = new Date();
  const TIME_LIMIT_MS = 5 * 60 * 1000;
  const props = PropertiesService.getScriptProperties();

  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('データ');
  const data = sheet.getDataRange().getValues();
  let startRow = parseInt(props.getProperty('lastProcessedRow') || '1');

  for (let i = startRow; i < data.length; i++) {
    if (new Date() - startTime >= TIME_LIMIT_MS) {
      props.setProperty('lastProcessedRow', String(i));

      // 2分後に自分自身を再実行するトリガーをセット
      ScriptApp.newTrigger('processWithAutoResume')
        .timeBased()
        .after(2 * 60 * 1000)
        .create();

      Logger.log(`${i} 行目で中断。2分後に自動再開します。`);
      return;
    }

    processRow(data[i]);
  }

  props.deleteProperty('lastProcessedRow');
  Logger.log('全件処理完了');
}

注意: 古いトリガーの削除を忘れずに

動的にトリガーを作成し続けると、不要なトリガーが蓄積してGASのトリガー上限(20個)に達する場合があります。処理完了時に ScriptApp.getProjectTriggers() でトリガー一覧を取得し、不要なものを削除する処理も必ず追加してください。

テクニック4・5: バッチ分割と並列処理の活用

テクニック4: データをバッチに分割して処理する

1回の実行で処理する件数をあらかじめ制限する方法も有効です。たとえば「1回の実行では最大100件だけ処理する」という設計にすれば、実行時間が予測しやすくなります。トリガーで毎時実行する場合、100件/回なら1日2,400件処理できます。

const BATCH_SIZE = 100; // 1回の実行で処理する件数

function processBatch() {
  const props = PropertiesService.getScriptProperties();
  const startRow = parseInt(props.getProperty('lastProcessedRow') || '1');

  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('データ');
  const data = sheet.getDataRange().getValues();
  const endRow = Math.min(startRow + BATCH_SIZE, data.length);

  for (let i = startRow; i < endRow; i++) {
    processRow(data[i]);
  }

  if (endRow >= data.length) {
    props.deleteProperty('lastProcessedRow');
    Logger.log('全件完了');
  } else {
    props.setProperty('lastProcessedRow', String(endRow));
    Logger.log(`${endRow} 行目まで完了。次回は ${endRow} 行目から。`);
  }
}

テクニック5: getValues/setValuesでAPIコール数を削減する

実行時間が長くなる原因のひとつに「セルへの個別アクセス」があります。sheet.getRange('A1').getValue() をループ内で何千回も呼ぶと、その度にGoogleサーバーへのAPIコールが発生して処理が遅くなります。

解決策は、処理前に getDataRange().getValues() で全データを一括取得して配列に持ち、処理後に setValues() で一括書き込みすることです。この1つの改善だけで、処理時間が数分から数秒に短縮されるケースも珍しくありません。GASで大量データを扱う際の基本中の基本です。

QGoogle Workspaceにすれば6分制限は完全になくなりますか?

Aなくなるわけではなく、上限が30分に延びます。30分を超える処理には、この記事で紹介したテクニックを適用する必要があります。また、1日あたりの総実行時間の上限もあるため、大量のデータを処理する場合はトリガーの設計も合わせて考慮してください。

QPropertiesServiceに保存できるデータ量に上限はありますか?

APropertiesServiceには1プロパティあたり最大9KB、スクリプト全体では500KBという上限があります。行番号や簡単な状態フラグを保存する用途では問題になりませんが、大量のデータそのものをPropertiesServiceに保存しようとすると上限に引っかかります。大量データはスプレッドシートに保存してください。

Q実行時間制限のエラーが出ても、途中まで処理した結果は保存されていますか?

AGASが強制終了されるまでに実行が完了した処理は保存されます。ただし、途中で書き込み処理が実行されていた場合、中途半端な状態で保存されることがあります。重要なデータを扱う場合は、処理の開始前にバックアップを取るか、1件処理するごとに保存する設計にすることをお勧めします。

まとめ

この記事のポイント

  • GASの実行時間制限は無料版6分・Google Workspace版30分。超えると強制終了される
  • テクニック1: 実行時間を監視して5分前後で安全に中断する
  • テクニック2: PropertiesServiceで「どこまで処理したか」を保存し、次回再開する
  • テクニック3: 中断時に動的トリガーを設定して2分後に自動再開する(テクニック2と組み合わせ最強)
  • テクニック4: バッチサイズを固定して1回の処理件数を制限する
  • テクニック5: getValues/setValuesで一括処理してAPIコールを減らし速度を大幅改善する

実行時間の壁を乗り越えたら、次は外部APIとの連携で処理の幅をさらに広げることができます。GASと外部APIを組み合わせた高度な自動化の設計と実装方法も、あわせて参考にしてください。

吉元大輝

よしもとひろき

株式会社BoostX 代表取締役社長

中小企業の生成AI導入を支援する「生成AI伴走顧問」サービスを提供。業務可視化から定着支援まで、一気通貫で企業のAI活用を推進している。

※本記事の情報は2026年4月時点のものです。

SNSで共有する
無料個別相談

貴社の業務に、 AIという確かな選択肢を。

「何から始めればいいか分からない」という段階でも構いません。現状の課題を伺い、最適な導入計画をプロと一緒に整理します。

\ 専門家による30分のヒアリング /

無料相談を予約する

オンライン対応可能・強引な勧誘なし

まずは資料で情報収集したい方へ

サービス概要・料金・導入事例をまとめた資料を無料でお送りします。

資料をダウンロード