ねらい:最終行の高速取得とは?
Excel VBAで「データがどこまで入っているか」を調べるときに必ず出てくるのが 最終行の取得 です。初心者がよくやるのは UsedRange や CurrentRegion を使う方法ですが、これらは 遅い・不正確 になることがあります。大量データを扱う現場では「高速かつ正確に最終行を取得する」ことが重要です。
基本テンプレート:End(xlUp) を使う
Sub GetLastRow_Basic()
Dim ws As Worksheet
Set ws = Worksheets("Sheet1")
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
MsgBox "最終行は " & lastRow & " 行目です"
End Sub
VB重要ポイント(深掘り)
ws.Rows.Countはシートの総行数(Excelのバージョンによって 65,536 または 1,048,576)。End(xlUp)は「最下行から上に向かってデータがあるセルまでジャンプ」する。- 高速性: Excel内部のジャンプ機能を使うため、数十万行でも一瞬で最終行を取得できる。
- 注意: 空白セルが途中にある場合でも、最後に入力されているセルを正しく見つけられる。
応用テンプレート:任意の列で最終行を取得
Function GetLastRow(ByVal ws As Worksheet, ByVal colLetter As String) As Long
GetLastRow = ws.Cells(ws.Rows.Count, colLetter).End(xlUp).Row
End Function
Sub ExampleLastRow()
Dim ws As Worksheet: Set ws = Worksheets("Data")
Dim lr As Long
lr = GetLastRow(ws, "C") ' C列の最終行を取得
MsgBox "C列の最終行は " & lr
End Sub
VB重要ポイント(深掘り)
- 列を指定できる関数化: どの列を基準にするかを柔軟に選べる。
- データ構造に合わせる: 例えば「社員番号は必ずA列にある」ならA列を基準にする。
- 関数化のメリット: どのシートでも使い回せる。初心者が「毎回同じコードを書く」無駄を減らせる。
範囲全体の最終行を取得(複数列にデータがある場合)
Sub GetLastRow_MultiColumn()
Dim ws As Worksheet: Set ws = Worksheets("Sheet1")
Dim lastRowA As Long, lastRowB As Long, lastRowC As Long
lastRowA = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
lastRowB = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
lastRowC = ws.Cells(ws.Rows.Count, "C").End(xlUp).Row
Dim lastRow As Long
lastRow = Application.WorksheetFunction.Max(lastRowA, lastRowB, lastRowC)
MsgBox "A~C列の中で最終行は " & lastRow
End Sub
VB重要ポイント(深掘り)
- 複数列にデータがある場合: どの列を基準にするか迷うときは「最大値」を取る。
WorksheetFunction.Max: 複数の最終行を比較して一番下の行を返す。- 実務での使い方: 「入力欄が複数列に分かれている」帳票で有効。
高速化の工夫:UsedRangeとの比較
Sub CompareLastRowMethods()
Dim ws As Worksheet: Set ws = Worksheets("Sheet1")
Dim t0 As Double, t1 As Double
' End(xlUp)方式
t0 = Timer
Dim lr1 As Long
lr1 = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
t1 = Timer
Debug.Print "End(xlUp): " & lr1 & " | " & Format(t1 - t0, "0.000") & "秒"
' UsedRange方式
t0 = Timer
Dim lr2 As Long
lr2 = ws.UsedRange.Rows(ws.UsedRange.Rows.Count).Row
t1 = Timer
Debug.Print "UsedRange: " & lr2 & " | " & Format(t1 - t0, "0.000") & "秒"
End Sub
VB重要ポイント(深掘り)
- End(xlUp)の方が速い: 数十万行でも一瞬。
- UsedRangeは遅い+不正確: 一度入力して削除したセルも「使用済み」と判定されることがある。
- 結論: 実務では
End(xlUp)を基本にする。
例題で練習
- 例1: A列に10行データを入れて
GetLastRow_Basicを実行 → 「10」が返る。 - 例2: C列にデータを入れて
ExampleLastRowを実行 → C列の最終行が返る。 - 例3: A列とC列にデータがあり、
GetLastRow_MultiColumnを実行 → 最大の行番号が返る。 - 例4:
CompareLastRowMethodsを実行 → Immediateウィンドウで速度比較を確認。
実務の落とし穴と対策
- 落とし穴1:途中に空白行がある
- 対策:
End(xlUp)は「最後に入力されているセル」までジャンプするので問題なし。
- 対策:
- 落とし穴2:UsedRangeで誤判定
- 対策: UsedRangeは避ける。削除済みセルも「使用済み」と判定される。
- 落とし穴3:列選びを間違える
- 対策: 必ず「必ず埋まっている列」を基準にする。社員番号やID列が最適。
- 落とし穴4:シートが空の場合
- 対策: 最終行が「1」になる。データがない場合の処理分岐を入れる。
スターター手順
- まずは1列で試す:
GetLastRow_Basicを実行して最終行を確認。 - 次に関数化:
GetLastRowを使って任意列の最終行を取得。 - 複数列対応:
GetLastRow_MultiColumnで最大値を取る。 - 速度比較:
CompareLastRowMethodsで End(xlUp) の速さを体感。
