findメソッド

【VBA】Findメソッドの基本的な使い方(引数の使い方、戻り値、注意点と代替手段)

記事内に商品プロモーションを含む場合があります

こんにちは、hokkyokunです。

Findメソッドとは
特定の範囲から特定の条件に合ったセルの位置を一つ取得するメソッドです。

もともとVBAに備わっているメソッドなので
すぐ使え、書籍にも「セルを検索する手法」として多く取り扱われています

一方、ちょっと使い方に癖があり、難しめのメソッドでもあります。
使い方を確認していきましょう。

タイトルに「基本的」と入れましたが、
かなりマニアックなところまで含めて書きました。
この記事を読めばFindメソッドのことがかなりわかると思います。

Findメソッドの記事をいくつかかいています。
よかったら他の記事も見ていってください。

Findメソッドの基本構文

構文

基本構文は以下のようになります。

Dim Rng As Range

Rng.Find(what:="検索する値", _
        After:="セルを指定。このセルより後から検索", _
        LookIn:="xlValues:値 or xlFormula:計算式 or xlComments:コメント", _
        LookAt:="xlWhole:完全一致 or xlPart:部分一致", _
        SearchOrder:="xlByRows:横方向 or xlByColumns:縦方向", _
        SearchDirection:="xlNext:順方向 or xlPrevious:逆方向", _
        MatchCase:="True:大文字小文字区別する or False:区別しない", _
        MacthByte:="True:半角全角区別する or False:区別しない", _
        SearchFormat:="True:書式設定検索する or False:しない")

引数

引数の内容説明です。

名前(は必須)定数説明重要度
What検索するデータ
Afterセルを指定
指定するセルは一つのセル
指定したセルの次のセルから検索開始
指定したセルは最後に検索
×
LookInxlFormula : 計算式
xlValues : 値
xlComments:コメント
検索する対象を指定
xlCommentsを指定すると
コメントの内容を検索する
LookAtxlWhole:完全一致
xlPart:部分一致
検索する対象がWhatの値と
完全に一致するか部分的に一致するか
SearchOrderxlByRows:行方向
xlByColumns:列方向
検索する方向を指定
行方向(横)か列方向(縦)
×
SearchDirectionxlNext:順方向
xlPrevious:逆方向
検索する方向を指定
左から右、下から上(順方向)
もしくはその逆か
×
MatchCaseTrue:区別
False:区別しない
大文字と小文字を区別して検索
what:=appleで
「APPLE」をヒットさせたいかどうか
MatchByteTrue:区別
False:区別しない
全角と半角を区別して検索
what:=リンで
「リン」をヒットさせたいかどうか
SearchFormatTrue:指定する
False:指定しない
検索の書式を指定するか
複雑なため別記事で
△?
〇?

たくさんありますね、
ただほとんど不要です。

詳しい使い方は下記の「使い方」で
引数別に紹介します。

重要度で〇以上のものから使えるようになればOKです。
なれてくれば△のものを必要に応じて使ってください。

×はむしろ使うべきではありません

検索する位置や方向を指定していますが、
ここをいじって検索結果をどうこうするよりかは
エクセルの表の作り方やプログラミングコードを見直すべきです。

引数を省略するとどうなる?

Findメソッドを極端に難しくしている謎の仕様がこれなのですが、
引数によって省略した場合の対応が異なります

名前(は必須)定数引数を省略した場合最初に使った場合
What
Afterセル範囲の左上のセルセル範囲の左上のセル
LookInxlFormula : 計算式
xlValues : 値
xlComments:コメント
前回の引数の値と同等xlFormula
LookAtxlWhole:完全一致
xlPart:部分一致
前回の引数の値と同等xlPart
SearchOrderxlByRows:行方向
xlByColumns:列方向
前回の引数の値と同等xlByRows
SearchDirectionxlNext:順方向
xlPrevious:逆方向
xlNextxlNext
MatchCaseTrue:区別
False:区別しない
FalseFalse
MatchByteTrue:区別
False:区別しない
前回の引数の値と同等True
SearchFormatTrue:指定する
False:指定しない
検証中検証中

頭が痛くなりそうですが
ポイントは二つです。

  1. LookIn,LookAt,SearchOrder,MatchByte
    前回の引数を引き継ぐので毎回指定するか設定をリセットする
  2. MatchByteはデフォルトがTrue(=半角全角の区別をする)
    半角全角が混じった表を扱う場合は注意

詳しくは本ページ下記の「注意点」を見てください。

控えめに言っても大混乱させる仕様です(笑)

Findメソッドよりも簡単で高速、エラーも起こしにくい関数を作ったので
よかったら見て頂ければと思います。

【VBA】Findメソッドよりも簡単、早い!高速でセル位置を検索、取得する方法。完全一致、部分一致対応。複数セル取得対応。 わかること Findメソッドよりも高速で操作が簡単、エラーにも強い方法を紹介します。 オリジナル関数ですが、コピペで使えます。...

こちらはFindNextメソッドの代替手段(関数)です。

【VBA】FindNextメソッドうまくいかないなら試してみて!セル範囲を全検索する方法(簡単、高速、エラーにも強い) このページでわかること 指定したセル範囲のうち、特定のセルを全取得する方法がわかります。 オリジナル関数です。3つの関数をコピ...

戻り値

戻り値はレンジオブジェクトです。
つまりセルを返してくれます。

検索で見つからない場合は
Nothing」が返ってきます。

あるあるなのが
セルが返ってくると思って「.Value」で値を参照して
エラーが吐き出されるという現象
です。

しっかりエラー対策をしておきましょう。

こちらに記事がありますので参考にしてみてください

【VBA Findメソッド】あるのに見つからない場合に試すこと4選。エラー回避と代替手段 このページでわかること Findメソッドは見つからない場合、続けて処理するとエラーが生じる可能性がある。→エラー回避方法を紹介 ...

Findメソッドとエクセルのダイアログ検索ボックス(Ctrl + F)

複雑な構造のFindメソッドですが、
これはエクセル上で「Ctrl + F 」で開く検索ダイアログと同じ構造になっています。

比較してみましょう。

こうやってみるとダイアログボックスのほとんどの仕様を
VBAで動かせるようです。

引数別の使い方

下記の図のような表を用意します。
セル範囲 A1:C6 を引数を変えながら検索してみようと思います。

下記でも述べていますが、
Findメソッドには注意する点が三つあります。

  1. 指定したセル範囲の最初のセルは最後に検索される
  2. MatchByteの引数はかなり複雑
  3. 前回の設定を保持する引数がある

詳しくは下記に記載している「注意点」を確認してください

What:検索する値を指定

まずはWhatの使い方と
他の引数を指定しない場合(=デフォルト)での検索の仕方を確認しておこうと思います。

Sub test1()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")

Debug.Print ws.Range("A1:C6").Find(what:="リンゴ").Address
'>>$C$1

ws.Range("A1:C6").Find(what:="リンゴ").Borders.Color = vbRed

End Sub

Whatは必須の引数です。

セル範囲から該当のセルのうち、
最初にヒットしたセルを返します。

デフォルトでは行方向(横方向)への検索となるので
C1が最初にヒットします。
A2ではないことを注意しましょう。

※Whatの内容とは関係ないのですが、
上記のコードを試した後ダイアログボックスを確認してみると
「半角全角の区別をする」にチェックが入
っています。

上記のtest1を動かした後のダイアログボックスの設定
引数指定していないのに「半角と全角を区別する」にチェックが入ります。

引数を指定しないとデフォルトで
半角全角の区別をするになります。

また、その仕様は引き継がれます。

注意が必要です
というかなんだこの仕様…

After:検索開始位置を指定

Afterで検索開始位置を変更します。
A2を指定した場合の動きを確認しましょう。

Sub test2()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")

Debug.Print ws.Range("A1:C6").Find(what:="リンゴ", After:=ws.Range("A2")).Address
'>>$A$6

ws.Range("A1:C6").Find(what:="リンゴ", After:=ws.Range("A2")).Borders.Color = vbRed
End Sub

Afterは指定したセル範囲のうち
検索開始するセルを指定できます。

注意点は指定したセルの次のセルから検索するということです。
つまり指定したセル=最後に検索するセルということになります。

今回でいうとA6がヒットします。

A2ではないことに注意しましょう。
Findメソッドは指定したセルの次のセルから検索を開始する仕様となっています。

LookIn:検索対象を指定

LookInは何を対象として検索するかを指定できます。

コメントの内容を検索してみましょう。

Sub test3()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(1)

Debug.Print ws.Range("A1:C6").Find(what:="リンゴ", LookIn:=xlComments).Address
'>>$A$4

ws.Range("A1:C6").Find(what:="リンゴ", LookIn:=xlComments).Borders.Color = vbRed
End Sub

LookInは検索対象を指定できます。

検索する対象を
値、数式、コメントで検索できます。

デフォルトはxlFormula(数式)です。
※使い勝手は良くないので個人的にはxlValues(値)に変えて使っています。

引数は前回指定の引数の値を継承します。
詳しくは「注意点」

コメント検索ですので、
A4がヒットします。

C1やA2ではないですね。

LookAt:完全一致か部分一致か

かなりお世話になる引数です。
完全一致させるか部分的にでも一致しているかは実務において非常に重要です。

「リン」を完全一致させましょう。

Sub test4()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(1)

Debug.Print ws.Range("A1:C6").Find(what:="リン", LookAt:=xlWhole).Address
'>>$C$2

ws.Range("A1:C6").Find(what:="リン", LookAt:=xlWhole).Borders.Color = vbRed

End Sub

LookAtは完全一致か部分一致かを選択できます。

xlWholeで完全一致
xlPartで部分一致

デフォルトでは部分一致となっています。

引数は前回指定の引数の値を継承します。
詳しくは「注意点」

「リン」を部分一致させたら、C1がヒットしますが、
完全一致にしたのでC2がヒットしました。

最も重要な引数と言えるかもしれません。

SearchOrder:検索方向を行方向か列方向か指定

Sub test5()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(1)

Debug.Print ws.Range("A1:C6").Find(what:="リンゴ", searchorder:=xlByColumns).Address
'>>$A$2

ws.Range("A1:C6").Find(what:="リンゴ", searchorder:=xlByColumns).Borders.Color = vbRed
End Sub

検索方向を
行方向(横方向)か列方向(縦方向)かを選択できる

デフォルトは行方向

引数は前回指定の引数の値を継承します。
詳しくは「注意点」

C1ではなく、A2がヒットしました

SearchDirection:順方向か逆方向か

通常は左から右、上から下への検索をかけていきますが、
逆方向から検索をかけることも可能です。

Sub test6()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(1)

Debug.Print ws.Range("A1:C6").Find(what:="リンゴ", SearchDirection:=xlPrevious).Address
'>>$A$6

ws.Range("A1:C6").Find(what:="リンゴ", SearchDirection:=xlPrevious).Borders.Color = vbRed
End Sub

C1ではなくA6がヒットしました。

SearchDirectionは検索順序を指定します。

xlNext:上から下、左から右
xlPrevious:その逆方向

デフォルトは上から下、左から右

MatchCase:大文字小文字を区別する、しない

大文字小文字を区別する場合ももしかしたらあるかもしれません
「apple」ではなく「Apple」を検索してみましょう。

Sub test7()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(1)

Debug.Print ws.Range("A1:C6").Find(what:="Apple", MatchCase:=True).Address
'>>$A$5

ws.Range("A1:C6").Find(what:="Apple", MatchCase:=True).Borders.Color = vbRed
End Sub

MatchCaseは大文字小文字を区別して
検索するかどうかを指定します。

True:区別する
False:区別しない

デフォルトは区別しない

A4の「apple」を通り過ぎて
A5の「Apple」をヒットさせました。

MatchByte:半角全角を区別する、しない

半角「リン」をヒットさせてみます。
「リンゴ」などは無視させて、「リン」と「リン」の比較対象を行うため
完全一致で検索します。

Sub test8()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(1)

Debug.Print ws.Range("A1:C6").Find(what:="リン", LookAt:=xlWhole, MatchByte:=True).Address
'>>$A$3
ws.Range("A1:C6").Find(what:="リン", LookAt:=xlWhole, MatchByte:=True).Borders.Color = vbRed


'半角全角の区別をつけないとC2がヒットする
Debug.Print ws.Range("A1:C6").Find(what:="リン", LookAt:=xlWhole, MatchByte:=False).Address
'>>$C$2

End Sub

MatchByteは半角全角を区別して検索するかどうかを指定します。

True:区別する
False:区別しない

デフォルトは区別する

引数は前回指定の引数の値を継承します。
詳しくは「注意点」

ちなみにですが、
「リンゴ」ではうまくいきません。

MatchByteの引数をTrueにしようがFalseにしようが
What:=リンゴでは「リンゴ」はヒットしません。
いずれにしても「リンゴ」だけヒットします。

「リンゴ」の「゛」が原因だと思いますが、
あまり深追いしても使い道がないので検証はこのあたりにしておきます。

MatchByteは引数を指定しないと
True(=半角全角を区別する)となります。

半角全角が混じった表を使う場合は注意が必要です。

SearchFormat:検索する書式を指定する、しない

こちらに関しては内容が多岐にわたるので
別記事でご紹介します。

Findメソッドの注意点

ちょこちょこ申し上げましたが、
改めてFindメソッドの注意点をまとめてみます。

検索セル範囲の先頭は最後に検索される

例えば、下図のような表で
A1:C6の範囲で「リンゴ」を検索するとします。

Sub test_range()

Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(2)

Debug.Print ws.Range("A1:C6").Find("リンゴ").Address
'>>$C$1
End Sub

素直に考えればA1セルを取得できると思いますが、
実際にはC1セルです。

検索範囲の先頭は最後に検索されるので
自分が意図しない動きをしないか注意しておきましょう。

MatchByteの引数は要注意

MatchByteは半角全角を区別するかどうかの引数です。

エクセルを開いて最初にFindメソッドを使う場合、
引数を指定しないと勝手にTrueとして半角全角を区別します。

しかもその後は、前回の設定に依存するので
次回以降も区別し続けます。

上記のtest1プロシージャを動かした後のダイアログボックスの設定
引数指定していないのに「半角と全角を区別する」にチェックが入ります。

個人的には半角全角の混ざったエクセル運用を
禁止すべきだと思います。

が、マスタデータなどは
そうも言ってられないと思いますので、

エラーが起きそうなら引数の設定(特にMatchByte)は
さぼらず指定すべき
でしょう。

引数の設定が前回の処理に引っ張られる

上記でもまとめた表と同じですが、
特に前回の処理に引っ張られるものを赤字で協調しておきます。

名前(は必須)定数引数を省略した場合最初に使った場合
What
Afterセル範囲の左上のセルセル範囲の左上のセル
LookInxlFormula : 計算式
xlValues : 値
xlComments:コメント
前回の引数の値と同等xlFormula
LookAtxlWhole:完全一致
xlPart:部分一致
前回の引数の値と同等xlPart
SearchOrderxlByRows:行方向
xlByColumns:列方向
前回の引数の値と同等xlByRows
SearchDirectionxlNext:順方向
xlPrevious:逆方向
xlNextxlNext
MatchCaseTrue:区別
False:区別しない
FalseFalse
MatchByteTrue:区別
False:区別しない
前回の引数の値と同等True
SearchFormatTrue:指定する
False:指定しない
検証中検証中

使用状況により直ちに影響があるかどうかはケースバイケースですが、
挙動を安定させるためには少なくとも

  • しっかり引数を指定して使う
  • 使用後は設定をデフォルトに戻す

どちらかの対策を行うことをお勧めします。

私がよく使うデフォルトに戻すためのコードです。
これをプロシージャの最後に組んで、適切に引数を管理していただければと思います。

Dim Rng As Range
Set Rng = Range("A1").Find(what:="", _
            LookIn:=xlValues, _
            LookAt:=xlPart, _
            MatchByte:=False, _
            SearchOrder:=xlRows)

※正確にはLookInはFormula(数式)がデフォルト値ですが、
使い勝手が良いのはValues(値)なのでそうしています。
Formulaの方が都合が良ければお手数ですが少し変更してお使いください。

※変数を「Rng」としていますが、
もちろんなんでも大丈夫です。
プログラムに合わせて修正してください。

Findメソッドの代わりになる方法

いかがでしょうか

VBAで何かを検索する際にはついついFindメソッドを頼りがちですが
結構めんどくさい仕様があったりもします。

ちなみに、私はVBAで開発するとき
Findメソッドはほぼ使いません

For文を駆使して該当のセルを見つけるか
以下のオリジナル関数を使って対処しています。

とはいえ、FindメソッドにはFindメソッドの良さもあります。

Findメソッドの一番いいところは
事前準備が全くいらないこと。
新しいファイルを開いてすぐに使えることです。

ちょっとしたプログラムであれば
For文を書いたり、上記の関数をコピペしたりせずに
Findメソッドを使って書いてもいいと思います。

何はともあれ、自分の引き出し(=使える手段)は
多ければ多いほど良いです。

まとめ

まとめ
  • Findメソッドの基本構文
  • 引数はまずはWhat , LookIn , LookAt あたりを使いこなそう
  • 戻り値はレンジオブジェクト(つまりセル)
    見つからない場合は「Nothing」
  • 見つからない場合にそのまま処理を進めるとエラーが発生するかも
    エラー対策はしっかりと
  • Findメソッドの注意点
    ①検索セル範囲の先頭は最後に検索される
    ②MatchByteの引数は要注意
    ③引数によっては前回の設定に引っ張られる
  • Findメソッドの代々手段を検討してみて

VBAの学習方法をまとめました。

VBA(マクロ)のおすすめの学習方法 こんにちはhokkyokunです。 VBAを学ぶことで確実に業務は効率化し、余裕をもって仕事をすることができるようになります。 ...

VBAを高コスパで、短期間で学ぶにはUdemyがおすすめです。
Udemyは良質の学習プラットフォームですが、
動画数が多すぎてどれを見ればよいか迷います。

おすすめの講師をまとめました。

【Udemyは講師で選べ!】UdemyがVBA学習に最適な理由とおすすめのVBA講師 こんにちはhokkyokunです。 巨大学習プラットホームUdemyの中からVBAに関する動画について講師に焦点を当ててまとめま...

Findメソッドの他の記事です。

ブログ村ランキング参加中です。よかったらフォローお願いします!!

PVアクセスランキング にほんブログ村