VBAで行数を取得したいときによく使われるのがRows.Countプロパティです。
しかし、初めて使用する方の中には、
- 「Rows.Countで最終行が取得できると思っていた」
- 「1048576という数字しか返ってこない」
- 「Rows.CountとEnd(xlUp)の違いが分からない」
このような疑問を持つ方も少なくありません。
実は、Rows.Countはデータの最終行を取得するためのプロパティではありません。
Rows.Countは、ワークシートや指定した範囲が持つ行数を取得するためのプロパティです。
そのため、Rows.Count単体で使用することは少なく、実務では最終行取得や可変範囲指定などと組み合わせて利用されるケースがほとんどです。
この記事では、Rows.Countプロパティの基本的な使い方から、最終行取得との違い、実務で保守しやすいコードを書くポイントまで詳しく解説します。
✅ VBAのRows.Countプロパティとは
Rows.Countは、ワークシートや指定した範囲に存在する行数を取得するプロパティです。
例えば、ワークシート全体の行数を取得する場合は次のように記述します。
Sub GetWorksheetRowCount()
Dim targetWorksheet As Worksheet
Dim totalRowCount As Long
Set targetWorksheet = ActiveSheet
' ワークシート全体の行数を取得
totalRowCount = targetWorksheet.Rows.Count
MsgBox totalRowCount
End Sub
実行すると次の値が表示されます。
1048576
これはExcel 2007以降のワークシートが持つ総行数です。
つまりRows.Countは、
- データが入力されている行数
- 最終行番号
ではなく、
シート全体が持つ行数
を取得しています。
そのため、Rows.Countだけではデータの最終位置を判断することはできません。
Rows.CountはRowsオブジェクトの一部の機能です。Rows全体の使い方や行指定、複数行の操作まで理解したい方は、【VBA】Rowsの基本的な使い方|行指定・複数行・最終行取得まで解説も参考にしてください。
✅ Rows.Countで取得できる行数を理解しよう
Rows.Countの役割を理解するために、次のようなデータを例に考えてみます。
| 社員番号 | 氏名 |
|---|---|
| 1001 | 田中 |
| 1002 | 佐藤 |
| 1003 | 鈴木 |
データは4行目までしかありません。
それでも、
Debug.Print ActiveSheet.Rows.Count
を実行すると、
1048576
が表示されます。
これはRows.Countがデータを数えているのではなく、
Excelが持っているワークシートの仕様
を返しているためです。
つまり、
- データが10行でも
- 1000行でも
- 10万行でも
- 空のシートでも
Rows.Countの結果は変わりません。
この仕様を知らないと、
「Rows.Countを取得したら最終行になる」
と勘違いしてしまう原因になります。
Rows.Countを正しく理解するには、Rows・Range・Cells・Columnsそれぞれの役割を把握することが重要です。オブジェクトの違いや使い分けについては、【VBA】Range・Cells・Rows・Columnsの指定方法を徹底解説【基本と使い分け】で詳しく解説しています。
✅ VBAでRows.Countがよく使われる理由
ここまで読むと、
「Rows.Countだけでは役に立たないのでは?」
と思うかもしれません。
しかし、実務ではRows.Countは非常によく利用されます。
その理由は、
シートの一番下の行を取得できる
からです。
例えば、最終行を取得する代表的なコードは次のようになります。
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
このコードでは、
- Rows.Countでシートの最終行(1048576行目)を取得する
- A列の一番下のセルを指定する
- End(xlUp)で上方向へ移動する
- 最後にデータが入力されているセルへ到達する
という流れで処理しています。
つまりRows.Countそのものが重要なのではなく、
Rows.Countを最終行取得の基準として利用している
という点が重要です。
この考え方は、実務で最終行を取得するほぼすべてのコードに共通しています。
✅ Rows.Countと最終行取得を組み合わせる方法
Rows.Countは単独で使用するよりも、ほかのメソッドと組み合わせて使用する場面がほとんどです。
例えば、A列の最終行を取得するコードは次のようになります。
Sub GetLastDataRow()
Dim targetWorksheet As Worksheet
Dim lastDataRow As Long
Set targetWorksheet = ThisWorkbook.Worksheets("売上データ")
' A列の最終データ行を取得
lastDataRow = targetWorksheet.Cells( _
targetWorksheet.Rows.Count, "A" _
).End(xlUp).Row
MsgBox lastDataRow
End Sub
・ なぜこの書き方を採用するのか
ネット上では、
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
だけを紹介している記事も多くあります。
もちろん動作しますが、実務ではそれだけでは十分とは言えません。
今回のコードでは、
- 対象シートを変数で管理する
- 行番号をLong型で保持する
- コメントで処理の目的を明確にする
という構成にしています。
コードは数行長くなりますが、
- 他のシートへ流用しやすい
- 保守担当者にも意図が伝わる
- シート変更時の修正箇所が少ない
というメリットがあります。
実務では、「短く書くこと」よりも「あとから修正しやすいこと」の方が重要になるため、このような構成をおすすめします。
Rows.Countは最終行取得でよく使われますが、空白セルや数式が含まれるデータでは期待どおりに取得できないことがあります。取得できない原因や対処法については、【VBA】最終行を取得できない原因とは|空白・数式・UsedRangeの落とし穴で詳しく解説しています。
✅ VBAで保守しやすく行数を取得する書き方
Rows.Countは次のように書くこともできます。
MsgBox Rows.Count
しかし、この書き方は実務ではあまりおすすめできません。
理由は、どのシートを対象にしているのか分かりにくいためです。
例えば、処理中に別シートがアクティブになった場合、意図しないシートのRows.Countを取得してしまう可能性があります。
そこで実務では、対象シートを変数として保持し、
targetWorksheet.Rows.Count
のように記述することが一般的です。
・ 保守性を高めるために意識しているポイント
この書き方にしている理由は、コードを読みやすくするためだけではありません。
実務では、
- 他の開発者がコードを修正する
- 数か月後に自分で保守する
- 処理対象のシートが増える
といったケースが頻繁にあります。
対象シートを明示しておけば、仕様変更が発生しても修正箇所が分かりやすく、思わぬ誤動作も防ぎやすくなります。
また、Rows.Countを利用する変数もLong型で宣言しているため、Excelの最大行数にも問題なく対応できます。
✅ VBAのRange.Rows.Countで指定範囲の行数を取得する方法
Rows.Countは、ワークシート全体だけでなく、指定したセル範囲に対しても使用できます。
例えば、A2セルからD10セルまでの範囲に含まれる行数を取得する場合は、次のように記述します。
Sub GetRangeRowCount()
Dim targetWorksheet As Worksheet
Dim targetRange As Range
Dim rangeRowCount As Long
Set targetWorksheet = ThisWorkbook.Worksheets("売上データ")
Set targetRange = targetWorksheet.Range("A2:D10")
' 指定範囲に含まれる行数を取得
rangeRowCount = targetRange.Rows.Count
MsgBox "対象範囲の行数は " & rangeRowCount & " 行です。"
End Sub
この場合、2行目から10行目までが対象なので、取得結果は9になります。
ワークシート全体に対するRows.Countと、Rangeオブジェクトに対するRows.Countでは、取得する対象が異なります。
targetWorksheet.Rows.Count:ワークシート全体の総行数targetRange.Rows.Count:指定範囲に含まれる行数
同じRows.Countでも、どのオブジェクトに対して使用しているかによって結果が変わる点に注意が必要です。
・指定範囲を変数に格納している理由
サンプルコードでは、セル範囲を直接Rows.Countへつなげるのではなく、targetRangeという変数へ格納しています。
次のように1行で書くことも可能です。
rangeRowCount = targetWorksheet.Range("A2:D10").Rows.Count
短い処理であれば、この書き方でも問題ありません。
しかし、同じ範囲を値の取得、書式設定、配列への格納など複数の処理で使用する場合は、Range変数として管理した方が修正しやすくなります。
対象範囲が変更されたときも、Rangeを設定している1か所を修正するだけで済むため、実務では再利用しやすい構成になります。
✅ VBAのCells.Rows.CountとRows.Countの違い
ワークシート全体を対象にした場合、次の2つは基本的に同じ行数を返します。
targetWorksheet.Rows.Count
targetWorksheet.Cells.Rows.Count
どちらもワークシート全体の行数である1048576を取得します。
単純にシート全体の行数を取得するだけなら、より短く読みやすい次の書き方で十分です。
totalRowCount = targetWorksheet.Rows.Count
一方、最終行を取得するときは、Cellsプロパティと組み合わせる必要があります。
lastDataRow = targetWorksheet.Cells( _
targetWorksheet.Rows.Count, "A" _
).End(xlUp).Row
このコードでは、Rows.Countで取得した最終行番号をCellsの行番号として使用しています。
つまり、それぞれの役割は次のように異なります。
- Rows.Count:対象範囲が持つ行数を取得する
- Cells:行番号と列番号を指定してセルを取得する
- End(xlUp):指定したセルから上方向へ移動する
- Row:到達したセルの行番号を取得する
コードを丸暗記するよりも、それぞれの役割を分けて理解した方が、基準列の変更や別シートへの流用がしやすくなります。
✅ VBAのUsedRange.Rows.Countで行数を取得するときの注意点
使用されている範囲の行数を取得する方法として、UsedRange.Rows.Countを見かけることがあります。
Sub GetUsedRangeRowCount()
Dim targetWorksheet As Worksheet
Dim usedRowCount As Long
Set targetWorksheet = ThisWorkbook.Worksheets("売上データ")
' 使用されている範囲の行数を取得
usedRowCount = targetWorksheet.UsedRange.Rows.Count
MsgBox usedRowCount
End Sub
UsedRangeは、ワークシート上で使用されたセル範囲を表します。
ただし、UsedRange.Rows.Countをデータの最終行取得にそのまま使用するのはおすすめできません。
・UsedRangeは値が入っているセルだけを見ているとは限らない
UsedRangeには、次のようなセルが含まれることがあります。
- 過去に値が入力されていたセル
- 書式だけが設定されているセル
- 罫線や背景色が設定されたセル
- 削除後も使用済みとして認識されているセル
例えば、1000行目までデータを入力したあと、データを10行目まで残して削除したとします。
見た目では10行目までしか使用していなくても、UsedRangeでは1000行目付近まで使用済みと判断される場合があります。
そのため、実際のデータ件数を取得したい処理でUsedRange.Rows.Countを使用すると、想定より大きな値になる可能性があります。
・UsedRange.Rows.Countは最終行番号ではない
使用範囲が5行目から20行目までの場合、UsedRange.Rows.Countが返す値は16です。
しかし、最終行番号は20です。
この違いを整理すると、次のようになります。
| 確認内容 | 取得結果 |
|---|---|
| 使用範囲の開始行 | 5 |
| 使用範囲の最終行 | 20 |
| UsedRange.Rows.Count | 16 |
UsedRange.Rows.Countは、使用範囲に含まれる行数を取得しているのであり、ワークシート上の最終行番号を返しているわけではありません。
最終行番号を取得する目的で使用すると、開始行が1行目ではない場合にずれが発生します。
UsedRangeを利用した行数・最終行取得には、Rows.Countとは異なる注意点があります。UsedRangeの仕様や実務での活用方法について詳しく知りたい方は、【VBA】UsedRangeプロパティ:最終行と最終列数を取得する方法と実務での注意点をご覧ください。
✅ VBAで行数と最終行番号を正しく使い分ける方法
VBAで処理を組み立てる際は、「行数」と「最終行番号」を区別する必要があります。
例えば、2行目から10行目までデータが入力されている場合、次のようになります。
- データの開始行:2
- データの最終行番号:10
- データの行数:9
最終行番号が10だからといって、データが10件あるとは限りません。
見出し行や処理対象外の行が含まれているためです。
データ行数を計算する場合は、次の式を使用します。
データ行数 = 最終行 - 開始行 + 1
実際のコードでは次のようになります。
Sub CalculateDataRowCount()
Dim firstDataRow As Long
Dim lastDataRow As Long
Dim dataRowCount As Long
firstDataRow = 2
lastDataRow = 10
' 開始行と最終行の両方を含めて行数を計算
dataRowCount = lastDataRow - firstDataRow + 1
MsgBox "データ行数は " & dataRowCount & " 行です。"
End Sub
+ 1が必要なのは、開始行と終了行の両方を含めて数えるためです。
例えば、2行目から2行目までが対象の場合、データは1行あります。
しかし、単純に2 - 2と計算すると0になるため、最後に1を加えます。
行数と最終行番号を混同すると、ループ回数が1回不足したり、配列へ読み込む範囲がずれたりする原因になります。
データの途中に空白行がある場合は、Rows.CountとEnd(xlUp)だけでは正しく最終行を取得できないことがあります。空白を含むデータで安全に最終行を取得する方法については、【VBA】空白を含む最終行を正しく取得する方法|End(xlUp)がズレる原因で詳しく解説しています。
✅ VBAで見出しを除いたデータ行数を取得する実務例
実務では、表の先頭に見出しがあり、その下にデータが並んでいるケースが一般的です。
次のコードでは、A列を基準に最終行を取得し、見出し行を除いたデータ件数を計算します。
・空データにも対応できる形で行数を求める
単純に最終行から見出し行を引くだけでは、データが1件もない場合に正しく判定できないことがあります。
そこで、見出ししか存在しないケースを先に確認してから件数を計算します。
Sub CountSalesDataRows()
Const HEADER_ROW As Long = 1
Const KEY_COLUMN As String = "A"
Dim targetWorksheet As Worksheet
Dim lastDataRow As Long
Dim dataRowCount As Long
Set targetWorksheet = ThisWorkbook.Worksheets("売上データ")
' 管理番号が入力されるA列を基準に最終行を取得
lastDataRow = targetWorksheet.Cells( _
targetWorksheet.Rows.Count, KEY_COLUMN _
).End(xlUp).Row
' 見出ししかない場合はデータ件数を0件とする
If lastDataRow <= HEADER_ROW Then
dataRowCount = 0
Else
dataRowCount = lastDataRow - HEADER_ROW
End If
MsgBox "売上データは " & dataRowCount & " 件あります。"
End Sub
・定数で見出し行と基準列を管理するメリット
このコードでは、見出し行と基準列を定数として定義しています。
Const HEADER_ROW As Long = 1
Const KEY_COLUMN As String = "A"
数値や列名をコード内へ直接何度も書く方法と比べて、次のメリットがあります。
- 見出し行の変更に対応しやすい
- 基準列を変更する場所が明確になる
- 数字や文字列の意味を読み取りやすい
- 同じ設定を複数箇所で統一できる
例えば、将来見出しが2行構成になった場合も、HEADER_ROWを2へ変更するだけで対応できます。
業務ツールは、作成時よりもリリース後に仕様変更されることが少なくありません。
そのため、変わる可能性がある値をコードの途中へ散らさず、先頭で管理する設計が有効です。
・基準列は空白が入りにくい列を選ぶ
最終行取得に使用する基準列は、どの列でもよいわけではありません。
例えば、備考欄のように入力されない行がある列を基準にすると、実際より上の行を最終行として取得する可能性があります。
基準列には、次のような値が必ず入力される列を選ぶのが安全です。
- 管理番号
- 社員番号
- 商品コード
- 取引番号
- 日付
コード上は正しくても、基準列の選び方が悪いと処理結果は正しくなりません。
実務では構文だけでなく、データの運用ルールまで確認して基準列を決める必要があります。
Rows.Countで取得した最終行は、そのままFor文の終了条件として利用することがよくあります。可変データを安全に繰り返し処理する方法については、【VBA】For文で最終行まで繰り返す方法|可変データに対応する実務コードも参考にしてください。
✅ VBAのRows.Countでよくあるミスと対処法
Rows.Countは定番のプロパティですが、書き方によっては想定外の結果やエラーにつながります。
Rows.Countだけでデータの最終行を取得しようとする
次のコードで取得できるのは、ワークシートの総行数です。
lastDataRow = targetWorksheet.Rows.Count
データの最終行を取得したい場合は、End(xlUp)などと組み合わせます。
lastDataRow = targetWorksheet.Cells( _
targetWorksheet.Rows.Count, "A" _
).End(xlUp).Row
Rows.Countは最終行そのものではなく、最終行を探すための開始位置として使用します。
・Rows.CountとCellsで異なるシートを参照してしまう
次のようにシート指定が不完全なコードにも注意が必要です。
lastDataRow = targetWorksheet.Cells(Rows.Count, "A").End(xlUp).Row
targetWorksheet.Cellsは売上データシートを参照していますが、Rows.Countはアクティブシートを参照しています。
通常のExcelではシートの総行数が同じため、すぐには問題が見えないこともあります。
しかし、参照先が統一されていないコードは読み手を混乱させ、別の処理へ流用した際の不具合につながります。
次のように、CellsとRows.Countの両方へ同じWorksheet変数を付けましょう。
lastDataRow = targetWorksheet.Cells( _
targetWorksheet.Rows.Count, "A" _
).End(xlUp).Row
・Integer型で行数を管理する
次の宣言では、Excelの最大行数を格納できません。
Dim totalRowCount As Integer
Integer型が扱える最大値は32767なので、1048576を代入するとオーバーフローが発生します。
行数や行番号を扱う変数はLong型で宣言します。
Dim totalRowCount As Long
近年のVBAでは、行番号に限らず整数を扱う変数にはLong型を使用するのが基本です。
最終行の取得方法だけでなく、途中に空白行があるデータをどのように繰り返し処理するかも重要です。実務で安全にループ処理を行う方法については、【VBA】For文で空白行まで繰り返す方法|安全な実務設計で詳しく解説しています。
行数を取得したあとは、セルの値を読み取って処理を行うケースがほとんどです。セルの値を取得する基本から配列を使った高速処理まで知りたい方は、【VBA】セルの値を取得する方法|範囲指定・選択範囲・配列まで解説をご覧ください。
✅ VBAのRows.Countで行数を取得する方法のまとめ
Rows.Countは、ワークシートや指定範囲に含まれる行数を取得するためのプロパティです。
この記事のポイントを整理すると、次のようになります。
Worksheet.Rows.Countはシート全体の総行数を返すRange.Rows.Countは指定範囲に含まれる行数を返す- Rows.Count単体ではデータの最終行を取得できない
- 最終行取得ではEnd(xlUp)などと組み合わせる
- UsedRange.Rows.Countは使用範囲の行数であり、最終行番号ではない
- データ行数と最終行番号は異なる
- 行番号や行数を格納する変数にはLong型を使用する
- 実務では対象シートと基準列を明示する
- 基準列には空白が入りにくい列を選ぶ
Rows.Countは単純なプロパティですが、最終行取得、可変範囲の作成、配列へのデータ格納など、さまざまな処理の土台になります。
重要なのは、Rows.Countを最終行取得の命令として覚えるのではなく、対象範囲が持つ行数を取得するプロパティとして理解することです。
行数、最終行番号、データ件数を正しく区別し、対象シートと基準列を明示することで、データ量が変化しても安定して動作するVBAコードを作成できます。