GASでスプレッドシートの
最終行・最終列を正しく取得する方法

データの件数を数えたり末尾に追記したりするとき、まず必要になるのがgetLastRow()です。基本の使い方から、件数がずれる落とし穴と対処までコードで解説します。

|対象: GAS / スプレッドシート / 最終行取得

Table of Contents

最終行・最終列の取得でつまずく理由

GASでスプレッドシートを扱うとき、「何件データがあるか」「どこまで書き込まれているか」を知る場面がほぼ毎回あります。 ここで使うのがgetLastRow()(データがある一番下の行番号を返すメソッド)ですが、次のような理由でつまずきやすいメソッドでもあります。

行番号か範囲かが混同しやすい

getLastRowは数値を返すが、getDataRangeはRange(範囲)を返す。用途で使い分ける必要がある

消したはずの行がカウントに残る

値を入れたことがある行はクリアしても最終行として残ることがあり、件数が実データより大きく出る

途中の空行で件数がずれる

getLastRowはシート全体の最下行を返すため、特定列の実件数とは一致しないことがある

空シートで0が返る

1件もないシートでは0が返り、行数0でgetRangeを作るとエラーになる

getLastRow / getLastColumn の基本

getLastRow()はデータが入っている一番下の行番号、getLastColumn()は一番右の列番号を、どちらも数値(1始まり)で返します。まずはこの2つの基本を押さえます。

function showLastRowAndColumn() {
  const sheet = SpreadsheetApp.getActiveSheet();

  const lastRow = sheet.getLastRow();       // データがある一番下の行番号
  const lastColumn = sheet.getLastColumn(); // データがある一番右の列番号

  Logger.log("最終行: " + lastRow);   // 例: 100
  Logger.log("最終列: " + lastColumn); // 例: 5

  // 空のシートでは両方とも 0 が返る
}

返るのは行番号・列番号そのものです。例えば見出し1行+データ99行ならgetLastRow()は100を返します。データの「件数」を数えたいときは見出しの分を引いてgetLastRow() - 1とするのが基本です。

getDataRange で入力範囲を丸ごと取る

行番号ではなく「データが入っている範囲そのもの」がほしいときはgetDataRange()が便利です。A1からデータの右下までを自動で囲んだRange(範囲オブジェクト)を返すので、getValues()と組み合わせれば全データを二次元配列で一括取得できます。

function readAllData() {
  const sheet = SpreadsheetApp.getActiveSheet();

  // A1 からデータの右下までを囲んだ範囲を丸ごと取得
  const range = sheet.getDataRange();
  const values = range.getValues(); // 二次元配列 [[...], [...], ...]

  const header = values[0];   // 1行目(見出し)
  const rows = values.slice(1); // 2行目以降のデータ

  Logger.log("見出し: " + header.join(", "));
  Logger.log("データ件数: " + rows.length + "件");
}

行数と列数を自分で計算しなくて済むのが利点です。全件をまとめて読み込み、配列にしてから処理すると、1セルずつ読むよりも大幅に速くなります。

シート基準と範囲基準の getLastRow の違い

getLastRow()は、呼び出す相手がSheetかRangeかで意味が変わります。Sheetに対して呼ぶとシート全体の最終行を返しますが、getRange()で切り出したRangeに対して呼ぶと、その範囲の中での最終行(範囲の最下行)を返します。

function sheetVsRangeLastRow() {
  const sheet = SpreadsheetApp.getActiveSheet();

  // シート基準: シート全体でデータがある最終行(例: 100)
  const sheetLastRow = sheet.getLastRow();

  // 範囲基準: 指定した範囲の中での最終行
  // getRange(行, 列, 行数, 列数) の 4 引数で B2:C10 を指定
  const block = sheet.getRange(2, 2, 9, 2); // B2 から 9行 x 2列
  const rangeLastRow = block.getLastRow();  // この範囲の最下行 = 10

  Logger.log("シートの最終行: " + sheetLastRow);
  Logger.log("範囲の最終行: " + rangeLastRow);
}

ここで使っているgetRange(行, 列, 行数, 列数)の4引数は、開始セルと大きさを指定して範囲を作る書き方です。「A1記法の直書き」と違い、行番号を計算で組み立てられるのでコードから範囲を扱うときの基本になります。

空行があると件数がずれる落とし穴

getLastRow()が返すのは「シート全体で値がある最下行」です。そのため、A列の途中に空セルがあっても、別の列に値があればそこまでを最終行に含めます。 特定の列だけを基準に正確な件数を数えたいときは、その列の値を取得して空文字を除外します。

function countRowsByColumn(colIndex) {
  const sheet = SpreadsheetApp.getActiveSheet();
  const lastRow = sheet.getLastRow();
  if (lastRow < 2) return 0; // 見出しだけ、または空シート

  // 見出しを除いた対象列の値を一括取得(1列だけ)
  const values = sheet
    .getRange(2, colIndex, lastRow - 1, 1)
    .getValues();

  // 空文字を除いた実データの件数を数える
  const count = values.filter((r) => String(r[0]).trim() !== "").length;

  Logger.log(colIndex + "列目の実データ: " + count + "件");
  return count;
}

値を消したのにgetLastRow()が大きい数を返す場合も同じ考え方で対処できます。範囲を取得して末尾の空行をfilterで落とすと、見た目どおりの件数になります。

最終行の次に追記する定番パターン

ログの追記やフォーム結果の蓄積では、「最終行の1つ下」に書き込むのが定番です。getLastRow() + 1が次の空行の行番号になります。単純な末尾追記ならappendRow()がさらに簡単です。

function appendRowSafely(row) {
  const sheet = SpreadsheetApp.getActiveSheet();

  // 方法1: 最終行の次に自分で書き込む
  const nextRow = sheet.getLastRow() + 1;
  sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);

  // 方法2: appendRow は内部で最終行を計算して末尾に追記する
  // sheet.appendRow(row);
}

function demo() {
  appendRowSafely(["2026-07-23", "田中", "問い合わせ"]);
}

appendRow()は内部で最終行を計算して末尾に1行足すため、追記だけならこちらが手軽です。複数行をまとめて書く場合や、書き込む位置を細かく制御したい場合はgetRange().setValues()を使います。

実務での注意点

1. 件数0のときの分岐を必ず入れる

空シートではgetLastRow()が0を返します。この0を使ってgetRange(2, 1, lastRow - 1, ...)のように行数がマイナスや0の範囲を作るとエラーになります。if (lastRow < 2) return;のような早期returnを入れておきましょう。

2. ループ内で毎回呼ばない

getLastRow()はスプレッドシートへのアクセスを伴うため、ループの条件式で毎回呼ぶと遅くなります。ループの前に一度だけ取得して変数に入れておくのが基本です。

3. 追記の競合にはロックを検討する

フォーム送信やWebアプリで複数の処理が同時に最終行へ書き込むと、同じ行を奪い合って上書きが起きることがあります。同時実行が想定される場面ではLockServiceでの排他制御を検討してください。

まとめ

最終行・最終列の取得は、行番号がほしいならgetLastRow()/getLastColumn()、範囲を丸ごと扱いたいならgetDataRange()と、目的で使い分けるのが基本です。空行での件数ずれや空シートの0を意識し、追記や集計を安定して自動化しましょう。

よくある質問

getLastRow()はデータが入っている一番下の行番号(数値)を返します。getDataRange()はA1からデータの右下までを囲んだRange(範囲オブジェクト)を返します。行数だけ知りたいときはgetLastRow()、データを一括で読み書きしたいときはgetDataRange().getValues()を使い分けます。

getLastRow()は「値が入ったことがある一番下の行」を返すため、後から中身を消しても行としてカウントが残る場合があります。空セルの見た目に反して大きい値が返るときは、対象範囲のgetValues()を取り、末尾の空行をfilterで除外してから件数を数えると安定します。

getLastRow()はシート全体の最終行を返すため、A列の途中に空セルがあっても最下部のデータまでを範囲に含めます。特定列を基準に件数を数えたいときは、その列のgetValues()を取得し、空文字を除外した長さを使うと正確です。

sheet.getLastRow() + 1 が次の空行の行番号です。getRange(sheet.getLastRow() + 1, 1, 1, row.length).setValues([row])で追記できます。単純な末尾追記ならappendRow(row)が最も簡単で、内部で最終行を自動計算してくれます。

1件もデータがないシートでは、getLastRow()もgetLastColumn()も0を返します。この0を判定せずにgetRange(1, 1, 0, ...)のように行数0で範囲を作ろうとするとエラーになるため、件数が0のときは早期returnする分岐を入れておくと安全です。

GAS開発・業務Webシステムを
相談する。

最終行の取得や自動追記だけでなく、フォーム連携・帳票出力・Gmail自動化など、日々の業務を自動化するGAS開発をご相談いただけます。

GAS Webシステム開発を見る