Option Explicit
Private lngRow As Long
'This is the string that will be used to indent the folder names
Private Const IndentingChar As String = "---"
Public Type BROWSEINFO
hOwner As Long
pidlRoot As Long
pszDisplayName As String
lpszTitle As String
ulFlags As Long
lpfn As Long
lParam As Long
iImage As Long
End Type
'32-bit API declarations
Declare Function SHGetPathFromIDList Lib "shell32.dll" _
Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) _
As Long
Declare Function SHBrowseForFolder Lib "shell32.dll" _
Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long
Sub GetFolderList()
Dim strStartFolder As String
Dim FSORootFolder As Object
Dim FSORootSubFolders As Object
Dim FSOObj As Object
Dim sht As Worksheet
On Error GoTo ErrHandler
'This is the root folder
strStartFolder = GetDirectory("Please choose folder to start in")
If Len(strStartFolder) = 0 Then Exit Sub
'Increase the execution speed of the macro
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Set sht = Workbooks.Add(xlWBATWorksheet).Sheets(1)
sht.Name = "Folder List"
Set FSOObj = CreateObject("Scripting.FilesystemObject")
Set FSORootFolder = FSOObj.GetFolder(strStartFolder)
'lngRow represents which row we're going to write to on the active sheet
lngRow = 1
sht.Cells(lngRow, 1) = "Folder Path"
sht.Cells(lngRow, 2) = "Folder Size (MB)"
lngRow = lngRow + 1
sht.Cells(lngRow, 1) = FSORootFolder.path
sht.Cells(lngRow, 2) = Round(FSORootFolder.Size / 1024 / 1024, 0)
lngRow = lngRow + 1
'Loop through each of the folders that lie immediately beneath the subfolder
For Each FSORootSubFolders In FSORootFolder.SubFolders
ListSubFolders FSORootSubFolders, sht
Next FSORootSubFolders
sht.UsedRange.Font.Name = "Courier"
sht.UsedRange.Columns.AutoFit
ErrHandler:
Application.ScreenUpdating = True
Application.Calculation = xlCalculationManual
If Err.Number <> 0 Then
MsgBox Err.Description, vbExclamation, "Something has gone wrong :-("
End If
End Sub
Private Function GetParentFolderCount(PathSpec As String) As Long
Dim lngCharCounter As Long, lngRetVal As Long
For lngCharCounter = 1 To Len(PathSpec)
If Mid$(PathSpec, lngCharCounter, 1) = Application.PathSeparator Then _
lngRetVal = lngRetVal + 1
Next lngCharCounter
GetParentFolderCount = lngRetVal
End Function
Private Sub ListSubFolders(ParentFolder As Object, sht As Worksheet)
Dim FSOSubfolder As Object
'Does the folder that we're working with have any folders beneath it?
'If so, we'll call this procedure again for each of those folders
'beneath the parent folder.
If ParentFolder.SubFolders.Count > 0 Then
sht.Cells(lngRow, 1) = Application.WorksheetFunction.Rept(IndentingChar, _
GetParentFolderCount(ParentFolder.path) - 1) & ParentFolder.path
sht.Cells(lngRow, 2) = Round(ParentFolder.Size / 1024 / 1024, 0)
lngRow = lngRow + 1
For Each FSOSubfolder In ParentFolder.SubFolders
ListSubFolders FSOSubfolder, sht
Next FSOSubfolder
Else
'If ParentFolder has no folders beneath it then just
'output the folder's name to the worksheet
sht.Cells(lngRow, 1) = Application.WorksheetFunction.Rept(IndentingChar, _
GetParentFolderCount(ParentFolder.path) - 1) & ParentFolder.path
sht.Cells(lngRow, 2) = Round(ParentFolder.Size / 1024 / 1024, 0)
lngRow = lngRow + 1
End If
End Sub
Function GetDirectory(Optional Msg) As String
Dim bInfo As BROWSEINFO
Dim path As String
Dim r As Long, x As Long, pos As Integer
' Root folder = Desktop
bInfo.pidlRoot = 0&
' Title in the dialog
If IsMissing(Msg) Then
bInfo.lpszTitle = "Select a folder."
Else
bInfo.lpszTitle = Msg
End If
' Type of directory to return
bInfo.ulFlags = &H1
' Display the dialog
x = SHBrowseForFolder(bInfo)
' Parse the result
path = Space$(512)
r = SHGetPathFromIDList(ByVal x, ByVal path)
If r Then
pos = InStr(path, Chr$(0))
GetDirectory = Left(path, pos - 1)
Else
GetDirectory = ""
End If
End Function