似たようなプロシージャを一つにまとめてみる

昨日は、ユーザーフォーム上でフォルダの絞り込みを行い、最終的にファイルを選択するところまで作成した。
infoment.hatenablog.com
f:id:Infoment:20181031224448g:plain

これを行うにあたり、似たようなサブプロシージャを4つも作ってしまった。そこで今日は、これを一つにまとめてみる。
f:id:Infoment:20181101221347p:plain

クラスモジュール(SeaquenceClass)

昨日までに作成したのは、以下の4つ。


指定パスのサブフォルダ名を配列で取得。

Public Function GetSubFoldersSeq(folder_path As String) As Variant
    Dim TempCol As Collection
    Set TempCol = GetSubFoldersCol(folder_path)
    If TempCol.Count >= 1 Then
        GetSubFoldersSeq = ToArray(TempCol)
    Else
        GetSubFoldersSeq = Array()
    End If
End Function


指定パスのサブフォルダ名をコレクションで取得。

Public Function GetSubFoldersCol(folder_path As String) As Collection
    ' Microsoft Scripting Runtimeの参照設定要
    Dim FSO As FileSystemObject
    Set FSO = New FileSystemObject
    
    Dim TempCol As Collection
    Set TempCol = New Collection
    
    Dim myFolder As Folder
        For Each myFolder In FSO.GetFolder(folder_path).SubFolders
            TempCol.Add myFolder.Name
        Next
    
    Set GetSubFoldersCol = TempCol
End Function


指定パスのフォルダ内にあるファイル名を配列で取得。

Public Function GetFilesSeq(folder_path As String) As Variant
    Dim TempCol As Collection
    Set TempCol = GetFilesCol(folder_path)
    If TempCol.Count >= 1 Then
        GetFilesSeq = ToArray(TempCol)
    Else
        GetFilesSeq = Array()
    End If
End Function


指定パスのフォルダ内にあるファイル名をコレクションで取得。

Public Function GetFilesCol(folder_path As String) As Collection
    ' Microsoft Scripting Runtimeの参照設定要
    Dim FSO As FileSystemObject
    Set FSO = New FileSystemObject
    
    Dim TempCol As Collection
    Set TempCol = New Collection
    
    Dim myFile As File
        For Each myFile In FSO.GetFolder(folder_path).Files
            TempCol.Add myFile.Name
        Next
    
    Set GetFilesCol = TempCol
End Function


これを一つにまとめるために、最近自分の中で流行りの列挙型を用いてみる。

標準モジュール
' 取得する対象(フォルダ名か、ファイル名か)
Public Enum ReturnGroup
    myVbFolder
    myVbFile
End Enum

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

次に、先ほどの4つを統合する。作戦は、こうだ。

  1. 対象がフォルダ名なのかファイル名なのか、引数で判断。
  2. どちらにしても、とにかくコレクションに格納。
  3. 戻り値は配列なのかコレクションなのか、引数で判断。
  4. コレクションだったらそのまま。配列なら、配列に変換して戻す。

実際のコードが、こちら。

Option Explicit
Dim FSO As FileSystemObject

Private Sub Class_Initialize()
    Set FSO = New FileSystemObject
End Sub

'[用 途]
'   指定フォルダ下にあるフォルダ名やファイル名を取得

'[引 数]
'   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

ユーザーフォーム側は、関数の名前を変えるぐらいで、ほとんど差は無いので割愛する。一応正常に動作したので、良しとしよう。

でも、まだまだ簡略化できそうだ。これについては、明日改めて挑戦します。

参考まで。