今の会社に転職してからVBAで業務効率化を図る毎日を送っています。もともとはVBA全くわからないど素人だったのですが、4年ほど前に実務でぶつかった問題に取り組むうちにある程度書けるように。
先日、同僚にVBAを教える機会があり、「各項目の個数を数える」という処理をVBAで書いてみようとなりました。ぱっと思いつくだけで3つほど方法があったので、それぞれ整理しておきます。
①WorkSheetFunctionのCountIfを使う方法
今回実際に同僚に教えたのはこの方法。Forループが1個だけで書けるので、VBA初心者でも理解しやすいのがポイントです。
Sub CountItems()
Dim ws As Worksheet
Dim i As Long
Dim lastRow As Long
ws = ThisWorkbook.Sheets("Sheet1")
lastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
' A列の項目リストに対してB列に個数を書き出す
For i = 2 To lastRow
ws.Cells(i, 2).Value = WorksheetFunction.CountIf(ws.Range("D:D"), ws.Cells(i, 1).Value)
Next i
End Sub
Forループの入れ子をいきなりやれと言っても「はて?」となるので、まずはこの形から入るのがおすすめです。
②Forループの入れ子で数える方法
最初に思いついた方法はこれ。自分でコードを書くときはあまり使いませんが、実務でVBAをやっていればForの入れ子には必ず遭遇するので、そのうち教えたい方法です。
Sub CountItemsNested()
Dim ws As Worksheet
Dim i As Long, j As Long
Dim lastRowList As Long, lastRowData As Long
ws = ThisWorkbook.Sheets("Sheet1")
lastRowList = ws.Cells(Rows.Count, 1).End(xlUp).Row
lastRowData = ws.Cells(Rows.Count, 4).End(xlUp).Row
' 検索元リスト(A列)の各項目について
For i = 2 To lastRowList
' 検索先データ(D列)をループして一致したらセルに1を足す
For j = 2 To lastRowData
If ws.Cells(j, 4).Value = ws.Cells(i, 1).Value Then
ws.Cells(i, 2).Value = ws.Cells(i, 2).Value + 1
End If
Next j
Next i
End Sub
検索元の最初から最後までループする中に、検索先のループを入れ子にして、一致したら1を足していく方法です。セルに直接足していく方式なら2変数でもいけます。
③Dictionaryを使う方法
普段自分で使うならこれ。最初は全く理解できなかった連想配列も、めちゃくちゃわかりやすいYouTube動画を見てからはほぼこれを使っています。
Sub CountItemsDict()
Dim ws As Worksheet
Dim dict As Object
Dim i As Long, lastRow As Long
Dim key As Variant
ws = ThisWorkbook.Sheets("Sheet1")
lastRow = ws.Cells(Rows.Count, 4).End(xlUp).Row
Set dict = CreateObject("Scripting.Dictionary")
' D列のデータをDictionaryに集計
For i = 2 To lastRow
key = ws.Cells(i, 4).Value
If dict.exists(key) Then
dict(key) = dict(key) + 1
Else
dict.Add key, 1
End If
Next i
' 結果をA列・B列に書き出す
i = 2
For Each key In dict.Keys
ws.Cells(i, 1).Value = key
ws.Cells(i, 2).Value = dict(key)
i = i + 1
Next key
Set dict = Nothing
End Sub
3つの方法の中では一番処理が速く、検索元のリストがなくても個数を数えられるのがポイント。KeyにItemに個数を格納する形です。ただし連想配列の概念を理解していないといきなりはきついので、初心者にはだいぶ先に教える内容です。
まとめ:どの方法を使うべきか
- VBA初心者・入門:①WorkSheetFunction.CountIf
- Forループの練習として:②Forの入れ子
- 実務・処理速度重視:③Dictionary
最終的にはDictionaryが使えると応用が広がるので、慣れてきたら③を目指すのがおすすめです。
マイクロソフトエクセル2019 アイコン by Icons8