VBA to List all Folders, Subfolders and files in a directory

Status
Not open for further replies.

acrete

New Member
Joined
Dec 13, 2018
Messages
5
Hi all, I found many examples that prints file directories into a spreadsheet. I am trying to create a VBA in Excel that replicates a cmd script to list out contents of a folder, subfolders and files

Code:
tree "C:\list\" > C:\list\details.txt" /A /F

The spreadsheet needs to cascade so column A lists the files in the directory, column b lists the subfolders, column c lists the files in the subfolders, column d lists subfolders of the subfolder, etc....

Any help would be much appreciated. Thanks!

1647460880594.png
 

@mrsoliveira

'Call Sub Procedure
'List all folders & subfolders
sbListAllFolders sRootFolderName
the following code will list without calling FSO for each subfolder, instead it calls it once.

VBA Code:
Option Explicit

Sub ListAllFoldersForSubFolders()

Dim shtFldDetails As Worksheet
Dim fso As Object
Dim fldr As Object
Dim fldrSF As Object
Dim ofiles As Object
Dim wb As Workbook
Dim wbLinks As Workbook
Dim strPath As String
Dim strMsg As String
Dim strFld As String
Dim lRow As Long
Dim wsZip As Worksheet

'Disable visual updates
Application.Calculation = xlManual
Application.DisplayAlerts = True
Application.ScreenUpdating = False
On Error GoTo errHandler

Dim sRootFolderName As String

m_InitAfterRefresh.resetTableTracking
Sheet5.Unprotect
Range("File_List").Locked = True
m_FindColsandHide.HideColumns

'Browse Root Folder
sRootFolderName = sbBrowesFolder & "\"

'If path is not available, it display message and exit from the procedure
If sRootFolderName = "\" Then
    MsgBox "Please select folder to find and list its contents.", vbInformation, "Input Required!"
    Exit Sub
End If
 
'change sheet and range names
'  to match your workbook
strPath = sRootFolderName

Set wbLinks = ThisWorkbook

strMsg = "Could not start the list"
    'Delete Sheet if it exists
    Application.DisplayAlerts = False
        On Error Resume Next
        wbLinks.Sheets("Folder Details").Delete
    Application.DisplayAlerts = True
 
    'Add new Worksheet and name it as 'Folder Details'
    With wbLinks
        Set shtFldDetails = .Sheets.Add(After:=.Sheets(.Sheets.Count))
        shtFldDetails.Name = "Folder Details"
    End With
 
    'Create object for sheet name
    Set shtFldDetails = Sheets("Folder Details")
 
    'Clear Sheet
    shtFldDetails.Cells.Clear
Set wsZip = shtFldDetails
lRow = 4  'leave rows for heading

Set fso = _
  CreateObject("Scripting.FileSystemObject")
Set fldrSF = fso.GetFolder(strPath)

strMsg = "Could not count folders"
         
If Not fldrSF Is Nothing Then

processFolder fldrSF, strPath, wsZip, lRow

Else
  MsgBox "Could not find main folder"
  GoTo exitHandler
End If

With wsZip
  With .Cells(1, 1)
    .value = "Subfolders - " & strPath
    .Font.Bold = True
    .Font.Size = 14
  End With
  With .Range("B3:C3")
    .value = Array("Folder Path", "Files")
    .Font.Bold = True
  End With
  .Columns("B:C").EntireColumn.AutoFit
End With

strMsg = "List has been created"

exitHandler:
  Application.DisplayAlerts = True
  Application.ScreenUpdating = True
  MsgBox strMsg

  Exit Sub

errHandler:
    Resume exitHandler

End Sub

Function processFolder(fldr As Object, strPath As String, wsZip As Worksheet, lRow As Long)
    If Not fldr Is Nothing Then
        Dim ofiles As Files
        Set ofiles = fldr.Files
        With wsZip
            .Cells(lRow, 2).value = strPath
            .Cells(lRow, 3).value = ofiles.Count
        End With
        lRow = lRow + 1
        On Error Resume Next
        For Each fldr In fldr.SubFolders
            processFolder fldr, strPath & fldr.Name & "\", wsZip, lRow
        Next fldr
    End If
End Function

Public Function sbBrowesFolder()
    Dim FldrPicker As FileDialog
    Dim MyPath As String
      
    'Browse Folder Path
    Set FldrPicker = Application.FileDialog(msoFileDialogFolderPicker)
  
      With FldrPicker
        .Title = "Browse Root Folder Path"
        .AllowMultiSelect = False
                  If InitPath <> "" Then
            If Right$(InitPath, 1) <> "\" Then
                InitPath = InitPath & "\"
            End If
            .InitialFileName = InitPath
        Else
            .InitialFileName = "C:\"
        End If
          If .Show <> -1 Then Exit Function
          MyPath = .SelectedItems(1)
      End With
 
      sbBrowesFolder = MyPath
      If MyPath = vbNullString Then Exit Function

End Function
 
Last edited:
Upvote 0

Excel Facts

When did Power Query debut in Excel?
Although it was an add-in in Excel 2010 & Excel 2013, Power Query became a part of Excel in 2016, in Data, Get & Transform Data.
Try this macro. The usual method of processing folders, files and subfolders is a procedure which calls itself (a recursive procedure), however I decided to use a stack structure implemented as 2 VBA Collections for the folders and folder levels, which are kept in sync. This avoids the need to use a class module to store both properties.

VBA Code:
Option Explicit

Public Sub Main_List_Folders_and_Files()

    With ActiveSheet
        .Cells.Clear
        List_Folders_and_Files "C:\list", .Range("A1")
    End With

End Sub


Private Function List_Folders_and_Files(folderPath As String, destCell As Range) As Long

    Dim FSO As Object
    Dim FSfolder As Object, FSsubfolder As Object, FSfile As Object
    Dim folders As Collection, levels As Collection
    Dim subfoldersColl As Collection
    Dim n As Long, c As Long, i As Long
  
    Set FSO = CreateObject("Scripting.FileSystemObject")
    Set folders = New Collection
    Set levels = New Collection
  
    'Add start folder to stack
  
    folders.Add FSO.GetFolder(folderPath)
    levels.Add 0
     
    n = 0

    Do While folders.Count > 0
  
        'Remove next folder from top of stack
      
        Set FSfolder = folders(folders.Count): folders.Remove folders.Count
        c = levels(levels.Count): levels.Remove levels.Count
      
        'Output this folder and its files
      
        destCell.Offset(n, c).Value = "'" & FSfolder.Name
        n = n + 1
        c = c + 1
        For Each FSfile In FSfolder.Files
            destCell.Offset(n, c).Value = "'" & FSfile.Name
            n = n + 1
        Next
             
        'Get collection of subfolders in this folder
      
        Set subfoldersColl = New Collection
        For Each FSsubfolder In FSfolder.SubFolders
            subfoldersColl.Add FSsubfolder
        Next
      
        'Loop through collection in reverse order and put each subfolder on top of stack.  As a result, the subfolders are processed and
        'output in the correct ascending ASCII order
      
        For i = subfoldersColl.Count To 1 Step -1
            If folders.Count = 0 Then
                folders.Add subfoldersColl(i)
                levels.Add c
            Else
                folders.Add subfoldersColl(i), , , folders.Count
                levels.Add c, , , levels.Count
            End If
        Next
        Set subfoldersColl = Nothing
              
    Loop
  
    List_Folders_and_Files = n

End Function
@John_w thanks for your code . just question how add hyperlink to open folder or subfolder or f

Try this macro. The usual method of processing folders, files and subfolders is a procedure which calls itself (a recursive procedure), however I decided to use a stack structure implemented as 2 VBA Collections for the folders and folder levels, which are kept in sync. This avoids the need to use a class module to store both properties.

VBA Code:
Option Explicit

Public Sub Main_List_Folders_and_Files()

    With ActiveSheet
        .Cells.Clear
        List_Folders_and_Files "C:\list", .Range("A1")
    End With

End Sub


Private Function List_Folders_and_Files(folderPath As String, destCell As Range) As Long

    Dim FSO As Object
    Dim FSfolder As Object, FSsubfolder As Object, FSfile As Object
    Dim folders As Collection, levels As Collection
    Dim subfoldersColl As Collection
    Dim n As Long, c As Long, i As Long
   
    Set FSO = CreateObject("Scripting.FileSystemObject")
    Set folders = New Collection
    Set levels = New Collection
   
    'Add start folder to stack
   
    folders.Add FSO.GetFolder(folderPath)
    levels.Add 0
      
    n = 0

    Do While folders.Count > 0
   
        'Remove next folder from top of stack
       
        Set FSfolder = folders(folders.Count): folders.Remove folders.Count
        c = levels(levels.Count): levels.Remove levels.Count
       
        'Output this folder and its files
       
        destCell.Offset(n, c).Value = "'" & FSfolder.Name
        n = n + 1
        c = c + 1
        For Each FSfile In FSfolder.Files
            destCell.Offset(n, c).Value = "'" & FSfile.Name
            n = n + 1
        Next
              
        'Get collection of subfolders in this folder
       
        Set subfoldersColl = New Collection
        For Each FSsubfolder In FSfolder.SubFolders
            subfoldersColl.Add FSsubfolder
        Next
       
        'Loop through collection in reverse order and put each subfolder on top of stack.  As a result, the subfolders are processed and
        'output in the correct ascending ASCII order
       
        For i = subfoldersColl.Count To 1 Step -1
            If folders.Count = 0 Then
                folders.Add subfoldersColl(i)
                levels.Add c
            Else
                folders.Add subfoldersColl(i), , , folders.Count
                levels.Add c, , , levels.Count
            End If
        Next
        Set subfoldersColl = Nothing
               
    Loop
   
    List_Folders_and_Files = n

End Function
@John_w sincere gratitude for this excellent piece of code... its simply awesome.

Just one minor query here...

Each time we try to browse through the contents of a folder, we need to copy the folder path, go to the code module manually and and then paste the same in the code.

Was just wondering if there is a way if this process could be automated either by usung Folder Picker dialogue box [ Application.FileDialog(msoFileDialogFolderPicker) ] or copying the address of the folder and pasting it in a particular cell (example A2) and then automating the code to fetch the path from the designated cell (A2), and display the contents.

This automation would be of extreme help.

I am a novice in the field of excel VBA and tried my hand to make some upgrade, but that did not materialise. Your assistance in this regard shall be of immense help!

Thanks for your time & efforts in advance.
 
Upvote 0
Each time we try to browse through the contents of a folder, we need to copy the folder path, go to the code module manually and and then paste the same in the code.

Was just wondering if there is a way if this process could be automated either by usung Folder Picker dialogue box [ Application.FileDialog(msoFileDialogFolderPicker) ]

Replace the main routine with:

VBA Code:
Public Sub Main_List_Folders_and_Files()

    Dim startFolderPath As String
    
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "Select Folder"
        If Not .Show Then
            MsgBox "User cancelled"
            Exit Sub
        End If
        startFolderPath = .SelectedItems(1)
    End With

    With ActiveSheet
        .Cells.Clear
        List_Folders_and_Files startFolderPath, .Range("A1")
    End With

End Sub
 
Upvote 0
Status
Not open for further replies.

Forum statistics

Threads
1,214,920
Messages
6,122,269
Members
449,075
Latest member
staticfluids

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top