文字列を探す「Find」メソッド
今回の目標
「この文字列はどこにある?」や「この文字があるセルだけ処理をしたい」と、思ったあなたへ。
この記事では、Findメソッドの使い方を解説します!
基本的なだけでなく、実務で使える実例集付きです。
目標リスト
- 文字列を検索できるようになる
- 自作関数で文字列を検索した結果を取得できるようになる
説明
Findメソッドとは
FindメソッドはRangeオブジェクトの持つメソッドで、文字列がどこにあるかを返します。
セルの範囲内に検索文字が見つからなかった場合は「Nothing」を返します。
Findメソッドの構文と引数一覧
Findメソッドは、マクロ処理が完了するまでに2回以上使用したとき、2回目以降の規定値は『前回、指定した引数の値』となります。このため、規定値に頼らず、使用するたびに指定しましょう。
名前 | 省略 | 規定値 | 説明 |
---|---|---|---|
What | 不可 | (省略不可) | 検索する文字列 |
After | 可能 | (アクティブなセル) | 検索を開始するセル。 |
LookIn | 可能 | xlFormulas | 種別を指定する。セルの値(xlValues)、数式(xlFormulas)、コメント(xlComments )、スレッド(xlCommentsThreaded )のいずれかを指定。 |
LookAt | 可能 | xlPart | 検索文字は部分一致(xlPart)か、完全一致(xlWhole)か指定する。 |
SearchOrder | 可能 | xlByRows | 検索する方向は、行方向(xlByRows)か、列方向(xlByColumns)か指定する。 |
SearchDirection | 可能 | xlNext | 次に検索する方向は、前方向(xlNext)か後ろ方向(xlPrevious)か指定する。 |
MatchCase | 可能 | False | 大文字と小文字を区別するか。Trueの場合、区別する。Falseの場合、区別しない。 |
MatchByte | 可能 | 日本語環境なら、ほとんどの場合、False | 全角・半角を区別するか。Trueの場合、区別する。Falseの場合、区別しない。 |
SearchFormat | 可能 | False | 検索の書式を指定する。Trueの場合、区別する。Falseの場合、区別しない。なお、事前にFindFormatで検索する書式を指定しないと、Trueにしても動作しない。 |
一部、Microsoft社のリファレンスを参照しています。
【Microsoft公式】
Range.Find メソッド (Excel)
Findメソッドを使って、文字列があるセルを探す
『りんご』と記載されているセルがどのセルに存在するか、アドレスを表示します。
サンプルコード
Sub FindSample1()
Dim rng As Range
'アクティブなシートにある『りんご』のセルを探す
Set rng = ActiveSheet.UsedRange.Find("りんご")
'『りんご』がセルにない場合、Nothingを返す。
If rng Is Nothing Then
Debug.Print "文字列が見つかりませんでした"
Else
Debug.Print "見つかったセルのアドレス: " & rng.address
End If
End Sub
♦セルのどこかに「りんご」と入力されている場合♦
見つかったセルのアドレス:●●
※ ●●には、りんごと入力されているセルの位置が表示されます。
♦どのセルにも「りんご」と入力されていない場合♦
文字列が見つかりませんでした
複数のセルに検索文字がある場合
複数のセルに検索文字があり、それぞれに処理を行う場合、先ほどと少し異なった処理方法となります。
正直ややこしい動きをしますので、簡単に説明を読んだら、まずはサンプルプログラムを動かしてみましょう。
Range型の変数を2つ、String型の変数を1つ用意します。Range型の変数は、検索対象の範囲と検索した結果を代入します。String型の変数には、最初に検索されたセルのアドレスを入れます。
検索対象の範囲のRange変数の『FindNext』メソッドを使用し、引数には、もう1つのRange変数(検索した結果)を指定します。検索した次のセルが返ってきますので、受け取る変数に検索した結果のRange変数を指定します。
FindNextメソッドは終わることなく、全てのセルを検索しても最初のセルに戻って、そのアドレスを返す仕様になっています。プログラマーが最初のセルに戻ったかを確認し、戻っていればループを抜け出すようにしなければなりません。
サンプルコード
Sub FindSample2()
Dim rngBase As Range
Dim firstAddress As String
Dim rngResult As Range
Dim flag1 As Boolean
Dim flag2 As Boolean
Set rngBase = ActiveSheet.UsedRange
Set rngResult = ActiveSheet.UsedRange.Find(What:="りんご")
'検索した文字列があるか
If Not rngResult Is Nothing Then
'最初に検索したアドレスを保存(ループ終了の確認用)
firstAddress = rngResult.address
'検索が全て終わるまでループさせる
Do
'処理
Debug.Print "見つかったセルのアドレス: " & rngResult.address
'次の検索結果に進む。
Set rngResult = rngBase.FindNext(rngResult)
'処理中に検索文字列(りんご)が消された場合、検索結果が「Nothing」
flag1 = Not rngResult Is Nothing
'検索が1周したか
flag2 = rngResult.address <> firstAddress
'検索文字列が消された か 検索が1周した 場合は終了
Loop While flag1 And flag2
Else
Debug.Print "文字列が見つかりませんでした"
End If
End Sub
♦セルのどこかに「りんご」と入力されている場合♦
見つかったセルのアドレス:●●
見つかったセルのアドレス:●●
※ ●●には、りんごと入力されているセルの位置が表示されます。
♦どのセルにも「りんご」と入力されていない場合♦
文字列が見つかりませんでした
文字列があるセルのアドレスを返す関数を自作する
関数化して、使いまわす
文字列があるセルを全て検索する処理は手順が多かったり、Findメソッドの引数が前回使用した値を引き継ぐため、毎回設定したりなど、面倒なので、関数化しましょう。
文字列があるセルのアドレスを格納した配列を返す関数を作成します。なお、配列は「Variant型」で返す必要があるため注意が必要です。
サンプルコード
'----------------------------------------------------
' この関数を実行する
'----------------------------------------------------
Sub testMain()
Dim arr As Variant
Dim buf As Variant
'「りんご」があるセルのアドレスを返す
arr = FindString(ActiveSheet, "りんご")
If arr(0) <> -1 Then
For Each buf In arr
Debug.Print "見つかったセルのアドレス: " & buf
Next buf
Else
Debug.Print "文字列が見つかりませんでした"
End If
End Sub
'----------------------------------------------------
' 【自作関数】FindString関数
' 検索した文字列があるセルのアドレスを配列で返す
' 検索した文字列が無い場合、配列の要素0に"-1"を入れて返す
' 引数 ws :検索対象のシート
' strWhat :検索する文字列
' rngAddress:検索する範囲
'----------------------------------------------------
Function FindString(ByVal ws As Worksheet, ByVal strWhat As String, _
Optional rngAddress As String = "", _
Optional lookIn As Long = xlValues, _
Optional blSearchPart As Boolean = True, _
Optional blColumnOrder As Boolean = True, _
Optional blMatchCase As Boolean = True) As Variant
Dim rng As Range
Dim firstAddress As String
Dim result As Range
Dim num As Long
Dim buf() As String
'検索範囲を定める
If rngAddress = "" Then
Set rng = ws.UsedRange 'シート全て
Else
Set rng = ws.Range(rngAddress) '特定の範囲
End If
Set result = rng.Find(What:=strWhat, lookIn:=lookIn, _
LookAt:=IIf(blSearchPart, xlPart, xlWhole), _
SearchOrder:=IIf(blColumnOrder, xlByColumns, xlByRows), _
MatchCase:=blMatchCase)
num = -1
'検索した文字列が1つ以上ある場合、真となる
If Not result Is Nothing Then
firstAddress = result.address
Do
num = num + 1
ReDim Preserve buf(0 To num)
buf(num) = result.address
Set result = rng.FindNext(result)
Loop While Not result Is Nothing And result.address <> firstAddress
End If
'検索した文字列が1つもない場合、真となる
If num <> -1 Then
FindString = buf
Else
ReDim Preserve buf(0)
buf(0) = "-1"
FindString = buf
End If
End Function
♦セルのどこかに「りんご」と入力されている場合♦
見つかったセルのアドレス:●●
見つかったセルのアドレス:●●
※ ●●には、りんごと入力されているセルの位置が表示されます。
♦どのセルにも「りんご」と入力されていない場合♦
文字列が見つかりませんでした