Deleting part of string in subfolder name then in files within - excel

I have a ton of files that have a common string in the name "mch". Within one folder there are hundreds of subfolders named with this common string, then within those there are 5 pictures named similar; example picfront1234mch. I need to get rid of the mch at the end of all the names of picture files and the folders they are in. I was attempting a couple different examples from the web but non to work. I wrote this code to find the file names in the subfolders and to delete the last 3 characters of the name but its deleting the extensions instead. I have used the move/copy/ rename method in the past but I lost some of my old code and can’t figure out how use it again. Any suggestions on how to do this better?
Code ive been trying
Option Explicit
Sub ListFiles()
'Declare the variables
Dim objFSO As Scripting.FileSystemObject
Dim objTopFolder As Scripting.Folder
Dim strTopFolderName As String
'Assign the top folder to a variable
strTopFolderName = "C:\Users\aholiday\Desktop\Test"
'Create an instance of the FileSystemObject
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Get the top folder
Set objTopFolder = objFSO.GetFolder(strTopFolderName)
'Call the RecursiveFolder routine
Call RecursiveFolder(objTopFolder, True)
End Sub
Sub RecursiveFolder(objFolder As Scripting.Folder, IncludeSubFolders As Boolean)
'Declare the variables
Dim objFile As Scripting.File
Dim objSubFolder As Scripting.Folder
Dim str As String
Debug.Print Now
Application.SendKeys "^g ^a {DEL}"
Application.ScreenUpdating = False
'Loop through each folder in the Topfolder
For Each objFile In objFolder.Files
str = objFile.Name
Debug.Print str
'delete last 3 chara of string
str = Left(str, Len(str) - 3)
Debug.Print str
Next objFile
If IncludeSubFolders Then
For Each objSubFolder In objFolder.SubFolders
Call RecursiveFolder(objSubFolder, True)
Next objSubFolder
End If
Application.ScreenUpdating = True
End Sub

Usage:
RemoveTextFromFileName "mch", "I:\stackoverflow\temp"
Sub RemoveTextFromFileName(txt As String, FolderName As String)
Dim file
If Not Right(FolderName, 1) = "\" Then FolderName = FolderName & "\"
file = Dir(FolderName)
While (file "")
If InStr(file, txt) > 0 Then
FileCopy FolderName & file, FolderName & Replace(file, txt, "")
Kill FolderName & file
End If
file = Dir
Wend
End Sub
Update: Remove string from folder, sub folders, and file names.
These functions will recursively search the root folder and all it's subfolders to rename files and folders.
Usage:
Public Sub ProcessFoldersAndFiles()
ReplaceStringFileNames "C:\Data Files\mch files\", "mch"
ReplaceStringDirectories"C:\Data Files\mch files\", "mch"
End Sub
Here are the functions:
Sub ReplaceStringDirectories(FolderPath As String, SearchString As String, Optional ReplacementString As String = "", Optional fso As Object)
Dim fld, thisFolder
Dim NewName As String, PathOnly As String
If fso Is Nothing Then
Set fso = CreateObject("Scripting.FileSystemObject")
End If
Set thisFolder = fso.getFolder(FolderPath)
For Each fld In thisFolder.Subfolders
ReplaceStringDirectories fld.Path, SearchString, ReplacementString
Next
If InStr(thisFolder.Name, SearchString) Then
NewName = Replace(thisFolder.Name, SearchString, ReplacementString, , , vbTextCompare)
PathOnly = Left(thisFolder.Path, InStrRev(thisFolder.Path, "\"))
Do Until Not fso.FolderExists(PathOnly & NewName)
NewName = "_" & NewName
Loop
thisFolder.Name = NewName
End If
End Sub
Sub ReplaceStringFileNames(FolderPath As String, SearchString As String, Optional ReplacementString As String = "", Optional fso As Object)
Dim f, fld, thisFolder
Dim NewName As String, PathOnly As String
If fso Is Nothing Then
Set fso = CreateObject("Scripting.FileSystemObject")
End If
Set thisFolder = fso.getFolder(FolderPath)
For Each fld In thisFolder.Subfolders
ReplaceStringFileNames fld.Path, SearchString, ReplacementString
Next
For Each f In thisFolder.Files
If InStr(f.Name, SearchString) Then
NewName = Replace(f.Name, SearchString, ReplacementString, , , vbTextCompare)
PathOnly = Left(f.Path, InStrRev(thisFolder.Path, "\"))
Do Until Not fso.FolderExists(PathOnly & NewName)
NewName = "_" & NewName
Loop
f.Name = NewName
End If
Next
End Sub

Related

How to delete .xls files using VBA?

I am no expert when it comes to using VBA. However, I have a task to convert thousnds of files located in folders and sub folders. I have found online the below code and my question is: can the code be modified in a way that it can delete the old .xls files after conversion?
Public Sub test()
RenameFilesInFolders "M:\test\", True
MsgBox "Finished"
End Sub
Public Sub RenameFilesInFolders(path As String, Optional recurse As Boolean)
Dim fso As Object, fldr As Object
If Right(path, 1) <> "\" Then
path = path & "\"
End If
Set fso = CreateObject("Scripting.FileSystemObject")
Set fldr = fso.GetFolder(path)
renameFiles fldr, recurse
End Sub
Private Sub renameFiles(fldr As Object, recurse As Boolean)
Dim file As Object, subFldr As Object
For Each file In fldr.Files
changeFileExtension file
Next
If recurse And fldr.SubFolders.Count > 0 Then
For Each subFldr In fldr.SubFolders
renameFiles subFldr, recurse
Next
End If
End Sub
Private Sub changeFileExtension(file As Object)
Dim xlFile As Workbook
Dim strCurrentFileExt As String
Dim strNewFileExt As String
Dim strNewName As String
strCurrentFileExt = ".xls"
strNewFileExt = ".xlsx"
strNewName = file.Name
If Right(strNewName, Len(strCurrentFileExt)) = strCurrentFileExt Then
Set xlFile = Workbooks.Open(file.path, , True)
strNewName = Replace(strNewName, strCurrentFileExt, strNewFileExt)
Application.DisplayAlerts = False
Select Case strNewFileExt
Case ".xlsx"
xlFile.SaveAs file.ParentFolder & "\" & strNewName, XlFileFormat.xlOpenXMLWorkbook
Case ".xlsm"
xlFile.SaveAs file.ParentFolder & "\" & strNewName, XlFileFormat.xlOpenXMLWorkbookMacroEnabled
End Select
xlFile.Close
Application.DisplayAlerts = True
End If
End Sub
Store path (called in your RenameFilesInFolders Sub) in a variable (for example PathToFile) and use this command : Kill PathToFile.
Afterwards you can even check if the file is deleted with this (if you enabled Microsoft Scripting Runtime) :
Dim FSO As FileSystemObject
Set FSO = CreateObject("Scripting.FileSystemObject")
Dim PathToFile As String
If (FSO.FileExists(PathToFile) Then 'If the file still exists
'Your code
End If
Set FSO = Nothing

Code Does not Loop through All folder and Sub folders

I am trying to Loop through all files and sub folders but my code is just works for single folder.
I want to apply this code on all Folders and subfolder which have workbooks.
Any help will be appreciated.
Sub KeepColor()
Dim strFolder As String
Dim strFile As String
Dim wbk As Workbook
Dim wsh As Worksheet
Dim I As Long
Dim xRg As Range
With Application.FileDialog(4)
If .Show Then
strFolder = .SelectedItems(1)
Else
MsgBox "You 't selected a folder!", vbExclamation
Exit Sub
End If
End With
If Right(strFolder, 1) <> "\" Then
strFolder = strFolder & "\"
End If
Application.ScreenUpdating = FALSE
strFile = Dir(strFolder & "*.xls*")
Do While strFile <> ""
Set wbk = Workbooks.Open(strFolder & strFile)
For Each wsh In wbk.Worksheets
For Each xRg In wsh.UsedRange
If xRg.DisplayFormat.Interior.ColorIndex = xlColorIndexNone Then
xRg.Interior.ColorIndex = xlColorIndexNone
Else
xRg.Interior.Color = xRg.DisplayFormat.Interior.Color
End If
Next xRg
wsh.UsedRange.FormatConditions.Delete
Next wsh
wbk.Close SaveChanges:=True
strFile = Dir
Loop
Application.ScreenUpdating = TRUE
End Sub
Dir is much faster than FileSystemObject if you have a filename pattern, so here's a function which mixes both:
Sub Tester()
Dim col As Collection, t
t = Timer
Set col = GetMatches("C:\Tester", "*.xls*")
Debug.Print Timer - t, col.Count
End Sub
'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, fpath
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
If subFolders Then
For Each subFldr In fldr.subFolders
colSub.Add subFldr.Path
Next subFldr
End If
'this is faster...
fpath = fldr.Path
If Right(fpath, 1) <> "\" Then fpath = fpath & "\"
f = Dir(fpath & filePattern)
Do While Len(f) > 0
colFiles.Add fso.getfile(fpath & f)
f = Dir()
Loop
'this is slower...
'For Each f In fldr.Files
' If UCase(f.Name) Like filePattern Then colFiles.Add f
'Next f
Loop
Set GetMatches = colFiles
End Function
Please, try the next code:
Sub KeepColor()
Dim strFolder As String, fso As Object, parentFolder As Object, folder As Object
With Application.FileDialog(4)
If .Show Then
strFolder = .SelectedItems(1)
Else
MsgBox "You didn't select a folder!", vbExclamation
Exit Sub
End If
End With
Set fso = CreateObject("scripting.filesystemobject")
Set parentFolder = fso.GetFolder(strFolder)
Application.ScreenUpdating = False
ProcessAllFiles parentFolder, "xls*"
For Each folder In parentFolder.SubFolders
ProcessAllFiles folder, "xls*"
Next
Application.ScreenUpdating = True
End Sub
Sub ProcessAllFiles(strFold As Object, fileExt As String)
Dim fso As Object, objFile As Object, xRg As Range, wbk As Workbook, wsh As Worksheet
Set fso = CreateObject("scripting.filesystemobject")
For Each objFile In strFold.files
If fso.GetExtensionName(objFile.Name) Like fileExt Then
Set wbk = Workbooks.Open(objFile.path)
For Each wsh In wbk.Worksheets
For Each xRg In wsh.UsedRange
If xRg.DisplayFormat.Interior.ColorIndex = xlColorIndexNone Then
xRg.Interior.ColorIndex = xlColorIndexNone
Else
xRg.Interior.color = xRg.DisplayFormat.Interior.color
End If
Next xRg
wsh.UsedRange.FormatConditions.Delete
Next wsh
wbk.Close SaveChanges:=True
End If
Next
End Sub
This is a recursion job.
I am using a generic function, that returns a collection of all files (could be changed to array as well) - either for the folder or for all subfolders.
You need to add a reference to "Microsoft Scripting runtime"
Option Explicit
Sub testFindAllFiles()
Dim strFolder As String: strFolder = "XXXX" 'adjust to your needs
Dim colFiles As Collection
Set colFiles = findAllFilesByExtension(strFolder, "xls*", True)
Dim strFile As Variant
For Each strFile In colFiles
Debug.Print strFile
'do what you need with the file
Next
End Sub
Public Function findAllFilesByExtension(ByVal targetFolder As String, ByVal extension As String, _
Optional fWithSubfolders As Boolean = True) As Collection
Dim fso As FileSystemObject: Set fso = New FileSystemObject
Dim colFiles As Collection: Set colFiles = New Collection
findFilesByExtension targetFolder, colFiles, extension, fso, fWithSubfolders
Set findAllFilesByExtension = colFiles
End Function
Private Sub findFilesByExtension(ByVal targetFolder As String, ByRef colFiles As Collection, _
extension As String, fso As FileSystemObject, fWithSubfolders As Boolean)
Dim objFolder As Folder, objFile As File
Dim subFolders As Folders
Set objFolder = fso.GetFolder(targetFolder)
For Each objFile In objFolder.Files
If Not objFile.Name Like "~*" Then
If objFile.Name Like "*." & extension Then
colFiles.Add objFile.Path
End If
End If
Next
If fWithSubfolders = True Then
Set subFolders = objFolder.subFolders
For Each objFolder In subFolders
findFilesByExtension objFolder.Path, colFiles, extension, fso, fWithSubfolders
Next
End If
End Sub

Finding and replacing text in multiple files within a folder

Below is code that should let me select a folder, then find and replace periods in the word documents within the folder and replace them with a space.
I got the code to work, my computer crashed, and now I don't remember what I did, and I'm getting a 'user-defined type' error.
I'm not quite sure how to fix this.
I'm also trying to get this to work from excel (not just from word) so any help there would be appreciated.
Sub Step_1() 'select folder with raw files to clean up
Dim wordApp As Word.Application
Dim objDocument As Word.Document
Dim intResult As Integer
Dim strPath As String
Dim arrFiles() As String
Dim i As Integer
'box will open where user can pick folder with raw files
intResult = Application.FileDialog(msoFileDialogFolderPicker).Show
'checks if user has cancelled the dialog
If intResult <> 0 Then
'display folder search box
strPath = Application.FileDialog( _
msoFileDialogFolderPicker).SelectedItems(1)
arrFiles() = GetAllFilePaths(strPath)
For i = LBound(arrFiles) To UBound(arrFiles)
Call ModifyFile(arrFiles(i))
Next i
End If
End Sub
Private Sub ModifyFile(ByVal strPath As String)
Dim wordApp As Word.Application
Dim objDocument As Word.Document
Set objDocument = wordApp.Documents.Open(strPath)
objDocument.Activate
For Each objDocument In strPath
With Selection.Find
.Text = "."
.Replacement.Text = " "
.Find.Execute Replace:=wdReplaceAll
'there's a much longer list of things to replace
End With
objDocument.Close (True)
Next
Next
End Sub
Private Function GetAllFilePaths(ByVal strPath As String) _
As String()
Dim objFSO As Object
Dim objFolder As Object
Dim objFile As Object
Dim i As Integer
Dim arrOutput() As String
ReDim arrOutput(1 To 1)
'Create an instance of the FileSystemObject
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Get the folder object
Set objFolder = objFSO.GetFolder(strPath)
i = 1
'loops through each file in the directory and
'prints their names and path
For Each objFile In objFolder.Files
ReDim Preserve arrOutput(1 To i)
'print file path
arrOutput(i) = objFile.Path
i = i + 1
Next objFile
GetAllFilePaths = arrOutput
End Function
Cleaned up:
Sub ProcessFiles()
Dim wordApp As Word.Application
Dim wdDoc As Word.document
Dim strPath As String, allfiles As Collection, fPath
strPath = GetFolderPath()
If Len(strPath) = 0 Then Exit Sub
Set allfiles = GetAllFiles(strPath, "*.doc*")
If allfiles.Count = 0 Then
MsgBox "No Word files found"
Exit Sub
End If
Set wordApp = New Word.Application
wordApp.Visible = True
'loop over found files
For Each fPath In allfiles
Debug.Print "Processing " & fPath
Set wdDoc = wordApp.documents.Open(fPath)
ReplaceDocContent wdDoc, ".", " "
ReplaceDocContent wdDoc, ",", " "
ReplaceDocContent wdDoc, "~", " "
'etc.....
wdDoc.Close True 'close and save changes
Next fPath
MsgBox "done"
End Sub
'replace text in a Word document with some other text
Private Sub ReplaceDocContent(doc As Word.document, findWhat, replaceWith)
With doc.Range.Find
.Text = findWhat
.Replacement.Text = replaceWith
.Execute Replace:=wdReplaceAll
End With
End Sub
'collect all files under folder `strPath` which match `pattern`
Private Function GetAllFiles(ByVal strPath As String, pattern As String) As Collection
Dim objFile As Object, col As New Collection
'Create an instance of the FileSystemObject and list all files
For Each objFile In CreateObject("Scripting.FileSystemObject").GetFolder(strPath).Files
If objFile.Path Like pattern Then col.Add objFile.Path
Next objFile
Set GetAllFiles = col
End Function
'return selected folder path or empty string
Function GetFolderPath() As String
With Application.FileDialog(msoFileDialogFolderPicker)
If .Show <> 0 Then GetFolderPath = .SelectedItems(1)
End With
End Function

How to loop through subfolders?

The following code works for specified folder.
How to get it to work for all subfolders of X:\DataArchive\CMM\reports\?
Sub Copying()
Dim FSO As Object
Dim sFile As String
Dim sSFolder As String
Dim sDFolder As String
Dim fileExtn As String
fileExtn = ".PDF" ''File extension
sSFolder = "X:\DataArchive\CMM\reports\2019_01\" ''Source folder
sDFolder = "C:\Users\sc00709\Desktop\501 28\" ''Destination folder
Dim i As Integer
i = 2
Do While i < 74
With ThisWorkbook
''Filename
sFile = Dir(sSFolder & "364_040_501_0_D_OP270_INSP_" & _
Worksheets("50128").Cells(i, 2) & "*" & fileExtn)
''Create Object for File System
Set FSO = CreateObject("Scripting.FileSystemObject")
If Not FSO.FileExists(sSFolder & sFile) Then
ElseIf Not FSO.FileExists(sDFolder & sFile) Then
''Copying
FSO.CopyFile (sSFolder & sFile), sDFolder, TRUE
Else
End If
End With
i = i + 1
Loop
MsgBox "You did it!", vbInformation, "Done!"
End Sub
Here is code to loop through all the folders in a folder
Sub Main()
Dim FileSystem As Object
Set FileSystem = CreateObject("Scripting.FileSystemObject")
ExecuteOnAllSubFolders FileSystem.GetFolder("X:\DataArchive\CMM\reports\")
End Sub
Sub ExecuteOnAllSubFolders(Folder)
Dim SubFolder
For Each SubFolder In Folder.SubFolders
ExecuteOnAllSubFolders SubFolder
'Perform your operations here
Next
'Perform your operations and here
End Sub

move files from one folder to another

actually I am searching for code to move excel files from one folder to another if there is any way to do so Please someone help me. I am very sorry but I dont know how to do coding as I have never used VBA in fact I see it for the first time.
I will be grateful to you
Sub MoveFiles()
Dim FSO As Object
Dim SourceFileName As String, DestinFileName As String
Set FSO = CreateObject("Scripting.Filesystemobject")
SourceFileName = "C:\Users\Jun.xlsx"
DestinFileName = "C:\Users\Desktop\Jun.xlsx"
FSO.MoveFile Source:=SourceFileName, Destination:=DestinFileName
MsgBox (SourceFileName + " Moved to " + DestinFileName)
End Sub
Try with the below code
Sub test()
Set fso = CreateObject("scripting.filesystemobject")
fso.MoveFile Source:="C:\work\test1.xlsx", Destination:="c:\work\movecheck\" ' replace with source and destination as required.
End Sub
Below is code which moves only Excel (xlsx) files from source folder into destination folder. Other types files will be left in the destination folder.
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 = "D:\SourceFolder"
destinationFolderPath = "D:\DestinationFolder"
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
If you need move only one file the best solution is:
Name sourceFolderPath & fileName As destinationFilePath
You can use the Filesystemobject:
Dim FSO as Object
Set FSO = CreateObject("Scripting.Filesystemobject")
FSO.MoveFile("SourceFileName", "TargetFileName")
Feel free to comment, if you need further instructions.
Sub move_data()
'Move test data to folder
Dim FSO As Object
Dim FromPath As String
Dim ToPath As String
Dim Fdate As Date
Dim FileInFromFolder As Object
MkDir "D:\TEST\" 'Create new folder name TEST in D:
FromPath = "E:\test\" 'Source files
ToPath = "D:\TEST\" 'Target destination
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
try :
Sub movefile()
Dim fso As New FileSystemObject
Dim fil As file
Dim SourcePath, BackUpPath As String
SourcePath = "C:\mydata\"
BackUpPath = "G:\Backup\"
For Each fil In fso.GetFolder(SourcePath).Files
fName = fso.GetFileName(fil)
Name fil As BackUpPath & fName
Next fil
End Sub

Resources