図3のような表があり、「読みを入力」に「読み」を入力して「実行」ボタンをクリックすると、その「読み」に該当するセルが選択されるマクロを書いてみよう。「実行」ボタンはExcelメニューの[挿入]→[図形]から作成している。
セルに入力されているデータを検索するには、Findメソッドを使用する。書式は下記の通りだ(参考「Range.Find Method(Excel)- MSDN」)。
Rangeオブジェクト.Find(What:={What},LookIn:={LookIn},LookAt:={LookAt})
設定値 | 説明 |
---|---|
xlFormulas | 数式 |
xlValues | 値 |
xlComments | コメント |
設定値 | 説明 |
---|---|
xlWhole | 完全一致 |
xlPart | 部分一致 |
マクロはリスト2のようになる。「読みを入力」の欄に入力された「読み」を、完全一致検索で行う。
Sub 検索() Range("D8:D17").Find(What:=Range("C4").Value, LookAt:=xlWhole).Select End Sub
図3の「実行」ボタンを選択して、マウスの右クリックで表示されるメニューから[マクロの登録]を選択する。[マクロ登録]の画面が表示されるので、「検索」を選択して[OK]ボタンをクリックする。これで、「実行」ボタンにマクロが登録された。
では、「C4」のセルに「読み」を平仮名で入力して「実行」ボタンをクリックしてみよう。図4のように該当するセルが選択されるはずだ。
では、指定した「読み」のデータが見つからなかった場合はどうするか。プログラムでは、このようなデータがなかった場合の処理を書くことが非常に大切だ。データがなかった場合は「該当データがありません!」と表示させる心遣いが必要だ。その記述方法を解説しよう。
データがなかった場合のマクロはリスト3のように書く。
Sub 検索() Dim result As Range Set result = Range("D8:D17").Find(What:=Range("C4").Value, LookAt:=xlWhole) If result Is Nothing = False Then result.Select Else MsgBox "該当データがありません!" Exit Sub End If End Sub
2〜3行目でRange型のオブジェクト変数「result」を宣言し、検索結果をresult変数にSetステートメントで格納する。
4〜9行目では、「If〜Else〜End If」ステートメントで条件分岐を行っているが、この構文については前回の「If〜Thenによる二者択一の条件分岐」「Elseで指定した条件以外の処理」などを参照してほしい。
データがある(データがない状態ではない)場合(4行目)は、そのセルを選択し(5行目)、ない場合(6行目)はMsgBox関数でメッセージを表示する(7行目)。MsgBox関数については、後の連載で解説する。
実行結果は図5のようになる。
次に、同性同名の人物があった場合はどうするかを考えてみよう。膨大なデータの中には当然同姓同名の人物も存在する可能性は100%ある。そのような場合、全ての人物を選択する処理を書いてみよう。
このような場合の処理にはFindNextメソッドを使用する。書式は下記の通りだ。
Rangeオブジェクト.FindNext({After})
引数{After}は省略可能で、セルの場所を指定する。指定したセルの次のセルから検索が開始される。
FindNextメソッドを使うマクロはリスト4のように記述する。
Option Explicit Sub 同姓同名検索() Dim firstFindCell As Range Dim firstCell As Range Dim result As Range Set firstFindCell = Range("D8:D20").Find(What:=Range("C4").Value, LookAt:=xlWhole) Set firstCell = firstFindCell Set result = firstFindCell Do Set firstFindCell = Range("D8:D20").FindNext(firstFindCell) If firstFindCell.Address = firstCell.Address Then Exit Do Else Set result = Union(result, firstFindCell) End If Loop result.Select End Sub
最初に見つかったデータを格納するRangeオブジェクト変数「firstFindCell」と、最初に見つかったデータを保持しておくための変数「firstCel」、結果を格納するRangeオブジェクト変数「result」を宣言する(3〜5行目)。
「読みを入力」で入力された平仮名の「読み」を完全一致で検索し(7行目)、最初に見つかったセルのデータをfirstCellにセットしておく(8行目)。resultにも最初に見つかったセルのデータfirstFindCellの値をセットしておく(9行目)。
Do〜Loopで繰り返し処理を行う(11〜18行目)。この構文については前回の「条件が成立している間、処理を繰り返すDo While〜Loop」を参照してほしい。ここでは、繰り返しを終了する条件の「While」を使っていない。「Exit Do」ステートメントで繰り返し処理から抜けることになる(14行目)。
セルD8〜D20の範囲のセル内を、FindNextメソッドで、最初に見つかったデータを保持しているfirstFindCellの値で検索していく(12行目)。
最初に見つかったデータのアドレスと、次のデータのアドレスが同じの場合、つまりデータが1個しかない場合(13行目)は、それのみを選択して、繰り返し処理を抜ける(14行目)。
それ以外は、Unionメソッドでresultのセル範囲とfirstFindCell範囲を、1つのRangeオブジェクトに集約して返す(16行目)。この場合は変数resultに検索結果のセル範囲が集約してセットされる。
Unionメソッドの書式は下記の通り。第1引数と第2引数は必須だ。
Set {Rangeオブジェクト変数}=Union({セル範囲1},{セル範囲2}、……)
最後にSelectメソッドで該当するデータを全て選択する(19行目)。
実行すると、図19のようになる。
Copyright © ITmedia, Inc. All Rights Reserved.