web-dev-qa-db-ja.com

VBAを使用してフォルダー内のExcelファイルのリストを取得する

フォルダー内のすべてのExcelファイルの名前を取得してから、各ファイルに変更を加える必要があります。 「変更を加える」部分が整理されました。 1つのフォルダー内の.xlsxファイルのリストを取得する方法、たとえばD:\Personalを取得して、ストリング配列に保存する方法はありますか。

次に、ファイルのリストを繰り返し処理し、使用できると判断した各ファイルでマクロを実行する必要があります。

Filepath = "D:\Personal\"
For Each i in FileArray
    Workbooks.Open(Filepath+i)
Next

this を見ましたが、ファイルを開くことができなかったため、Variant形式で名前が保存されていました。

要するに、VBAを使用して特定のフォルダー内のExcelファイル名のリストを取得するにはどうすればよいですか?

18
Buzz Lightyear

パスを取得して、フォルダー内のファイル名の配列を返す関数は、これでうまくいくかもしれません。 ifステートメントを使用して、配列をループするときにExcelファイルのみを取得できます。

Function listfiles(ByVal sPath As String)

    Dim vaArray     As Variant
    Dim i           As Integer
    Dim oFile       As Object
    Dim oFSO        As Object
    Dim oFolder     As Object
    Dim oFiles      As Object

    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oFolder = oFSO.GetFolder(sPath)
    Set oFiles = oFolder.Files

    If oFiles.Count = 0 Then Exit Function

    ReDim vaArray(1 To oFiles.Count)
    i = 1
    For Each oFile In oFiles
        vaArray(i) = oFile.Name
        i = i + 1
    Next

    listfiles = vaArray

End Function

インデックス番号でファイルオブジェクトのファイルにアクセスできればいいのですが、VBAでは何らかの理由で壊れているようです(バグ?)。

35
Coder375

組み込みのDir関数またはFileSystemObjectを使用できます。

それぞれに長所と短所があります。

Dir関数

Dir関数は、ファイルのリストを取得するための組み込みの軽量メソッドです。それを使用する利点は次のとおりです。

  • 使いやすい
  • 良好なパフォーマンス(高速)
  • ワイルドカードのサポート

秘Theは、パラメータを指定して呼び出す場合と指定しない場合の違いを理解することです。以下に、非常に簡単な例を示します。

Public Sub ListFilesDir(ByVal sPath As String, Optional ByVal sFilter As String)

    Dim sFile As String

    If Right(sPath, 1) <> "\" Then
        sPath = sPath & "\"
    End If

    If sFilter = "" Then
        sFilter = "*.*"
    End If

    'call with path "initializes" the dir function and returns the first file name
    sFile = Dir(sPath & sFilter)

   'call it again until there are no more files
    Do Until sFile = ""

        Debug.Print sFile

        'subsequent calls without param return next file name
        sFile = Dir

    Loop

End Sub

ループ内のファイルのいずれかを変更すると、予測できない結果が得られます。ファイルに対して操作を行う前に、すべての名前を文字列の配列に読み込むことをお勧めします。以下は、前の例に基づいた例です。これは、文字列配列を返す関数です。

Public Function GetFilesDir(ByVal sPath As String, _
    Optional ByVal sFilter As String) As String()

    'dynamic array for names
    Dim aFileNames() As String
    ReDim aFileNames(0)

    Dim sFile As String
    Dim nCounter As Long

    If Right(sPath, 1) <> "\" Then
        sPath = sPath & "\"
    End If

    If sFilter = "" Then
        sFilter = "*.*"
    End If

    'call with path "initializes" the dir function and returns the first file
    sFile = Dir(sPath & sFilter)

    'call it until there is no filename returned
    Do While sFile <> ""

        'store the file name in the array
        aFileNames(nCounter) = sFile

        'subsequent calls without param return next file
        sFile = Dir

        'make sure your array is large enough for another
        nCounter = nCounter + 1
        If nCounter > UBound(aFileNames) Then
            'preserve the values and grow by reasonable amount for performance
            ReDim Preserve aFileNames(UBound(aFileNames) + 255)
        End If

    Loop

    'truncate the array to correct size
    If nCounter < UBound(aFileNames) Then
        ReDim Preserve aFileNames(0 To nCounter - 1)
    End If

    'return the array of file names
    GetFilesDir = aFileNames()

End Function

ファイルシステムオブジェクト

ファイルシステムオブジェクトは、ファイルを操作するためのオブジェクトモデルをサポートするIO操作のライブラリです。このアプローチの長所:

  • インテリセンス
  • 堅牢なオブジェクトモデル

「Windows Script Host Object Model」(または「Windows Scripting Runtime」)への参照を追加して、次のようにオブジェクトを宣言できます。

Public Sub ListFilesFSO(ByVal sPath As String)

    Dim oFSO As FileSystemObject
    Dim oFolder As Folder
    Dim oFile As File

    Set oFSO = New FileSystemObject
    Set oFolder = oFSO.GetFolder(sPath)
    For Each oFile In oFolder.Files
        Debug.Print oFile.Name
    Next 'oFile

    Set oFile = Nothing
    Set oFolder = Nothing
    Set oFSO = Nothing

End Sub

インテリセンスが必要ない場合は、参照を設定せずにそのようにすることができます。

Public Sub ListFilesFSO(ByVal sPath As String)

    Dim oFSO As Object
    Dim oFolder As Object
    Dim oFile As Object

    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oFolder = oFSO.GetFolder(sPath)
    For Each oFile In oFolder.Files
        Debug.Print oFile.Name
    Next 'oFile

    Set oFile = Nothing
    Set oFolder = Nothing
    Set oFSO = Nothing

End Sub
25
Don Jewett
Dim iIndex as Integer
Dim ws As Excel.Worksheet
Dim wb      As Workbook
Dim strPath As String
Dim strFile As String

strPath = "D:\Personal\"
strFile = Dir(strPath & "*.xlsx")

Do While strFile <> ""
    Set wb = Workbooks.Open(Filename:=strPath & strFile)

    For iIndex = 1 To wb.Worksheets.count
        Set ws = wb.Worksheets(iIndex)

        'Do something here.

    Next iIndex

 strFile = Dir 'This moves the value of strFile to the next file.
Loop
5
MatthewD

必要なのがファイル拡張子のないファイル名だけである場合

Dim fileNamesCol As New Collection
Dim MyFile As Variant  'Strings and primitive data types aren't allowed with collection

filePath = "c:\file directory" + "\"
MyFile = Dir$(filePath & "*.xlsx")
Do While MyFile <> ""
    fileNamesCol.Add (Replace(MyFile, ".xlsx", ""))
    MyFile = Dir$
Loop

Excelワークシートに出力するには

Dim myWs As Worksheet: Set myWs = Sheets("SheetNameToDisplayTo")
Dim ic As Integer: ic = 1

For Each MyFile In fileNamesCol
    myWs.Range("A" & ic).Value = fileNamesCol(ic)
    ic = ic + 1
Next MyFile

主にここで詳述する手法に基づいています: https://wordmvp.com/FAQs/MacrosVBA/ReadFilesIntoArray.htm

1
gimmegimme

賛成の回答については、結果の「listfiles」配列が配列式{CSE}で使用される場合、リストの値がすべて水平の行に表示されることを除いて、それが気に入りました。それらを垂直の列に表示するには、次のように単純に配列を2次元にします。

ReDim vaArray(1 To oFiles.Count, 0)
i = 1
For Each oFile In oFiles
    vaArray(i, 0) = oFile.Name
    i = i + 1
Next
0
aVIPtoYou