get lists names folders & subfolders and count the files extensions

tubrak

Board Regular
Joined
May 30, 2021
Messages
216
Office Version
  1. 2019
Platform
  1. Windows
hello

I search for macro to shows the folders names & subfolders names and count the files extensions

in column A it will bring the folders names and each folder contains subfolders as in column B it should bring it , each subfolders contains many files in differnt extensions pdf,avi,docx.... for instance the folder name RRT contains two subfolders name is JAN, DGH . subfolder JAN contain many files (pdf,jpj,docx)
and the same thing with DGH . should count how many in the subfolders . somtimes some folders contains many subfolders and somtimes there is no subfolder at all in the folder . with considerin when press cells in column A,B I can open it
FILES.xlsm
ABC
1folder namesubfolder nameextensions files counts
2RRTJAN5 PDF
33 JPG
41 DOCX
5DGH2 PDF
61 XLS
7RRNO SUBFOLDER3 XLS
8UPLOADIMAGES4 JPG
91 PNG
10INVNONO SUBFOLDER30 PDF
11VIDEOSNO SUBFOLDER15 MP4
12ACTION3 AVI
13
14
1
 
Last edited:

Excel Facts

Create a Pivot Table on a Map
If your data has zip codes, postal codes, or city names, select the data and use Insert, 3D Map. (Found to right of chart icons).
It's pretty easy using Power Query.

Book1
ABC
1PathExtensionCount
2F Drive\Desktop\.accdb3
3.csv1
4F Drive\Desktop\Access\.accdb5
5F Drive\Desktop\Documents\.accdb12
6.xlsx6
8F Drive\Desktop\Documents\FOB\Index\Thumbnail\.jpg1
9F Drive\Desktop\Documents\GPS Info\Index\Thumbnail\.jpg1
10F Drive\Desktop\Documents\MyProject1\Index\Thumbnail\.jpg1
11F Drive\Desktop\Documents\MyProject2\Index\Thumbnail\.jpg4
12F Drive\Desktop\Documents\New Template\Index\Thumbnail\.jpg1
13F Drive\Desktop\Excel\.xlsx13
14.csv10
15F Drive\Desktop\Excel\New folder\.xlsx4
16F Drive\Desktop\Excel\RXL\.csv10
17F Drive\Desktop\New folder\.jpg3
18F Drive\Desktop\New folder (2)\.jpg11
21.csv1
23F Drive\Desktop\Python\.py5
24F Drive\Desktop\Supercharge BI\.xlsx2
25.accdb1
Documents


Power Query:
let
    Source = Folder.Files("C:\YourPath"),
    Group = Table.Group(Source, {"Folder Path", "Extension"}, {{"Count", each Table.RowCount(_), Int64.Type}}),
    Extract = Table.TransformColumns(Group, {{"Folder Path", each Text.AfterDelimiter(_, "\", 3), type text}}),
    Index = Table.AddIndexColumn(Extract, "Index", 0, 1, Int64.Type),
    Format = Table.AddColumn(Index, "Path", each try if Extract[Folder Path]{[Index]}=Extract[Folder Path]{[Index]-1}  then "" else [Folder Path] otherwise [Folder Path]),
    Reorder = Table.ReorderColumns(Format,{"Folder Path", "Path", "Extension", "Count", "Index"}),
    RC = Table.RemoveColumns(Reorder,{"Folder Path", "Index"})
in
    RC
 
Upvote 0
as in your picture . it seems great. truly I thought to be by vba . so I don't used PQ . may you guide me where I put this,please?



Power Query:
let
    Source = Folder.Files("C:\YourPath"),
    Group = Table.Group(Source, {"Folder Path", "Extension"}, {{"Count", each Table.RowCount(_), Int64.Type}}),
    Extract = Table.TransformColumns(Group, {{"Folder Path", each Text.AfterDelimiter(_, "\", 3), type text}}),
    Index = Table.AddIndexColumn(Extract, "Index", 0, 1, Int64.Type),
    Format = Table.AddColumn(Index, "Path", each try if Extract[Folder Path]{[Index]}=Extract[Folder Path]{[Index]-1}  then "" else [Folder Path] otherwise [Folder Path]),
    Reorder = Table.ReorderColumns(Format,{"Folder Path", "Path", "Extension", "Count", "Index"}),
    RC = Table.RemoveColumns(Reorder,{"Folder Path", "Index"})
in
    RC
 
Upvote 0
Sure thing.

First you would go to the ribbon and go to the 'Data' tab. There you will see a group where it says 'Get & Transform'. Click on the 'Get Data' button and under 'Other Sources', select 'Blank Query'. That will bring you into the Power Query editor.

From there you can select 'Advanced editor' and paste the code I provided.

You will need to edit the line that says 'Source' to reflect the actual directory you want to look at.

Also, you may need to adjust the integer value in this line.

Power Query:
Extract = Table.TransformColumns(Group, {{"Folder Path", each Text.AfterDelimiter(_, "\", 3), type text}}),

I did this as a way to get rid of some of the redundant parts of the folder path to closer match what you were going for in your original post. So, depending on how much of the path you want to cut off, you would just need to adjust that number '3'.
 
Upvote 0
Here is a VBA option if you would rather. Again, you may need to adjust the 'SkipNum' variable depending on how many levels deep your root path is.

Book1
ABC
1FolderExtCount
2RootTXT1
3Root\RootSub1TXT1
4Root\RootSub2XLS1
5TXT2
6Root\RootSub2\RootSubSub1XLS1
Sheet3


VBA Code:
Public Sub FileExtCount()
    Dim oFolder As Object, oSubfolder As Object, oFile As Object
    Dim TP As String, fExt As String
    Dim FSO As Object:          Set FSO = CreateObject("Scripting.FileSystemObject")
    Dim SD As Object:           Set SD = CreateObject("Scripting.Dictionary")
    Dim AL As Object:           Set AL = CreateObject("System.Collections.ArrayList")
    Dim queue As Collection:    Set queue = New Collection
    Dim SkipNum As Integer:     SkipNum = 4
    Dim r As Range:             Set r = Range("A2")
        
    queue.Add FSO.GetFolder("C:\Users\EBAAJ7O\OneDrive - US Customs and Border Protection\Desktop\Root")

    Do While queue.Count > 0
        Set oFolder = queue(1)
        queue.Remove 1
        For Each oSubfolder In oFolder.SubFolders
            queue.Add oSubfolder
        Next oSubfolder
        
        TP = TRIMPATH(oFolder.Path, SkipNum)
        
        For Each oFile In oFolder.Files
            fExt = Split(oFile.Name, ".")(1)
            If Not SD.exists(fExt) Then
                SD.Add fExt, 1
            Else
                SD(fExt) = SD(fExt) + 1
            End If
        Next oFile
        
        For j = 0 To SD.Count - 1
            If j = 0 Then
                AL.Add Join(Array(TP, SD.keys()(j), SD.items()(j)), "*")
            Else
                AL.Add Join(Array(vbNullString, SD.keys()(j), SD.items()(j)), "*")
            End If
        Next j
        
        SD.RemoveAll
    Loop

Set r = r.Resize(AL.Count)

With r
    .Value = Application.Transpose(AL.toArray)
    .TextToColumns , DataType:=xlDelimited, Other:=True, OtherChar:="*"
End With

End Sub

Function TRIMPATH(s As String, n As Integer)
Dim SP() As String:     SP = Split(s, "\")
Dim RS() As Variant:    ReDim RS(1 To UBound(SP) - n)
Dim Pos As Integer:     Pos = 1

For i = n + 1 To UBound(SP)
    RS(Pos) = SP(i)
    Pos = Pos + 1
Next i

TRIMPATH = Join(RS, "\")

End Function
 
Last edited:
Upvote 0
wow ! two ways work both . for me I prefer vba . I have question about PQ if I add new files in directory . does update automatically or I have to update manually by right click and select refresh? . last thing how should can I open directory in column A when press any cell contain directory .
 
Last edited:
Upvote 0
Sure.

Had to change it up a bit on the setup for the original code.

Book1
ABCDEF
1FolderExtCountPath:C:\Users\ME\OneDrive\Desktop\Root
2Roottxt1
3Root\RootSub1txt1
4Root\RootSub2xlsx1
5txt2
6Root\RootSub2\RootSubSub1xlsx1
Sheet3


VBA Code:
Public Sub FileExtCount()
    On Error Resume Next
    Dim oFolder As Object, oSubfolder As Object, oFile As Object
    Dim TP As String, fExt As String
    Dim FSO As Object:          Set FSO = CreateObject("Scripting.FileSystemObject")
    Dim SD As Object:           Set SD = CreateObject("Scripting.Dictionary")
    Dim AL As Object:           Set AL = CreateObject("System.Collections.ArrayList")
    Dim queue As Collection:    Set queue = New Collection
    Dim SkipNum As Integer:     SkipNum = 4
    Dim r As Range:             Set r = Range("A2")
    Dim path As String:         path = Range("F1").Value2
        
    queue.Add FSO.GetFolder(path)

    Do While queue.Count > 0
        Set oFolder = queue(1)
        queue.Remove 1
        For Each oSubfolder In oFolder.SubFolders
            queue.Add oSubfolder
        Next oSubfolder
        
        TP = TRIMPATH(oFolder.path, SkipNum)
        
        For Each oFile In oFolder.Files
            fExt = Split(oFile.Name, ".")(1)
            If Not SD.exists(fExt) Then
                SD.Add fExt, 1
            Else
                SD(fExt) = SD(fExt) + 1
            End If
        Next oFile
        
        For j = 0 To SD.Count - 1
            If j = 0 Then
                AL.Add Join(Array(TP, SD.keys()(j), SD.items()(j)), "*")
            Else
                AL.Add Join(Array(vbNullString, SD.keys()(j), SD.items()(j)), "*")
            End If
        Next j
        
        SD.RemoveAll
    Loop

Set r = r.Resize(AL.Count)

With r
    .Value = Application.Transpose(AL.toArray)
    .TextToColumns , DataType:=xlDelimited, Other:=True, OtherChar:="*"
End With

End Sub

Function TRIMPATH(s As String, n As Integer)
Dim SP() As String:     SP = Split(s, "\")
Dim RS() As Variant:    ReDim RS(1 To UBound(SP) - n)
Dim Pos As Integer:     Pos = 1

For i = n + 1 To UBound(SP)
    RS(Pos) = SP(i)
    Pos = Pos + 1
Next i

TRIMPATH = Join(RS, "\")

End Function

And then you need to add a worksheet event handler like this.

VBA Code:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim r As Range:     Set r = Range("A2:A" & Range("A" & Rows.Count).End(xlUp).Row)

If Not Intersect(r, Target) Is Nothing And Target.Cells.Count = 1 Then
    Dim path As String: path = Range("F1").Value2
    path = Left(path, InStrRev(path, "\"))
    If Target.Value = vbNullString Then Set Target = Target.End(xlUp)
    Shell "explorer.exe " & path & Target.Value2, vbNormalFocus
End If
End Sub

Seems to be working the way it should testing it out on this end.
 
Upvote 0
Solution
And to answer your question... Yes, with the Power Query solution, you would need to refresh each time a new file is added. But, if a new file is added, you would also need to re-run the VBA code as well.
 
Upvote 0
fantastic ! you're legend (y)
And to answer your question... Yes, with the Power Query solution, you would need to refresh each time a new file is added. But, if a new file is added, you would also need to re-run the VBA code as well.
but by vba can refresh automatically by put the procedure in workbook open_event . when file open . it will refresh automatically.
 
Upvote 0
Great! Glad I could help.

Yes, you could definitely call the subroutine in workbook_open or worksheet_activate and have it run automatically.
 
Upvote 0

Forum statistics

Threads
1,215,336
Messages
6,124,328
Members
449,155
Latest member
ravioli44

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