リストボックスのクリックをWIthEventsで検知してファイルの絞り込みを行う ~改~

昨日は、ListBoxのクリックイベントを用いて、ファイルの絞り込みを行ってみた。
infoment.hatenablog.com
f:id:Infoment:20181103220301g:plain

でも、何だかまだしっくりこない。もう少し模索してみた。
f:id:Infoment:20181104130151p:plain

しっくりこない理由は、直ぐに分かった。
リストボックスが4つ、5つと増えた場合、併せて直さなければならない箇所が複数あるからだ。そこで、リストボックスの増減に追従するよう変更してみた。

標準モジュール

まずListBoxの名称について、役割を名称に反映するのではなく、

  1. ListBox1
  2. ListBox2
  3. ListBox3

のようにListBox + 連番とした。
そのため、昨日あったEnumの一部が無くなっている。

Option Explicit
' 取得する対象(フォルダ名か、ファイル名か)
    Public Enum ReturnGroup
        myVbFolder
        myVbFile
    End Enum
' 何に格納するか(配列か、コレクションか)
    Public Enum ReturnType
        myVbSeq
        myVbCol
    End Enum
    Public Const ParentFolderPath As String = "C:\Temp"
    Public myListBoxes() As MSForms.ListBox
    Public LB() As SelectFileClass
ユーザーフォーム(SelectFileForm)

リストボックスの増減に、機能を追従させる。
作戦はこうだ。

  1. ユーザーフォーム上にリストボックスがいくつあるか調べる。
  2. リストボックスを配列化
  3. 併せて、クリックイベント用に登録
Option Explicit
Dim SQC As SeaquenceClass
Private Sub UserForm_Initialize()
    PathLabel.Caption = ParentFolderPath
' ↓今回追加した箇所
    Dim myControl As Control
    Dim iMax As Long
        iMax = 0
    For Each myControl In Me.Controls
        If TypeName(myControl) = "ListBox" Then
            iMax = iMax + 1
        End If
    Next
    Dim i As Long
    ReDim LB(1 To iMax)
    ReDim myListBoxes(1 To iMax)
    
    For i = 1 To iMax
        Set myListBoxes(i) = Me.Controls("ListBox" & i)
        Set LB(i) = New SelectFileClass
            LB(i).SetListBox myListBoxes(i), i
    Next
 ' ↑今回追加した箇所
    Set SQC = New SeaquenceClass
         myListBoxes(1).List = SQC.GetFolderFileNames(ParentFolderPath)    
End Sub
クラスモジュール(SelectFileClass)

最後に、昨日のクラスモジュールにつて、リストボックス数を可変にした。

Option Explicit
    ' リストボックスのクリックイベント検知用
    Private WithEvents myListBox As MSForms.ListBox    
    ' クリックされたリストボックスの番号
    Dim myIndex As Long    
    ' 指定フォルダ内のフォルダ名やファイル名を配列化
    Dim SQC As SeaquenceClass
' 各リストボックスをクリックイベント検知用にセット
Public Sub SetListBox(newListBox As MSForms.ListBox, _
                      Index As Long)
    Set myListBox = newListBox
        myIndex = Index
End Sub

※↓昨日の、リストボックスの配列化分を削除

Private Sub Class_Initialize()
    Set SQC = New SeaquenceClass
End Sub

※↓リストボックスの増減に対応

' リストボックスのクリックイベント
Private Sub myListBox_Click()
    Dim myList As Variant
        ' ラベルの値変更。
        SelectFileForm.PathLabel = myPath
    
    Dim iMax As Long
        iMax = UBound(myListBoxes)
        ' クリックされたリストボックスごとに、myListの内容変更。
        Select Case myIndex
            Case 1 To iMax - 2
                myList = SQC.GetFolderFileNames(myPath)
            Case iMax - 1
                myList = SQC.GetFolderFileNames(myPath, myVbFile)
            Case iMax
                myList = Array()
                Exit Sub
        End Select
        
        ' クリックされたリストボックスの次以降を全てクリア。
        Dim i As Long
            For i = myIndex + 1 To UBound(LB)
                myListBoxes(i).Clear
            Next
        If UBound(myList) <> -1 Then
            With myListBoxes(myIndex + 1)
                .List = myList
            End With
        End If
End Sub
' リストボックスがクリックされた時点での、クリックされた内容を
' 反映したパスの取得。
Private Function myPath() As String
    Dim TempCol As Collection
        Set TempCol = New Collection
            TempCol.Add ParentFolderPath
    Dim i As Long
        For i = 1 To myIndex
            TempCol.Add myListBoxes(i).Value
        Next
        myPath = Join(SQC.ToArray(TempCol), "\")
End Function

結果、同じ動きを実現できた。

一つのフォルダ内に、ファイルとサブフォルダが混在する場合などについては、後日また検討してみるとします。

参考まで。