Move files from multiple folders to a single folder - excel

I am trying to consolidate Excel files from different folders to a single folder. Within each folder there is a single Excel file.
Sub move_data()
Dim FSO As Object
Dim FromPath As String
Dim ToPath As String
Dim Fdate As Date
Dim FileInFromFolder As Object
MkDir "C:\User\TEST\"
FromPath = "C:\User\MainFolder\"
ToPath = "C:\User\TEST\"
Set FSO = CreateObject("scripting.filesystemobject")
If FSO.FolderExists(FromPath) = False Then
MsgBox FromPath & " doesn't exist"
Exit Sub
End If
For Each FileInFromFolder In FSO.GetFolder(FromPath).Files
FileInFromFolder.Move ToPath
Next FileInFromFolder
End Sub
The code is unable to get the files from the subfolder within the folder (as shown in the image).
The area I am looking to change is 'FromPath', if it is possible to include a wildcard to specify the subfolders?
Multiple Folders, One Excel file per Folder

Move Files From Multiple Folders to Single Folder (FileSystemObject)
Sub MoveFiles()
Const FromPath As String = "C:\MainFolder\"
Const ToPath As String = "C:\Test\"
Const LCaseExtensionPattern As String = "xls*"
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FolderExists(FromPath) Then
MsgBox "The folder '" & FromPath & "' doesn't exist.", vbCritical
Exit Sub
End If
If Not fso.FolderExists(ToPath) Then MkDir ToPath
Dim SubFolderPaths() As String: SubFolderPaths = ArrSubFolderPaths(FromPath)
Dim fsoFile As Object
Dim NotMoved() As String
Dim n As Long
Dim mCount As Long
Dim nmCount As Long
For n = 0 To UBound(SubFolderPaths)
For Each fsoFile In fso.GetFolder(SubFolderPaths(n)).Files
If LCase(fso.GetExtensionName(fsoFile)) _
Like LCaseExtensionPattern Then
If Not fso.FileExists(ToPath & fsoFile.Name) Then
mCount = mCount + 1
fsoFile.Move ToPath
Else
nmCount = nmCount + 1
ReDim Preserve NotMoved(1 To nmCount)
NotMoved(nmCount) = fsoFile.Path
End If
End If
Next fsoFile
Next n
Dim MsgString As String
MsgString = "Files moved: " & mCount & "(" & mCount + nmCount & ")"
If nmCount > 0 Then
MsgString = MsgString & vbLf & vbLf & "Files not moved: " & mCount _
& "(" & mCount + nmCount & "):" & vbLf & vbLf & Join(NotMoved, vbLf)
End If
MsgBox MsgString, vbInformation
End Sub
Function ArrSubFolderPaths( _
ByVal InitialFolderPath As String, _
Optional ByVal ExcludeInitialFolderPath As Boolean = False) _
As String()
Const ProcName As String = "ArrSubFolderPaths"
On Error GoTo ClearError
' Ensure that a string array is passed if an error occurs.
Dim Arr() As String: Arr = Split("") ' LB = 0 , UB = -1
' Locate the trailing path separator.
Dim pSep As String: pSep = Application.PathSeparator
If Right(InitialFolderPath, 1) <> pSep Then
InitialFolderPath = InitialFolderPath & pSep
End If
' Add the initial folder path to a new collection.
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
Dim coll As Collection: Set coll = New Collection
coll.Add fso.GetFolder(InitialFolderPath)
' Add the initial folder path (or don't) to the result.
Dim n As Long
If ExcludeInitialFolderPath Then ' don't add
n = -1
Else ' add
ReDim Preserve Arr(0 To 0): Arr(0) = coll(1)
End If
Dim fsoFolder As Object
Dim fsoSubFolder As Object
Do While coll.Count > 0
Set fsoFolder = coll(1)
coll.Remove 1
For Each fsoSubFolder In fsoFolder.SubFolders
coll.Add fsoSubFolder
n = n + 1: ReDim Preserve Arr(0 To n): Arr(n) = fsoSubFolder
Next fsoSubFolder
Loop
ArrSubFolderPaths = Arr
ProcExit:
Exit Function
ClearError:
Debug.Print "'" & ProcName & "' Run-time error '" _
& Err.Number & "':" & vbLf & " " & Err.Description
Resume ProcExit
End Function

This is simple to achieve if you adopt recursive procedure.
Sub Starter()
Call FilesMover("C:\User\MainFolder\", "C:\User\TEST\")
End Sub
Sub FilesMover(FromPath As String, DestinationPath As String)
Dim fso As object
Set fso = CreateObject("scripting.filesystemobject")
Dim f As File
Dim d As Folder
' first move the files in the folder
For Each f In fso.GetFolder(FromPath).Files
f.Move DestinationPath
Next f
' then check the subfolders
For Each d In fso.GetFolder(FromPath).SubFolders
Call FilesMover(d.Path, DestinationPath)
Next d
End Sub

Related

to move files from one folder to another using VBA

I have a code which can transfer the Excel files from one folder to another but i would like to update the code so that it can move all the files (.xml, .txt, .pdf, etc.) from one folder to another.
Sub MoveFiles()
Dim sourceFolderPath As String, destinationFolderPath As String
Dim FSO As Object, sourceFolder As Object, file As Object
Dim fileName As String, sourceFilePath As String, destinationFilePath As String
Application.ScreenUpdating = False
sourceFolderPath = "E:\Source"
destinationFolderPath = "E:\Destination"
Set FSO = CreateObject("Scripting.FileSystemObject")
Set sourceFolder = FSO.GetFolder(sourceFolderPath)
For Each file In sourceFolder.Files
fileName = file.Name
If InStr(fileName, ".xlsx") Then ' Only xlsx files will be moved
sourceFilePath = file.Path
destinationFilePath = destinationFolderPath & "\" & fileName
FSO.MoveFile Source:=sourceFilePath, Destination:=destinationFilePath
End If ' If InStr(sourceFileName, ".xlsx") Then' Only xlsx files will be moved
Next
'Don't need set file to nothing because it is initialized in for each loop
'and after this loop is automatically set to Nothing
Set sourceFolder = Nothing
Set FSO = Nothing
End Sub
can you please help
Move Files Using MoveFile
You would get greater control of things by using CopyFile and DeleteFile instead of MoveFile.
Using Dir, FileCopy, and Kill, instead of the FileSystemObject object and its methods, would make it simpler and also faster.
Option Explicit
Sub MoveFilesTEST()
Const sFolderPath As String = "E:\Source"
Const dFolderPath As String = "E:\Destination"
Const FilePattern As String = "*.*"
MoveFiles sFolderPath, dFolderPath, FilePattern
End Sub
Sub MoveFiles( _
ByVal SourceFolderPath As String, _
ByVal DestinationFolderPath As String, _
Optional ByVal FilePattern As String = "*.*")
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FolderExists(SourceFolderPath) Then
MsgBox "The source folder path '" & SourceFolderPath _
& "' doesn't exist.", vbCritical
Exit Sub
End If
If Not fso.FolderExists(DestinationFolderPath) Then
MsgBox "The destination folder path '" & DestinationFolderPath _
& "' doesn't exist.", vbCritical
Exit Sub
End If
Dim apSep As String: apSep = Application.PathSeparator
Dim sPath As String: sPath = SourceFolderPath
If Left(sPath, 1) <> apSep Then sPath = sPath & apSep
Dim sFolder As Object: Set sFolder = fso.GetFolder(sPath)
If sFolder.Files.Count = 0 Then
MsgBox "There are no files in the source folder '" & sPath & "'.", _
vbExclamation
Exit Sub
End If
Dim dPath As String: dPath = DestinationFolderPath
If Left(dPath, 1) <> apSep Then dPath = dPath & apSep
Dim dFolder As Object: Set dFolder = fso.GetFolder(dPath)
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Dim sFile As Object
Dim dFilePath As String
Dim ErrNum As Long
Dim MovedCount As Long
Dim NotMovedCount As Long
For Each sFile In sFolder.Files
dFilePath = dPath & sFile.Name
If fso.FileExists(dFilePath) Then
dict(sFile.Path) = Empty
NotMovedCount = NotMovedCount + 1
Else
On Error Resume Next
fso.MoveFile sFile.Path, dFilePath
ErrNum = Err.Number
' e.g. 'Run-time error '70': Permission denied' e.g.
' when the file is open in Excel
On Error GoTo 0
If ErrNum = 0 Then
MovedCount = MovedCount + 1
Else
dict(sFile.Path) = Empty
NotMovedCount = NotMovedCount + 1
End If
End If
Next sFile
Dim Msg As String
Msg = "Files moved: " & MovedCount & "(" & NotMovedCount + MovedCount & ")"
If NotMovedCount > 0 Then
Msg = Msg & vbLf & "Files not moved:" & NotMovedCount & "(" _
& NotMovedCount + MovedCount & ")" & vbLf & vbLf _
& "The following files were not moved:" & vbLf _
& Join(dict.keys, vbLf)
End If
MsgBox Msg, IIf(NotMovedCount = 0, vbInformation, vbCritical)
End Sub

VBA - How to open folder without knowing the full name

I'm trying to open a folder where I don't know the full path.
For example, the parent folder dir is "D:\Documents" and the folder I want to open is called "22.111 - PROJECT_NAME", where I know the code, but don't know the name. I've tried with "*", but no luck.
Sub OpenFolder()
On Error GoTo Err_cmdExplore_Click
Dim Code As String
Code = Range("A1").Value
GoToFolder = "C:\Windows\explorer.exe D:\Documents\" & Code & "*"
Call Shell(GoToFolder, 1)
Exit_cmdExplore_Click:
Exit Sub
Err_cmdExplore_Click:
MsgBox ("Pasta não encontrada")
Resume Exit_cmdExplore_Click
End Sub
Found the answer on another forum (mrexcel.com), leaving it below for anyone that faces the same problem:
Public Sub Find_and_Open_Folder()
Dim Code As String
Dim targetFolder As String
Code = Range("A1").Value
targetFolder = Dir("D:\Documents\" & Code & "*", vbDirectory)
If targetFolder <> vbNullString Then
Shell "explorer.exe """ & "D:\Documents\" & targetFolder & """", vbNormalFocus
Else
MsgBox "Folder matching D:\Documents\" & Code & "* not found"
End If
End Sub
With the parent folder available and the knowledge that the subfolder starts with 22.111, you could loop through all subfolders in the parent folder, and list all the potential matches using InStr. Example of how you might do this:
Sub CodeSnippet()
Dim myFolderName As String
'GetFolders returns array
Dim folderNamesWithPattern As Variant
'searching for "22.111" at 1st pos in string of potential subfolder
folderNamesWithPattern = GetFolders("D:\Documents", "22.111", 1)
If UBound(folderNamesWithPattern) > 0 Then
'more than one folder that meets your pattern:
'decide what to do
Else
'only one entry in array, this is your folder or if "" then ( no such folder | parent folder does not exist )
myFolderName = folderNamesWithPattern(0)
End If
End Sub
Function GetFolders(strDirectory As String, pattern As String, position As Long) As Variant
Dim objFSO As Object
Dim objFolders As Object
Dim objFolder As Object
'create filesystem obj
Set objFSO = CreateObject("Scripting.FileSystemObject")
'create folder obj and access subfolders property
On Error GoTo errorHandler
Set objFolders = objFSO.GetFolder(strDirectory).SubFolders
'dim array for matches
Dim arrFolderNames() As Variant
arrFolderNames = Array()
'loop through all folders
For Each objFolder In objFolders
'InStr() returns 0 if not found | index 1st char in string if found
If InStr(objFolder.Name, pattern) = 1 Then
'add match to array
ReDim Preserve arrFolderNames(UBound(arrFolderNames) + 1)
arrFolderNames(UBound(arrFolderNames)) = objFolder.Name
End If
Next objFolder
'assign array for return
GetFolders = arrFolderNames
errorHandler:
If objFolders Is Nothing Then
'parent folder does not exist
GetFolders = Array("")
ElseIf UBound(arrFolderNames) = -1 Then
'we never found a subfolder that starts with pattern
GetFolders = Array("")
End If
End Function
If you want to use RegEx, you might want to look at How do i use regex using instr in VBA.
Explore a Folder Using Workbook.FollowHyperlink
Workbook.FollowHyperlink method (MSDocs)
A Known Worksheet in the Workbook Containing This Code (ThisWorkbook)
Sub ExploreFolder()
Const iFolderPath As String = "D:\Documents\"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets("Sheet1")
Dim Code As String: Code = CStr(ws.Range("A1").Value)
Dim dFolderPattern As String: dFolderPattern = iFolderPath & Code & "*"
Dim dFolder As String: dFolder = Dir(dFolderPattern, vbDirectory)
If Len(dFolder) > 0 Then
wb.FollowHyperlink iFolderPath & dFolder
Else
MsgBox "A folder matching the pattern '" & dFolderPattern _
& "' was not found.", vbCritical, "Explore Folder"
End If
End Sub
ActiveSheet (not recommended)
Sub ExploreFolderActiveSheet()
Const iFolderPath As String = "D:\Documents\"
Dim ws As Worksheet: Set ws = ActiveSheet
Dim Code As String: Code = CStr(ws.Range("A1").Value)
Dim dFolderPattern As String: dFolderPattern = iFolderPath & Code & "*"
Dim dFolder As String: dFolder = Dir(dFolderPattern, vbDirectory)
If Len(dFolder) > 0 Then
ws.Parent.FollowHyperlink iFolderPath & dFolder
Else
MsgBox "A folder matching the pattern '" & dFolderPattern _
& "' was not found.", vbCritical, "Explore Folder"
End If
End Sub

Get file names from folder and subfolder function change

i have this code below to get files names from a specific folder and it works great. i like how is transposes the file names it works really well with how i do my work.
what i want to change is to have it also return the file names with in the subfolders to. but carry on transposing it accrss my work sheet.
Thank you.
Function GetFileNames6(ByVal FolderPath As String) As Variant
Dim Result As Variant
Dim i As Integer
Dim MyFile As Object
Dim MyFSO As Object
Dim myFolder As Object
Dim MyFiles As Object
Set MyFSO = CreateObject("Scripting.FileSystemObject")
Set myFolder = MyFSO.GetFolder(FolderPath)
Set MyFiles = myFolder.Files
ReDim Result(1 To MyFiles.Count)
i = 1
o = 1
For Each MyFile In MyFiles
Result(i) = MyFile.name & " " & MyFile.DateCreated
i = i + 1
Next MyFile
GetFileNames6 = Result
End Function
Return File Names From All Folders and Subfolders
Issues
Files containing 'non-standard' characters like e.g. žćčšđ will be returned by the ArrFilePaths function using the WScript Host but will not be found by the FileSystemObject object (nor the Dir function) hence the complications in the GetFileNames6function. If you have such characters in your file- or folder names, you can ask another question.
I've used something like Dim Arr() As String: Arr = Split("") to get an 'empty' string array in both functions. Not sure if that's the ideal way since I've never seen it done before.
Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Tests the 'GetFileNames6' function.
' Calls: GetFileNames6
' ArrFilePaths
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub GetFileNames6TEST()
Const FolderPath As String = "C:\Test\"
Dim NamesDates() As String: NamesDates = GetFileNames6(FolderPath)
If UBound(NamesDates) = -1 Then
Debug.Print "No files found."
Exit Sub
End If
Debug.Print Join(NamesDates, vbLf)
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns a zero-based string array containing the concatenated
' names and dates ('DateCreated') from a given zero-based string
' array containing file paths.
' Calls: ArrFilePaths.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function GetFileNames6( _
ByVal FolderPath As String, _
Optional ByVal Delimiter As String = " ") _
As String()
Const ProcName As String = "GetFileNames6"
On Error GoTo ClearError
' Ensuring that a string array is passed if an error occurs.
GetFileNames6 = Split("") ' LB = 0 , UB = -1
Dim FilePaths() As String: FilePaths = ArrFilePaths(FolderPath)
'Debug.Print Join(FilePaths, vbLf)
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
Dim fsoFile As Object
Dim n As Long ' Files Count
Dim fCount As Long ' Found Files Count
For n = 0 To UBound(FilePaths)
If fso.FileExists(FilePaths(n)) Then
Set fsoFile = fso.GetFile(FilePaths(n))
FilePaths(fCount) = fsoFile.Name & Delimiter & fsoFile.DateCreated
fCount = fCount + 1
Else ' happens if not 'standard characters' (character map?)
Debug.Print "Not found: " & FilePaths(n)
End If
Next n
If fCount < n Then
ReDim Preserve FilePaths(0 To fCount - 1)
'Debug.Print Join(FilePaths, vbLf)
Debug.Print "Initially found files: " & n
Debug.Print "Finally found files: " & fCount
End If
GetFileNames6 = FilePaths
ProcExit:
Exit Function
ClearError:
Debug.Print "'" & ProcName & "' Run-time error '" _
& Err.Number & "':" & vbLf & " " & Err.Description
Resume ProcExit
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns the file paths of the files in a folder in an array.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function ArrFilePaths( _
ByVal FolderPath As String, _
Optional ByVal FilePattern As String = "*.*", _
Optional ByVal DirSwitches As String = "/s/b/a-d") _
As String()
Const ProcName As String = "ArrFilePaths"
On Error GoTo ClearError
' Ensuring that a string array is passed if an error occurs.
ArrFilePaths = Split("") ' LB = 0 , UB = -1
Dim pSep As String: pSep = Application.PathSeparator
If Right(FolderPath, 1) <> pSep Then FolderPath = FolderPath & pSep
Dim ExecString As String ' '%comspec%' or 'cmd.exe' ?
ExecString = "%comspec% /c Dir """ _
& FolderPath & FilePattern & """ " & DirSwitches
Dim Arr() As String: Arr = Split(CreateObject("WScript.Shell") _
.Exec(ExecString).StdOut.ReadAll, vbCrLf)
If UBound(Arr) > 0 Then
ReDim Preserve Arr(0 To UBound(Arr) - 1)
End If
ArrFilePaths = Arr
ProcExit:
Exit Function
ClearError:
Debug.Print "'" & ProcName & "' Run-time error '" _
& Err.Number & "':" & vbLf & " " & Err.Description
Resume ProcExit
End Function

Renaming Files in directory not only a folder

I am working on a project in excel, where I am renaming multiple files.
Fow now I am using this code
Sub RenameFiles()
Dim xDir As String
Dim xFile As String
Dim xRow As Long
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
If .Show = -1 Then
xDir = .SelectedItems(1)
xFile = Dir(xDir & Application.PathSeparator & "*")
Do Until xFile = ""
xRow = 0
On Error Resume Next
xRow = Application.Match(xFile, Range("A:A"), 0)
If xRow > 0 Then
Name xDir & Application.PathSeparator & xFile As _
xDir & Application.PathSeparator & Cells(xRow, "G").Value
End If
xFile = Dir
Loop
End If
End With
End Sub
which lets me change the names of the files in one specific folder, but I would like to be able to pick the main folder containing subfolders and it would change all the names corresponding with names I have made in my excel sheet.
I’m sure you are aware that renaming files if go wrong can have very serious, sometimes even catastrophic consequences, with that been said I hope that all necessary step to avoid any of those problems have been taken.
Data and Code:
It seems that columns A and G contain the "old" and "new" names of the files (excluding the path), and that’s the reason of asking the user for the path and the possibility of running the renaming of the files for subfolders as well.
The code posted compares every file in the folders (and subfolder as expected) against the list of files in the data, which could be time consuming.
Also, I’ll would suggest to have a track of what files have been renamed, so in case of any error, this allows to easily track back and undo what could have be an error.
Solution Proposed
The solution proposed below uses the FileSystemObject object which provides a robust access to the machine file system, you can interact with it in two manners: Early and Late Binding (Visual Basic). These procedures use late binding, to use early binding see How do I use FileSystemObject in VBA?
Folders_ƒGet_From_User: A function that ask the user to select the folder and to process or not subfolders. It returns a list of the subfolder selected (names only), excluding folders with no files.
Files_Get_Array: Creates and array with all the Filenames to be processed (Old & New)
Files_ƒRename: This function renames all files found in any of the folders from the list obtained from point 1. These procedure instead of validating every file present in the subfolders against the list, check if the files in the list Exist in any folder, and if so passes to the function File_ƒRename_Apply that does the renaming and returns the result, allowing the creation of the “Audit Track” array. It returns an array with the results of all the files names in the list in all the folders list ( from point 1 and 2) respectively.
File_Rename_Post_Records: Creates a worksheet named FileRename(Track) (if not present) to post the Audit Track of the results of the Files_ƒRename function.
All of them are called from the procedure: Files_Rename
Let me know of any questions you might have regarding the resources used.
Option Explicit
Private Const mk_Wsh As String = "FileRename(Track)"
Private Const mk_MsgTtl As String = "Files Rename"
Private mo_Fso As Object
…
Sub Files_Rename()
Dim aFolders() As String, aFiles As Variant
Dim aRenamed As Variant
Set mo_Fso = CreateObject("Scripting.FileSystemObject")
If Not (Folders_ƒGet_From_User(aFolders)) Then Exit Sub
Call Files_Get_Array(aFiles)
If Not (Files_ƒRename(aRenamed, aFolders, aFiles)) Then
Call MsgBox("None file was renamed", vbInformation, mk_MsgTtl)
Exit Sub
End If
Call File_Rename_Post_Records(aFiles, aRenamed)
Call MsgBox("Files were renamed" & String(2, vbLf) _
& vbTab & "see details in sheet [" & mk_Wsh & "]", vbInformation, mk_MsgTtl)
End Sub
…
Private Function Folders_ƒGet_From_User(aFolders As Variant) As Boolean
Dim aFdrs As Variant
Dim oFdr As Object, sFolder As String, blSubFdrs As Boolean
Erase aFolders
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
If .Show <> -1 Then Exit Function
sFolder = .SelectedItems(1)
End With
If MsgBox("Do you want to include subfolders?", _
vbQuestion + vbYesNo + vbDefaultButton2, _
mk_MsgTtl) = vbYes Then blSubFdrs = True
Set oFdr = mo_Fso.GetFolder(sFolder)
Select Case blSubFdrs
Case False
If oFdr.Files.Count > 0 Then
aFdrs = aFdrs & "|" & oFdr.Path
Else
MsgBox "No files found in folder:" & String(2, vbLf) & _
vbTab & sFolder & String(2, vbLf) & _
vbTab & "Process is being terminated.", _
vbInformation, mk_MsgTtl
Exit Function
End If
Case Else
Call SubFolders_Get_Array(aFdrs, oFdr)
If aFdrs = vbNullString Then
MsgBox "No files found in folder & subfolders:" & String(2, vbLf) & _
vbTab & sFolder & String(2, vbLf) & _
vbTab & "Process is being terminated.", _
vbInformation, mk_MsgTtl
Exit Function
End If
End Select
Rem String To Array
aFdrs = Mid(aFdrs, 2)
aFdrs = Split(aFdrs, "|")
aFolders = aFdrs
Folders_ƒGet_From_User = True
End Function
…
Private Sub SubFolders_Get_Array(aFdrs As Variant, oFdr As Object)
Dim oSfd As Object
With oFdr
If .Files.Count > 0 Then aFdrs = aFdrs & "|" & .Path
For Each oSfd In .SubFolders
Call SubFolders_Get_Array(aFdrs, oSfd)
Next: End With
End Sub
…
Private Sub Files_Get_Array(aFiles As Variant)
Dim lRow As Long
With ThisWorkbook.Sheets("DATA") 'change as required
lRow = .Rows.Count
If Len(.Cells(lRow, 1).Value) = 0 Then lRow = .Cells(lRow, 1).End(xlUp).Row
aFiles = .Cells(2, 1).Resize(-1 + lRow, 7).Value
End With
End Sub
…
Private Function Files_ƒRename(aRenamed As Variant, aFolders As Variant, aFiles As Variant) As Boolean
Dim vRcd As Variant: vRcd = Array("Filename.Old", "Filename.New")
Dim blRenamed As Boolean
Dim oDtn As Object, aRcd() As String, lRow As Long, bFdr As Byte
Dim sNameOld As String, sNameNew As String
Dim sFilename As String, sResult As String
aRenamed = vbNullString
Set oDtn = CreateObject("Scripting.Dictionary")
vRcd = Join(vRcd, "|") & "|" & Join(aFolders, "|")
vRcd = Split(vRcd, "|")
oDtn.Add 0, vRcd
With mo_Fso
For lRow = 1 To UBound(aFiles)
sNameOld = aFiles(lRow, 1)
sNameNew = aFiles(lRow, 7)
vRcd = sNameOld & "|" & sNameNew
For bFdr = 0 To UBound(aFolders)
sResult = Chr(39)
sFilename = .BuildPath(aFolders(bFdr), sNameOld)
If .FileExists(sFilename) Then
If File_ƒRename_Apply(sResult, sNameNew, sFilename) Then blRenamed = True
End If
vRcd = vRcd & "|" & sResult
Next
vRcd = Mid(vRcd, 2)
vRcd = Split(vRcd, "|")
oDtn.Add lRow, vRcd
Next: End With
If Not (blRenamed) Then Exit Function
aRenamed = oDtn.Items
aRenamed = WorksheetFunction.Index(aRenamed, 0, 0)
Files_ƒRename = True
End Function
…
Private Function File_ƒRename_Apply(sResult As String, sNameNew As String, sFileOld As String) As Boolean
With mo_Fso.GetFile(sFileOld)
sResult = .ParentFolder
On Error Resume Next
.Name = sNameNew
If Err.Number <> 0 Then
sResult = "¡Err: " & Err.Number & " - " & Err.Description
Exit Function
End If
On Error GoTo 0
End With
File_ƒRename_Apply = True
End Function
…
Private Sub File_Rename_Post_Records(aFiles As Variant, aRenamed As Variant)
Const kLob As String = "lo.Audit"
Dim blWshNew As Boolean
Dim Wsh As Worksheet, Lob As ListObject, lRow As Long
Rem Worksheet Set\Add
With ThisWorkbook
On Error Resume Next
Set Wsh = .Sheets(mk_Wsh)
On Error GoTo 0
If Wsh Is Nothing Then
.Worksheets.Add After:=.Sheets(.Sheets.Count)
Set Wsh = .Sheets(.Sheets.Count)
blWshNew = True
End If: End With
Rem Set ListObject
With Wsh
.Name = mk_Wsh
.Activate
Application.GoTo .Cells(1), 1
Select Case blWshNew
Case False
Set Lob = .ListObjects(kLob)
lRow = 1 + Lob.ListRows.Count
Case Else
With .Cells(2, 2).Resize(1, 4)
.Value = Array("TimeStamp", "Filename.Old", "Filename.New", "Folder.01")
Set Lob = .Worksheet.ListObjects.Add(xlSrcRange, .Resize(2), , xlYes)
Lob.Name = "lo.Audit"
lRow = 1
End With: End Select: End With
Rem Post Data
With Lob.DataBodyRange.Cells(lRow, 1).Resize(UBound(aRenamed), 1)
.Value = Format(Now, "YYYYMMDD_HHMMSS")
.Offset(0, 1).Resize(, UBound(aRenamed, 2)).Value = aRenamed
.CurrentRegion.Columns.AutoFit
End With
End Sub
Renaming Files (Subfolders)
Not nearly enough tested.
You better create a copy of the folder where it should run to avoid losing files.
It will write all files in the folder and its subfolders to a dictionary object whose keys (file paths) will be checked against the file paths in column A. If matched, the files will be renamed to the name in column G with the same file path.
It checks each new file path only against the file paths in the dictionary before renaming.
It will fail if a file name is not valid.
Copy the complete code to a standard module, e.g. Module1.
Adjust the values in the constants section of the first procedure.
Run only the first procedure, the rest is being called by it.
The Code
Option Explicit
Sub renameFiles()
' Define constants.
Const wsName As String = "Sheet1"
Const FirstRow As Long = 2
Dim Cols As Variant
Cols = Array("A", "G")
Dim wb As Workbook
Set wb = ThisWorkbook
' Define worksheet.
Dim ws As Worksheet
Set ws = wb.Worksheets(wsName)
' Define Lookup Column Range.
Dim rng As Range
Set rng = defineColumnRange(ws, Cols(LBound(Cols)), FirstRow)
' Write values from Column Ranges to jagged Column Ranges Array.
Dim ColumnRanges As Variant
ColumnRanges = getColumnRanges(rng, Cols)
' Pick a folder.
Dim FolderPath As String
FolderPath = pickFolder
' Define a Dictionary object.
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
' Write the paths and the names of the files in the folder
' and its subfolders to the Dictionary.
Set dict = getFilesDictionary(FolderPath)
' Rename files.
Dim RenamesCount As Long
RenamesCount = renameColRngDict(ColumnRanges, dict)
' Inform user.
If RenamesCount > 0 Then
MsgBox "Renamed " & RenamesCount & " file(s).", vbInformation, "Success"
Else
MsgBox "No files renamed.", vbExclamation, "No Renames"
End If
End Sub
Function defineColumnRange(Sheet As Worksheet, _
ColumnIndex As Variant, _
FirstRowNumber As Long) _
As Range
Dim rng As Range
Set rng = Sheet.Cells(FirstRowNumber, ColumnIndex) _
.Resize(Sheet.Rows.Count - FirstRowNumber + 1)
Dim cel As Range
Set cel = rng.Find(What:="*", _
LookIn:=xlFormulas, _
SearchDirection:=xlPrevious)
If Not cel Is Nothing Then
Set defineColumnRange = rng.Resize(cel.Row - FirstRowNumber + 1)
End If
End Function
Function getColumnRanges(ColumnRange As Range, _
BuildColumns As Variant) _
As Variant
Dim Data As Variant
ReDim Data(LBound(BuildColumns) To UBound(BuildColumns))
Dim j As Long
With ColumnRange.Columns(1)
For j = LBound(BuildColumns) To UBound(BuildColumns)
If .Rows.Count > 1 Then
Data(j) = .Offset(, .Worksheet.Columns(BuildColumns(j)) _
.Column - .Column).Value
Else
Dim OneCell As Variant
ReDim OneCell(1 To 1, 1 To 1)
Data(j) = OneCell
Data(1, 1) = .Offset(, .Worksheet.Columns(BuildColumns(j)) _
.Column - .Column).Value
End If
Next j
End With
getColumnRanges = Data
End Function
Function pickFolder() _
As String
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
If .Show = -1 Then
pickFolder = .SelectedItems(1)
End If
End With
End Function
' This cannot run without the 'listFiles' procedure.
Function getFilesDictionary(ByVal FolderPath As String) _
As Object
Dim dict As Object ' ByRef
Set dict = CreateObject("Scripting.Dictionary")
With CreateObject("Scripting.FileSystemObject")
listFiles dict, .GetFolder(FolderPath)
End With
Set getFilesDictionary = dict
End Function
' This is being called only by 'getFileDictionary'
Sub listFiles(ByRef Dictionary As Object, _
fsoFolder As Object)
Dim fsoSubFolder As Object
Dim fsoFile As Object
For Each fsoFile In fsoFolder.Files
Dictionary(fsoFile.Path) = Empty 'fsoFile.Name
Next fsoFile
For Each fsoSubFolder In fsoFolder.SubFolders
listFiles Dictionary, fsoSubFolder
Next
End Sub
' Breaking the rules:
' A Sub written as a function to return the number of renamed files.
Function renameColRngDict(ColumnRanges As Variant, _
Dictionary As Object) _
As Long
Dim Key As Variant
Dim CurrentIndex As Variant
Dim NewFilePath As String
For Each Key In Dictionary.Keys
Debug.Print Key
CurrentIndex = Application.Match(Key, _
ColumnRanges(LBound(ColumnRanges)), 0)
If Not IsError(CurrentIndex) Then
NewFilePath = Left(Key, InStrRev(Key, Application.PathSeparator)) _
& ColumnRanges(UBound(ColumnRanges))(CurrentIndex, 1)
If IsError(Application.Match(NewFilePath, Dictionary.Keys, 0)) Then
renameColRngDict = renameColRngDict + 1
Name Key As NewFilePath
End If
End If
Next Key
End Function

Move only files with matching files names from one folder to another folder

I want to copy only the files from one folder “the FromPath” that have the same file name (with different extensions) as in another folder the “the ToPath”. Only the shared file named files will be moved. I think the code would have to first look in the ToPath folder to get the names of the files and then cross reference those in the “FromPath” folder.
Thanks
Private Sub CmdBtn_transfer_Click()
Dim FSO As Object
Dim FromPath As String
Dim ToPath As String
Dim FileExt As String
Dim Val As String
Dim i As Integer
FromPath = "C:\Users\rossi\Desktop\Production files\" & (Me.ListBox1) '<< Change
For i = 0 To ListBox2.ListCount - 1
If ListBox2.Selected(i) = True Then
Val = ListBox2.List(i)
End If
Next i
FileExt = "*.sli*" '<< Change
If Right(FromPath, 1) <> "\" Then
FromPath = FromPath & "\"
End If
Set FSO = CreateObject("scripting.filesystemobject")
If FSO.FolderExists(FromPath) = False Then
MsgBox FromPath & " doesn't exist"
Exit Sub
End If
For i = 0 To ListBox2.ListCount - 1
If ListBox2.Selected(i) Then
ToPath = "\\bego.hb\MED_PRODUCTION\USA_Datapreparation\" & (Me.ListBox2.List(i)) '<< Change
If Right(ToPath, 1) <> "\" Then
ToPath = ToPath & "\"
End If
If FSO.FolderExists(ToPath) = False Then
MsgBox ToPath & " doesn't exist"
Exit Sub
End If
FSO.CopyFile Source:=FromPath & FileExt, Destination:=ToPath
MsgBox "You can find the files from " & FromPath & " in " & ToPath
End If
Next i
End Sub
You pretty much have it. I made a couple of small additions. First I make a unique list of local files in the colFiles collection. I did this because you are copying to a remote server. I think it will probably be quicker this way. Once you have the list of local files, you simply loop through the collection checking to see if they exist in the remote folder, and copy them if they do.
Private Sub CmdBtn_transfer_Click()
Dim FSO As Object
Dim FromPath As String
Dim ToPath As String
Dim FileExt As String
Dim Val As String
Dim i As Integer
Dim x As Integer
Dim colFiles As New Collection
Dim strFilename As String
FromPath = "C:\Users\rossi\Desktop\Production files\" & (Me.ListBox1) '<< Change
For i = 0 To ListBox2.ListCount - 1
If ListBox2.Selected(i) = True Then
Val = ListBox2.List(i)
End If
Next i
FileExt = "*.sli*" '<< Change
If Right(FromPath, 1) <> "\" Then
FromPath = FromPath & "\"
End If
If FSO.FolderExists(FromPath) = False Then
MsgBox FromPath & " doesn't exist"
Exit Sub
End If
'Create a list of local filenames
strFilename = Dir(FromPath & "*" & FileExt) 'Corrected
While strFilename <> ""
colFiles.Add Left(strFilename, _
InStr(1, strFilename, ".", vbBinaryCompare) - 1), _
Left(strFilename, InStr(1, strFilename, ".", vbBinaryCompare) - 1)
strFilename = Dir()
Wend
Set FSO = CreateObject("scripting.filesystemobject")
For i = 0 To ListBox2.ListCount - 1
If ListBox2.Selected(i) Then
ToPath = "\\bego.hb\MED_PRODUCTION\USA_Datapreparation\" & (Me.ListBox2.List(i)) '<< Change
If Right(ToPath, 1) <> "\" Then
ToPath = ToPath & "\"
End If
If FSO.FolderExists(ToPath) = False Then
MsgBox ToPath & " doesn't exist"
Exit Sub
End If
'Now loop through our list of files to see if they exist on the remote server
For x = 1 To colFiles.Count 'Corrected
If FSO.FileExists(ToPath & colFiles.item(x) & FileExt) Then
FSO.CopyFile Source:=FromPath & FileExt, Destination:=ToPath
End If
Next
MsgBox "You can find the files from " & FromPath & " in " & ToPath
End If
Next i
End Sub

Resources