Excel VBAで「データが何行目まで入っているか」を取得するには、次の1行が定番です。
MaxRow = Cells(Rows.Count, 1).End(xlUp).RowA列の一番下から上に向かって探し、最初に値が見つかった行の番号をMaxRowに入れます。最終列なら、次の1行です。
MaxCol = Cells(1, Columns.Count).End(xlToLeft).Columnこの記事では、この2つの仕組みに加えて、別シートで使う方法、次の空いている行の取得、シート全体の最終行の取得、よくある失敗までまとめます。
実際の業務においても、レポートの最終行や最終列を取得して、その値に応じた処理をするという場面は非常に多いですし、この処理を間違えると、大きなミスにつながってしまいます。
値が入っている最終行を取得する(End(xlUp))
Sub 最終行の取得()
Dim MaxRow As Long
MaxRow = Cells(Rows.Count, 1).End(xlUp).Row
MsgBox MaxRow
End SubA列で最後に値が入っている行の番号を、メッセージボックスに表示します。

Excel VBA A1〜A10にデータがあり、「10」と表示された画面。alt:Excel VBAでA列の最終行「10」を取得した結果
仕組みは次のとおりです。
| 書き方 | 意味 |
|---|---|
| Rows.Count | シートの行数(Excel 2007以降は1,048,576) |
| Cells(Rows.Count, 1) | A列の一番下のセル(A1048576) |
| .End(xlUp) | そこから上に向かって、値のあるセルまで移動。Ctrl + ↑キーと同じ動き |
| .Row | 移動したセルの行番号 |
B列で調べたいときは、Cells(Rows.Count, 2) のように2つめの数字を列番号に変えます。
Cells(Rows.Count, “B”) のように列の英字でも指定できます。
変数をIntegerではなくLongで宣言しているのは、Integerは32,767までしか扱えず、それより下の行までデータがあるとエラーになるためです。
値が入っている最終列を取得する(End(xlToLeft))
Sub 最終列の取得()
Dim MaxCol As Long
MaxCol = Cells(1, Columns.Count).End(xlToLeft).Column
MsgBox MaxCol
End Sub1行目で最後に値が入っている列の番号を表示します。結果は数字で、A列なら1、E列なら5です。

Excel VBA 1行目で最後に値が入っている列の番号を表示。結果はE列なので「5」
| 書き方 | 意味 |
|---|---|
| Columns.Count | シートの列数(Excel 2007以降は16,384、最後は XFD列) |
| Cells(1, Columns.Count) | 1行目の一番右のセル |
| .End(xlToLeft) | そこから左に向かって、値のあるセルまで移動。Ctrl + ←キーと同じ動き |
| .Column | 移動したセルの列番号 |
列番号ではなく「E」のような列の英字がほしいときは、次のように書けます。
Sub 最終列の英字を取得()
Dim MaxCol As Long
Dim ColName As String
MaxCol = Cells(1, Columns.Count).End(xlToLeft).Column
ColName = Split(Cells(1, MaxCol).Address(True, False), "$")(0)
MsgBox ColName
End Sub
Excel VBA 1行目で最後に値が入っている列の英字を表示。結果はE列なので「E」
別のシートの最終行を取得する
上のコードは、今開いているシートが対象です。別のシートを調べるときは、シートを変数に入れて、CellsとRowsの両方に付けます。
Sub 別シートの最終行を取得()
Dim ws As Worksheet
Dim MaxRow As Long
Set ws = ThisWorkbook.Worksheets("データ")
MaxRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
MsgBox MaxRow
End Sub「ws.」をCellsにだけ付けてRowsに付け忘れると、表示中のシートの行数を参照してしまいますので、両方に付けておくのが安全です。

Excel VBA 別のシートの最終行を取得する
最終行の下(次の空いている行)にデータを追加する
データを追記していくマクロでは、最終行に1を足した行が「次に書き込む行」になります。
Sub 次の行に追加()
Dim ws As Worksheet
Dim NextRow As Long
Set ws = ThisWorkbook.Worksheets("データ")
NextRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row + 1
ws.Cells(NextRow, 1).Value = Date
ws.Cells(NextRow, 2).Value = "新しいデータ"
End Sub下記の例では、データ追加前の最終行は8行目のため、9行目に新しいデータが追加されています。
にデータを追加する.png)
最終行の下(次の空いている行)にデータを追加する
シート全体の最終行・最終列を取得する(Find)
End(xlUp)は「指定した1列」の最終行です。列ごとにデータの長さが違う表で、どの列も含めて一番下の行を知りたいときは、Findを使います。
Sub シート全体の最終行を取得()
Dim ws As Worksheet
Dim LastCell As Range
Set ws = ThisWorkbook.Worksheets("データ")
Set LastCell = ws.Cells.Find(What:="*", LookIn:=xlFormulas, _
SearchOrder:=xlByRows, SearchDirection:=xlPrevious)
If LastCell Is Nothing Then
MsgBox "データがありません"
Else
MsgBox LastCell.Row
End If
End Sub
Excel VBA シート全体の最終行を取得
「*」(何か入っているセル)を、シートの最後から逆向き(xlPrevious)に行ごと(xlByRows)探しています。最終列を知りたいときは、SearchOrder:=xlByColumns にして LastCell.Column を使います。
シートが空だと何も見つからずNothingになるので、If文で確かめています。Findの使い方は、こちらの記事で詳しく解説しています。

その他の方法と使い分け
| 方法 | 対象 | 向いている場面 | 注意点 |
|---|---|---|---|
| End(xlUp) | 指定した1列 | いつも値が入る列(日付やIDなど)がある表 | その列の最後が空欄だと短くなる |
| Find(“*”, xlPrevious) | シート全体 | 列ごとに長さが違う表 | 空のシートではNothingになる |
| UsedRange | 使われたことのある範囲 | おおよその範囲を知りたいとき | 罫線や色だけのセル、削除したデータの距が含まれることがある |
| CurrentRegion | 指定したセルを含むひとかたまりの表 | 空白行のない表を丸ごと扱うとき | 途中に空白行・空白列があるとそこで切れる |
UsedRangeとCurrentRegionで最終行を取得する場合は、次のように書きます。
Sub UsedRangeとCurrentRegionで最終行を取得()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("データ")
With ws.UsedRange
MsgBox "UsedRangeの最終行:" & .Row + .Rows.Count - 1
End With
With ws.Range("A1").CurrentRegion
MsgBox "CurrentRegionの最終行:" & .Row + .Rows.Count - 1
End With
End SubUsedRange.Rows.Count だけだと「行数」になり、データが1行目から始まっていないと最終行とずれます。そのため、開始行(.Row)を足しています。
迷ったら、まずはEnd(xlUp)、列ごとに長さが違う表ならFind、と覚えておけば十分です。
よくある失敗
① データがないのに「1」が返る
End(xlUp)は、列が空だと1行目で止まるので、結果は「1」になります。
「データが1行だけある」のか「何もない」のかを区別したいときは、A1が空かどうかも確かめます。
If MaxRow = 1 And Cells(1, 1).Value = "" Then
MsgBox "データがありません"
End If② 列の途中が空欄で、最終行が短くなる
調べている列の最後の方が空欄だと、その上の行が最終行になります。
備考欄のように空欄があり得る列ではなく、日付や番号のように必ず入力される列を指定しましょう。
どの列も空欄があり得るなら、Findを使います。
③ 数式で空白に見えるセルも「値あり」になる
=IF(A2=””,””,A2*2) のように空白を返す数式が入ったセルも、End(xlUp)では「値があるセル」として扱われます。
数式を下までコピーしてある列では、見た目より下の行が最終行になります。
数式ではなく値が入っている列を指定しましょう。

④ フィルターで最後の行が隠れている
オートフィルターで最後の方の行が非表示になっていると、正しい最終行が取れないことがあります。
マクロの最初でフィルターを解除するか、結果を確かめてから使いましょう。
生成AIに最終行のコードを頼むときのコツ
ChatGPTなどの生成AIに「最終行を取得するコードを書いて」と頼むと、たいていEnd(xlUp)のコードが返ってきます。
ただし、どの列を基準にするかはAIには分からないので、次のように表の形を伝えると、そのまま使えるコードになりやすくなります。
- シート名(例:「データ」シート)
- 見出しが何行目にあるか
- 必ず値が入る列はどこか(例:A列の日付)
- 空欄や数式、フィルターがあるか
AIが書いたコードも、この記事の「よくある失敗」に当てはまらないか確かめてから使うと安心です。
まとめ
- 値が入っている最終行は Cells(Rows.Count, 列番号).End(xlUp).Row
- 最終列は Cells(行番号, Columns.Count).End(xlToLeft).Column
- 別シートでは、CellsとRowsの両方にシートを付ける
- 次の空いている行は、最終行+1
- 列ごとに長さが違う表では、Findでシート全体の最終行を取る


