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

昨日は、リストボックスのクリックをとりあえず検知してみた。
infoment.hatenablog.com
f:id:Infoment:20181102185701g:plain

今日は、実際にファイルの絞り込みを行ってみる。
f:id:Infoment:20181103214727p:plain

といっても私的都合で、今日は詳しい解説を書く元気がない。それは後日に回すとして、とりあえず今までの分も含めた一式、作成した分を掲載しておく。

クラスモジュール(SeaquenceClass)

指定フォルダのファイル名を取得したり、コレクションを配列化するためのもの。

Option Explicit
    Dim FSO As FileSystemObject
Private Sub Class_Initialize()
    Set FSO = New FileSystemObject
End Sub
'[用 途]
'   コレクションを一次元配列に変換する
'[引 数]
'   col as Collection   元データ
'[戻り値]
'   一次元配列
Public Function ToArray(col As Collection) As Variant
    Dim seq As Variant
    ReDim seq(col.Count - 1)
    Dim c As Variant
    Dim i As Long
        i = 0
        For Each c In col
            seq(i) = c
            i = i + 1
        Next    
    ToArray = seq
End Function
'[用 途]
'   指定フォルダ下にあるフォルダ名やファイル名を取得
'[引 数]
'   folder_path As String       指定フォルダ
'   return_group As ReturnGroup 取得対象(フォルダ or ファイル) ※初期値:フォルダ
'   return_type As ReturnType   格納方法(配列 or コレクション)  ※初期値:配列
'[戻り値]
'   「フォルダまたはファイル」名称を格納した「配列またはコレクション」
'[備 考]
'   標準モジュールの列挙型(ReturnGroup および ReturnType)とセットで使用
Public Function GetFolderFileNames(folder_path As String, _
                          Optional return_group As ReturnGroup = myVbFolder, _
                          Optional return_type As ReturnType = myVbSeq) As Variant
    Dim TempCol As Collection
    Set TempCol = New Collection    
        On Error GoTo er
        ' 名称取得。
        Select Case return_group
            'フォルダの場合。
            Case myVbFolder
                Dim myFolder As Folder
                For Each myFolder In FSO.GetFolder(folder_path).SubFolders
                    TempCol.Add myFolder.Name
                Next
            ' ファイルの場合。
            Case myVbFile
                Dim myFile As File
                For Each myFile In FSO.GetFolder(folder_path).Files
                    TempCol.Add myFile.Name
                Next
        End Select

        ' 格納方法。
        Select Case return_type
            ' 配列の場合。
            Case myVbSeq
                GetFolderFileNames = ToArray(TempCol)
            ' コレクションの場合。
            Case myVbCol
                Set GetFolderFileNames = TempCol
        End Select
        Exit Function
er:
        GetFolderFileNames = Array()
End Function
クラスモジュール(SelectFileClass)

ユーザーフォーム内のリストボックス等コントロール用。

Option Explicit
    ' リストボックスのクリックイベント検知用
    Private WithEvents myListBox As MSForms.ListBox    
    ' クリックされたリストボックスの番号
    Dim myIndex As Long    
    ' 指定フォルダ内のフォルダ名やファイル名を配列化
    Dim SQC As SeaquenceClass    
    '各リストボックス
    Dim myListBoxes(ListBoxNumber.myVbFolder1 To ListBoxNumber.myVbFile1) As MSForms.ListBox
' 各リストボックスを配列化
Private Sub Class_Initialize()
    Set SQC = New SeaquenceClass
    Set myListBoxes(ListBoxNumber.myVbFolder1) = SelectFileForm.FolderListBox1
    Set myListBoxes(ListBoxNumber.myVbFolder2) = SelectFileForm.FolderListBox2
    Set myListBoxes(ListBoxNumber.myVbFile1) = SelectFileForm.FileListBox1
End Sub
' 各リストボックスをクリックイベント検知用にセット
Public Sub SetListBox(newListBox As MSForms.ListBox, _
                      Index As Long)
    Set myListBox = newListBox
        myIndex = Index
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
' リストボックスのクリックイベント
Private Sub myListBox_Click()
    Dim myList As Variant
        ' ラベルの値変更。
        SelectFileForm.PathLabel = myPath
        ' クリックされたリストボックスごとに、myListの内容変更。
        Select Case myIndex
            Case ListBoxNumber.myVbFolder1
                myList = SQC.GetFolderFileNames(myPath)
            Case ListBoxNumber.myVbFolder2
                myList = SQC.GetFolderFileNames(myPath, myVbFile)
            Case Else
                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
標準モジュール
Option Explicit
' 取得する対象(フォルダ名か、ファイル名か)
    Public Enum ReturnGroup
        myVbFolder
        myVbFile
    End Enum

' 何に格納するか(配列か、コレクションか)
    Public Enum ReturnType
        myVbSeq
        myVbCol
    End Enum

' リストボックス
    Public Enum ListBoxNumber
        myVbFolder1 = 1
        myVbFolder2
        myVbFile1
    End Enum
    
    Public Const ParentFolderPath As String = "C:\Temp"
    Public LB(ListBoxNumber.myVbFolder1 To ListBoxNumber.myVbFile1) As New SelectFileClass
' リストボックスのクリックイベント検知用。
Public Sub SetLB()
    With SelectFileForm
        LB(ListBoxNumber.myVbFolder1).SetListBox .FolderListBox1, ListBoxNumber.myVbFolder1
        LB(ListBoxNumber.myVbFolder2).SetListBox .FolderListBox2, ListBoxNumber.myVbFolder2
        LB(ListBoxNumber.myVbFile1).SetListBox .FileListBox1, ListBoxNumber.myVbFile1
    End With
End Sub
ユーザーフォーム(SelectFileForm)

今のところ、これだけ。

Option Explicit

Dim SQC As SeaquenceClass

Private Sub UserForm_Initialize()
    PathLabel.Caption = ParentFolderPath
    Set SQC = New SeaquenceClass
        FolderListBox1.List = SQC.GetFolderFileNames(ParentFolderPath)
    Call SetLB
End Sub

結果は、以前と同じ動作をさせることができた。
f:id:Infoment:20181103220301g:plain

でも、まだ何だかしっくりこない。もっと簡単にできるような気がする。

引き続き、模索してみます。

参考まで。