一行のコードで終わらせる ②-1 指定フォルダ内のファイルパス取得

昨日は、特定列の空白セルを行ごと削除するマクロについて紹介した。
infoment.hatenablog.com
今日は指定フォルダ内にある全ファイルの、ファイルパス取得について紹介する。
f:id:Infoment:20190102081137p:plain

例えば「C:\Temp」フォルダに、以下4つのファイルがあるとする。

f:id:Infoment:20190102081318p:plain

Dir関数で取得

このようなケースで私が最初に学んだのは、Dir関数を用いた方法だった。
Dir 関数 (Visual Basic for Applications) | Microsoft Docs

例えば、こんな感じだ。ユーザー定義関数で、ファイルパスを配列に格納する。

Function GetFilePathes(folder_path As String) As Variant

    Dim FileName As String
        ' 指定パスの最初にあるファイルについて、
        ' Dir関数でファイル名を取得する。
        FileName = Dir(folder_path & "\*.*")
        
    ' 取得したファイルパス格納用コレクション。
    Dim TempCol As Collection
    Set TempCol = New Collection
    
    ' 指定フォルダ内の全てのファイル(※)について、
    ' ファイルパスをコレクションに格納する。
    ' ※サブフォルダ下のファイルを除く。
    Do While FileName <> ""
        TempCol.Add folder_path & "\" & FileName
        FileName = Dir
    Loop
    
    ' 空っぽのフォルダだった場合、空配列を返して終了。
    If TempCol.Count = 0 Then
        GetFilePathes = Array()
        Exit Function
    End If
    
    ' コレクションを配列に変換する。
    Dim TempSeq() As Variant
    ReDim TempSeq(1 To TempCol.Count)
    
    Dim i As Long: i = 1
    Dim c As Variant
    For Each c In TempCol
        TempSeq(i) = c
        i = i + 1
    Next
    
    GetFilePathes = TempSeq

End Function

こちらのマクロでテストしてみよう。

Sub hogeTest()
    Dim seq As Variant
        seq = GetFilePathes("C:\Temp")
End Sub

結果、ファイルパスを取得することが出来た。

f:id:Infoment:20190102083154p:plain

FileSystemObject で取得

次に学んだのは、FileSystemObjectだった。
FileSystemObject オブジェクト

例えば、こんな感じだ。※事前にMicrosoft Scripting Runtimeを参照設定済み。

Function GetFilePathes(folder_path As String) As Variant

    ' FileSystemObject用変数の宣言と初期化。
    Dim FSO As FileSystemObject
    Set FSO = New FileSystemObject
    
    ' ファイルが存在しない場合、空配列を返す。
    Dim iMax As Long
        iMax = FSO.GetFolder(folder_path).Files.Count
    
        If iMax = 0 Then
            GetFilePathes = Array()
            Exit Function
        End If
    
    ' 指定フォルダ内の全ファイルパスを、配列に格納する。
    ' ※サブフォルダ下のファイルを除く。
    Dim i As Long: i = 1
    Dim TempSeq() As Variant
    ReDim TempSeq(1 To iMax)
    Dim myFile As File
        For Each myFile In FSO.GetFolder(folder_path).Files
            TempSeq(i) = myFile.Path
            i = i + 1
        Next
        
        GetFilePathes = TempSeq

End Function

Dir関数が高速でお手軽である一方、FileSystemObjectは遅いが高機能、ということらしい。個人的には、FileSystemObjectの方が好みだ。

3番目の方法

主に今までの二つを用いつつ、新たなファイル検索の方法を探していた私はつい先日、以下のコードに出会ってしまった。

Function Function_FileList(FolderLocation As String) 
    Function_FileList = Filter(Split(CreateObject("wscript.shell").exec("cmd /c Dir """ & FolderLocation & """ /b /a-d").stdout.readall, vbCrLf), ".") 
End Function 

出典は↓ こちら。
stackoverrun.com

グルグルとループさせることなく、一行で、一撃で処理を完了させている。衝撃だった。全てのケースに適用できる訳では無いようだが、それでも凄いと思った。

それにしても、この一行で、一体何をやっているんだろう?慣れた人には馴染み深いものばかりなのだろうが、私の場合、初めて見るものが幾つもある。

そこで明日は、勉強のために、これを読み解くことに挑戦してみます。

参考まで。