Excel VBAで行数や列数が毎回変わる表を処理するときは、最終行と最終列を自動で取得できるようにしておくと便利です。 コピー範囲、For文の終了行、グラフの参照範囲を手で直さずに済みます。
迷ったら、最終行は End(xlUp)、最終列は End(xlToLeft) を基本にします。xlDown と xlToRight は、途中に空白がない表だと分かっている場合だけ使うと安全です。
この記事は「コードだけ知りたい」方だけでなく、「自分の表ではどの書き方を使えばいいのか」で迷っている方の到達点になるように、基本コード、図解、4方向の使い分け、実務パターン、失敗例、FAQを1ページにまとめています。
【 この記事の概要 】
| よく使う度 | |
| 難しさ | |
| 覚えておくと安心度 |
VBAで最終行・最終列を取得する基本コード
まずは、次のコードだけコピーしてみてください。
このコードでは、B列の最終行と、2行目の最終列を取得することができます。
Sub GetLastRowAndColumn()
Dim ws As Worksheet
Dim lastRow As Long
Dim lastCol As Long
Set ws = ActiveSheet
lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
lastCol = ws.Cells(2, ws.Columns.Count).End(xlToLeft).Column
MsgBox "最終行: " & lastRow & vbCrLf & "最終列: " & lastCol
End Subこのコードは「B列を基準に最終行を探す」「2行目を基準に最終列を探す」という前提です。
A列を基準にしたい場合は "B" を "A" に、1行目の最終列を見たい場合は 2 を 1 に変えます。

最終行・最終列を取得できると、表の行数や列数が増えても処理範囲を自動で調整できます。
コードを読む前提: Cells(行, 列) の意味
Cells(行, 列) は「何行目・何列目のセルか」を指定する書き方です。
列は "B" のようなアルファベットでも、2 のような列番号でも指定できます。
| 書き方 | 意味 |
|---|---|
Cells(2, "B") | B列2行目のセルを指定します。 |
Cells(2, 2) | 2行目・2列目、つまりB列2行目のセルを指定します。 |
ws.Cells(...) | ws で指定したシートのセルを見ます。別シートを誤って見ないために重要です。 |
実務では、最終行を調べる列と、最終列を調べる行を先に決めるのが大事です。
たとえば売上明細なら、最終行は伝票番号や日付の列、最終列は見出し行を基準にすると安定しやすくなります。
| やりたいこと | 変える場所 | コード例 |
|---|---|---|
| A列の最終行を取得したい | "B" を "A" に変える | ws.Cells(ws.Rows.Count, "A").End(xlUp).Row |
| 2行目から最終行まで処理したい | For i = 2 To lastRow にする | For i = 2 To lastRow |
| 1行目の最終列を取得したい | 2 を 1 に変える | ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column |
| 最終列をアルファベットで使いたい | .Column 後に列名へ変換する | Split(ws.Cells(1, lastCol).Address(False, False), "1")(0) |
最終行を取得するコード1行の意味
最終行は、シートの一番下から上方向に探す End(xlUp) を使うのが基本です。

| 部分 | 意味 |
|---|---|
lastRow | 取得した最終行の行番号を入れる変数です。 |
Rows.Count | そのシートの一番下の行番号を返します。 Excel 365では通常 1,048,576 です。 |
Cells(Rows.Count, "B") | B列の一番下のセルを指定しています。 |
.End(xlUp) | 一番下のセルから上方向へ移動し、最初にデータが見つかったセルで止まります。 |
.Row | 見つかったセルの行番号を取得します。 |

Rows.Countでシートの最下行から始め、上に向かって最初に見つかったデータ行を取得します。
最終列を取得するコード1行の意味
最終列は、シートの一番右から左方向に探す End(xlToLeft) を使います。

| 部分 | 意味 |
|---|---|
lastCol | 取得した最終列の列番号を入れる変数です。D列なら 4 が入ります。 |
2 | 調べたい行です。この例では2行目を右から左に探します。 |
Columns.Count | そのシートの一番右の列番号を返します。 Excel 365では通常 16,384、列名では XFD です。 |
.End(xlToLeft) | 右端のセルから左方向へ移動し、最初にデータが見つかったセルで止まります。 |
.Column | 見つかったセルの列番号を取得します。 |

Columns.Countでシートの最右列から始め、左に向かって最初に見つかったデータ列を取得します。
xlUp・xlDown・xlToLeft・xlToRightの使い分け
Endメソッドは、Excelで Ctrl + 矢印キーを押したときのように、指定した方向へデータの端まで移動する仕組みです。方向によって、空白行や空白列への強さが変わります。
最終行・最終列を取得する4方向の使い分け
| 項目 | End(xlUp) | End(xlDown) | End(xlToLeft) | End(xlToRight) |
|---|---|---|---|---|
| 主な用途 | 最終行 | 連続データの終端行 | 最終列 | 連続データの終端列 |
| 検索方向 | 下から上 | 上から下 | 右から左 | 左から右 |
| 向いている表 | 途中に空白行がある 可能性がある表 | データが完全に連続 している表 | 右側に空白列がある 可能性がある表 | 列方向に完全に 連続している表 |
| 注意点 | データ0件は別途判定する | 途中の空白行で止まる | 右側の不要な値を拾う 場合がある | 途中の空白列で止まる |
| リンク |
最終行は xlUp、最終列は xlToLeft を先に覚えます。xlDown と xlToRight は、表が連続していると分かっている場面で使います。
「最終行」の行番号・値取得する方法
■ End(xlUp) : 下から上へ探すため、途中に空白行がある表でも使いやすい基本形です。
次のコードは、シートの最終行から上方向に検索し、最初にデータが見つかった行番号・値を取得します。

Dim lastRow As Long
Dim lastValue As Variant
'// 最終行の行番号を取得
lastRow = Cells(Rows.Count, "B").End(xlUp).Row
'// 最終行の値を取得
lastValue = Cells(lastRow, "B").Value■ End(xlDown) : 上から下へ探します。途中に空白があると止まるため、連続データ専用と考えます。
次のコードは、シートの指定したセルから下方向に検索し、最後のデータが見つかった行番号を取得します。

Dim lastRow As Long
Dim lastValue As Variant
'// 最終行の行番号を取得
lastRow = Cells(2, "B").End(xlDown).Row
'// 最終行の値を取得
lastValue = Cells(lastRow, "B").Value「最終列」の行番号・値取得する方法
■ End(xlToLeft) : 右から左へ探すため、右側に空白列がある表の最終列取得に向きます。
次のコードは、シートの最終列から左方向に検索し、最初にデータが見つかった列番号・値を取得します。

Dim lastCol As Long
Dim lastValue As Variant
'// 最終列の列番号を取得
lastCol = Cells(2, Columns.Count).End(xlToLeft).Column
'// 最終列の値を取得
lastValue = Cells(2, lastCol).Value■ End(xlToRight) : 左から右へ探します。途中に空白列があると止まるため、横方向に連続した表で使います。
次のコードは、シートの指定したセルから右方向に検索し、最後のデータが見つかった列番号とその値を取得します。

Dim lastCol As Long
Dim lastValue As Variant
'// 最終列の列番号を取得
lastCol = Cells(2, "B").End(xlToRight).Column
'// 最終列の値を取得
lastValue = Cells(2, lastCol).Value結局どのように4方向を使い分けたらいいの?
下方向のデータ量を見たいなら最終行、右方向の項目数を見たいなら最終列です。
最終行は下から上の xlUp、最終列は右から左の xlToLeft を使います。
列ごとにデータ量が違う表では、指定列だけでなくシート全体を見る必要があります。
lastRow と lastCol は、取得して終わりではなく範囲指定の材料です。
シート全体の最終行を取得するならFindも候補
End(xlUp)は「指定した列の最終行」を探す方法です。
A列、B列、C列で最終行が違う表の場合、シート全体で本当に最後に入力されたセルを知りたいなら Findメソッドを使います。
Dim foundCell As Range
Set foundCell = ws.Cells.Find( _
What:="*", _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious)
If Not foundCell Is Nothing Then
lastRow = foundCell.Row
End If普段の表処理では End(xlUp) で十分なことが多いです。
複数列にデータが散らばっていて「シート全体の最後」を見たいときだけ、Find を選ぶと考えると迷いにくくなります。
wsのようにシート名を付けて書く理由
Cells や Rows.Count を使用する際に、オブジェクト変数(ws)を使用しシート指定を付けないと、今開いているシートを見てしまうことがあります。
実務では ws.Cells、ws.Rows.Count のように対象シートを明示します。
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("売上データ")
lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
最終行最終列まで繰り返す使用例と失敗対策
最終行・最終列は、取得して終わりではありません。
コピー、ループ、集計、グラフ更新の範囲指定に使うことで、手作業を減らせます。
使用例1 : For文で最終行まで繰り返す
日次データの処理フラグや、チェック済みの印をまとめて入力したいときに使えます。
Sub MarkProcessedRows()
Dim ws As Worksheet
Dim lastRow As Long
Dim i As Long
Set ws = ActiveSheet
lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
If lastRow < 2 Then Exit Sub
For i = 2 To lastRow
ws.Cells(i, "F").Value = "処理済み"
Next i
End SubIf lastRow < 2 Then Exit Sub は、見出し行しかない場合に処理を止めるための保険です。
空データの表で不要な処理を走らせないようにします。

| 実務でやりたいこと | 使う値 | 考え方 |
|---|---|---|
| 2行目から最終行まで処理する | lastRow | For i = 2 To lastRow の形にします。 |
| 最終行の1つ下に追記する | lastRow + 1 | 既存データの下に新しい行を追加します。 |
| 範囲を最終行まで選択する | lastRow | Range("A2:F" & lastRow) のように範囲文字列へ組み込みます。 |
| 表全体をコピーする | lastRow と lastCol | Cells(1, 1) から最終セルまでを範囲にします。 |
使用例2 : 最終行の1つ下にデータを追加する例
Sub AddNextRow()
Dim ws As Worksheet
Dim lastRow As Long
Set ws = Worksheets("売上データ")
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
ws.Cells(lastRow + 1, "A").Value = Date
ws.Cells(lastRow + 1, "B").Value = "追加データ"
End SublastRow + 1 にすると、現在の最終行の次の行を指定できます。
データ追記、ログ保存、月次明細の追加でよく使います。
使用例3 : コピー範囲とグラフ範囲を最終行・最終列で広げる
明細シートの表サイズが毎月変わる場合は、最終行と最終列を両方取得してから範囲を作ると、コピー範囲を自動で広げられます。
Sub CopyToSummary()
Dim wsSrc As Worksheet
Dim wsDst As Worksheet
Dim lastRow As Long
Dim lastCol As Long
Set wsSrc = Worksheets("明細")
Set wsDst = Worksheets("集計")
lastRow = wsSrc.Cells(wsSrc.Rows.Count, "A").End(xlUp).Row
lastCol = wsSrc.Cells(1, wsSrc.Columns.Count).End(xlToLeft).Column
wsSrc.Range(wsSrc.Cells(1, 1), wsSrc.Cells(lastRow, lastCol)).Copy
wsDst.Range("A1").PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False
End SubRange(wsSrc.Cells(1, 1), wsSrc.Cells(lastRow, lastCol)) は、左上のA1セルから、取得した最終行・最終列のセルまでを範囲指定する書き方です。

よくあるミス: 基準列と空白行を見落とす
xlDown は上から下に進む途中で空白行があると、そこで止まることがあります。
途中に空白行がありそうな表では xlUp を使います。

最終行を取るときは、社員番号、伝票番号、日付など、基本的に空白にならない列を基準にします。
備考列やメモ列は空白になりやすいため、最終行の基準には向きません。
どういう列が最終行に向いているでしょうか?
| 基準列 | 向いているか | 理由 |
|---|---|---|
| 伝票番号・ID列 | 向いている | 1行に1つ必ず入ることが多く、最終行の基準にしやすいです。 |
| 備考列 | 向いていない | 空白の行が多く、実際より上の行で止まりやすいです。 |
| 金額列 | 場合による | 未入力や0円があり得る表では注意が必要です。 |
VBAの最終行・最終列取得でよくある質問とまとめ
最後に、検索でよく出る疑問をFAQで解説します。
まとめ
- 最終行は
End(xlUp)を基本にしましょう。
最終行を取得する1行の意味 をもう一度見る - 最終列は
End(xlToLeft)を基本にしましょう。
最終列を取得する1行の意味 をもう一度見る xlDownとxlToRightは、データが連続している場面に限定しましょう。
最終行・最終列を取得する4方向の使い分け をもう一度見る- 実務では
ws.Cellsのように対象シートを明示しましょう。
wsのようにシート名を付けて書く理由 をもう一度見る - 空データや基準列の選び方は、最終行取得でよくある失敗ポイントとして先に対策しましょう。
最終行まで繰り返す使用例と失敗対策 をもう一度見る



