『Excel VBA 表計算とプログラミング学習サイト』では、アフィリエイトプログラムを利用して商品を紹介しています。

【VBA】FindメソッドとFindNextメソッドで住所検索

【VBA】Findメソッドと FindNextメソッド

データベース研究所の記事です。今回は下のような住所録で氏名を検索して該当セルに移動するというマクロを作ってみましょう。もちろん Excel には最初から「検索と置換」機能が備わっていますが、VBAFindメソッド の引数には検索開始位置を指定する After, 検索方向を指定する SearchDirection など、Excel の「検索と置換」にはない専用機能も備わっているので、Replace メソッドなどを組合わせると、もっと便利なデータベースアプリケーションを開発することもできます。

氏名 性別 年齢 住所
波光佳 16 東京都港区北青山 2-3-2
中村未久 53 東京都足立区西新井 7-10-9
保母育実 17 東京都葛飾区宝町 2-47-8
高林園香 56 東京都板橋区仲宿 3-49-4
坪松嘉浩 33 東京都江戸川区鹿骨町 4-2-4
中村次郎 26 東京都新宿区四谷 1-28-8
土井響子 27 東京都江戸川区東葛西 6-45-4
千綿享典 60 東京都練馬区上石神井 2-47-0
三籐克昭 67 東京都世田谷区新町 2-9-8
井田聡美 67 東京都江東区大島 2-26-6

【VBA】「住所検索」マクロと「続けて検索」マクロ

それでは、Findメソッドと FindNextメソッドを使って簡単な検索マクロを作ってみますよ。
 
Findメソッドでセルを参照する
 
先にどんなことをやるのかってことを大まかに説明しておきます。上の図にあるように、たとえばユーザーさんが「保母育実」というキーワードで検索したときに、A 列の中から該当するキーワードのセルを Findメソッドで探し当てて、そのセルを含む行を選択します。もし該当するデータがなければ「そんなのないよ」てことを表示します。まあとにかく、下のマクロをコピーして試してみてくださいな。宣言セクションに変数のデータ型宣言をまとめて「住所検索」と「続けて検索」の2つのマクロを並べておきますよ。

'[VBA] 住所検索プログラム

Dim wd As String
Dim myMsg1 As String, myMsg2 As String
Dim myTitle As String
Dim myRange As Range, myField As Range

'住所検索
Sub AddressSearch()

  myMsg1 = "検索キーワードを入力してください"
  myMsg2 = "見つかりませんでした"
  myTitle = "住所検索"

  'ユーザーさんにキーワードの入力を促します
  wd = Application.InputBox(myMsg1, myTitle)

  'セルA1のある表をオブジェクト型変数に入れます
  Set myField = Range("A1").CurrentRegion.Columns(1).Cells

  '入力した氏名に完全一致するデータを取得します
  Set myRange = myField.Find(What:=wd, Lookat:=xlWhole)

  'データが空であれば「見つかりませんでした」と表示します
  If myRange Is Nothing Then
    MsgBox myMsg2
    Exit Sub
  End If

  '該当するデータの行に移動します
  Rows(myRange.Row).Select

End Sub
 
'同じ氏名で続けて検索します
Sub NextSearch()

  '現在の行のA列にあるセルを選択し直します
  ActiveCell.Cells(1, 1).Select

  Set myField = Range("A1").CurrentRegion.Columns(1).Cells

  '現在選択されているセルの次の行以降を探します
  Set myRange = myField.FindNext(ActiveCell.Offset(1))

  Rows(myRange.Row).Select

End Sub

さっそく「住所検索」と「続けて検索」を使ってみましょう。下の図のように、それぞれのマクロにボタンを用意してください。
 
FindNextメソッドで続けて検索
 
まず「住所検索」をクリックして、現れたダイアログに「中村*」と入力してみます。「*」はワイルドカードです。「中村*」は「中村」が頭につく文字全てを対象にするという意味です。つまり「フルネーム思い出せないけど、確か苗字は中村だったよねー」て時に使うのです。[OK] ボタンを押すと「中村未久」さんのデータの行が選択されます。で、今度は同じキーワードでさらにその下を検索したいときは「続けて検索」をクリックします。すると次の「中村次郎」さんの行が選択されるのです。
 
コードの重要箇所を解説しておきます。まず Range型変数 myField にセル A1 を含むフィールド(表)の 1 列目を放り込みます。

Set myField = Range("A1").CurrentRegion.Columns(1).Cells

そして、Findメソッドによって、このオブジェクトから検索キーワードに一致するデータの入ったセルを抜き出して、Range 型変数 myRange に入れます。

Set myRange = myField.Find(What:=wd, Lookat:=xlWhole)

引数の what には「検索文字列」を指定します。このマクロではユーザーさんが入れたキーワードです。Lookat は「検索方法」で、上のように xlWhole と指定すれば「検索文字列に完全に一致するデータ」を探します。「部分一致」にしたい場合は xlPart を指定します。myRange.Row で該当セルの行番号が得られるので、

Rows(myRange.Row).Select

によって、該当セルの行全体を選択することになります。Findメソッドには他にも色々な引数を指定できるので、表にまとめておきますね。

Findメソッドの引数 説明
What 検索する文字列を指定
After 検索を開始するセルを指定
LookIn xlValue:セルの値、xlFormulas:数式
LookAt xlWhole:全体一致、xlPart:部分一致
SearchOrder xlByRows:行方向の検索を優先
xlByColumns:列方向の検索を優先
SearchDirection xlNext:前方向を検索、xlPrevious:後方向を検索
MatchCase True:大文字と小文字を区別する
False:大文字と小文字を区別しない
MatchByte True:全角と半角を区別する
False:全角と半角を区別しない
SearchFormat True:書式検索オン、False:書式検索オフ

次は「続けて検索」マクロの解説です。
「住所検索」マクロの実行で行が選択されている可能性があるので、

ActiveCell.Cells(1, 1).Select

で A 列にあるセルを選択した状態に戻しておきます。たとえ別のマクロであっても、Findメソッドで指定した検索文字列は、新しい検索条件が指定されるまで、そのままの形で記憶されています。なので同じ条件で検索する場合にはあらためてキーワードを入力する必要はなく、FindNextメソッドを用いて直ちに次の検索を行なうことができるのです:

Set myRange = myField.FindNext(ActiveCell.Offset(1))

引数には「どこから次の検索を始めるのか」を指定します。今の場合は選択されている次のセルなので ActiveCell.Offset(1) と記述しています … ぜえぜえ。今回はさすがに話が長かったし、表まで作ったので疲れてしまいましたよ。こばとは小っちゃいので、キーボード叩くにも相当な体力を使ってしまうのです。ぜえぜえ。あとは皆さんで色々と応用してみてくださいな。
 
≫ データベース研究所

コメント

  1. オムレツ麺 より:

    シート内をFind,Findnextで文字列”A”を含むセルを検出
    検出セル内のみをReplaceで文字列”B”から”C”に置き換え
    ということをしたかったのだけど
    最初のFindで”A”を含むのセル検出ができ
    Replaceで”B”から”C”に置き換えができるが
    次のFindnextから”A”ではなく,”B”を検出し始める.
    FindnextとReplaceの引数は独立していないのですか?

    • こばと より:

       Replaceメソッドは指定文字を「検索」してから、 別の文字に置き換えるので、おそらく内部で Findメソッドを使用していると考えられます (仮にマイクロソフトが Replaceメソッドを用意していなかったとすれば、私たちは文字を置き換えるマクロを同じようなスタイルで書くはずです)。記事で述べている通り、Find で指定した検索文字列は Findnext に引き継がれるので、Replace の引数も間接的に Findnext に引き継がれることになります。