the High Seas of Information Technology

Retrieving file names/paths from a folder (and subfolders):

To work with files in a folder, I have found it helpful in VBA to drop the filepaths of the files into an array . This way I can deal with capturing the array of filenames as a discrete step prior to whatever I may do with the files. As another benefit, whatever procedure I have that uses the list of files is separated from the code for retrieving the list. This provides a modular structure that is easier to maintain and promotes code re-use.

The code here implements the FileSystemObject of the Microsoft Scripting Runtime Library, which is normally already a part of your Windows operating environment. The FileSystemObject provides methods for working with files and folder. We use a rather simple set of instructions that incidentally demonstrates how a recursive procedure can do a good bit of work with very little code - the same procedure continually calls itself until it has exhausted its folder explorations. With only two flag variables, we can instruct the code to stick to only the first folder, its immediate subfolders, or all subfolders.

Below is the code for the Directory_Listing function. It's output will be a string array of all the files in the folder you give it, and optionally file from subfolders. Note that this is merely a string array of the complete filepaths for the files - the next step is up to you, namely, to do something with that list. There are three procedures listed:

  1. Directory_List - a public function used to call the procedure (mainly a wrapper for the "real" function but it serves a critical purpose of initializing the string array that we are aiming at)
  2. Directory_List_Main - a private function that iterates folders capturing file names
  3. Demonstrate_Directory_List - a subroutine to demonstrate using the code. It will output three lists of file names to Excel, given three different depths for searching, and additionally picking out the Excel files that it found.

Public Function Directory_List(ByVal startInFolder As String, _
Optional includeImmediateSubFolders As Boolean = False, _
Optional includeAllSubFolders As Boolean = False) As Variant
    '   Directory_List public function (exposes the code for use)
    '   Returns: Variant/Array if at least one file is found, Variant/Empty otherwise.

Dim a() As String '//Array to hold filepaths
Dim i As Long '//Counter of files found
Dim FSO As Object
Set FSO = CreateObject("Scripting.FileSystemObject")
ReDim a(0 To 0)
Call Directory_List_Main(FSO, a, i, _
startInFolder, _
includeImmediateSubFolders, _
If i > 0 Then
Directory_List = a
End If
Set FSO = Nothing
End Function

Private Sub Directory_List_Main(ByRef FSO As Object, ByRef a() As String, ByRef i As Long, _
ByRef startInFolder As String, _
Optional includeImmediateSubFolders As Boolean = False, _
Optional includeAllSubFolders As Boolean = False)
    '   Directory_List_Main private function (iterates files/folders to retrieve filepaths).

Dim MyFolder As Folder
Dim mySubfolder As Folder
Dim f As File
Dim msg As String

On Error GoTo Handler
'//Error - initial folder not found
    If Not (FSO.FolderExists(startInFolder)) Then
msg = "Error. Folder not Found:" & vbNewLine & startInFolder
MsgBox msg, vbExclamation
Exit Sub
End If
'//Process files in folder
    With FSO
Set MyFolder = .GetFolder(startInFolder)
For Each f In MyFolder.Files
ReDim Preserve a(0 To i)
a(i) = f.Path
i = i + 1
Next f
'//optional recursive call(s) for subfolder(s)
        If (includeImmediateSubFolders Or includeAllSubFolders) Then
For Each mySubfolder In MyFolder.SubFolders
Call Directory_List_Main(FSO, a, i, _
mySubfolder.Path, _
includeAllSubFolders, _
Next mySubfolder
End If
End With

Exit Sub
MsgBox "Error in Sub Directory_List_Main" & Err.Number & " " & Err.Description
Set FSO = Nothing
Resume My_Exit

End Sub

Sample use of Directory_List:

Sub Demonstrate_Directory_List()

'//Demonstrate Directory_List - output is four columns
'    * Column A: Files in folder
'    * Column B: Files in folder and immediate subfolders
'    * Column C: Files in folder and all subfolder
'    * Column D: Excel files found (if any) by name

'//To Run the Demonstration
'    * Change the value of variable *sFolder* to a folder on your PC
'    * Choose a folder with a few files in it
'    * If possible, one with subfolders and nested subfolders also containing files

Dim a, b() As String
Dim i As Long, j As Long
Dim wb As Workbook
Dim sFolder As String
Dim FSO As FileSystemObject

sFolder = "C:\myTemp"
Set wb = Workbooks.Add
'//Get an array of filepaths in folder (output to Excel).
    a = Directory_List(sFolder, False, False)
If IsEmpty(a) Then
wb.Sheets(1).Cells(1, 1) = "File in Folder: " & sFolder & " (0 found)"
With wb.Sheets(1)
.Cells(1, 1) = "Files in Folder: " & sFolder & " (" & UBound(a) + 1 & " found)"
.Cells(2, 1).Resize(UBound(a) + 1).Value = WorksheetFunction.Transpose(a)
.Cells(1, 1).Font.Bold = True
.Cells(1, 1).WrapText = True
.Cells(1, 1).VerticalAlignment = -4160
.Columns(1).ColumnWidth = 35
.Columns(2).ColumnWidth = 1.5
End With
'//Run again, this time including immediate subfolders (output to Excel).
        a = Directory_List(sFolder, True, False)
With wb.Sheets(1)
.Cells(1, 3) = "Files in Folder and Immediate SubFolders: " _
& sFolder & " (" & UBound(a) + 1 & " found)"
.Cells(2, 3).Resize(UBound(a) + 1).Value = WorksheetFunction.Transpose(a)
.Cells(1, 3).Font.Bold = True
.Cells(1, 3).WrapText = True
.Cells(1, 3).VerticalAlignment = -4160
.Columns(3).ColumnWidth = 35
.Columns(4).ColumnWidth = 1.5
End With
'//Run again, this time including all subfolders (output to Excel).
        a = Directory_List(sFolder, True, True)
With wb.Sheets(1)
.Cells(1, 5) = "File in Folder and All SubFolders: " & sFolder _
& " (" & UBound(a) + 1 & " found)"
.Cells(2, 5).Resize(UBound(a) + 1).Value = WorksheetFunction.Transpose(a)
.Cells(1, 5).Font.Bold = True
.Cells(1, 5).WrapText = True
.Cells(1, 5).VerticalAlignment = -4160
.Columns(5).ColumnWidth = 35
.Columns(6).ColumnWidth = 1.5
End With
End If
'//List Excel files found (output to Excel).
    Set FSO = CreateObject("Scripting.FileSystemObject")
For i = 0 To UBound(a)
If LCase(FSO.GetFile(a(i)).Type) Like "*excel*" Then
ReDim Preserve b(0 To j)
b(j) = FSO.GetFileName(a(i))
j = j + 1
End If
Next i
If j > 0 Then
With wb.Sheets(1)
.Cells(1, 7).Value = "Excel Files Found: " & " (" & UBound(b) + 1 & " found)"
.Cells(2, 7).Resize(UBound(b) + 1).Value = WorksheetFunction.Transpose(b)
.Cells(1, 7).Font.Bold = True
.Cells(1, 7).WrapText = True
.Cells(1, 7).VerticalAlignment = -4160
.Columns(7).ColumnWidth = 35
End With
End If
wb.Saved = True

End Sub
last modified: 28-Jan-2015
Copyright © 2015