メール送信の自動化ツールを作ってまして、ToやCC、件名などを一覧で渡すことで大量メールの自動送信…を開発してます。
そこで一覧を読み込みながらメールを自動送信する分けですが、ワークシート上の最終セル(最終行)までFor文/Do文をグルグル回す訳です。
そこで新しい技を覚えましたので、備忘録しておきます。
■ 動作環境
OS: Windows 8.1
Excel: 2013
Outlook: 2013
■ 今までのやり方(最終行の取得?ではなく判断?)
最終行の取得というか、最終行かな?と思えるところまでFor文/Do文をグルグル回すって方式です。具体的には次のとおり。
※これ以降も同様ですが、「m_」で始まる英語大文字の変数名みたいな名称は、何れも私が別途定義している定数です。
本質は、「最終行かな?と思えるところ」=「必須項目列が空っぽになるところ」という観点で、「必須項目列に何かしら値が入っている間」Do While文でグルグル回しています。
ずーっと中身が詰まってて、最後に値が切れるような列が判断ターゲットであれば、これはこれで、的を得たアプローチ方法です。また、アルゴリズムの基本を理解する上ではおすすめの考え方でもあります。
(ただしこの方法は、ずーっと中身が詰まってて…が弱点です。途中に空のセルがあるような性質の列では、意図した繰り返し処理ができません💦)
ただし、これは、最終行が分からないから、恐る恐る前に進む…ようなものです💦
それが、今回新たに見つけた技は、最終行が分かる!技なのです^^
■ 最終行の取得(前から)
RangeクラスのEndプロパティを活用することで、指定した方向(Direction)の終端(のRangeオブジェクト)を獲得することができます。
> Rangeオブジェクト.End(Direction)
引数 Direction の設定値は次のとおり。
xlUp; 上方向への移動
xlDown; 下方向へ移動
xlToLeft; 左方向へ移動
xlToRight; 右方向へ移動
返される値は終端のRangeオブジェクトのため、そのRowプロパティを参照することで、最終行を取得します。
前述のソースを改善したのが、次のとおりです。
どうですか?
スッキリ感はどっちもどっちかな?と思いますが、私は、Do文よりFor文が好きなので、これからはこっちをヘビーローテしそうです。
ちなみにわざわざ変数 lngRowLimit に突っ込んでるのは蛇足です。本来は、For文のTo以降へダイレクトにぶつけちゃえばいいと思います。
(ただ、ソースが右のほーに長くなっちゃうので、少しでも圧縮…と思い、事前に変数へ突っ込む方法にしました)
あとは、せっかくなので…
■ 最終行の取得(後ろから)
折角なので、前2つの方式の弱点となる「ずーっと中身が詰まってて」を解決する方法も備忘録しておきます。
結論は、ずばり「後ろから」です。
所々中身がない(=空っぽ)なセルがある列だとしても、一番最後の値が入っているセルを、ワークシートの終端から逆順に探し出せば見つけられるだろう…な考え方です。
前述のソースを改善したのが、次のとおりです。
ポイントは…
Rows.Countで、ワークシート全体の最大行数を示します。Excelのパーションによって値は異なりますが、それぞれのバージョンに応じた最大行数を獲得できます。
Endプロパティには、xlUpを指定します。ワークシート全体の最大行数から上に向かって検索をかけるためです。
■ 処理速度的な観点
見た目はどっこいどっこいだったので、もしかして処理速度に差が出るかな…?と思ったのですが、さほど大差ありませんでした💦
□ 1,000件のレコードが対象
今までのやり方; 約1.83秒
最終行の取得(前から); 約1.86秒
最終行の取得(後ろから); 約1.83秒
■ まとめ
いかがでしたでしょうか?
本来は、メール送信の自動化の大量メール発信…的なテーマで備忘録を纏めたかったのですが、大した処理の部分でないところで新たな発見がありまして今回のテーマとなりました。
次回以降も、苦労した点を備忘録しようと思います。
Comments