I have a number of excel (.xls) stored in a folder in a local drive. I need to do some process to every file in this folder. What is the code that will
loop through every file
open the file
Do some processing and then Save & close the file
move the file to another folder after processing
To be more clear, I want go over every file and do processing to it. After finishing a file, go to another file and so till the end of all the files in the folder. I do have the code for the processing; I just need to know the code that will loop through the files and move then to another folder.
Thanks for your help in advance,
What you need is a recursive function that iterates over the tree that represents a file system. It means to iterate over all the childs of some 'parent folder'. I send you a function that does something similar, to the one you need (this is currently in usage). This function deletes all the empty folders given a parent folder.
Public Function gf_DeleteEmptyFolder(path As String) As Boolean
On Error GoTo Error_Handler
Dim fso_folder As Scripting.Folder, sub_folder As Scripting.Folder
If g_FSO.FolderExists(path) Then
Set fso_folder = g_FSO.GetFolder(path)
'-- eliminates de folder only if is empty
If 0 = fso_folder.Files.Count And 0 = fso_folder.SubFolders.Count Then
Call g_FSO.DeleteFolder(path, False)
'-- recursively calls the function
Else
For Each sub_folder In fso_folder.SubFolders
Call gf_DeleteEmptyFolder(sub_folder.path)
Next
End If
End If
gf_DeleteEmptyFolder = True
Exit Function
'~~~ on error
Error_Handler:
gf_DeleteEmptyFolder = False
End Function
If your files are stored in a simple folder, then you can use the following code to iterate each file.
Public Sub fsoProcessFilesInFolder(sFolder As String)
Dim fso As Scripting.FileSystemObject, fld As Scripting.Folder, fil As Scripting.File
Set fso = New FileSystemObject
Set fld = fso.GetFolder(sFolder)
For Each fil In fld.Files
'--- add code to process your files
Next fil
End Sub
Here's the easy VBA object way to do it:
Dim fs As FileSearch
Dim i As Integer
Dim wbk As Workbook
Set fs = Application.FileSearch
With fs
.LookIn = ThisWorkbook.Path
.FileName = "*.xls"
For i = 1 to .Execute()
Set wbk = Workbooks.Open(.FoundFiles(i))
''//DO STUFF HERE
wbk.Close(SaveChanges:=True)
Next i
End With
In VB6 you have three options, as shown in the following KB articles:
How to Search Directories to Find or List Files
HOW TO: Recursively Search Directories by Using FileSystemObject
The following code will read xlsx/xls files from given folder neglecting other files and iterate through each item.
You can use it for any set of extensions and filters.
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(folderPath)
Set objFiles = objFolder.Files
'Iterate through the files in the folder
For Each Item In objFiles
If LCase(Right(Item.Name, 5)) = ".xls" Or LCase(Right(Item.Name, 4)) = ".xlsx" Then
''''''Do Stuffs Here''''''
End If
Next
Related
I'm running an Excel VBA macro. It includes the following code:
Private Sub ListTheFiles(inFldr as Scripting.Folder)
Dim fl as Scripting.File, subfldr as Scripting.Folder
If inFldr.Files.Count > 0 then
For Each fl in inFldr.Files
'List the file and its size and LastModifiedDate on a worksheet, making no changes to the file
Next fl
End If
For Each subfldr in inFldr.Subfolders
ListTheFiles subfldr
Next subfldr
End Sub
The module runs this subroutine hundreds of times, usually successfully. But for just a couple of folders, it reaches the first "For Each" (which indicates there ARE files in inFldr), but then it skips right to the "End If" without processing any files. The two folders that don't get processed each contains 12 PDF files and no other files and no subfolders. Many of the other folders also contain PDF files only, and they work fine.
Why would this happen? Thanks.
List Files in a Folder and in Its Subfolders
I am using this without a reference to the Scripting FileSystemObject object. As you can see, the 'recursion' code is 'basically' the same (except for the .Count). You could test it, to see if the issue repeats itself.
The Code
Option Explicit
Sub FilesRecurseTEST()
Const FolderPath As String = "F:\Test\2021"
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
FilesRecurse fso.GetFolder(FolderPath)
End Sub
Sub FilesRecurse( _
fsoFolder As Object)
Dim fsoSubFolder As Object, fsoFile As Object
For Each fsoFile In fsoFolder.Files
With fsoFile
Debug.Print .Name, .Size, .DateLastModified
End With
Next fsoFile
For Each fsoSubFolder In fsoFolder.Subfolders
FilesRecurse fsoSubFolder
Next
End Sub
I need help on implementing a filter to accelerate a file search using DIR function in VBA.
Context :
I have a folder of contracts.
Some contracts are directly on it, some are in separate "category" sub folders.
So it looks like this :
On each contract folder, I need to find a file, whose name contains "RENS_RES", located in "2000*\2300*\". And I need to get the path to that file
Situation :
The function works.
But it is slow, because everything is on a server, and there are a lot of folders/subfolders/files to go through, and it tests them all. It can take up to 15 minutes.
So I want to make it faster.
Right now, I have a code that looks like this :
Dim fso 'As New FileSystemObject
Dim fld 'As Folder
Public tampon(120) As Variant 'Where I stock my selected files path
sFol = "C:\something\" The path to my main folder, that contains everything, created as String
sFile = "*RENS_RES*.xlsx" 'The criteria to determine the files to select, created as String
Function FindFile(ByVal sFol As String, sFile As String) As String 'Arguments initially from somewhere else specified
'initially called somewhere else
Dim tFld, tFil as String 'The currently selected folder and file
Dim FileName As String 'FileName the name of the selected file
Set fso = CreateObject("Scripting.FileSystemObject")
Set fld = fso.GetFolder(sFol)
FileName = Dir(fso.BuildPath(fld.path, sFile), vbNormal Or _
vbHidden Or vbSystem Or vbReadOnly) 'I search the first file respecting the criteria sFile
While Len(FileName) <> 0 'I keep going until all files int he folder are tested
FindFile = FindFile + FileLen(fso.BuildPath(fld.path, _
FileName))
tampon(i) = fso.BuildPath(fld.path, FileName) 'We save the value
i = i + 1
FileName = Dir() ' Get next file
DoEvents
Wend
If fld.SubFolders.Count > 0 Then 'If the current folder has subfolders
For Each tFld In fld.SubFolders 'We consider each subfolder
If Not (tFld.Name Like "#000*") Or tFld.Name Like "2000*" Or tFld.Name Like "2300*" Then ' We exclude all the subfolders that start with 4 numbers (format x000) and are not 2000 or 2300 from the search
DoEvents
FindFile = FindFile + FindFile(tFld.path, sFile) 'We call again the function to test all files in that subfolder
End If
Next
End If
Exit Function
Catch: FileName = ""
Resume Next
End Function
I have tried to put a filter on the subfolder selection :
If Not (tFld.Name Like "#000*") Or tFld.Name Like "2000*" Or tFld.Name Like "2300*" Then
It has inverted logic because to simulate an exit for in the "for each loop".
In theory it should not enter the "if" if the name begins by 4 digits (a number followed by three zeros and is not "2000*" or "2300*" (the two folders we want to go in). I have this because there is no logic in the category or contract name that I could use on the filter.
But the filter does not work : it keeps going through every folder, and I don't understant why.
That's where I'm asking for help.
Or would there be another way to do that search that would be faster ?
Thank you in advance for your help,
hope I formatted the code decently
If find this this non-recursive approach for finding matches easier to reason about/modify:
'Return a collection of file objects given a starting folder and a file pattern
' e.g. "*.txt"
'Pass False for last parameter if don't want to check subfolders
Function GetMatches(startFolder As String, filePattern As String, _
Optional subFolders As Boolean = True) As Collection
Dim fso, fldr, f, subFldr
Dim colFiles As New Collection
Dim colSub As New Collection
Set fso = CreateObject("scripting.filesystemobject")
colSub.Add startFolder
Do While colSub.Count > 0
Set fldr = fso.getfolder(colSub(1))
colSub.Remove 1
For Each f In fldr.Files
'check filename pattern
If UCase(f.Name) Like UCase(filePattern) Then colFiles.Add f
Next f
If subFolders Then
For Each subFldr In fldr.subFolders
'check subfolder criteria
'another attempt at your logic...
If subFldr.Name Like "2000*" or Not subFldr.Name Like "#000*" Then
colSub.Add subFldr.Path
End If
Next subFldr
End If
Loop
Set GetMatches = colFiles
End Function
Example usage:
Dim colFiles as Collection
Set colFiles = GetMatches("C:\something\", ""*RENS_RES*.xlsx"")
I need to traverse a zip files using VBA. In particular I need to, without unzipping the file, locate the xl folder in order to find the media subfolder. I then need to copy the images out of the media subfolder and save them to another folder.
Public Sub Extract_Images()
Dim fso As FileSystemObject
Dim objFile As File
Dim myFolder
Const zipDir As String = "\\...\ZIP FILES"
Const xlFolder As String = "xl"
Const mediaFolder As String = "media"
Dim picname As String
Dim zipname As String
Set fso = New FileSystemObject
Set myFolder = fso.GetFolder(zipDir)
For Each objFile In myFolder.Files
zipname = objFile.Name
Next objFile
End Sub
^That code successfully loops through the folder and gathers the names of the zip files. But I need to get into the files and traverse the structures to get to the Media folder.
Building off: https://www.rondebruin.nl/win/s7/win002.htm
Edit: - this shows how you can incorporate the extraction into your code. Just pass the full zip path and the location to where you want to extract the files. You can do this from within your existing loop.
You may need to account for media files sharing the same name if you're planning on extracting them all to the same location...
Sub Tester()
ExtractMediaFiles "C:\Users\twilliams\Desktop\tempo.zip", _
"C:\Users\twilliams\Desktop\extracted\"
End Sub
Sub ExtractMediaFiles(zipFile As Variant, outFolder As Variant)
Dim oApp As Object
Dim fileNameInZip As Variant, oNS As Object
Set oApp = CreateObject("Shell.Application")
On Error Resume Next
Set oNS = oApp.Namespace(zipFile & "\xl\media")
On Error GoTo 0
If Not oNS Is Nothing Then
For Each fileNameInZip In oNS.items
Debug.Print fileNameInZip
oApp.Namespace(outFolder).copyhere oNS.items.Item(CStr(fileNameInZip))
Next
Else
Debug.Print "No xl\media path for " & zipFile
End If
End Sub
I have a question regarding looping through a folder of two different kinds of files: xlsm and mdb (Access).
I have currently written a macro that would open 1 single xlsm file and 1 single mdb file before copying some data from the xlsm to mdb file and then saving the mdb file.
Now, I would like this process to repeat through a folder that has 50 xlsm files and 50 mdb files. They have the same names, so for example the loop should do this:
Open both xlsm and mdb files called "2001".
Perform copying and pasting etc from xlsm to mdb (I have written this part).
Save the mdb file.
Close both xlsm and mdb files called "2001".
Repeat steps 1-4 for "2002", "2003", etc in the folder.
I am really new to VBA so much help is appreciated! Looking forward to any guidance at all. Merry Christmas!
I just did today sample code for listing JPG files in folder, you can adopt and modify to do exactly what you like it to do, but would be very hard to give you exact code without being able to see your solution.
Public Sub listImages(folderPath As String)
'define variables
Dim fso As Object
Dim objFolder As Object
Dim objFolders As Object
Dim objF As Object
Dim objFile As Object
Dim objFiles As Object
Dim strFileName As String
Dim strFilePath As String
Dim myList As String
'set file system object
Set fso = CreateObject("Scripting.FileSystemObject")
'set folder object
Set objFolder = fso.GetFolder(folderPath)
'set files
Set objFiles = objFolder.files
Set objFolders = objFolder.subfolders
'list all images in folder
For Each objFile In objFiles
If Right(objFile.Name, 4) = ".jpg" Then
strFileName = objFile.Name
strFilePath = objFile.Path
myList = myList & strFileName & " - " & strFilePath & vbNewLine
End If
Next
'go through all subflders
For Each objF In objFolders
Call listImages(objF.Path)
Next
Debug.Print myList
Set objFolder = Nothing
Set objFile = Nothing
Set fso = Nothing
End Sub
This question already has answers here:
Get list of sub-directories in VBA
(5 answers)
Closed 8 years ago.
I understand that the answer to this question may be similar to another, but the question is posed in a different way. This question is based on the fact that the user, me, did not know FileSearch was removed. The other is conceptually based, and contains prior knowledge of excel's 2010 changes...
I have found some code here
Sub Search()
Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = True
Set objSearch = objExcel.FileSearch
objSearch.Lookin = "D:\Music"
objSearch.SearchSubfolders = TRUE
objSearch.FileName = "*.wma"
objSearch.Execute
For Each strFile in objSearch.FoundFiles
Wscript.Echo strFile
Next
objExcel.Quit
End Sub
I tried to run that code on my machine, with it adapted to one of my folders and an extention within the folder, but it returned an error 445 (object doesn't support this action). I'm using excel 2010.
Does anyone know what's going on? I'm trying to help out a co-worker, but I don't know much about File I/O beyond the simple stuff in VBA.
FileSearch was removed from VBA in Office 2007. Thankfully it's not difficult to create your own routine for searching files using the FileSystemObject (add the Windows Scripting Runtime as a reference to get Intellisense code hints).
This is the one that I use - your list of files will be returned as a Collection by the FileList function. It should be simple to add a filter to this to only populate the collection with files of a particular extension.
[Note that you'll need to add the Windows Scripting Runtime reference as mentioned above since the objects are early bound in my example]
Function FileList(Path As String) As Collection
Dim FSO as New Scripting.FileSystemObject
Dim StartingFolder As Scripting.Folder
Set StartingFolder = FSO.GetFolder(Path)
Set FileList = New Collection
RecursiveGetFiles StartingFolder, FileList
End Function
Private Sub RecursiveGetFiles(StartingFolder As Scripting.Folder, ByRef FullFileList As Collection)
Dim File As Scripting.File
For Each File In StartingFolder.Files
FullFileList.Add File, File.Path
Next File
Dim SubFolder As Scripting.Folder
For Each SubFolder In StartingFolder.SubFolders
RecursiveGetFiles SubFolder, FullFileList
Next SubFolder
End Function
This code can then be called by some parent routine, i.e.
Sub Search(Path As String)
Dim ListOfFiles As Collection
Set ListOfFiles = FileList(Path)
Dim File As Scripting.File
For Each File In ListOfFiles
Debug.Print File.Name
Next File
End Sub
Sub Search()
Dim StrFile As String, Path As String, FileName As String
Path = "D:\Music"
FileName = "*.wma"
StrFile = Dir(Path & FileName)
Do While Len(StrFile) > 0
Msgbox StrFile
StrFile = Dir
Loop
End Sub