Yesterday i have been provided with a wonderful code by #VBasic2008 that is working perfectly fine.
In a parent directory if there are 500 subfolders, the code lists down the names of each subfolder in excel sheet and also count number of files available in each subfolder and return the value in excel sheet as well and by this way I am able to verify which folders have how many files in it.
However, I request I need to add one more step in it which is difficult for me.
I have noticed that within each subfolders there are 3 to 4 more folders and the files are organized in these folders extension wise (see below screenshot). means in each subfolders there are (Zip) (Word) (PDF) (XML) etc.
Is there any possibility where the code can also read these folders which are in each subfolder and can return the answer like mentioned below
If the result is not possible the way i suggested above than any format will be okay. but the only requirement is that it can read the folder properties within each subfolder and can return result.
Sub ListSubfolders()
' Define constants.
Const FolderPath As String = "E:\2022\"
' Reference the folder.
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FolderExists(FolderPath) Then
MsgBox "The folder """ & FolderPath & """ doesn't exist.", vbCritical
Exit Sub
End If
Dim fsoFolder As Object: Set fsoFolder = fso.GetFolder(FolderPath)
' Reference the first cell.
If ActiveSheet Is Nothing Then Exit Sub ' no visible workbooks open
If Not TypeOf ActiveSheet Is Worksheet Then Exit Sub ' not a worksheet
Dim ws As Worksheet: Set ws = ActiveSheet
Dim fCell As Range
Set fCell = ws.Cells(ws.Rows.Count, "A").End(xlUp).Offset(1)
' Write the folder properties.
' If you don't want this, then out-comment it but also copy the line
' 'Set fCell = fCell.Offset(1)' to the bottom of the loop.
fCell.Value = fsoFolder.Name
fCell.Offset(, 1).Value = fsoFolder.Files.Count
' Write the subfolders' properties.
Dim fsoSubfolder As Object
For Each fsoSubfolder In fsoFolder.SubFolders
Set fCell = fCell.Offset(1)
fCell.Value = fsoSubfolder.Name
fCell.Offset(, 1).Value = fsoSubfolder.Files.Count
Next fsoSubfolder
End Sub
This will be much appreciated.
I can not see the images that you put in your question, but you can do a recursive function to count all files in subfolders
In example bellow, in first cell of each subdirectory is put a number indicating the sublevel, then in column of that sublevel is the name and the total of files is in the next column.
Sub CountAllFiles()
Const FolderPath As String = "E:\2022\"
' Reference the folder.
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FolderExists(FolderPath) Then
MsgBox "The folder """ & FolderPath & """ doesn't exist.", vbCritical
Exit Sub
End If
Dim fsoFolder As Object: Set fsoFolder = fso.GetFolder(FolderPath)
' Reference the first cell.
If ActiveSheet Is Nothing Then Exit Sub ' no visible workbooks open
If Not TypeOf ActiveSheet Is Worksheet Then Exit Sub ' not a worksheet
Dim ws As Worksheet: Set ws = ActiveSheet
Dim fCell As Range
Set fCell = ws.Cells(ws.Rows.Count, "A").End(xlUp).Offset(1)
' Write the folder properties.
' If you don't want this, then out-comment it but also copy the line
' 'Set fCell = fCell.Offset(1)' to the bottom of the loop.
fCell.Value = fsoFolder.Name
fCell.Offset(, 1).Value = fsoFolder.Files.Count
' Write the subfolders' properties.
Dim fsoSubfolder As Object
For Each fsoSubfolder In fsoFolder.SubFolders
Set fCell = ws.Cells(ws.Rows.Count, "A").End(xlUp).Offset(1)
fCell.Value = fsoSubfolder.Name
fCell.Offset(, 1).Value = fsoSubfolder.Files.Count
Call countFiles(ws, fCell.Row, fsoSubfolder)
Next fsoSubfolder
End Sub
Sub countFiles(ByVal ws As Worksheet, ByVal pRow As Integer, ByVal pFsoSubfolder As Object)
Dim col As Integer
Dim totCol As Integer
Dim foundName As Boolean
For Each fsoSubfolder In pFsoSubfolder.SubFolders
' find subfolder name in columns
totCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
foundName = False
For col = 3 To totCol
If ws.Cells(1, col).Value = fsoSubfolder.Name Then
foundName = True
Exit For
End If
Next col
If Not foundName Then
ws.Cells(1, col).Value = "'" & fsoSubfolder.Name
End If
ws.Cells(pRow, col).Value = "'" & fsoSubfolder.Files.Count
Call countFiles(ws, pRow, fsoSubfolder)
Next fsoSubfolder
End Sub
Related
I need help in the code i have found from youtube and request if anyone could please edit it so that it displays the following requirement.
currently it only counts excel files, Can anyone please edit so that it should read all the extension in folder(s).
Secondly it just count one main directory, is it possible if it can be edited so it should read the subfolders and count files in them as well.
third for now it displays the count answer in a message box, it is possible if it displays the answer in Column B.
E.g. There are 5 sub folders with different names and each folder contains files with different extensions.
The code can read all the Subfolders and list down the name of folder in excel and also count and return the answer in front of each folder name.
Sub CountFiles()
Dim strDir As String
Dim fso As Object
Dim objFiles As Object
Dim obj As Object
Dim lngFileCount As Long
strDir = "E:\2022\"
Set fso = CreateObject("Scripting.FileSystemObject")
Set objFiles = fso.GetFolder(strDir).Files
lngFileCount = objFiles.count
MsgBox lngFileCount 'Total number of files
'***************************************************
'NOTE: Ensure that the following code does not overwrite _
anything in your workbook.
'Active worksheet should be a blank worksheet
For Each obj In objFiles
ActiveSheet.Cells(Rows.count, "A").End(xlUp).Offset(1, 0) = obj.Name
Next obj
Set objFiles = Nothing
Set fso = Nothing
Set obj = Nothing
End Sub
I shall remain thankful
List Subfolders
Sub ListSubfolders()
' Define constants.
Const FolderPath As String = "E:\2022\"
' Reference the folder.
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FolderExists(FolderPath) Then
MsgBox "The folder """ & FolderPath & """ doesn't exist.", vbCritical
Exit Sub
End If
Dim fsoFolder As Object: Set fsoFolder = fso.GetFolder(FolderPath)
' Reference the first cell.
If ActiveSheet Is Nothing Then Exit Sub ' no visible workbooks open
If Not TypeOf ActiveSheet Is Worksheet Then Exit Sub ' not a worksheet
Dim ws As Worksheet: Set ws = ActiveSheet
Dim fCell As Range
Set fCell = ws.Cells(ws.Rows.Count, "B").End(xlUp).Offset(1)
' Write the folder properties.
' If you don't want this, then out-comment it but also copy the line
' 'Set fCell = fCell.Offset(1)' to the bottom of the loop.
fCell.Value = fsoFolder.Name
fCell.Offset(, -1).Value = fsoFolder.Files.Count
' Write the subfolders' properties.
Dim fsoSubfolder As Object
For Each fsoSubfolder In fsoFolder.Subfolders
Set fCell = fCell.Offset(1)
fCell.Value = fsoSubfolder.Name
fCell.Offset(, -1).Value = fsoSubfolder.Files.Count
Next fsoSubfolder
' Inform.
MsgBox "Folders listed.", vbInformation
End Sub
Below script works perfect for importing multiple text files without duplicate header. But, requirement is paste the data in second row of worksheet. In first row, there is Import button for calling macro. But, as soon as execution completes first row is vanished and data is pasted.
Sub ReadFilesIntoActiveSheet()
Dim fso As FileSystemObject
Dim folder As folder
Dim file As file
Dim FileText As TextStream
Dim TextLine As String
Dim Items() As String
Dim i As Long
Dim cl As Range
Dim sFolder As String, vDB, Ws As Worksheet
Dim rngT As Range
' Get a FileSystem object
Set fso = New FileSystemObject
' get the directory you want
sFolder = "G:\Team Learning\vbapractice\Dunning\Import\"
Set folder = fso.GetFolder(sFolder)
' set the starting point to write the data to
'Worksheets("Sheet1").Activate
'Set Ws = ActiveSheet
Set Ws = Sheets("Data")
'Set cl = ActiveSheet.Cells(1, 1)
Ws.Cells.Clear
' Loop thru all files in the folder
For Each file In folder.Files
i = i + 1
Workbooks.Open Filename:=sFolder & file.Name, Format:=1
With ActiveWorkbook.ActiveSheet
If i = 1 Then
vDB = .UsedRange
Else
vDB = .UsedRange.Offset(1)
End If
End With
ActiveWorkbook.Close
Set rngT = Ws.Range("a" & Rows.Count).End(xlUp)(2) ' it's lastrow +1
rngT.Resize(UBound(vDB, 1), UBound(vDB, 2)) = vDB
Next file
Ws.Range("a1").EntireRow.Delete
Set FileText = Nothing
Set file = Nothing
Set folder = Nothing
Set fso = Nothing
End Sub
I am trying to come up with a routine that copies only certain files out of a directory, and all sub-directories, and pastes each copied file into a destination directory. I came up with the code below, which copies all files, in a filtered list, into a destination folder, but I can't figure out how to do a recursive loop through the hierarchy. Any guidance on this would be greatly appreciated.
Sub CopyFilteredFiles()
Dim rng As Range, cell As Range
Dim sht As Worksheet
Dim LastRow As Long
Dim FSO As Object
Dim FromPath As String
Dim ToPath As String
Dim lastChar As Integer
Dim fileName As String
DestinationFolder = "C:\Users\ryans\OneDrive\Desktop\AllYAML\"
Set sht = ActiveSheet
LastRow = sht.Cells(sht.Rows.Count, "D").End(xlUp).Row
Set rng = Range("D14:D" & LastRow)
Set FSO = CreateObject("scripting.filesystemobject")
For Each cell In rng.SpecialCells(xlCellTypeVisible)
If cell.Value <> "" Then
CopyFile = cell.Value
Debug.Print cell.Value
lastChar = InStrRev(CopyFile, "\")
fileName = Mid(CopyFile, lastChar + 1, 199)
On Error Resume Next
FSO.CopyFile Source:=CopyFile, Destination:=DestinationFolder & fileName
End If
Next cell
End Sub
I want to create something that would loop through all the files from a directory with subfolders. Then, it would open each excel file and copy the total amount. The cell that contains the total is not always in a specific row, but column B of that row contains the text " TOTAL AMOUNT". The cell that contains the total is ALWAYS in column I. After it copies the cell, paste in the Master workbook ( the workbook the macro is running from ) in a new sheet in cell (i,2)
Cell(1,1) and Cell(1,2) are headers. "GROUPER" and "EFT_AMOUNT"
Here is what I have so far :
Sub PaymentFileMatching()
Dim HostFolder As String
Dim f As String, i As Long, arr, sht As Worksheet
Dim FSO As Object, objFolder As Object, FileInFolder As Object
Dim wb As Workbook, Masterwb As Workbook
Set sht = ActiveSheet
Set FSO = CreateObject("Scripting.filesystemobject")
Dim objSubFolder As Object
HostFolder = "C:\Users\kxc8574\Documents\Payment Files\Payment Files (Corrected)\PE20170701\"
Set objFolder = FSO.GetFolder(HostFolder)
Set Masterwb = Workbooks("Master Template")
Sheets("Sheet9").Activate
sht.Cells(1, 1).Resize(1, 2).Value = _
Array("GROUPER", "EFT_AMOUNT")
i = 2
For Each objSubFolder In objFolder.subfolders
For Each FileInFolder In objSubFolder.Files
sht.Cells(i, 1).Value = Left(FileInFolder.Name, InStr(FileInFolder.Name, "PE 2017") - 1)
Set wb = Workbooks.Open(objSubFolder & "\" & FileInFolder.Name)
For Each sht In Worksheets
For Each Cell In Sheets("Payment Summary").Range("B:B")
If Cell.Value = "Final EFT Payment Amount" Then
matchRow = Cell.Row
Cells(matchRow, 8).Copy
Workbooks("Master Template").Worksheets("Sheet9").Cells(i, 2).PasteSpecial xlPasteValues
i = i + 1
End If
Next Cell
Next FileInFolder
Next objSubFolder
End Sub
You arent defining what Cell is - put Option Explicit at the very top of your module and then try compiling and it will tell you the things you forgot to define. To define it use
Dim Cell as Range
Untested:
Sub PaymentFileMatching()
Const HostFolder As String = _
"C:\Users\kxc8574\Documents\Payment Files\Payment Files (Corrected)\PE20170701\"
Dim i As Long
Dim FSO As Object, objFolder As Object, FileInFolder As Object
Dim wb As Workbook, Masterwb As Workbook, MasterSht As Worksheet, sht As Worksheet
Dim objSubFolder As Object, f As Range, fName As String
Set FSO = CreateObject("Scripting.filesystemobject")
Set objFolder = FSO.GetFolder(HostFolder)
Set Masterwb = Workbooks("Master Template")
Set MasterSht = Masterwb.Sheets("Sheet9")
MasterSht.Activate
MasterSht.Cells(1, 1).Resize(1, 2).Value = Array("GROUPER", "EFT_AMOUNT")
i = 2
For Each objSubFolder In objFolder.subfolders
For Each FileInFolder In objSubFolder.Files
fName = FileInFolder.Name
MasterSht.Cells(i, 1).Value = Left(fName, InStr(fName, "PE 2017") - 1)
Set wb = Workbooks.Open(objSubFolder & "\" & fName)
For Each sht In wb.Worksheets
Set f = sht.Columns(2).Find("Final EFT Payment Amount", , xlValues, xlWhole)
If Not f Is Nothing Then
MasterSht.Cells(i, 2).Value = f.EntireRow.Cells(8).Value
i = i + 1
Exit For 'found the value...
End If
Set f = Nothing
Next sht
wb.Close False
Next FileInFolder
Next objSubFolder
End Sub
I've built an Excel Macro which takes the first sheets from all XLS files in a selected folder (including XLS files in any sub-folders) and copies the sheets onto a single sheet in a new Workbook. The code seems to work fine for the most part and I intend to use it to merge thousands of Excel sheets into a single file.
However the problem is that the loop just stops working at some point, with no errors raised. Sometimes it's a couple of hundred files, sometimes more. But the process seems to be unreliable and I can't tell why.
This is my code (I call the Merge macro which in turn calls the DoFolder Sub):
Sub Merge()
Dim FileSystem As Object
Dim HostFolder As String
HostFolder = "C:\XLSfiles"
Set FileSystem = CreateObject("Scripting.FileSystemObject")
DoFolder FileSystem.GetFolder(HostFolder)
End Sub
Sub DoFolder(Folder)
Dim unusedRow As Long 'used for writing the file path info before each copied sheet
Dim path As String, ThisWB As String, lngFilecounter As Long
Dim wbDest As Workbook, shtDest As Worksheet, ws As Worksheet
Dim Filename As String, Wkb As Workbook
Dim CopyRng As Range, Dest As Range
Dim RowofCopySheet As Integer
RowofCopySheet = 2 ' Row to start on in the sheets you are copying from
ThisWB = ActiveWorkbook.Name
Set shtDest = ActiveWorkbook.Sheets(1)
Dim SubFolder
For Each SubFolder In Folder.SubFolders
DoFolder SubFolder
Next
Dim File
ActiveWindow.WindowState = xlMinimized
For Each File In Folder.Files
' Operate on each file
unusedRow = Cells.SpecialCells(xlCellTypeLastCell).Offset(1, 0).Row
If Not Filename = ThisWB Then
Set Wkb = Workbooks.Open(File)
Set CopyRng = Wkb.Sheets(1).Range(Cells(RowofCopySheet, 1),Cells(ActiveSheet.UsedRange.Rows.Count, ActiveSheet.UsedRange.Columns.Count))
Set Dest = shtDest.Range("A" & shtDest.UsedRange.SpecialCells(xlCellTypeLastCell).Row + 1)
CopyRng.Copy Dest
Wkb.Close False
End If
Cells(unusedRow, 1) = File
Application.StatusBar = File
Next
Range("A1").Select
End Sub
What am I missing?
Try this:
Instead of copying ranges, you can simply set their value
Do not use Cells when working with multiple sheets; always explicitely state the object/sheet whose Cells you like to address
Sample that worked for me:
For Each fi In f.Files
If InStr(1, Right(fi.Name, 5), ".xls") > 0 Then
Set Wkb = Workbooks.Open(fi)
Set ws = Wkb.Sheets(1)
rowCount = ws.UsedRange.Rows.Count
colCount = ws.UsedRange.Columns.Count
ranString = shtDest.Cells(curRow, 1).Address & ":" & shtDest.Cells(curRow + rowCount, colCount).Address
Set ran = ws.Range(ws.Cells(2, 1).Address, ws.Cells(rowCount, colCount).Address)
Set destRan = shtDest.Range(ranString)
destRan.Value = ran.Value
curRow = curRow + rowCount
Wkb.Close False
End If
Next fi
It may look a bit long-winded building a range string first, but it made debugging easier.