おさらい
前回まででListBox内の値をセルに吐き出したり、エラートラップを仕掛けたりしましたね。
何度も言いますが、ListBoxの中身を追加する為には「AddItem」メソッドを使用してきました。
また、CommandButtonに処理を登録してListBox内のアイテムが選択されていたらD2のセルに値を入力するところまで出来上がりましたね。
それでは実際に検索機能をつけていきましょう。
イベント登録
イベント登録というとちょっと難しく感じるかも知れません。具体的に何をするのかというと検索ワード入力スペースとして作ったTextBoxの値が変わったらプログラムが実行される仕組みを作ろうかという事です。
イベントの登録方法は至って簡単です。
検索ワード入力スペースとして作成したTextBox1をダブルクリックしてみてください。
そうすると↓
Private Sub TextBox1_Change() End Sub
と出てきましたね。
この中にプログラムを記述すればTextBox1の値がChangeしたら(変わったら)プログラムを走らせることができます。
練習プログラムを書いてみましょう
では実際にどうなるのかという事を試す為にTextBox1の値が書き変わる度にTextBox1の値をMsgBoxで出力するようにしてみましょう。
Private Sub TextBox1_Change() MsgBox Me.TextBox1.Value End Sub
たったのこれだけです。
これだけでTextBox1の値が変わる度にMsgBoxでTextBox1の値を教えてくれます。
半角英数字入力の場合は即時、日本語入力の時はEnterで確定した時に処理が走りますね。
ListBoxのItemを取得
ではここまでやったものを使用して実際に検索機能を実現する為にまずはListBoxのItemを取得してみましょう。
という事で配列に一旦格納しましょう。
ここで覚えておいて頂きたいのがListBoxのアイテム数は「オブジェクト名.ListCount」で取得出来るという事です。今回はListBoxの名前はListBox1なので「ListBox1.ListCount」でアイテム数が取れます。そしてListBox内のItemは「オブジェクト名.List(Itemのインデックス数)」で取得出来ます。
今回は都道府県なのでもちろん47が返ってきます。ただし、ListBox内のItemを取得する場合は0から始まるので注意しましょう。
という事で今回はDo Loopで配列に格納していきましょう。
Private Sub TextBox1_Change() Dim arr() As String Dim i As Long ReDim arr(0) i = 0 Do arr(UBound(arr)) = Me.ListBox1.List(i) i = i + 1 If i = Me.ListBox1.ListCount Then Exit Do ReDim Preserve arr(UBound(arr) + 1) Loop End Sub
この様にすれば右側のローカルウィンドウに表示されているようにListBox内のItem一覧を取得する事が出来ます。
後は検索ワードの文言が含まれていればその文言を一番上に来るように並び替えればOKですね。僕の場合は検索ワードが間違っていた場合も選び直す事が出来るようにヒットしたものだけを表示するのではなくヒットしたものを上にもってきてヒットしなかったものをその下に表示させるようにしています。
ワイルドカード
Excelの文字列検索等に使用するワイルドカードってご存知でしょうか?
*(アスタリスク)を付けると曖昧な検索が出来る機能ですね。
例えば『山』という文字が入った都道府県を抜き出したいとした場合は
これは前後に何かしらが入っていて(入っていなくても可)尚且つ山という文字が含まれているもの。という意味です。
これで山という文字が入った都道府県を抽出する事が出来ます。この機能を使って検索機能を実現しようかと思います。
今回は簡単に「ヒットした場合の文字列」と「ヒットしなかった場合の文字列」を用意して配列に変換後、文字列の区切りは,(カンマ)で統一します。
そして最後にListBoxにAddItemする仕様で作っていきましょう。
検索部分の記述
Private Sub TextBox1_Change() Dim arr() As String ' ListBoxの全Item Dim sHit As String ' ヒットした場合の文字列 Dim sNot As String ' ヒットしなかった場合の文字列 Dim search As String ' 検索ワード Dim all As Variant ' 最終的にまとめる配列 Dim i As Long ReDim arr(0) i = 0 Do arr(UBound(arr)) = Me.ListBox1.List(i) i = i + 1 If i = Me.ListBox1.ListCount Then Exit Do ReDim Preserve arr(UBound(arr) + 1) Loop ' まずはListBox内のItemを削除 Me.ListBox1.Clear ' 配列arrからヒット・ノーヒットに切り分ける search = Me.TextBox1.Value For i = LBound(arr) To UBound(arr) If arr(i) Like "*" & search & "*" Then sHit = sHit & arr(i) & "," Else sNot = sNot & arr(i) & "," End If Next ' ヒット・ノーヒットを一つの文字列に変換 all = sHit & sNot ' デリミッタ,(カンマ)で配列に変換 all = Split(all, ",") ' 要素が空じゃなければListBoxにAddItem For i = LBound(all) To UBound(all) If Not all(i) Like "" Then Me.ListBox1.AddItem all(i) End If Next End Sub
完成
後はご自身で動かしてみて下さい。
あくまでもメモリ空間上で行っている処理なのでもったりすることもなく快適に検索が出来ると思います。
今回は少し長かったので全文を下に載せますのでご参考までに。
Option Explicit Private Sub CommandButton1_Click() Dim inputRng As Range Set inputRng = Range("d2") If Me.ListBox1.Value Like "" Then MsgBox "リストから選択してください" Exit Sub End If inputRng.Value = Me.ListBox1.Value Unload Me End Sub Private Sub CommandButton2_Click() Unload Me End Sub Private Sub TextBox1_Change() Dim arr() As String ' ListBoxの全Item Dim sHit As String ' ヒットした場合の文字列 Dim sNot As String ' ヒットしなかった場合の文字列 Dim search As String ' 検索ワード Dim all As Variant ' 最終的にまとめる配列 Dim i As Long ReDim arr(0) i = 0 Do arr(UBound(arr)) = Me.ListBox1.List(i) i = i + 1 If i = Me.ListBox1.ListCount Then Exit Do ReDim Preserve arr(UBound(arr) + 1) Loop ' まずはListBox内のItemを削除 Me.ListBox1.Clear ' 配列arrからヒット・ノーヒットに切り分ける search = Me.TextBox1.Value For i = LBound(arr) To UBound(arr) If arr(i) Like "*" & search & "*" Then sHit = sHit & arr(i) & "," Else sNot = sNot & arr(i) & "," End If Next ' ヒット・ノーヒットを一つの文字列に変換 all = sHit & sNot ' デリミッタ,(カンマ)で配列に変換 all = Split(all, ",") ' 要素が空じゃなければListBoxにAddItem For i = LBound(all) To UBound(all) If Not all(i) Like "" Then Me.ListBox1.AddItem all(i) End If Next End Sub Private Sub UserForm_Initialize() Dim i As Long For i = 2 To Cells(Rows.Count, 2).End(xlUp).Row Me.ListBox1.AddItem Cells(i, 2).Value Next End Sub
では、次回はまた何かテーマを見つけて更新したいと思います。