リストの絞り込み の続き⑥ ~ いずれかのリストボックスがクリックされたことを検知する ~
昨日は、本棚を表すセルをクリックするたびに、リストボックスの内容が更新されるようにしました。
本日は機能拡張を一旦終え、今までに作ったコードのスリム化に挑戦です。
やはり一番気になるのは、ユーザーフォームのリストボックスに関する、この個所でしょうか。
Private Sub ListBox1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) For Each Book In Books If Book.通し番号 = ListBox1.List(ListBox1.ListIndex, 1) Then 本棚番号Label = Book.本棚番号 書籍名称Label = Book.書籍名称 著者氏名Label = Book.著者氏名 Dim Sh As Worksheet Set Sh = Sheets("レイアウト図") Dim FoundCell As Range Set FoundCell = Sh.Cells.Find(What:=Book.本棚番号, LookAt:=xlWhole) If Not FoundCell Is Nothing Then ChangeColor Sh, FoundCell End If Exit Sub End If Next End Sub Private Sub ListBox2_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) For Each Book In Books If Book.通し番号 = ListBox2.List(ListBox2.ListIndex, 1) Then 本棚番号Label = Book.本棚番号 書籍名称Label = Book.書籍名称 著者氏名Label = Book.著者氏名 Dim Sh As Worksheet Set Sh = Sheets("レイアウト図") Dim FoundCell As Range Set FoundCell = Sh.Cells.Find(What:=Book.本棚番号, LookAt:=xlWhole) If Not FoundCell Is Nothing Then ChangeColor Sh, FoundCell End If Exit Sub End If Next End Sub
リストボックス毎に、リストボックス名だけ違うコードが書かれています。
リストボックスが100個あれば、100回同じような記述が続きます。これは、果てしなく面倒臭い。修正が生じた場合、100か所の修正が必要になります。
そこで次の手順を導入することで、スリム化を図ります。
- とにかく、いずれかのリストボックスがクリックされたことを切っ掛けに発生するイベントを作る。
- イベントの中で、クリックされたリストボックスに合わせた処理を行う。
これであれば、リストボックスの数だけコードを複製する必要はありません。
それでは、まずクラスモジュールを一つ追加します。モジュール名は、ListBoxControlClassとします。内容は、下記のとおりです。
Option Explicit Private WithEvents myListBox As MSForms.ListBox Private myIndex As Long Public Sub Set_ListBox(newListBox As MSForms.ListBox, Index As Long) Set myListBox = newListBox myIndex = Index End Sub Private Sub myListbox_Click() With BookShelfForm For Each Book In Books If Book.通し番号 = myListBox.List(myListBox.ListIndex, 1) Then .本棚番号Label = Book.本棚番号 .書籍名称Label = Book.書籍名称 .著者氏名Label = Book.著者氏名 Dim Sh As Worksheet Set Sh = Sheets("レイアウト図") Dim FoundCell As Range Set FoundCell = Sh.Cells.Find(What:=Book.本棚番号, LookAt:=xlWhole) If Not FoundCell Is Nothing Then ChangeColor Sh, FoundCell End If If myIndex = 2 Then .TextBox1.Value = "" .ListBox1.Clear End If Exit Sub End If Next End With End Sub
リストボックスがクリックされたことを検知するために(WithEvents)、myListBoxを宣言しています。myIndexは、何番目のリストボックスかを知るためのものです。
Set_ListBoxで、検知したいリストボックスを登録しています。
myListBox_Clickで、リストボックスがクリックされた際の処理を一手に引き受けています。内容はユーザーフォームで繰り返し記述されていたものとほぼ同じです。
次に、標準モジュールに以下を追加します。
Public BookShelfListBox(1 To 2) As ListBoxControlClass Sub SetBookShelfListBox() Dim i As Long For i = 1 To 2 Set BookShelfListBox(i) = New ListBoxControlClass BookShelfListBox(i).Set_ListBox BookShelfForm.Controls("ListBox" & i), i Next End Sub
これでリストボックスを一つずつ登録して、クリックを検知できるようにしていきます。リストボックスが100個あれば、1 To 2 を 1 To 100 にするだけでよく、コードの長さは殆ど変わりません。
最後に、ユーザーフォームのコードを変更します。
Option Explicit Private Sub TextBox1_Change() Dim str As String str = TextBox1.Value ListBox1.Clear Dim seq As Variant ReDim seq(1 To Books.Count, 1 To 2) Dim i As Long i = 1 For Each Book In Books If Book.書籍名称 Like "*" & str & "*" Then seq(i, 1) = Book.書籍名称 seq(i, 2) = Book.通し番号 i = i + 1 End If Next ListBox1.List = seq End Sub Private Sub UserForm_Initialize() Call InitUserform Call SetBookShelfListBox End Sub Private Sub CloseButton_Click() Unload Me End Sub
リストボックスのクリックに関する部分が外に出たため、とてもスッキリしました。
次回に続く(かもしれない)。
参考まで。