和風スパゲティのレシピ

日本語でコーディングするExcelVBA

指定のセル範囲(Range)の最終行を取得する

あるセル範囲(Rangeオブジェクト)があったとき、
その最終行を取得する方法を解説します。

セル範囲のアドレスがC3:E8ならば、「8」を取得するコードですね。

基本コードと解説

あるセル範囲の最終行を求める、最も基本的なコードがこちらです。

Dim セル範囲 As Range
Set セル範囲 = Range("C3:E8")

Dim LastR As Long
LastR = セル範囲.Rows.Count + セル範囲.Row - 1

まずはセル範囲.Rows.Countでセル範囲の全行数を数えます。
C3:E8なら「6」がここで求まります。

あとはセル範囲より上にある行数(1~2行目の2)を足せばよく、
これは「セル範囲の第1行 - 1」で求まりますので、セル範囲.Row - 1


両者を足せば目的の式になりますね。


Rangeオブジェクトのプロパティとして、

  • 行数を数える ⇒ Rangeオブジェクト.Rows.Count
  • 第1行を取得する ⇒ Rangeオブジェクト.Row

は重要なプロパティですので、必ず覚えておきましょう。

セル範囲の最終行を求める関数

今回の「あるセル範囲の最終行」のように、
Rangeオブジェクトの情報を調べるコードは非常に汎用性が高いため、
関数にしておくとかなり便利に使いまわすことができます。


作成する関数のコードはこちら↓

Function GetLastRセル範囲(セル範囲 As Range) As Long
    GetLastRセル範囲 = セル範囲.Rows.Count + セル範囲.Row - 1
End Function

たった1行で、しかも中身は基本コードそのまんまです。


ですが、この関数を作っておくだけで、

シートの最終行 = GetLastRセル範囲(ActiveSheet.UsedRange)
オートフィルターの最終行 = GetLastRセル範囲(ws処理シート.AutoFilter.Range)
表の最終行 = GetLastRセル範囲(Range("A1").CurrentRegion)
テーブルの最終行 = GetLastRセル範囲(ws処理シート.ListObject(1).Range)

このようにいろいろなセル範囲の最終行が、
すべて1行のコードで取得できるようになります。


この世のすべてのRangeオブジェクトに.LastRというプロパティをつけることができたようなもので、鬼の用に便利なので是非とも関数にしておきましょう。


関数を作ったことが無かったり、苦手意識がある方もいるかもしれませんが、
実は関数ってこんな簡単です。


難しい処理をこなすとか、コードの共通部分を抜き出すとかではなく、
ちょっとしたコードを瞬殺できるようにする、いわゆる汎用関数は、
作るのも楽で、しかも便利です。

気が向いたら作ってみてください。


よろしければこちらの記事をどうぞ。

www.limecode.jp

おまけ:別解

豆知識的に基本コード以外の別解も置いておきます。
引き出し増やしにでもどうぞ。
 

Dim セル範囲 As Range
Set セル範囲 = Range("C3:E8")

Dim LastR As Long
LastR = セル範囲.Rows(セル範囲.Rows.Count).Row

セル範囲.Rows(1) でセル範囲の第1行を取得できます。
セル範囲.Rows(n) でセル範囲の第n行を取得できます。

ということで、セル範囲の最終行はセル範囲.Rows(セル範囲の全行数)ですね。

Rows(n)はRangeオブジェクトを取得しますので、
最終行「番号」を求めたいときは、最後に.Rowをつけます。


また、セル範囲が行全体・列全体・単独セルではないという条件なら、

LastR = Split(セル範囲.Address, "$")(4)

というトリッキーな技もあります。

.Addressで取得したセルアドレス「$B$2:$E$8 」を$で分割(Split)すると、
[][B][2:][E][8]という配列になり、
この5つ目を取ってくれば、それが最終行ですね。

※ 配列は0から始まるので、5つ目を取ってくるなら(4)


最後に、

LastR = セル範囲.SpecialCells(xlLastCell).Row

と、SpecialCellsプロパティの「最終セル」機能を使うこともできます。


しかしこの方法実は罠があり、
SpecialCells(xlLastCell)は行の削除をなぜか検知できません。

Set セル範囲 = Range("C3:E8")
Rows(5).Delete

LastR = ○○

このような処理をすると、変数「セル範囲」は5行目が削除された時点で「C3:E7」に変わっているため、今までの例ではちゃんと7を返してくれるのですが、
SpecialCells(xlLastCell)だけは8を返してしまいます。

※ データの削除がSpecialCells(xlLastCell)に反映されるタイミングは「上書き保存」です。
※ SpecialCells(xlLastCell)は「入力」最終行を取得するため、8行目が空だと7になります。


まあほとんど使わないプロパティですし、罠の発生率も高くはないですが、
心の片隅にでも置いておいてください。


その他最終行に関するコードはこちらをどうぞ
www.limecode.jp