ExcelマクロVBA技術解説 | 最終行の判定、Rangeオブジェクトと配列、高速化の為に | ExcelマクロVBAの問題点と解決策、エクセルVBAの技術的解説



最終更新日:2015-08-16

最終行の判定、Rangeオブジェクトと配列、高速化の為に


最終行の判定


以前に、モジュール「顧客一覧へ登録」において、

.Cells.SpecialCells(xlLastCell).End(xlUp).Row

Cells(Rows.Count, 1).End(xlUp).).Row

を紹介しましたが、どちらも問題があります。


以下の表で説明します。



.Cells.SpecialCells(xlLastCell).End(xlUp).Row

では、8行目になってしまいます。

.Cells.SpecialCells(xlLastCell)が、F12になりますので、その上の空白ではないセルになるからです。


Cells(Rows.Count, 2).End(xlUp).).Row

これは、9行目になってしまいます。

Rows.Countはシートの全行数、つまり、B列の最終行から上の空白ではないセルになります。


追加説明として、罫線を下の方まで引いていなかったり、計算式をいれていない場合は、

.Cells.SpecialCells(xlLastCell)だけでも最終行は取得できます。


今回の場合、一覧で自由に登録出来るようにしたいと思います。

例えば、コードを入力せずに、他の項目を入れた状態で、

「顧客登録」へ移動して、新規登録を行う事もありえます。、

上の判定では、どちらも問題があります、最終行は10行を取得したいところです。

「顧客コード」は先に必ず入力することを、決めごととすれば良いのですが、

今後のトラブル対策と、勉強を兼ねて工夫してみましょう。


以下がその結果です。

「Mod共通」に貼り付けて下さい。


Function 最終行取得(ByVal sht As Worksheet) As Long
  Dim ary As Variant
  Dim i As Long, j As Long
  ary = sht.Range(sht.Cells(1, 1), sht.Cells.SpecialCells(xlLastCell))
  Do
    For i = UBound(ary, 1) To LBound(ary, 1) Step -1
      j = 1
      For j = LBound(ary, 2) To UBound(ary, 2)
        If ary(i, j) <> "" Then
          最終行取得 = i
          Exit Function
        End If
      Next j
    Next i
  Loop
End Function

簡単に説明します。


ary = sht.Range(sht.Cells(1, 1), sht.Cells.SpecialCells(xlLastCell))
ここで、配列にRangeを代入しています。

この配列を下から空白以外のセルがでてくるまで、検索しています。


For i = UBound(ary, 1) To LBound(ary, 1) Step -1
aryは2次元配列です。

Uboundは配列の最大要素数を返す関数です。

Lboundは最小要素数を返す関数です。

Step -1は、1づつカウントダウンします。省略時は、Step 1になります。


やっている事は、使用されているセル範囲を下から空白セルを見つけているだけです。


では、直接セルを検索すれば良いのですが、それでは、処理速度が遅くなってしまいます。

今は、データ件数が少ないので気にならないと思いますが、数千、数万行になったとき、影響が出てきます。

処理速度を向上させる為に、このような記述にしています。

(ただし、今回程度の処理では、ほとんど実測出来るほどの違いは無いと思います。)

初心者には、配列は少し難しいので、理解できない場合は、配列というのが使える程度の理解で良いでしょう。

中級者以上の人の為に、もう少し説明します。


以下は、私がいきなり書いた時の記述です。

Dim rng As Range

Dim i As Long, j As Long
Set rng = sht.Range(sht.Cells(1, 1), sht.Cells.SpecialCells(xlLastCell))

Do
For i = rng.Rows.Count To 1 Step -1

・・・

If rng(i, j) <> "" Then

・・・

このような記述でも、正常に動作します。

しかし、あれ、これでは、直接セルを参照しているので、遅くなってしまうなー。!?

と考えて、上記に変更しました。

この2つの違いが、直ぐに分かる人は、今後私のブログを見ないでください。

それは冗談ですが、Rangeオブジェクトを正しく理解するのは、結構難しいと思います。

そういう私も、時々、あれっ、どうなんだ?と考え込んでしまいますから。


Rangeオブジェクトは、直接セル範囲を参照(値の取得ではない)しています。

従って、そのセルを直接操作していることと同じです。

最終的なコードでは、配列には値だけが入り、その配列を操作しているので、

はるかに高速です。たぶんですけど・・・実測してはいません。

まあ、長々と書きましたが、1つのテクニックとして覚えて下さい。



最終行の求め方、配列、UBound、LBound位を、記憶してもらえれば結構です。


今後も配列はいろいろと出てくると思いますので、少しづつ説明していきます。






同じテーマ「マクロVBA技術解説」の記事

VBAの配列まとめ(静的配列、動的配列)
記述による処理速度の違い
速度比較決定版【Range,Cells,Do,For,ForEach】
エクセルVBAのパフォーマンス・処理速度に関するレポート
VBAのFindメソッドの使い方には注意が必要です
WorksheetFunction.Matchで配列を指定した場合の制限について
マクロVBAの高速化・速度対策の具体的手順と検証
動的2次元配列の次元を入れ替えてシートへ出力(Transpose)
大量データで処理時間がかかる関数の対処方法(SumIf)
大量データにおける処理方法の速度王決定戦

新着記事 ・・・新着記事一覧を見る

For Next の使い方いろいろ|VBA技術解説(6月14日)
VBAを定型文で覚えよう|ExcelマクロVBA技術解説(3月26日)
VBAスタンダード試験対策まとめ|MOS VBAエキスパート対策(3月16日)
ユーザーフォームとメニューの操作|MOS VBAエキスパート対策(3月14日)
ファイルの操作|MOS VBAエキスパート対策(3月14日)
ユーザーフォームの各種イベント|Excelユーザーフォーム(3月13日)
レジストリの操作|MOS VBAエキスパート対策(3月12日)
変数と配列|MOS VBAエキスパート対策(3月12日)
Colorプロパティの設定値一覧|VBA技術解説(3月12日)
APIとOLEオートメーション|MOS VBAエキスパート対策(3月11日)

アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.変数とデータ型(Dim)|ExcelマクロVBA入門
3.マクロって何?VBAって何?|ExcelマクロVBA入門
4.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
5.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
6.RangeとCellsの使い方|ExcelマクロVBA入門
7.とにかく書いて見よう(Sub,End Sub)|VBA入門
8.まずはマクロVBAを使う準備|ExcelマクロVBA入門
9.繰り返し処理(For Next)|ExcelマクロVBA入門
10.マクロはどこに書くの(VBEの起動)|VBA入門



  • >
  • >
  • >
  • 最終行の判定、Rangeオブジェクトと配列、高速化の為に

  • このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


    記述には細心の注意をしたつもりですが、
    間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
    なお、掲載のVBAコードは自己責任で使ってください。万一データ破損等の損害が発生しても責任は負いません。





    このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。

    本文下部へ

    ↑ PAGE TOP