【2023/03/10】こちらの新しい記事もどうぞ
Excel VBAで何かするときに必ずと言って使う処理に「最終行を求める」処理があります。
ネットで検索するとだいたいはEnd(xlDown)を使った方法が紹介されています。僕はこれを使わず、愚直にDo~Loopで回して最終行を求めています。
下方向に最終行を求めるもっとも一般的な方法はおそらく次のようなものだと思います。
Range("A1").End(xlDown).Row
僕も以前は上記のコードを使っていました。
最終行はそこじゃない
あるとき確かテーブルの表だったと思うのですが、何度か行削除をした後に最終行を出してみると、行を削除する前の結果が依然として返ってきたんです。
何行かは削除していますのでもちろんそれは間違った結果ですが、どこをどう見直してもコードにも間違いはありません。というかそもそも上記のコードに間違いはありません。しかも直前までは正しく結果が出ていたのですから。
このようなことがあってからもっとも上記のコードは使用しなくなってしまいました。
件のトラブルはエクセル側のバグであったのか、原因もはっきりとしないのですが、とにかく「期待される結果と違うことがある」記述を用いるべきでないと判断をしたわけです。
それなら自前で作ってしまえ
現在は最終行を求めるためにはDo~Loopで愚直に空行を見つけていく関数を書いてそれを使うようにしています。
例えばこんな感じです。
Public Function getLastRow(ByVal startRow As Long, targetColumn As Long) As Long
Dim i As Long
i = startRow
Do Until Cells(i, targetColumn) = ""
i = i + 1
Loop
getLastRow = i
End Function
内容的には解説するまでもない単純なことですが、一番確実に最終行を求めることができると信じています (笑)
一応、引数を取ることで、最終行を求める際に勘定をスタートする行数と、どの列の最終を求めるかという対象列を指定できるようにしてあります。
意外な利点
この方法の利点は少し改良するだけで「どの行を最終行として見なすか」を変更できるところにあったりします。
一般的には最終行はブランクの行ですが、たまに「1行くらいはブランクがありますよ」という表も存在します。そんな時はブランクの行をカウントする変数をかましてやれば対応できます。
こんな感じです。
Public Function getLastRow(ByVal startRow As Long, targetColumn As Long) As Long
Dim i As Long
i = startRow
Dim blankCount As Integer
Do Until blankCount = 2
If Cells(i, targetColumn) = "" Then
blankCount = blankCount + 1
End If
i = i + 1
Loop
getLastRow = i - 1
End Function
膨大なデータを扱うこともほぼありませんし、この方法で処理速度が著しく遅くて難儀したという経験もありませんので実用上まったく問題はありません。
僕が経験したトラブルも現在のエクセルでは起こらないことなのかもしれませんし、そもそもその時の僕の操作が何か悪かったのかもしれません。
でもこうして少し面倒なことをさせられたことによってプログラムの基本的なことを繰り返し学べたとも思っていますし、少々のことなら自分の知っていることで工夫してみることも学習しました。
ググればなんでも解決するようなことですが、自分の頭の中に入っているものが一番手間なくササッと使えますものね。
コメント