【ExcelVBA】Findメソッドの種類と使い方
更新日:2023/12/01
Excel VBAのFindメソッドは、指定範囲内から条件に一致するセルを検索するメソッドです。
今回は、Findメソッドの使い方についてコード例とともに紹介します。
Findメソッドの概要
Findメソッドは範囲内から一つのセルを検索するメソッドです。
実際には、Excelの検索ダイアログでの操作をVBAコードでおこないます。
■Excel検索ダイアログ
複数のセルを検索するときは、FindNextまたはFindPreviousメソッドを組み合わせて検索します。
メソッド | 引数 | 戻り値 | 意味 |
---|---|---|---|
Find | 複数の検索条件 | セル | 検索パネルに検索条件をセットして、後方または前方検索する |
FindNext | 検索開始セル | セル | 検索パネルの条件を使って、検索開始セルの次から後方検索する |
FindPrevious | 検索開始セル | セル | 検索パネルの条件を使って、検索開始セルの次から前方検索する |
Findメソッド実行後にExcel検索ダイアログを開くと、検索条件が置き換わっていることを確認できます。
※ダイアログを開いたままで実行した場合は、置き換わりません。
FindNextまたはFindPreviousは、検索範囲内をループします。
そのため、VBAコードで終了判定する必要があります。
Findでの検索例
次の図のようにExcelシートのA列に都道府県名が入力されているとします。
ここから、名前に『山』を含むものをFindとFindNextメソッドを使用して抽出するコードを検索例として紹介します。
Sub sample1()
Dim rng As Range ' 検索範囲
Dim resultRange As Range ' 検索結果
Dim loopStart As String ' ループ判定用
Dim result As String
result = ""
' 検索範囲を設定
Set rng = Worksheets("Sheet1").Range("A:A")
' 最初の検索
Set resultRange = rng.Find("山")
If Not resultRange Is Nothing Then
' ループ判定用オブジェクトをセット
loopStart = resultRange.Address
Do
result = result & resultRange.Value & vbCrLf
' 次の値を検索
Set resultRange = rng.FindNext(resultRange)
Loop Until resultRange Is Nothing Or resultRange.Address = loopStart
End If
MsgBox result
End Sub
実行すると、次のようなメッセージが表示されます。
初回に取得したセルのAddressプロパティと、それ以降に取得したセルのAddressプロパティを比較して内容が一致したら、一周したとみなして終了です。
Findメソッド
Findメソッドは検索条件を設定して、範囲内を後方または前方検索した結果を返します。
Findメソッドの構文は次のようになっています。
検索結果 = Rangeオブジェクト.find( What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat)
条件に一致するセルが見つかった場合は、そのセルが返ります。
見つからないときは、Nothingです。
引数は次のようになっています。
- What
検索する文字列。
次のワイルドカードを使用可能。
"*":0文字以上の任意文字列と一致
"?":任意の一文字と一致 - After
検索範囲内のセルを指定する。
指定したセルの次のセルから検索が開始する。
省略可能。
規定値は左上端(左隅の次のセルから検索開始) - LookIn
検索対象を指定する。
・xlValues:値
・xlFormulas:数式
・xlComments:コメント
・xlCommentsThreaded:スレッド化されたコメント(メモ)
省略可能。規定値は前回の値。 - LookAt
テキスト全体と一致させるか、一部と一致させるかを指定する。
・xlPart:一部と一致
・xlWhole:全体と一致
省略可能。規定値は前回の値。 - SearchOrder
行方向に検索するか、列方向に検索するかを指定する
・xlByColumns:行方向に検索後、次の列を検索
・xlByRows:列方向に検索後、次の行を検索
省略可能。規定値は前回の値。 - SearchDirection
前方方向に検索するか、後方方向に検索するかを指定する
・xlNext:後方を検索
・xlPrevious:前方を検索
省略可能。規定値はxlNext。 - MatchCase
大文字と小文字を区別するかどうかを指定する
・True:区別する
・False :区別しない
省略可能。規定値はFalse。 - MatchByte
同一とみなせる全角文字と半角文字( "A" と "A" など)を区別するかどうかを指定する
・True:区別する
・False :区別しない
省略可能。規定値は前回の値。 - SearchFormat
Application.FindFormat.で指定した書式を検索するかどうかを指定する
・True:書式で検索する
・False :書式で検索しない
省略可能。規定値はFalse。
各引数と検索ダイアログは、次図のような関係になっています。
AfterとSearchDirectionおよびSearchFormatはVBA固有のため、ダイアログに対応する項目がありません。
LookIn、LookAt、SearchOrder、MatchByteは次回のFindメソッド呼び出しで規定値として使用されます。
またExcelのインスタンスを複数起動しているとき、他のインスタンスでの検索設定の影響を受けます。
これらの引数の規定値は不定と考えて、コードを作成する必要があります。
FindNextメソッド
FindNextは現在の検索設定を元に、後方検索した結果を返します。
FindNextの構文は、次のようになっています。
検索結果 = Rangeオブジェクト.FindNext( After )
Afterで指定したセルの次のセルから検索を開始します。
範囲内の最後尾に到達した場合、先頭に戻ってAfterまで検索します。
条件に一致するセルが見つかった場合は、そのセルが返ります。
見つからないときは、Nothingです。
FindNextは、FindのSearchFormatを引き継ぎません。
そのため書式検索で使用できません。
FindPreviousメソッド
FindPreviousは現在の検索設定を元に、前方検索した結果を返します。
FindPreviousの構文は、次のようになっています。
検索結果 = Rangeオブジェクト.FindPrevious( Before )
Beforeで指定したセルの前のセルから検索を開始します。
範囲内の先頭に到達した場合、最後尾に戻ってBeforeまで検索します。
条件に一致するセルが見つかった場合は、そのセルが返ります。
見つからないときは、Nothingです。
FindPreviousは、FindのSearchFormatを引き継ぎません。
そのため書式検索で使用できません。
Findメソッドの使用例
Findメソッドの使用例を、いくつか紹介します。
文字数一致(?の使用)
特定の文字数の文字列を一致させたいときは、"?"を使用します。
次のコードは、3文字の県を検索しています。
Set resultRange = rng.Find("???県", LookAt:=xlWhole, LookIn:=xlValues)
先頭/後方一致(*の使用)
先頭から一致させるときは、次のように引数指定します。
LookAt: xlWhole
次のコードは、"山"から始まる都道府県を検索しています。
Set resultRange = rng.Find("山*", LookAt:=xlWhole, LookIn:=xlValues)
後方一致は、whatの前方に"*"を記述します。
LookAt: xlWhole
次のコードは、"府"で終わる都道府県を検索しています。
Set resultRange = rng.Find("*府", LookAt:=xlWhole, LookIn:=xlValues)
数値と一致
任意の数値を一致させるときは、LookAtにxlWholeを指定します。
次のコードは、数値3を一致させています。
Set resultRange = rng.Find(3, LookAt:=xlWhole, LookIn:=xlValues)
※LookAtにxlPartを指定すると、33 や 10003 など 3を含むセルに一致します。
書式が一致
次のコードは、特定のセルと同じ背景色を持つセルを検索しています。
Sub sample2()
Dim rng As Range ' 検索範囲
Dim resultRange As Range ' 検索結果
Dim loopStart As String ' ループ判定用
Dim result As String
result = ""
' 書式検索条件クリア
Application.FindFormat.Clear
' 書式検索条件の設定
Application.FindFormat.Interior.Color = Worksheets("Sheet1").Range("B2").Interior.Color
' 検索範囲を設定
Set rng = Worksheets("Sheet1").Range("A:A")
' 最初の検索
Set resultRange = rng.Find("*", LookIn:=xlValues, SearchFormat:=True)
If Not resultRange Is Nothing Then
' ループ判定用オブジェクトをセット
loopStart = resultRange.Address
Do
result = result & resultRange.Value & vbCrLf
' 次の値を検索
Set resultRange = rng.Find("*", after:=resultRange, LookIn:=xlValues, SearchFormat:=True)
Loop Until resultRange Is Nothing Or resultRange.Address = loopStart
End If
MsgBox result
End Sub
FindNextが書式検索を行わないので、2回目以降もfindを使用しています。
使用するApplication.FindFormatのプロパティは、検索ダイアログの書式設定をExcelのマクロ記録機能で記録して生成されたプロシージャを見るのが一番手っ取り早いです。
複数条件と一致
Findメソッドは複数条件を指定できません。
そのため、一工夫する必要があります。
AND条件
二つの条件の両方に一致するセルを取得するときは、まず一つの条件でFind検索をおこないます。
その結果に対して、二つ目の条件が一致するかを確認します。
次のコードは、"川"と"神"を含む都道府県を検索しています。
Sub sample3()
Const key1 = "川"
Const key2 = "神"
Dim rng As Range ' 検索範囲
Dim resultRange As Range ' 検索結果
Dim loopStart As String ' ループ判定用
Dim result As String
Debug.Print Worksheets("Sheet1").Range("A2").Value
result = ""
' 検索範囲を設定
Set rng = Worksheets("Sheet1").Range("A:A")
' 最初の検索
Set resultRange = rng.Find(key1, LookAt:=xlPart, LookIn:=xlValues)
If Not resultRange Is Nothing Then
' ループ判定用オブジェクトをセット
loopStart = resultRange.Address
Do
' 二つ目のキーとの一致判定
If InStr(resultRange.Value, key2) > 0 Then
result = result & resultRange.Value & vbCrLf
End If
' 次の値を検索
Set resultRange = rng.FindNext(resultRange)
Loop Until resultRange Is Nothing Or resultRange.Address = loopStart
End If
MsgBox result
End Sub
キーにワイルドカードが含まれるときは、Like演算子で比較をおこないます。
' 二つ目のキーとの一致判定
If resultRange.Value Like key2 Then
result = result & resultRange.Value & vbCrLf
End If
OR条件
二つの条件のうち、どちらか、または両方が一致するセルを取得します。
方法としては一つ目の条件で一致するセルを取得します。
次に二つ目の条件で一致するものを取得しますが、一つ目との重複をチェックします。
Sub sample4()
Const key1 = "山"
Const key2 = "島"
Dim rng As Range ' 検索範囲
Dim resulArray() As Range
Dim count As Integer
count = -1
' 検索範囲を設定
Set rng = Worksheets("Sheet1").Range("A:A")
' key1の検索
Set resultRange = rng.Find(key1, LookAt:=xlPart, LookIn:=xlValues)
If Not resultRange Is Nothing Then
' ループ判定用オブジェクトをセット
loopStart = resultRange.Address
Do
count = count + 1
ReDim Preserve resulArray(count)
Set resulArray(count) = resultRange
Set resultRange = rng.FindNext(resultRange)
Loop Until resultRange Is Nothing Or resultRange.Address = loopStart
End If
' key2の検索
Set resultRange = rng.Find(key2, LookAt:=xlPart, LookIn:=xlValues)
Dim i As Integer
If Not resultRange Is Nothing Then
' ループ判定用オブジェクトをセット
loopStart = resultRange.Address
Dim inFlg As Boolean
Do
' 重複チェック
inFlg = False
For i = 0 To count
If resulArray(i) Is resultRange Then
inFlg = True
Exit For
End If
Next
If inFlg = False Then
count = count + 1
ReDim Preserve resulArray(count)
Set resulArray(count) = resultRange
End If
Set resultRange = rng.FindNext(resultRange)
Loop Until resultRange Is Nothing Or resultRange.Address = loopStart
End If
Dim result As String
result = ""
For i = 0 To count
result = result & resulArray(i).value & vbCrLf
Next
MsgBox result
End Sub
一つ目の条件にマッチするセルが多いと、二つ目の検索の重複チェックループの回数が増大します。
場合によってはFindを使わずに、次のようにセルをループして値を確認した方がいいかもしれません。
Sub sample5()
Const key1 = "山"
Const key2 = "島"
Dim rng As Range ' 検索範囲
Dim value As String
Dim result As String
result = ""
For Each rng In Worksheets("Sheet1").Range("A:A")
value = rng.value
If InStr(value, key1) > 0 Or InStr(value, key2) > 0 Then
result = result & value & vbCrLf
End If
Next rng
MsgBox result
End Sub
更新日:2023/12/01
関連記事
スポンサーリンク
記事の内容について
こんにちはけーちゃんです。
説明するのって難しいですね。
「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。
裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。
掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。
ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php
このサイトは、リンクフリーです。大歓迎です。