- Findメソッドの基本構文(引数、戻り値)
- 引数を省略した場合どうなるか?
- Findメソッドの注意点
①検索セル範囲の先頭は最後に検索される
②MatchByteの引数は要注意
③引数によっては前回の設定に引っ張られる - Findメソッドの代替手段
こんにちは、hokkyokunです。
もともと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 | セルを指定 指定するセルは一つのセル 指定したセルの次のセルから検索開始 =指定したセルは最後に検索 | × | |
LookIn | xlFormula : 計算式 xlValues : 値 xlComments:コメント | 検索する対象を指定 xlCommentsを指定すると コメントの内容を検索する | 〇 |
LookAt | xlWhole:完全一致 xlPart:部分一致 | 検索する対象がWhatの値と 完全に一致するか部分的に一致するか | ◎ |
SearchOrder | xlByRows:行方向 xlByColumns:列方向 | 検索する方向を指定 行方向(横)か列方向(縦) | × |
SearchDirection | xlNext:順方向 xlPrevious:逆方向 | 検索する方向を指定 左から右、下から上(順方向) もしくはその逆か | × |
MatchCase | True:区別 False:区別しない | 大文字と小文字を区別して検索 what:=appleで 「APPLE」をヒットさせたいかどうか | △ |
MatchByte | True:区別 False:区別しない | 全角と半角を区別して検索 what:=リンで 「リン」をヒットさせたいかどうか | △ |
SearchFormat | True:指定する False:指定しない | 検索の書式を指定するか 複雑なため別記事で | △? 〇? |
たくさんありますね、
ただほとんど不要です。
重要度で〇以上のものから使えるようになればOKです。
なれてくれば△のものを必要に応じて使ってください。
×はむしろ使うべきではありません。
検索する位置や方向を指定していますが、
ここをいじって検索結果をどうこうするよりかは
エクセルの表の作り方やプログラミングコードを見直すべきです。
引数を省略するとどうなる?
Findメソッドを極端に難しくしている謎の仕様がこれなのですが、
引数によって省略した場合の対応が異なります。
名前(※は必須) | 定数 | 引数を省略した場合 | 最初に使った場合 |
---|---|---|---|
※What | ー | ||
After | セル範囲の左上のセル | セル範囲の左上のセル | |
LookIn | xlFormula : 計算式 xlValues : 値 xlComments:コメント | 前回の引数の値と同等 | xlFormula |
LookAt | xlWhole:完全一致 xlPart:部分一致 | 前回の引数の値と同等 | xlPart |
SearchOrder | xlByRows:行方向 xlByColumns:列方向 | 前回の引数の値と同等 | xlByRows |
SearchDirection | xlNext:順方向 xlPrevious:逆方向 | xlNext | xlNext |
MatchCase | True:区別 False:区別しない | False | False |
MatchByte | True:区別 False:区別しない | 前回の引数の値と同等 | True |
SearchFormat | True:指定する False:指定しない | 検証中 | 検証中 |
頭が痛くなりそうですが
ポイントは二つです。
- LookIn,LookAt,SearchOrder,MatchByteは
前回の引数を引き継ぐので毎回指定するか設定をリセットする - MatchByteはデフォルトがTrue(=半角全角の区別をする)
半角全角が混じった表を扱う場合は注意
控えめに言っても大混乱させる仕様です(笑)
Findメソッドよりも簡単で高速、エラーも起こしにくい関数を作ったので
よかったら見て頂ければと思います。
こちらはFindNextメソッドの代替手段(関数)です。
戻り値
戻り値はレンジオブジェクトです。
つまりセルを返してくれます。
検索で見つからない場合は
「Nothing」が返ってきます。
あるあるなのが
セルが返ってくると思って「.Value」で値を参照して
エラーが吐き出されるという現象です。
しっかりエラー対策をしておきましょう。
Findメソッドとエクセルのダイアログ検索ボックス(Ctrl + F)
複雑な構造のFindメソッドですが、
これはエクセル上で「Ctrl + F 」で開く検索ダイアログと同じ構造になっています。
比較してみましょう。
こうやってみるとダイアログボックスのほとんどの仕様を
VBAで動かせるようです。
引数別の使い方
下記の図のような表を用意します。
セル範囲 A1:C6 を引数を変えながら検索してみようと思います。
下記でも述べていますが、
Findメソッドには注意する点が三つあります。
- 指定したセル範囲の最初のセルは最後に検索される
- MatchByteの引数はかなり複雑
- 前回の設定を保持する引数がある
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の内容とは関係ないのですが、
上記のコードを試した後ダイアログボックスを確認してみると
「半角全角の区別をする」にチェックが入っています。
引数を指定しないとデフォルトで
半角全角の区別をするになります。
また、その仕様は引き継がれます。
注意が必要です
というかなんだこの仕様…
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として半角全角を区別します。
しかもその後は、前回の設定に依存するので
次回以降も区別し続けます。
個人的には半角全角の混ざったエクセル運用を
禁止すべきだと思います。
が、マスタデータなどは
そうも言ってられないと思いますので、
エラーが起きそうなら引数の設定(特にMatchByte)は
さぼらず指定すべきでしょう。
引数の設定が前回の処理に引っ張られる
上記でもまとめた表と同じですが、
特に前回の処理に引っ張られるものを赤字で協調しておきます。
名前(※は必須) | 定数 | 引数を省略した場合 | 最初に使った場合 |
---|---|---|---|
※What | ー | ||
After | セル範囲の左上のセル | セル範囲の左上のセル | |
LookIn | xlFormula : 計算式 xlValues : 値 xlComments:コメント | 前回の引数の値と同等 | xlFormula |
LookAt | xlWhole:完全一致 xlPart:部分一致 | 前回の引数の値と同等 | xlPart |
SearchOrder | xlByRows:行方向 xlByColumns:列方向 | 前回の引数の値と同等 | xlByRows |
SearchDirection | xlNext:順方向 xlPrevious:逆方向 | xlNext | xlNext |
MatchCase | True:区別 False:区別しない | False | False |
MatchByte | True:区別 False:区別しない | 前回の引数の値と同等 | True |
SearchFormat | True:指定する 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を高コスパで、短期間で学ぶにはUdemyがおすすめです。
Udemyは良質の学習プラットフォームですが、
動画数が多すぎてどれを見ればよいか迷います。
おすすめの講師をまとめました。
Findメソッドの他の記事です。
ブログ村ランキング参加中です。よかったらフォローお願いします!!