Loading

ROUTE

ルートゼロの
アクティビティ

VBAのFindで値が見つからない原因と確認方法

1

Excelのセルに「営業」と書いてあるのに、VBAの`Range.Find`が見つけられない。そんなときは、検索対象(LookIn)、一致方法(LookAt)、書式検索(SearchFormat)を確かめましょう。`Find`は以前の設定を引き継ぐことがあるため、毎回明示するのが安全です。

結論:Findの検索条件を省略しない

`Range.Find`は指定範囲から値や文字列を探すExcel VBAのメソッドです。Microsoft Learnによると、`LookIn`・`LookAt`・`SearchOrder`・`MatchByte`などの設定は次の検索へ保存されます。Excelの検索ダイアログとも設定を共有するため、コードを変えていなくても結果が変わることがあります。

項目 意味 例
LookIn どこを見るか xlValues:値、xlFormulas:数式
LookAt 完全一致か部分一致か xlWhole / xlPart
SearchFormat セル書式を条件にするか False:書式条件を使わない
MatchCase 大文字小文字を区別するか False:区別しない

用語解説:Nothing
VBAでオブジェクトが見つからない、またはセットされていないことを表す特別な値。Findが失敗したときに返るため、使う前に確認します。


3行だけのサンプルで実行する

Excelの新しいブックを開き、シート名を`Sheet1`にして、A2に「営業」、A3に「営業部」、A4に「開発」と入力します。マクロが使えるデスクトップ版Excelで標準モジュールへ次のコードを貼ります。既存の重要なブックでは試さないでください。

Option Explicit

Sub FindExactSales()
    Dim ws As Worksheet
    Dim found As Range
    Set ws = ThisWorkbook.Worksheets("Sheet1")

    Set found = ws.Range("A2:A4").Find( _
        What:="営業", _
        After:=ws.Range("A4"), _
        LookIn:=xlValues, _
        LookAt:=xlWhole, _
        SearchOrder:=xlByRows, _
        SearchDirection:=xlNext, _
        MatchCase:=False, _
        MatchByte:=False, _
        SearchFormat:=False)

    If found Is Nothing Then
        Debug.Print "見つかりません"
    Else
        Debug.Print found.Address(False, False)
    End If
End Sub

VBAエディターのイミディエイトウィンドウ(Ctrl+G)で、想定出力は`A2`です。`LookAt:=xlWhole`なので「営業部」とは一致させません。`After`は検索開始位置の直前に当たるセルで、指定したセルそのものは折り返したあとに検索されます。

デスクトップ版Excelやマクロの実行権限がない環境では実行できません。セキュリティ警告を回避するための設定変更はせず、組織の運用ルールに従ってください。


完全一致と部分一致の違いを確認

同じ範囲で`LookAt:=xlPart`へ変更すれば、「営業」と「営業部」が両方候補になります。ただし`Find`は最初に見つけた1セルだけを返します。すべての結果が必要なら`FindNext`などで繰り返します。

Set found = ws.Range("A2:A4").Find( _
    What:="営業", LookIn:=xlValues, _
    LookAt:=xlPart, SearchOrder:=xlByRows, _
    SearchDirection:=xlNext, MatchCase:=False, _
    MatchByte:=False, SearchFormat:=False)

`xlValues`はセルに評価された値を対象にします。一方、数式そのものの文字列を調べたい場合は`xlFormulas`を選びます。「画面で値が見えるのに一致しない」場合、どちらを探しているかが重要です。


Nothingを確認してエラーを防ぐ

見つからなかったとき、`found.Address`のように直接プロパティを読もうとするとエラーになります。先に`Is Nothing`で判定してください。次は検索文字を「存在しない語句」に変えた例です。

Set found = ws.Range("A2:A4").Find( _
    What:="経理", LookIn:=xlValues, _
    LookAt:=xlWhole, SearchOrder:=xlByRows, _
    SearchDirection:=xlNext, MatchCase:=False, _
    MatchByte:=False, SearchFormat:=False)

If found Is Nothing Then
    Debug.Print "対象なし"
Else
    Debug.Print found.Address(False, False)
End If

この例の想定出力は`対象なし`です。セルが`Nothing`になったあとで`.Address`へ進むコードを書かないことがポイントです。

まだ見つからない場合のチェック表

確認点 起こりやすい問題 対処
検索範囲 A2:A4の外を探している 対象範囲とSheet名を確認
LookIn 数式を探すつもりが値を指定 目的に応じxlValues/xlFormulasを指定
LookAt 部分一致が必要なのにxlWhole xlPartへ変更
SearchFormat 以前の書式条件が残る Falseを明示し書式検索を無効化
データ 余計な空白や改行が含まれる セルの文字列を確認
大文字小文字 想定外に区別される MatchCaseを明示

`SearchFormat:=False`を指定しても「文字列が空白を含む」問題は直りません。まずセルの内容と検索条件を1つずつ揃え、条件を変えたら再実行して差を比べましょう。

複数ヒットのFindNextでは折り返しに注意

`Find`は検索範囲の末尾で先頭に戻るため、`FindNext`の繰り返しでは最初のセルのアドレスを覚えて停止します。次は先ほどの3行を探し、2件のセル番地を表示する例です。

Dim firstAddress As String
Set found = ws.Range("A2:A4").Find( _
    What:="営業", LookIn:=xlValues, LookAt:=xlPart, _
    SearchOrder:=xlByRows, SearchDirection:=xlNext, _
    MatchCase:=False, MatchByte:=False, SearchFormat:=False)
If Not found Is Nothing Then
    firstAddress = found.Address
    Do
        Debug.Print found.Address(False, False)
        Set found = ws.Range("A2:A4").FindNext(found)
        If found Is Nothing Then Exit Do
    Loop While found.Address <> firstAddress
End If

想定される2つのセルはA2とA3です。`FindNext`で先頭に戻るところまで探したら止めます。途中で見つからず`Nothing`になった場合も、先に退出するようにしています。

関連する学習と次の一手

VBAに慣れていない場合は、セルを指定する`Range`と`Cells`の違いを復習すると、検索範囲の見落としを減らせます。今回の記事はFindの引数を固定し、見つからない問題を切り分けることに絞りました。

(VBAでセルを指定する方法については『VBA RangeとCellsの使い分け判断マップ』をご参照ください)

(VBAの学習背景については『SES現場でVBAできますか?未経験向けExcelマクロ実践術』をご参照ください)

SearchFormatはTrueにすれば見つかりやすくなりますか?

いいえ。Trueはセル書式を検索条件に含める用途です。通常の値検索ではFalseを明示する方が予期しない絞り込みを避けられます。

検索対象が複数ある場合、Findだけで全部返りますか?

Findが返すのは最初の一致セルです。FindNextを使い、最初のセルに戻ったら終了するようにします。

まず3行の表でxlWholeとxlPartを切り替え、結果が変わることを自分のExcel環境で確認してみてください。

ルートゼロの採用情報を見る

すべてを開示している会社です

ポジティブな面もネガティブな面も、包み隠さず誠実にお答えします。
気になることがあれば、面談の際にすべてオープンにお話します。