Findメソッドによるセルの検索
2021-03-12 00:00:00
RangeオブジェクトのFindメソッドによるセルの検索方法についてまとめました。このメソッドは一部の引数を省略したときに前回の指定した値が使われたり、FindNextやFindPreviousと組み合わせて使ったり、使いこなすにはちょっとコツが必要ではないかと思います。
パラメーター
- What – 検索するデータ。
- After – 1つのセルを指定。この後から検索が始まる。指定しない場合は左上のセル。
- LookIn ※ – どの値を検索するか。xlFormulas、xlValues、xlComments、xlCommentsThreaded のいずれか。
- LookAt ※ – 完全一致か部分一致か。xlWhole か xlPart。
- SearchOrder ※ – 検索順。xlByRows か xlByColumns。
- SearchDirection – 検索の向き。xlNext(既定値) か xlPrevious。
- MatchCase – 大文字と小文字を区別する True、しない False(既定値) を指定する。
- MatchByte – 全角と半角を区別する True(既定値)、しない False を指定する。
- SearchFormat – 検索の書式
※ 指定しない場合は前回指定したものが使われる。
一つのセルを検索する処理
シート全体から”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
どちらのサンプルも完ぺきではないので、処理内容に応じた対応が必要でしょう。