FINDALL(全件検索)
複数の一致を一気に拾い上げて処理するなら、Range.Find + FindNext が定番です。最初のヒットのアドレスを覚えて一周したら終了、という型を覚えれば初心者でも安全に「全件検索」を扱えます。
基本:Find → FindNext の全件列挙テンプレ
Sub FindAll_Basic()
Dim rng As Range, hit As Range, first As String
Set rng = Range("A2:A10000")
Set hit = rng.Find(What:="ERROR", LookAt:=xlPart, LookIn:=xlValues) '部分一致で値を検索
If hit Is Nothing Then Exit Sub
first = hit.Address
Do
Debug.Print "ヒット: " & hit.Address & " 値=" & hit.Value
Set hit = rng.FindNext(hit)
Loop While Not hit Is Nothing And hit.Address <> first
End Sub
VB- ポイント:
- first を記録し一周で終了: 最初のヒット住所に戻ったらループを終えるのが定石。
- LookAt/LookIn を毎回明示: Find は設定を保持するため、意図しない検索を防げます。
応用:全ヒットをまとめて処理(Unionで集合化)
Sub FindAll_UnionAndProcess()
Dim rng As Range, hit As Range, first As String, allHits As Range
Set rng = Range("A2:A50000")
Set hit = rng.Find(What:="WARN", LookAt:=xlPart, LookIn:=xlValues)
If hit Is Nothing Then Exit Sub
first = hit.Address
Set allHits = hit
Do
Set hit = rng.FindNext(hit)
If hit Is Nothing Then Exit Do
If hit.Address = first Then Exit Do
Set allHits = Union(allHits, hit)
Loop
'一括処理:色付けや別シートへコピーなど
allHits.Interior.Color = RGB(255, 235, 156)
Worksheets("抽出").Range("A2").Resize(allHits.Count, 1).Value = Application.Transpose(allHits.Value)
End Sub
VB- ポイント:
- Unionで一括対象を作る: 集合化してから書式やコピーを一度に適用できる。
- FindNextは自動終了しない: 自分で「一周確認」する必要がある。
見出し検索と行・列への展開
'列見出しを探して列番号を取得 → その列だけ処理
Sub FindAll_HeaderColumn()
Dim headRow As Range, hit As Range
Set headRow = Range("A1:Z1")
Set hit = headRow.Find(What:="単価", LookAt:=xlWhole, LookIn:=xlValues)
If Not hit Is Nothing Then
Dim colNo As Long: colNo = hit.Column
Range(Cells(2, colNo), Cells(10000, colNo)).Value = _
Range(Cells(2, colNo), Cells(10000, colNo)).Value
End If
End Sub
'1件ヒットした行で横展開の計算
Sub FindAll_RowProcess()
Dim hit As Range
Set hit = Range("A2:A10000").Find(What:="顧客1001", LookAt:=xlWhole, LookIn:=xlValues)
If Not hit Is Nothing Then
Dim r As Long: r = hit.Row
Cells(r, "H").Value = Val(Cells(r, "C").Value) * Val(Cells(r, "D").Value)
End If
End Sub
VB- ポイント:
- 見出し検索に向く: 完全一致で見出しを特定して安全に列番号を取る。
- 行番号利用: hit.Row で同じ行の別列へアクセスが簡単。
複数キーワードの全件検索(誤ヒット抑制付き)
Sub FindAll_MultiKeywords()
Dim kw As Variant: kw = Array("ERROR", "WARN", "CRITICAL")
Dim src As Range: Set src = Range("A2:A80000")
Dim i As Long, first As String, hit As Range
For i = LBound(kw) To UBound(kw)
Set hit = src.Find(What:=kw(i), LookAt:=xlPart, LookIn:=xlValues, MatchCase:=False, SearchOrder:=xlByRows)
If hit Is Nothing Then GoTo NextKw
first = hit.Address
Do
'誤ヒットを減らすなら前後を検査(例:区切り記号など)
If InStr(1, hit.Value, kw(i), vbTextCompare) > 0 Then
hit.Font.Color = vbRed
End If
Set hit = src.FindNext(hit)
Loop While Not hit Is Nothing And hit.Address <> first
NextKw:
Next i
End Sub
VB- ポイント:
- LookAt/LookIn/MatchCase を都度指定: 設定保持に影響されないように。
- FindNextの巡回はキーワードごとに完結: 状態混線を防げます。
安全・高速ラップ(業務テンプレ)
Sub FindAll_SafeWrap()
Dim scr As Boolean: scr = Application.ScreenUpdating
Dim ev As Boolean: ev = Application.EnableEvents
Dim calc As XlCalculation: calc = Application.Calculation
On Error GoTo Cleanup
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'=== ここにFind/FindNextの本処理を記述 ===
Cleanup:
Application.Calculation = calc
Application.EnableEvents = ev
Application.ScreenUpdating = scr
End Sub
VB- ポイント:
- 設定退避→復帰: エラー時でも環境を元に戻す。大量検索の体感速度も向上します。
よくある落とし穴と対策
- 設定が保持されて意図と違う検索になる:
- 対策: 毎回 LookAt・LookIn・MatchCase を明示する。
- FindNextが終わらず無限ループ:
- 対策: 最初のヒットの Address を記録し、戻ってきたら終了。
- 完全一致のつもりが部分一致で拾ってしまう:
- 対策: LookAt:=xlWhole を使い、必要なら前後条件や区切りで確認。
- 数式が対象なのに見つからない:
- 対策: LookIn:=xlFormulas を使う。値なら xlValues。
- 大量件数で遅い:
- 対策: ヒットを Union で集合化し一括処理。書式やコピーを最小回数にする。
