VBAオジサンのらくがき帳

Findメソッドによるセルの検索

2021-03-12 00:00:00

RangeオブジェクトのFindメソッドによるセルの検索方法についてまとめました。このメソッドは一部の引数を省略したときに前回の指定した値が使われたり、FindNextやFindPreviousと組み合わせて使ったり、使いこなすにはちょっとコツが必要ではないかと思います。

パラメーター

※ 指定しない場合は前回指定したものが使われる。

一つのセルを検索する処理

シート全体から”AAA”を含むセルを検索して選択する。

Cells.Find("AAA").Select

検索条件にマッチするセルがなかった時にはNothingが返ってくるため、エラーを回避するため下のようにチェックする必要があります。

Dim r As Range
Set r = Cells.Find("AAA")
If Not r Is Nothing Then
    r.Select
End If

引数のLookInを指定することにより、セル値だけではなく式やコメントを検索することもできます。

Set r = Cells.Find(""VLOOKUP"", , xlFormulas, xlPart)

順番に検索する処理

下のようにマッチするセルがたくさんある時の検索方法を見てみます。

引数のSearchOrderにxlByRowsを選択した場合には上の行から順番に検索されます。

Dim r As Range
Dim i As Integer
Set r = Range("A1:C3").Find("A", , , xlWhole, xlByRows)
Do Until r Is Nothing
    i = i + 1
    r.Value = i
    Set r = Range("A1:C3").FindNext
 Loop

引数のSearchOrderにxlByColumnsを選択した場合には左の行から順番に検索されます。

Set r = Range("A1:C3").Find("A", , , xlWhole, xlByColumns)
Do Until r Is Nothing
    i = i + 1
    r.Value = i
    Set r = Range("A1:C3").FindNext
Loop

左上のセルに9が設定されるのが少し違和感ありますが、これが引数のAfterのデフォルトが左上のセルになっているためです。左上セルから検索を行うためには下のように引数のAfterに右下を設定します。

Set r = Range("A1:C3").Find("A", Range("C3"), , xlWhole, xlByColumns)
Do Until r Is Nothing
    i = i + 1
    r.Value = i
    Set r = Range("A1:C3").FindNext
Loop

無限ループにならないように

ループの中で検索にマッチするセルがなくならない場合は、無限ループにならないような考慮が必要です。

下のコードはマッチしたセルのValueを変更しないため、FindNextがいつまでもマッチするセルを返すので無限ループとなります。(もしFindNextにAfterを指定しなければ、一つのセルで無限ループとなります。)

Set r = Range("A1:C3").Find("A", , , xlWhole)
Do Until r Is Nothing
    r.Interior.Color = vbRed
    Set r = Range("A1:C3").FindNext(r)
Loop

解決策1、最初にマッチしたセルの場所を残しておく。

Dim r As Range
Dim addr As String
Set r = Range("A1:C3").Find("A", , , xlWhole)
Do Until r Is Nothing
    If addr = "" Then
        addr = r.Address '最初にマッチしたセルのアドレス
    ElseIf addr = r.Address Then
        Exit Do
    End If
    r.Interior.Color = vbRed
    Set r = Range("A1:C3").FindNext(r)
Loop

解決策2、今までマッチしたセルのどれかが再度検索されたらやめる。

Dim r As Range
Dim addr As String
addr = "|"
Set r = Range("A1:C3").Find("A", , , xlWhole)
Do Until r Is Nothing
    If InStr(addr, "|" & r.Address & "|") > 0 Then
        Exit Do
    Else
        addr = addr & r.Address & "|"
     End If
    r.Interior.Color = vbRed
    Set r = Range("A1:C3").FindNext(r)
Loop

どちらのサンプルも完ぺきではないので、処理内容に応じた対応が必要でしょう。