Findの検索条件も再現条件に含める

LWP | 記事T254 同じコード・同じデータなのにFindの結果が変わる

図解1|同じ表、同じ検索語でも結果が違う

同じA2:A4と検索語Aでも、前回のLookAtが部分一致ならA01が候補となり、完全一致ならNothingになる比較

図1|検索条件も再現条件に含めます。図中のA2・A4は一致候補で、Find単体が複数セルを返す意味ではありません。

解説1|コードとデータのほかに、何が同じか

ストーリー

コイ丸先輩が以前から使っている検索マクロで、同じ商品コード表を調べているのに結果が変わりました。表もコードも変更していません。「直前に手で検索しただけなんだ」。その一言で、シャケモンはコードの外にある条件も確認することにしました。

入力例:比較する表は一つ

新しい検証用ブックに「Find確認」シートを作り、次の文字列を入力します。検索範囲は見出しを除いたA2:A4です。業務中のブックで試すと検索設定にも影響するため、確認用のブックで行います。

セル

入力する値

A1

商品コード

A2

A01

A3

B01

A4

A01

検索語Aと、値A01の関係

部分一致では、A01の一部分であるAも一致します。完全一致では、Aという値そのものが必要です。この表にはAそのものがないため、完全一致で探すと該当なしになります。表の変更がなくても、一致の定義が違えば結果は変わります。 図中のFind(What:="A")は検索範囲に対する呼び出しの省略表記です。LookAtを省略して以前の条件を引き継ぐことを観測する例であり、完成版の実装ではありません。Findが返すのは最初の一致セル1個、またはNothingです。

読むポイント

再現メモには、ブック・範囲・検索語だけでなく、直前の検索条件と期待する一致の意味も残します。部分一致と完全一致を比較するときは、LookAt以外の条件をそろえます。まだ原因を特定していない段階で「データが壊れた」と決めつけないことが大切です。

図解2|手作業の検索とFindは条件を共有する

検索ダイアログとVBA FindがLookIn、LookAt、SearchOrder、MatchByteの保存設定を共有し、省略呼び出しへ影響する構造

図2|4引数の保存値と、検索ダイアログとの相互影響を示す模式図です。

解説2|省略した条件は、前回の値から補われる

Range.Findは、ある範囲から指定した値を探してRangeを返すメソッドです。検索文字列Whatだけが入力のすべてではありません。次の4引数は設定が保存され、省略すると前回の値が使われます。

引数

決めること

今回の固定値

LookIn

値・数式など、何を調べるか

xlValues

LookAt

完全一致か部分一致か

xlWhole

SearchOrder

行方向か列方向か

xlByRows

MatchByte

全角と半角を区別するか

False

共有される状態が、コードの外にある

検索ダイアログでこれらの条件を変えると、次のFindにも影響します。逆に、Findで指定した条件は検索ダイアログ側へ反映されます。図の双方向の矢印は、この相互影響を表しています。ダイアログは模式図で、特定版の画面操作手順ではありません。 手作業を禁止することが解決ではありません。マクロが必要とする条件を呼び出し側で指定すれば、前回の設定へ依存する箇所を減らせます。「前回はたまたま完全一致だった」状態に頼らず、今回の要件をコードへ残します。

4引数の保持と、必要な全指定を区別する

次の完全例では、保存される4引数に加え、After、SearchDirection、MatchCase、SearchFormatも明示します。これらすべてが同じ保存規則を持つという意味ではありません。開始位置、方向、大文字小文字、書式条件まで今回の例として固定するためです。

読むポイント

LookAtを明示することは「何を一致とするか」の対策です。FindNextをどこで終了させるかは、反復処理を終えるための別の条件です。二つを混同せず、どちらも完全例の中で確認します。

図解3|条件を明示した検索を一つの関数にする

FindCellAddressesの入力と出力、検索条件、Afterの次から探す位置、Nothingと一巡の終了条件

図3|検索条件を固定し、見つからない場合と一巡した場合の終了を備えます。

解説3|検索条件を固定して一致するセルを列挙する

サンプルコード FindCellAddresses(全文30行)

01

Option Explicit

02

03

Public Function FindCellAddresses( _

04

        ByVal a_target As Range, _

05

        ByVal a_searchText As String) As String

06

    Rem @name       FindCellAddresses

07

    Rem @desc       値が完全一致するセルのアドレスを返します。

08

    Rem @param      a_target 単一の連続した検索範囲。

09

    Rem @param      a_searchText 検索文字列。この例ではA01等を指定。

10

    Rem @return     カンマ区切りのアドレス。該当なしは空文字列。

11

    Dim foundCell As Range

12

    Set foundCell = a_target.Find( _

13

        What:=a_searchText, _

14

        After:=a_target.Cells(a_target.Cells.Count), _

15

        LookIn:=xlValues, LookAt:=xlWhole, _

16

        SearchOrder:=xlByRows, SearchDirection:=xlNext, _

17

        MatchCase:=False, MatchByte:=False, SearchFormat:=False)

18

    If foundCell Is Nothing Then Exit Function

19

20

    Dim firstAddress As String

21

    Dim result As String

22

    firstAddress = foundCell.Address

23

    Do

24

        If Len(result) > 0 Then result = result & ","

25

        result = result & foundCell.Address(False, False)

26

        Set foundCell = a_target.FindNext(After:=foundCell)

27

        If foundCell Is Nothing Then Exit Do

28

    Loop While foundCell.Address <> firstAddress

29

    FindCellAddresses = result

30

End Function

コードの説明

12~17行目で値・完全一致などを指定します。14行目のAfterは範囲最後のセルで、この例はA4の次のA2から検索します。18行目はNothingならAddressを読まず終了します。22~28行目は最初の絶対アドレスを保存し、一巡して戻ったら終了します。途中のNothingも27行目で判定します。

入力・概要

標準モジュールへ全文を置きます。引数は単一連続範囲と検索文字列、戻り値はカンマ区切りのアドレスです。該当なしは空文字列。呼び出しと確認は次の解説へ続きます。

図解4|手作業の履歴を替えても同じ結果か

事前の部分一致と完全一致を替えたうえでA01、B01、Z99、Aの戻り値と終了を確認する表

図4|同じデータで、複数件・1件・該当なしと検索終了を再確認します。

解説4|アドレスと終了まで、同じ条件で再確認する

入力後:イミディエイトで呼び出す

「Find確認」シートを持つ検証ブックの標準モジュールに前頁の関数を置き、VBEのイミディエイト ウィンドウで次の1行を実行します。ThisWorkbookは、そのコードを置いたブックを指します。

サンプルコード イミディエイトの呼び出し

01

? FindCellAddresses(ThisWorkbook.Worksheets("Find確認").Range("A2:A4"), "A01")

結果:検索語を一つずつ変える

検索語

期待する戻り値

確認する場面

A01

A2,A4

複数件を一巡して終了

B01

A3

1件を追加して終了

Z99

空文字列

該当なしで終了

A

空文字列

完全一致を維持

直前の検索を部分一致にした場合と、完全一致にした場合の両方で確かめます。件数だけでなく、返されたセルのアドレス、重複の有無、処理が終了することを確認します。この関数は検索条件を明示しますが、実行後に以前の検索設定へ戻す処理は含みません。

読むポイント:適用できる範囲

この例は一つの連続範囲で文字列の値を検索します。検索中に条件やセル値を変えない前提です。「*」「?」「~」を含む検索語、結合セル、複数領域へそのまま一般化しません。別の要件では、その条件に合う検索と確認例を用意します。 記事制作時はExcel 16.0で、事前のLookAtを変えた省略検索2ケースと、原稿関数8ケースを確認しました。手作業の検索ダイアログ操作と他のExcel版は未実測です。

出典メモ

『デバッキング Excel VBA』V026_261006、5.2.6「Find・FindNextの検索条件と終了条件を確認する」、VDBG-C05-040の30行と入力例を採用。構造・理由・適用条件を保ち、相談場面を加えました。Range.Find公式仕様/Range.FindNext公式仕様。

利用について

Copyright © 2026 LWP 山中 一弘。 本資料は、出典を明記いただければ、商用・非商用を問わず、ご自由に複製・改変・再配布していただけます。なお、著作権表示は改変せず、そのまま記載してご利用くださいますようお願いいたします。