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