Excel VBA 逆引き集 | 最終行の高速取得

Excel VBA
スポンサーリンク

ねらい:最終行の高速取得とは?

Excel VBAで「データがどこまで入っているか」を調べるときに必ず出てくるのが 最終行の取得 です。初心者がよくやるのは UsedRangeCurrentRegion を使う方法ですが、これらは 遅い・不正確 になることがあります。大量データを扱う現場では「高速かつ正確に最終行を取得する」ことが重要です。


基本テンプレート: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. 例1: A列に10行データを入れて GetLastRow_Basic を実行 → 「10」が返る。
  2. 例2: C列にデータを入れて ExampleLastRow を実行 → C列の最終行が返る。
  3. 例3: A列とC列にデータがあり、GetLastRow_MultiColumn を実行 → 最大の行番号が返る。
  4. 例4: CompareLastRowMethods を実行 → Immediateウィンドウで速度比較を確認。

実務の落とし穴と対策

  • 落とし穴1:途中に空白行がある
    • 対策: End(xlUp) は「最後に入力されているセル」までジャンプするので問題なし。
  • 落とし穴2:UsedRangeで誤判定
    • 対策: UsedRangeは避ける。削除済みセルも「使用済み」と判定される。
  • 落とし穴3:列選びを間違える
    • 対策: 必ず「必ず埋まっている列」を基準にする。社員番号やID列が最適。
  • 落とし穴4:シートが空の場合
    • 対策: 最終行が「1」になる。データがない場合の処理分岐を入れる。

スターター手順

  1. まずは1列で試す: GetLastRow_Basic を実行して最終行を確認。
  2. 次に関数化: GetLastRow を使って任意列の最終行を取得。
  3. 複数列対応: GetLastRow_MultiColumn で最大値を取る。
  4. 速度比較: CompareLastRowMethods で End(xlUp) の速さを体感。
タイトルとURLをコピーしました