2026年7月16日木曜日

GASで範囲(Range)を一括操作する方法|getValues・setValues入門

「遅いGAS」はRange一括操作でほぼ解決できる

GASでスプレッドシートを操作し始めると、 最初は問題なく動いていた処理が、データ量の増加とともに急激に遅くなることがあります。

その原因の多くは、「1セルずつ操作している」ことです。
GAS011で学んだ getValue / setValue は理解しやすい反面、 行数が増えるとすぐに限界が見えてきます。

この記事では、GAS高速化の第一歩となる Range(範囲)の一括操作について解説します。
getValues・setValues を正しく使えるようになると、 GASの処理時間は体感で数十倍改善することも珍しくありません。

目次

なぜ1セル操作は遅くなるのか

GASで1回 getValue / setValue を実行するたびに、 内部では「GAS ⇔ スプレッドシート間の通信」が発生しています。

  • GASからリクエスト送信
  • スプレッドシート側で処理
  • 結果をGASに返却

この通信をループ内で何百回・何千回も行うと、 それだけで処理時間が大きく伸びてしまいます。

Range一括操作では、この通信を最小限の回数に抑えられるため、 大幅な高速化が可能になります。

Range一括操作の基本概念

Range一括操作とは、 複数セルをまとめて配列として扱う考え方です。

複数セルを取得すると、GASでは 2次元配列として値が返ってきます。


const values = sheet.getRange(1, 1, 3, 2).getValues();

上記コードの戻り値は、次のような構造になります。


[
  [A1, B1],
  [A2, B2],
  [A3, B3]
]

「行 → 列」の順で並んでいる点が重要です。

getValuesでまとめて取得する

getValuesを使えば、複数セルを一度に取得できます。


const range = sheet.getRange(1, 1, 100, 3);
const values = range.getValues();

取得後は、JavaScriptの配列として自由に加工できます。


values.forEach(row => {
  const status = row[0]; // A列
  const amount = row[1]; // B列
});

列番号は 0始まり になる点に注意してください。

setValuesでまとめて書き込む

setValuesは、getValuesと必ずセットで使うメソッドです。


sheet.getRange(1, 1, values.length, values[0].length)
     .setValues(values);

setValuesに渡す配列は、 Rangeと完全に同じ行数・列数である必要があります。

1セルでもズレるとエラーになるため、 配列サイズの管理は非常に重要です。

配列構造の理解(2次元配列)

Range一括操作でつまずきやすいポイントが、 2次元配列の扱いです。

アクセス方法は次の形になります。


values[行インデックス][列インデックス]

たとえば、2行目B列の値は次のように取得します。


const value = values[1][1];

よくある失敗と注意点

  • setValuesの配列サイズが合っていない
  • 1次元配列を渡してしまう
  • 空配列をsetValuesしてしまう

特に、0行の配列は setValues できません。
実務では、必ず行数チェックを行います。


if (values.length === 0) {
  return;
}

PropertiesService+try-catchで安全に一括操作する

Range一括操作は高速ですが、 設定ミスがあると大量のセルを一気に壊すリスクもあります。

そのため実務では、次の2点を必ず組み合わせます。

  • PropertiesServiceによる設定値管理
  • try-catchによる例外処理

設定値を取得する


function getSheetSettings() {
  const props = PropertiesService.getScriptProperties();
  const spreadsheetId = props.getProperty('SPREADSHEET_ID');
  const sheetName = props.getProperty('SHEET_NAME');

  if (!spreadsheetId) {
    throw new Error('SPREADSHEET_ID が未設定です');
  }
  if (!sheetName) {
    throw new Error('SHEET_NAME が未設定です');
  }

  return { spreadsheetId, sheetName };
}

try-catch付き一括更新例


function updateStatusBulkSafe() {
  try {
    const { spreadsheetId, sheetName } = getSheetSettings();
    const ss = SpreadsheetApp.openById(spreadsheetId);
    const sheet = ss.getSheetByName(sheetName);

    if (!sheet) {
      throw new Error('シートが存在しません:' + sheetName);
    }

    const range = sheet.getRange(1, 1, 1000, 1);
    const values = range.getValues();

    let updated = false;
    for (let i = 0; i < values.length; i++) {
      if (values[i][0] === '') {
        values[i][0] = '完了';
        updated = true;
      }
    }

    if (updated) {
      range.setValues(values);
      Logger.log('一括更新完了');
    }
  } catch (e) {
    Logger.log('エラー発生:' + e.message);
  }
}

実務での改善パターン例

遅い例(1セルずつ)


for (let i = 1; i <= 1000; i++) {
  const cell = sheet.getRange(i, 1);
  if (cell.getValue() === '') {
    cell.setValue('完了');
  }
}

改善例(Range一括操作)


const range = sheet.getRange(1, 1, 1000, 1);
const values = range.getValues();

for (let i = 0; i < values.length; i++) {
  if (values[i][0] === '') {
    values[i][0] = '完了';
  }
}

range.setValues(values);

まとめ

この記事では、GASでRangeを一括操作する方法として、 getValues・setValuesの基本から、実務向けの安全設計までを解説しました。

Range一括操作は、GAS高速化の最重要スキルです。
次回は、シート自体を操作する方法(追加・削除・コピー)を解説します。

GAS Range 一括操作 getValues setValues 解説イメージ

0 件のコメント:

コメントを投稿