Excel

【ExcelVBA】Findメソッドの種類と使い方

更新日:2023/12/01

Excel VBAのFindメソッドは、指定範囲内から条件に一致するセルを検索するメソッドです。
今回は、Findメソッドの使い方についてコード例とともに紹介します。

 

Findメソッドの概要

Findメソッドは範囲内から一つのセルを検索するメソッドです。
実際には、Excelの検索ダイアログでの操作をVBAコードでおこないます。

■Excel検索ダイアログ
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。

各引数と検索ダイアログは、次図のような関係になっています。

what:検索する文字 LookIn:検索対象 LookAt:セル内容が完全に… SearchOrder:検索方向 MatchCase:大文字と小文字を…  MatchByte:半角と全角を…

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)

先頭/後方一致(*の使用)

先頭から一致させるときは、次のように引数指定します。

What: 後方に"*"を記述
LookAt: xlWhole

次のコードは、"山"から始まる都道府県を検索しています。

Set resultRange = rng.Find("山*", LookAt:=xlWhole, LookIn:=xlValues)

後方一致は、whatの前方に"*"を記述します。

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

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。