大量のデータを絞り込むには、オートフィルタが便利です。ここでは、VBAからオートフィルタを使い倒すテクニックをご紹介します。なお、ボリュームがありますので、以下の項目にページを分けて解説します。なお、ここで解説するオートフィルタは、通常のワークシートに設定されているとします。テーブルでオートフィルタを操作するときは、また別の考え方が必要です。VBAでテーブルを扱う方法に関しては「VBAでテーブルの操作」をご覧ください。
上図の表に対して「1列目を"田中"」で絞り込みます。まず、上記のように「全体に対してひとつのことをすると、Excelがうまくやってくれる」という動作を確認してみます。なお、ここからは、絞り込んだ結果のうちタイトル行を除くデータだけを対象にします。その考え方は「オートフィルタで絞り込んだデータだけ特定する」をご覧ください。
まずはセルの書式を設定してみましょう。"可視セル"選択をしていない点に留意してくださいね。
Sub Macro1() Range("A1").AutoFilter 1, "田中" With Range("A1").CurrentRegion.Offset(1, 0) .Resize(.Rows.Count - 1).Font.ColorIndex = 3 End With Range("A1").AutoFilter End Sub
ね、見えているセルだけ処理されたでしょ。次はコピーしてみましょうか。一般的には、別のシートにコピーすることが多いですけど、ここでは見やすくするために、同じシート内でコピーします。
Sub Macro2() Range("A1").AutoFilter 1, "田中" With Range("A1").CurrentRegion.Offset(1, 0) .Resize(.Rows.Count - 1).Copy Range("E2") End With Range("A1").AutoFilter End Sub
これもうまくいきます。ちなみに、オートフィルタで絞り込んだ結果の「全体に対してひとつのことをすると、Excelがうまくやってくれる」という仕様は、Excel 2002からです。その前の、Excel 2000まではダメでした。こんなことをすると、隠れているセルまで全部処理されてしまいました。
さあ、本題はここからです。じゃあ、絞り込んだ結果を1行ずつ処理をするには、どうしたらいいでしょう。たとえば、次のような操作です。今度は、次のような表で考えます。
この表を「1列目を"田中"」で絞り込みます。
見えている行を、1行ずつ操作します。ここでは、B列からD列までの数値を合計してE列に代入するとしましょう。つまり、行ごとに、行内のセルをひとつずつ操作したいというケースです。
これ、もし操作対象の行が特定できたら、次のように操作できます。
Sub Macro3() Dim A As Range, S As Long, i As Long Set A = Range("A3:D3") For i = 2 To 4 S = S + A.Cells(1, i) Next i MsgBox S End Sub
A.Cells(1, i) のあたりで「なんじゃこりゃ~」的に感じる方もいるかもしれませんね。VBAは、こういうこともできるんですよ~がんばってスキルアップしてくださいねぇ~。まぁ、とにかく。操作対象の行を Set A = Range("A3:D3") みたく特定できたら、その行内のセルをひとつずつ操作できるということです。じゃ、オートフィルタで絞り込んだ結果のすべての行を1行ずつ特定するにはどうしたらいいのでしょうか。
まずは、絞り込んだ結果のRowsコレクションを調べてみましょう。なお、ここからは面倒くさいので「1列目を"田中"」で絞り込むところは割愛します。
Sub Macro4() With Range("A1").CurrentRegion.Offset(1, 0) MsgBox .Resize(.Rows.Count - 1).Rows.Count End With End Sub
絞り込んだ結果、見えているのは4行です。その4行とは「3行目」「5行目」「6行目」「9行目」です。もし、絞り込んだ結果のRows.Countが「4」だったら、それらを順番に操作すればできそうです。結果は次のとおり。
「1」って何だよ「1」ってw。んなわきゃーねーだろって。まさか、先頭行しか認識してないとか?じゃ、その1行のアドレスを調べてみましょう。
Sub Macro4() With Range("A1").CurrentRegion.Offset(1, 0) MsgBox .Resize(.Rows.Count - 1).Rows.Address End With End Sub
ああ、なるほどね。Rowsで取得できたのは、見えている行だけじゃなくて、オートフィルタ全体だったんですね。じゃ、ここで"可視セル"を使いましょう。