【VBAリファレンス】VBA入門Findメソッド(Find,FindNext,FindPrevious)

スポンサーリンク

概要

Excel VBAにおけるFindメソッドは、指定した条件に合致するセルを効率的に検索するための強力な機能です。特に、`Find`、`FindNext`、`FindPrevious`メソッドを組み合わせることで、シート内に散らばる特定のデータを網羅的に探し出し、必要に応じて置換したり、集計したりといった高度な処理が可能になります。

このメソッドは、単に特定の文字列を探すだけでなく、数値、日付、数式、あるいはセルの書式設定(色、フォントなど)を条件として指定することもできます。これにより、手作業では膨大な時間がかかるようなデータ検索作業を、数行のVBAコードで瞬時に完了させることができます。

本記事では、Excel VBAの`Find`メソッド、`FindNext`メソッド、`FindPrevious`メソッドについて、その基本的な使い方から応用的なテクニックまで、詳細に解説します。さらに、実務で役立つ具体的なサンプルコードと、開発時に考慮すべきアドバイスも提供します。

詳細解説

Findメソッドの基本

`Find`メソッドは、指定した範囲内で、指定した条件に合致する最初のセルを検索します。見つかったセルはRangeオブジェクトとして返されます。見つからなかった場合は`Nothing`が返されます。

基本的な構文は以下の通りです。

Range.Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat)

各引数の意味は以下の通りです。

* `What`: 検索する値(文字列、数値、日付など)。必須の引数です。
* `After`: 検索を開始するセルを指定します。このセル「の後」から検索が始まります。省略すると、検索範囲の最後のセルから検索が始まります。
* `LookIn`: 検索対象を指定します。
* `xlFormulas`: 数式を検索します(デフォルト)。
* `xlValues`: 値を検索します。
* `xlComments`: コメントを検索します。
* `LookAt`: 検索するセルの全体または一部を指定します。
* `xlWhole`: セル全体が検索条件と一致する場合のみ対象とします(デフォルト)。
* `xlPart`: セルの一部が検索条件と一致すれば対象とします。
* `SearchOrder`: 検索順序を指定します。
* `xlByRows`: 行ごとに検索します(デフォルト)。
* `xlByColumns`: 列ごとに検索します。
* `SearchDirection`: 検索方向を指定します。
* `xlNext`: 指定した`After`セルの後から検索します(デフォルト)。
* `xlPrevious`: 指定した`After`セルの前から検索します。
* `MatchCase`: 大文字と小文字を区別するかどうかを指定します。
* `True`: 区別します。
* `False`: 区別しません(デフォルト)。
* `MatchByte`: 全角/半角を区別するかどうかを指定します。
* `True`: 区別します。
* `False`: 区別しません(デフォルト)。
* `SearchFormat`: 書式設定を検索条件に含めるかどうかを指定します。
* `True`: 書式設定も検索条件に含めます。
* `False`: 書式設定は考慮しません(デフォルト)。

**例:特定の文字列を検索する**

Sub FindSpecificString()
Dim foundCell As Range
Dim searchRange As Range

‘ 検索対象の範囲を指定 (例: Sheet1のA1からZ1000)
Set searchRange = ThisWorkbook.Sheets(“Sheet1”).Range(“A1:Z1000”)

‘ “検索したい文字列” を値として検索
Set foundCell = searchRange.Find(What:=”検索したい文字列”, LookIn:=xlValues, LookAt:=xlWhole)

‘ 見つかった場合
If Not foundCell Is Nothing Then
MsgBox “見つかりました!セルアドレス: ” & foundCell.Address
‘ 見つかったセルを選択
foundCell.Select
Else
MsgBox “見つかりませんでした。”
End If
End Sub

このコードは、`Sheet1`の`A1`から`Z1000`の範囲内で、値が「検索したい文字列」と完全に一致する最初のセルを検索します。見つかればそのセルのアドレスを表示し、選択します。

FindNextメソッドとFindPreviousメソッド

`Find`メソッドは最初に見つかったセルしか返しません。シート内に同じ条件で複数箇所にデータが存在する場合、それらをすべて処理するには`FindNext`メソッドまたは`FindPrevious`メソッドを繰り返し使用する必要があります。

`FindNext`メソッドは、直前に`Find`メソッドまたは`FindNext`メソッドで見つかったセルの「次」のセルを検索します。`FindPrevious`メソッドは、直前に見つかったセルの「前」のセルを検索します。

これらのメソッドは、`Find`メソッドの引数(特に`After`引数)と連動して動作します。

**FindNextを使った複数検索の例**

`FindNext`メソッドを使う場合、最初に`Find`メソッドで検索を開始し、見つかったセルを基準にループ処理を行います。

Sub FindAllOccurrences()
Dim firstAddress As String
Dim foundCell As Range
Dim searchRange As Range
Dim targetString As String

targetString = “繰り返し処理” ‘ 検索したい文字列
Set searchRange = ThisWorkbook.Sheets(“Sheet1”).Range(“A1:Z1000”) ‘ 検索範囲

‘ 最初にFindメソッドで検索を開始
Set foundCell = searchRange.Find(What:=targetString, LookIn:=xlValues, LookAt:=xlWhole)

‘ 初回検索で見つかった場合
If Not foundCell Is Nothing Then
firstAddress = foundCell.Address ‘ 最初に見つかったセルのアドレスを記録

Do
‘ 見つかったセルに対する処理 (例: セルに印をつける)
foundCell.Interior.Color = vbYellow ‘ 背景色を黄色にする

‘ 次のセルをFindNextで検索
‘ SearchDirection:=xlNext はデフォルトなので省略可能
Set foundCell = searchRange.FindNext(After:=foundCell)

‘ 最初に見つかったセルに戻ってきたらループを終了
If foundCell.Address = firstAddress Then
Exit Do
End If

Loop While Not foundCell Is Nothing ‘ 見つからなくなるまでループ

MsgBox “すべて見つかりました。”
Else
MsgBox “見つかりませんでした。”
End If
End Sub

このコードでは、`targetString`に指定した文字列が`searchRange`内に複数存在する場合、それらをすべて探し出し、見つかったセルの背景色を黄色に変更します。`Do…Loop`構造と`firstAddress`変数を用いて、すべての該当セルを処理し、無限ループを防いでいます。

**FindPreviousを使った複数検索の例**

`FindPrevious`メソッドは、`FindNext`とは逆に、検索範囲を逆順に辿ります。

Sub FindAllOccurrencesReverse()
Dim firstAddress As String
Dim foundCell As Range
Dim searchRange As Range
Dim targetString As String

targetString = “逆順検索” ‘ 検索したい文字列
Set searchRange = ThisWorkbook.Sheets(“Sheet1”).Range(“A1:Z1000”) ‘ 検索範囲

‘ 最初にFindメソッドで検索を開始 (通常は最後の方から検索を始める方がFindPreviousと相性が良い)
‘ ここでは検索範囲の最後のセルから逆順に検索を開始する例を示す
Set foundCell = searchRange.Find(What:=targetString, LookIn:=xlValues, LookAt:=xlWhole, SearchDirection:=xlPrevious)

‘ 初回検索で見つかった場合
If Not foundCell Is Nothing Then
firstAddress = foundCell.Address ‘ 最初に見つかったセルのアドレスを記録

Do
‘ 見つかったセルに対する処理 (例: セルに印をつける)
foundCell.Interior.Color = vbGreen ‘ 背景色を緑色にする

‘ 前のセルをFindPreviousで検索
Set foundCell = searchRange.FindPrevious(After:=foundCell)

‘ 最初に見つかったセルに戻ってきたらループを終了
If foundCell.Address = firstAddress Then
Exit Do
End If

Loop While Not foundCell Is Nothing ‘ 見つからなくなるまでループ

MsgBox “すべて逆順で見つかりました。”
Else
MsgBox “見つかりませんでした。”
End If
End Sub

`FindPrevious`を使う場合、`Find`メソッドで検索を開始する際に`SearchDirection:=xlPrevious`を指定すると、検索範囲の最後のセルから遡って検索を開始するため、`FindPrevious`との連携がスムーズになります。

Findメソッドの高度な使い方

`Find`メソッドは、単なる文字列検索にとどまらず、様々な条件で検索できます。

* **数値、日付の検索**: `What`引数に数値や日付を指定します。日付は`Date`型または文字列として指定できます。
* **数式の検索**: `LookIn:=xlFormulas`を指定すると、数式そのものを検索対象とします。
* **セルの書式設定での検索**: `SearchFormat:=True`を指定し、`Find`メソッドの引数に`FormatConditions`オブジェクトや`Font`オブジェクト、`Interior`オブジェクトなどを設定することで、書式設定を条件に検索できます。ただし、この機能は少し複雑で、事前に検索したい書式を設定したセルを用意し、そのセルの書式を`Find`メソッドに渡すという方法が一般的です。

**書式設定での検索例(背景色が黄色で、フォントが太字のセルを検索)**

Sub FindByFormat()
Dim foundCell As Range
Dim searchRange As Range
Dim formatCell As Range

Set searchRange = ThisWorkbook.Sheets(“Sheet1”).Range(“A1:Z1000”)

‘ 検索したい書式を設定した一時的なセルを用意(例:B1セル)
‘ または、既存の書式設定をコピーして利用
Dim tempFormatSheet As Worksheet
Set tempFormatSheet = ThisWorkbook.Sheets.Add

‘ 検索したい書式を設定
tempFormatSheet.Range(“B1”).Interior.Color = vbYellow ‘ 背景色を黄色に
tempFormatSheet.Range(“B1″).Font.Bold = True ‘ フォントを太字に

‘ Findメソッドで書式を検索
Set foundCell = searchRange.Find(What:=””, _
SearchFormat:=True, _
Format:=tempFormatSheet.Range(“B1”)) ‘ Format引数で書式を指定

‘ 一時シートを削除
Application.DisplayAlerts = False
tempFormatSheet.Delete
Application.DisplayAlerts = True

‘ 結果の表示
If Not foundCell Is Nothing Then
MsgBox “書式に一致するセルが見つかりました: ” & foundCell.Address
foundCell.Select
Else
MsgBox “書式に一致するセルは見つかりませんでした。”
End If
End Sub

**注意:** `Format`引数は、Excelのバージョンによっては直接指定できない場合があります。その場合は、`Application.FindFormat`プロパティや`Application.Find.Format`プロパティを使用するなどの代替手段が必要になります。上記コード例では、`Format`引数を使用する一般的な方法を示していますが、環境によっては調整が必要です。

Findメソッドの引数の初期化

`Find`メソッドや`FindNext`メソッドは、一度実行されると、その検索条件(`LookIn`, `LookAt`, `MatchCase`など)がExcelのFind/Replaceダイアログの設定として保持されてしまいます。これにより、意図しない検索結果になってしまうことがあります。

これを避けるために、`Find`メソッドを実行する前に、これらの検索条件をデフォルト値に戻すことが推奨されます。

Sub ResetFindSettings()
‘ Find/Replaceダイアログの設定をリセット
Application.FindFormat.Clear ‘ Format設定のリセット
Application.Find.Clear ‘ Find設定のリセット (LookIn, LookAt, MatchCaseなど)

‘ または、個別にデフォルト値に戻す
‘ Application.Find.LookIn = xlFormulas
‘ Application.Find.LookAt = xlWhole
‘ Application.Find.MatchCase = False
‘ Application.Find.MatchByte = False
‘ Application.Find.SearchFormat = False
‘ Application.Find.SearchOrder = xlByRows
‘ Application.Find.SearchDirection = xlNext

MsgBox “Find/Replaceダイアログの設定をリセットしました。”
End Sub

この`ResetFindSettings`のような処理を、`Find`メソッドを使用するコードの冒頭に挿入することで、他のマクロや手動操作による影響を受けずに、意図した通りの検索を実行できます。

サンプルコード

例1:特定の文字列を含むセルをすべて探し、置換する

Sub FindAndReplaceAll()
Dim searchRange As Range
Dim foundCell As Range
Dim firstAddress As String
Dim targetString As String
Dim replaceString As String

‘ 設定
targetString = “旧データ”
replaceString = “新データ”
Set searchRange = ThisWorkbook.Sheets(“Sheet1”).Range(“A1:Z1000″)

‘ Find/Replaceダイアログの設定をリセット
Application.FindFormat.Clear
Application.Find.Clear

‘ 最初の検索
Set foundCell = searchRange.Find(What:=targetString, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False) ‘ 大文字小文字を区別しない

If Not foundCell Is Nothing Then
firstAddress = foundCell.Address
Do
‘ 置換処理
foundCell.Value = replaceString

‘ 次の検索
Set foundCell = searchRange.FindNext(After:=foundCell)

‘ 最初に戻ったかチェック
If foundCell.Address = firstAddress Then
Exit Do
End If
Loop While Not foundCell Is Nothing
MsgBox targetString & ” をすべて ” & replaceString & ” に置換しました。”
Else
MsgBox targetString & ” は見つかりませんでした。”
End If
End Sub

例2:検索条件に合致するセルの数をカウントする

Sub CountMatchingCells()
Dim searchRange As Range
Dim foundCell As Range
Dim firstAddress As String
Dim targetValue As Variant ‘ 数値、文字列など何でも対応できるようにVariant型
Dim count As Long

‘ 設定
targetValue = 100 ‘ 例: 数値100をカウント
Set searchRange = ThisWorkbook.Sheets(“Sheet1”).Range(“A1:Z1000″)
count = 0

‘ Find/Replaceダイアログの設定をリセット
Application.FindFormat.Clear
Application.Find.Clear

‘ 最初の検索
Set foundCell = searchRange.Find(What:=targetValue, _
LookIn:=xlValues, _
LookAt:=xlWhole) ‘ 完全一致で検索

If Not foundCell Is Nothing Then
firstAddress = foundCell.Address
Do
count = count + 1
‘ 次の検索
Set foundCell = searchRange.FindNext(After:=foundCell)
‘ 最初に戻ったかチェック
If foundCell.Address = firstAddress Then
Exit Do
End If
Loop While Not foundCell Is Nothing
MsgBox targetValue & ” は ” & count & ” 個見つかりました。”
Else
MsgBox targetValue & ” は見つかりませんでした。”
End If
End Sub

例3:特定の日付以降のデータを検索し、リストアップする

Sub FindDatesAfter()
Dim searchRange As Range
Dim foundCell As Range
Dim firstAddress As String
Dim targetDate As Date
Dim outputRow As Long

‘ 設定
targetDate = CDate(“2023/01/01”) ‘ 検索したい日付
Set searchRange = ThisWorkbook.Sheets(“Sheet1”).Range(“A1:A100”) ‘ 日付が入っている列を指定
outputRow = 1 ‘ 結果を出力する行番号

‘ Find/Replaceダイアログの設定をリセット
Application.FindFormat.Clear
Application.Find.Clear

‘ 最初の検索 (日付はシリアル値として検索される)
Set foundCell = searchRange.Find(What:=targetDate, _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)

If Not foundCell Is Nothing Then
firstAddress = foundCell.Address
Do
‘ 結果を出力
ThisWorkbook.Sheets(“Sheet2”).Cells(outputRow, 1).Value = foundCell.Value ‘ 日付
ThisWorkbook.Sheets(“Sheet2”).Cells(outputRow, 2).Value = foundCell.Address ‘ セルアドレス
outputRow = outputRow + 1

‘ 次の検索
Set foundCell = searchRange.FindNext

タイトルとURLをコピーしました