【Excel VBA】値が入っている最終行・最終列を取得する方法|MaxRowの書き方と別シート・空白の注意点

受講料の最大70%の給付金あり
経済産業省リスキリングを通じたキャリアアップ支援事業対象
サムライエンジニア「生成AI」コース

Excel VBAで「データが何行目まで入っているか」を取得するには、次の1行が定番です。

MaxRow = Cells(Rows.Count, 1).End(xlUp).Row

A列の一番下から上に向かって探し、最初に値が見つかった行の番号を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 Sub

A列で最後に値が入っている行の番号を、メッセージボックスに表示します。

Excel VBA A1〜A10にデータがあり、「10」と表示された画面。alt:Excel VBAでA列の最終行「10」を取得した結果

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 Sub

1行目で最後に値が入っている列の番号を表示します。結果は数字で、A列なら1、E列なら5です。

Excel VBA 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」

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 別のシートの最終行を取得する

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行目に新しいデータが追加されています。

最終行の下(次の空いている行)にデータを追加する

最終行の下(次の空いている行)にデータを追加する

シート全体の最終行・最終列を取得する(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 シート全体の最終行を取得

Excel VBA シート全体の最終行を取得

「*」(何か入っているセル)を、シートの最後から逆向き(xlPrevious)に行ごと(xlByRows)探しています。最終列を知りたいときは、SearchOrder:=xlByColumns にして LastCell.Column を使います。

シートが空だと何も見つからずNothingになるので、If文で確かめています。Findの使い方は、こちらの記事で詳しく解説しています。

【Excel VBA】Findで文字を検索して行番号・列番号を取得する方法|見つからないときのエラー対策も
Excel VBAで、指定した文字がある行番号や列番号を取得するには、Findメソッドを使います。結論から言うと、実務では次の形で書くのが安全です。 Sub 行番号を取得() Dim f As Range Se...

その他の方法と使い分け

方法対象向いている場面注意点
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 Sub

UsedRange.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でシート全体の最終行を取る
タイトルとURLをコピーしました