我需要获取文件夹中所有Excel文件的名称,然后对每个文件进行更改。我已经解决了“改变”部分。有没有办法在一个文件夹中获取.xlsx
文件列表,比如D:\Personal
并将其存储在String Array中。
然后我需要遍历文件列表并在我认为可以使用的每个文件上运行一个宏:
Filepath = "D:\Personal\"
For Each i in FileArray
Workbooks.Open(Filepath+i)
Next
我看了this,然而,我无法打开文件,因为它以Variant
格式存储了名称。
简而言之,我如何使用VBA获取特定文件夹中的Excel文件名列表?
好吧,这可能适合你,一个获取路径并返回文件夹中的文件名数组的函数。在循环遍历数组时,您可以使用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中被破坏了(bug?)。
您可以使用内置的Dir函数或FileSystemObject。
他们每个人都有自己的优点和缺点。
你的功能
Dir函数是一种内置的轻量级方法,用于获取文件列表。使用它的好处是:
诀窍是理解使用或不使用参数调用它之间的区别。这是一个非常简单的示例:
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
如果您更改循环内的任何文件,您将得到不可预测的结果。在对文件执行任何操作之前,最好将所有名称读入字符串数组中。这是一个基于前一个示例的示例。这是一个返回String数组的函数:
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脚本宿主对象模型”(或“Windows脚本运行时”)的引用,并声明您的对象,如下所示:
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
如果你不想要intellisense,你可以这样做,而无需设置参考:
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
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
如果你想要的只是没有文件扩展名的文件名
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
关于upvoted答案,我喜欢它,除了如果在数组公式{CSE}中使用得到的“listfiles”数组,列表值全部出现在水平行中。为了使它们在垂直列中出现,我简单地将数组制作成二维,如下所示:
ReDim vaArray(1 To oFiles.Count, 0)
i = 1
For Each oFile In oFiles
vaArray(i, 0) = oFile.Name
i = i + 1
Next