How to auto rename multiple files with different indexing in VB.NET - vb.net

how do i auto rename multiple files that are being copied with different indexing? i mean the (0), (1), etc... i.e. if i have two files in Folder1 that has a.txt and b.txt, And another two same files inside the Folder2 And copy the a.txt and b.txt from Folder1 to Folder2 then the a.txt will become a(1).txt and the b.txt to b(1).txt. how do i do it in a single instance? what came to my mind is to have many Strings and Integers as many as the files, but i will be dealing thousands of files. This is what i have so far.
Dim ii as Integer = 0
Dim iii as Integer = 0
Sub Copy()
For i = 0 To updatedFiles.Count - 1
Dim fileName As String = Path.GetFileNameWithoutExtension(updatedFiles(i))
Dim filePath As String = Path.GetDirectoryName(updatedFiles(i))
Dim fileExt As String = Path.GetExtension(updatedFiles(i))
Dim newFile As String = filePath & "\" & fileName & "(" & ii & ")" & fileExt
Dim newFile2 As String = filePath & "\" & fileName & "(" & iii & ")" & fileExt
If File.Exists(Path.Combine(dest, updatedFiles(i))) Then
ii += 1
'Copy newFile
ElseIf File.Exists(Path.Combine(dest, newFile)) Then
iii += 1
'Copy newFile2
End If
Next
End Sub
This doesn't do it right, from the situation above, the a.txt becomes a(1).txt but the b.txt becomes b(2).txt. the result should be
a (1).txt
b (1).txt

You will need to have: Imports System.IO
When Copy() is run, all of the files from the source folder will be copied over to the destination folder, and renamed file(1).ext, file(2).ext, etc. if the file already exists in the destination folder:
Dim sourceFolder As String = "C:\Users\Public\Documents\Folder1"
Dim destFolder As String = "C:\Users\Public\Documents\Folder2"
Sub Copy()
Dim allFiles() As String 'Put all files in an array
allFiles = Directory.GetFiles(sourceFolder)
Dim i As Integer = 0 'File counter
Dim fileName As String = "" 'This will be name of file without path
Dim fileNameNoExt As String = "" 'Name of file without extension
Dim fileExt As String = "" 'File Extension
For j As Integer = 0 To allFiles.Count - 1
i = 1 're-initialize i
fileName = allFiles(j).Substring(allFiles(j).LastIndexOf("\") + 1)
fileNameNoExt = allFiles(j).Substring(allFiles(j).LastIndexOf("\"), allFiles(i).LastIndexOf(".") - allFiles(j).LastIndexOf("\"))
fileExt = allFiles(j).Substring(allFiles(j).LastIndexOf(".") + 1)
If File.Exists(destFolder & "\" & fileName) Then
While File.Exists(destFolder & "\" & fileNameNoExt & "(" & i & ")." & fileExt)
i += 1
'when while fails, i will hold the next value for file
End While
File.Copy(allFiles(j), destFolder & "\" & fileNameNoExt & "(" & i & ")." & fileExt)
Else
File.Copy(allFiles(j), destFolder & "\" & fileName)
'if there is no file with the same name, there is a direct copy of the file to the destination folder
End If
Next
End Sub

Easiest way is iterate twice. Once to add something to the name like aTBR.txt, bTBR.txt. TBR(To be renamed). You can put anything.
Second time to change name to what you would like it to be.
Harder way but maybe faster is to start with renaming last object. d.txt to e.txt?? then c.txt to d.txt, b.txt to c.txt
For that option you would need to keep their names in order in some array, or have them in alphabetic order and store their names array when you load app.
Update:
put Dim ii as Integer = 0
Dim iii as Integer = 0
inside for loop

Related

Moving files into subfolders according to partial filename with VBA

I have been trying to move over 300+ pdf files to subfolders, which partially match filenames. The file names format is as follow:
Definition, PN 123456, SN unique
Definition(may change), PN 657634(may change), SN unique(always different)
Their pattern is two commas followed by PN and SN: ..., PN ..., SN ...
The folder names are: PN 123456 SN unique.
The example:
filenames
VALVE AFT SAFETY, PN 81155B010101, SN 00515
CABIN PRESSURIZATION MODULE, PN 92147A020103, SN 00501
AIR CYCLE MACHINE, PN 820906-3, SN 2010010011
AIR CYCLE MACHINE, PN 820906-3, SN 2010010014
TEMP REDUCTION SWITCH, PN 820907-2, SN 0414
folder names
PN 81155B010101 SN 00515
PN 92147A020103 SN 00501
PN 820906-3 SN 2010010011
PN 820906-3 SN 2010010014
PN 820907-2 SN 0414
The folders are subdirectories, second level.
I tried the information that, was kindly provided by #BNR bnr.455560 here: https://www.mrexcel.com/board/threads/moving-files-to-a-subfolder-based-on-partial-filename-with-vba.1120135/
My original post: https://www.mrexcel.com/board/threads/moving-files-to-a-subfolder-based-on-partial-filename-with-vba.1221014/
The below code run as Macro - does nothing.
Public Function Return_SubDirectory_Name(FileName As String) As String
'define a string array
Dim Splitter() As String
' check if we have a filename with a length > 0 - i.e. no empty filenames
If Len(FileName) > 0 Then
' let's assume the filename is "Definition, PN 123456, SN unique.pdf"
' Split creates a string array with the ", " as the break point - notice the space before and after the "-" character
' element 0 in the array will hold "Definition"
' element 2 in the array will hold "SN inique.pdf
Splitter = Split(FileName, ", ", 2)
' test to make sure the array has JUST two elements
' 1st element of ANY array starts with zero
' logic would need to be adjusted if file name was something like "02 - 12345 - 123.pdf" - as plsit function would create more elements
If UBound(Splitter) = 1 Then
' now splitter (1) holds the value "PN 123456, SN unique.pdf"
' split out the ".pdf" or whatever file extention
Splitter = Split(Splitter(1), ".")
' element (0) now just holds "PN 123456, SN unique" - this *SHOULD* be the sub directory or deal #
'Remove comma "," by replace it to ""
Splitter = Replace(Splitter(0), ",", "")
Return_SubDirectory_Name = CStr(Splitter(0))
' now exit the function
Exit Function
End If
' if above logic didn't work (maybe weird file name or whatever) - then drop out here with vbnullstring (empty) filename
Return_SubDirectory_Name = vbNullString
End If
End Function
Public Sub Check_Files(Search_Path As String)
Dim File_Name As String
Dim File_Type As String
Dim strFileName As String
Dim Deal_Name As String
Dim Archive_Path As String
Dim Target_Path As String
Dim File_Count As Integer
' setup where the archive directory is - maybe a network location?
' I'll assume it is the same directory path as the work book - change the following path as required
' path should be in a format like "C:\Desktop\MyFiles" or something
Archive_Path = ThisWorkbook.Path
' the search_path is handed into the function as an argument
' checks the Search path - this path is where the file currently are - maybe different than where you want to archive them
Confirm_Directory Search_Path
' changes excel's default directory path to the one you want to search
ChDir Search_Path
' assumes .msg files, but could be .pdf files - make changes as needed
File_Type = Search_Path & "*.pdf"
' identifies file name within the target directory
strFileName = Dir(File_Type)
' cycles through each file within the search directory - will continue until the length of the strFileName = 0 (i.e. no files)
Do While Len(strFileName) > 0
' get the sub directory or #deal name
Deal_Name = Return_SubDirectory_Name(strFileName)
' test if we have a valid deal name (not a vbnullstring)
If Len(Deal_Name) > 0 Then
' update the target_path - the target path will change as the different #deal name subdirectories within the archive path change
Target_Path = Archive_Path & "\" & Deal_Name
' checks if THAT target archive path exists - makes one if it doesn't
Confirm_Directory Target_Path
' copy required file to the target archive directory
FileCopy Search_Path & "\" & strFileName, Target_Path & "\" & strFileName
' delete original copy from search directory
Kill Search_Path & "\" & strFileName
File_Count = File_Count + 1
End If
' aquires the next filename in the search directory
strFileName = Dir
Loop
Debug.Print "Moved " & File_Count & " file(s)"
End Sub
Public Sub Confirm_Directory(This_Path As String)
' used to test for directory locations
' will make sub directories if required
Dim Splitter() As String
Dim Test_Path As String
If Dir(This_Path, vbDirectory) <> vbNullString Then
Splitter = Split(This_Path, "\")
For I = LBound(Splitter) To UBound(Splitter)
If I = 0 Then
Test_Path = Splitter(0)
Else
Test_Path = Test_Path & "\" & Splitter(I)
End If
ReTest:
If Dir(Test_Path, vbDirectory) = vbNullString Then
'Debug.Print "'" & Test_Path & "' does not exist"
MkDir Test_Path
'Debug.Print "Making ' " & Test_Path & "'"
GoTo ReTest
Else
'Debug.Print "'" & Test_Path & "' exists"
End If
Next I
End If
End Sub
Sub Sort_files_2_folders_()
End Sub
Try this out (adjust file paths as needed)
Sub RelocateFiles()
Dim allFiles As Collection 'of File objects
Dim allFolders As Collection 'of Folder objects
Dim f As Object, fld As Object, sn As String, bMoved As Boolean
'find all files (include subfolders)
Set allFiles = GetFiles("C:\Temp\TestFiles\", "*.pdf", True)
'find all destination folders
Set allFolders = GetFolders("C:\Temp\TestFiles\", True)
For Each f In allFiles 'loop over files
sn = GetSN(f.Name) 'get SN part of name
bMoved = False 'reset flag
If Len(sn) > 0 Then 'has "sn" part ?
For Each fld In allFolders 'loop over folders
If GetSN(fld.Name) = sn Then 'check folder name
Debug.Print "Moving '" & f.Name & _
"' to '" & fld.Path & "'"
f.Move fld.Path & "\" 'move the files
bMoved = True 'flag moved
Exit For 'stop checking
End If
Next fld
End If
If Not bMoved Then Debug.Print "## Not moved: " & f.Name
Next f
End Sub
'Return the "sn" part for a folder or file name
Function GetSN(txt As String) As String
Dim arr, sn, pos As Long
arr = Split(txt, " SN ")
If UBound(arr) > 0 Then
sn = arr(UBound(arr))
pos = InStr(sn, ".") 'any extension? (if a filename)
If pos > 0 Then sn = Left(sn, pos - 1) 'remove extension
GetSN = sn
End If
End Function
'Find all folders under `startFolder`
' Returns a collection of Folder objects
Function GetFolders(startFolder As String, _
Optional subFolders As Boolean = True) As Object
Dim fso, fldr, f, subFldr, fpath
Dim colFolders 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 subFldr In fldr.subFolders
If subFolders Then colSub.Add subFldr.Path
colFolders.Add fso.getfolder(subFldr.Path)
Next subFldr
Loop
Set GetFolders = colFolders
End Function
'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 GetFiles(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
fpath = fldr.Path
If Right(fpath, 1) <> "\" Then fpath = fpath & "\"
f = Dir(fpath & filePattern) 'Dir is faster...
Do While Len(f) > 0
colFiles.Add fso.getfile(fpath & f)
f = Dir()
Loop
Loop
Set GetFiles = colFiles
End Function

VBA - Saving multiple copies of a workbook with a specific naming convention

I have code below to save the current workbook and attach today's date to the end of the file name. How would I modify the code so if two copies of the workbook were to be saved on the same day, the first one would save normally as "Workbook Name, Today's Date.xlsm" and the second one would save as "Workbook Name, Today's Date Copy 2.xlsm". Same thing if the workbook were to be saved 3,4,5 times a day they should save as Copy 3,4,5,etc...
Sub Save_Workbook()
Const Path = "H:\HR\Cole G\Timehseet Test Path\"
Dim FileName As String
Dim Pos As Long
Pos = InStrRev(ActiveWorkbook.Name, ".") - 1
' If there wasn't a ".", then the file doesn't have an extension and Pos = -1
If Dir(Path & Left(ActiveWorkbook.Name, Pos) & Format(Now, "d-mm-yyyy") & Mid(ActiveWorkbook.Name, Pos + 1)) <> "" Then
ActiveWorkbook.SaveAs FileName:=Path & Left(ActiveWorkbook.Name, Pos) & "copy 2" & Mid(ActiveWorkbook.Name, Pos + 1)
Else
ActiveWorkbook.SaveAs FileName:=Path & Left(ActiveWorkbook.Name, Pos) & Format(Now, "d-mm-yyyy") & Mid(ActiveWorkbook.Name, Pos + 1)
End If
End Sub
Instead of appending "Copy xxx", why not to append the time?
eg
"Workbook Name, 2018-04-05 12.30.23.xlsm"
Well, the question could be changed a bit, to get what you are looking for. In general, you are looking for a function, which splits some strings by dots and spaces and increments the last one with 1.
E.g., if this is your input:
"WorkbookName 12.12.12.xlsm"
"WorkbookName 13.18.22 Copy 230.xlsm"
"WorkbookName 12.11.19 Copy 999.xlsm"
Your function should give the folowing output:
"WorkbookName 12.12.12.xlsm"
"WorkbookName 13.18.231.xlsm"
"WorkbookName 12.11.1000.xlsm"
Once you achieve this, the saving of the workbook could be carried out through that function. This is some function that gets that output:
Sub TestMe()
Dim path1 As String: path1 = "WorkbookName 12.12.12.xlsm"
Dim path2 As String: path2 = "WorkbookName 13.18.22 Copy 230.xlsm"
Dim path3 As String: path3 = "WorkbookName 12.11.19 Copy 999.xlsm"
Debug.Print changeName(path1)
Debug.Print changeName(path2)
Debug.Print changeName(path3)
End Sub
Public Function changeName(path As String) As String
changeName = path
Dim varArr As Variant
varArr = Split(path, ".")
Dim splitNumber As Long
splitNumber = UBound(varArr)
Dim preLast As String: preLast = varArr(splitNumber - 1)
If IsNumeric(preLast) Then Exit Function
Dim lastWithSpace As String
lastWithSpace = Split(preLast)(UBound(Split(preLast)))
Dim incrementSome As String
incrementSome = Left(preLast, Len(preLast) - Len(lastWithSpace))
If IsNumeric(lastWithSpace) Then
preLast = Split(preLast)(UBound(Split(preLast))) + 1
varArr(splitNumber - 1) = incrementSome & preLast
changeName = Join(varArr, ".")
End If
End Function
The changeName function could be a bit sanitized, with some checks, whether UBound-1 exists in order to avoid error.The function splits the input string to array by . symbol and works with the pre-last value received. Then, if the value is numeric, it does nothing, but if the value looks like this 22 Copy 230, it splits once again and increments the last element with one.
At the end it returns the string.
If you need to check the date as well, then one more layer of splits and arrays should be added.
Listen, you added a comma after the original name, Great! (now use it)
Dim FileName as String, FileExtension as String
FileName = "Workbook Name, Today's Date Copy 2.xlsm"
Pos = InStrRev(FileName, ".") - 1
FileExtension = ".xlsx" ' <-- Set a default
If Pos > 0 then
FileExtension = Mid(FileName, Pos)
FileName = Left(FileName, Pos)
End if
FileExtension has been pulled out from the FileName, and the Filename doesn't have an extension anymore. Now lets go after the Comma
Pos = InStrRev(FileName, ",")
If Pos2 > 0 then FileName = Left(FileName, Pos2 -1)
That was easy, FileName has now been cleaned of the Date and Copy junk. While you could have looked for the copy before we cleaned it, I think it's easier to just try a few times, since you're going to want to check if the file exists anyway.
You can alternatively just add the time like PhantomLord mentioned.
Dim Try as long
Dim FullName as String
Try = 0
FullName = Path & FileName & Format(Now, ", d-mm-yyyy") & FileExtension
' Lets put a safety limit to stop the code if something goes wrong
Do While Try < 1000 And Dir(FullName) = vbNullString
Try = Try + 1
FullName = Path & FileName & Format(Now, ", d-mm-yyyy") & " Copy " & IIF(Try > 1, Try, vbNullString) & FileExtension
Loop
ActiveWorkbook.SaveAs FileName:=FullName
I even thru in the IIF() for fun!

VBA Append Character to Beginning of Filename in Directory

I am wondering if anyone can help me edit this VBA script so that it not only moves the files (this part is complete by the way), but it also appends a 0 to the front of the filename (this part has not been started.
So, if the original filename is 123456789.tif, then the resultant will be 0123456789.tif.
Thank you!
Sub MoveIfFilelength()
'This script moves files from a source directory to a final directory based on the number of characters in the filename (e.g., 14, as below)
Dim srcDir As String
Dim dstDir As String
Dim f As String
srcDir = "S:\\" 'Input source directory
dstDir = "S:\\" 'Input destination directory
f = Dir(srcDir)
Do While f <> ""
If Len(f) = 13 Then Name srcDir & "\" & f As dstDir & "\" & f 'Input filename length
f = Dir()
Loop
End Sub
Name .. As is the move operation which is semantically a rename already, so specify the new name as "\0" & f:
If Len(f) = 13 Then Name srcDir & "\" & f As dstDir & "\0" & f

ObjFile.Name not comapring with String in VBA Excel

i have a variable String named fileName and another variable named finalDoc
i am trying to compare both but it is not working. the program does not go in the if condition
Dim fileName As String
fileName = objFile.Name
finalDoc = cellValue & "-" & Range(sheetNo).Value & ".pdf"
//The fileName and finalDoc are getting values as expected
If finalDoc = fileName Then
'MsgBox finalDoc & " " & fileName
End If
the if condition is not working. it only works if i hardcode the value in fileName like
fileName ="abc.pdf"
any suggestions, i think this is a type issue String etc. Any help would be appreciated.
Using VBA of Excel 2013
You can't compare a string using "=". You must use the StrComp command that will return an integer depending on the outcome.
More information can be found Here
But here is an example that returns a match when comparing ABC.pdf and abc.pdf:
Sub test1()
Dim fileName1 As String
Dim fileName2 As String
Dim TestComp As Integer
fileName1 = "abc.pdf"
fileName2 = "ABC.pdf"
TestComp = StrComp(fileName1, fileName2, vbTextCompare)
If TestComp = 0 Then
MsgBox ("Match!")
Else
MsgBox (fileName1 & " and " & fileName2 & " are No Match. Outcome is " & TestComp)
End If
End Sub
All you now need to do is adjust this code to suit your needs.
Basically:
Dim fileName As String
Dim TestComp As Integer
fileName = objFile.Name
finalDoc = cellValue & "-" & Range(sheetNo).Value & ".pdf"
TestComp = StrComp(fileName,finalDoc,vbTextCompare)
If TestComp = 0 Then
//Insert code to run for a correct match
Else
//Insert code to run for incorrect match
End If

VBA to find multiple files

I have this code which finds file names(along with file paths) based on search string.This code works fine in finding single files. I would like this macro to find multiple files and get their names displayed separated using a comma.
Function FindFiles(path As String, SearchStr As String)
Dim FileName As String ' Walking filename variable.
Dim DirName As String ' SubDirectory Name.
Dim dirNames() As String ' Buffer for directory name entries.
Dim nDir As Integer ' Number of directories in this path.
Dim i As Integer ' For-loop counter.
Dim Name As String
Dim Annex As String
On Error GoTo sysFileERR
If Right(path, 1) <> "\" Then path = path & "\"
' Search for subdirectories.
nDir = 0
ReDim dirNames(nDir)
DirName = Dir(path, vbDirectory Or vbHidden Or vbArchive Or vbReadOnly _
Or vbSystem) ' Even if hidden, and so on.
Do While Len(DirName) > 0
' Ignore the current and encompassing directories.
If (DirName <> ".") And (DirName <> "..") Then
' Check for directory with bitwise comparison.
If GetAttr(path & DirName) And vbDirectory Then
dirNames(nDir) = DirName
DirCount = DirCount + 1
nDir = nDir + 1
ReDim Preserve dirNames(nDir)
'List2.AddItem path & DirName ' Uncomment to list
End If ' directories.
sysFileERRCont:
End If
DirName = Dir() ' Get next subdirectory.
Loop
' Search through this directory and sum file sizes.
FileName = Dir(path & SearchStr, vbNormal Or vbHidden Or vbSystem _
Or vbReadOnly Or vbArchive)
'Sheet1.Range("C1").Value2 = path & "\" & FileName
While Len(FileName) <> 0
FindFiles = path & "\" & FileName
FileCount = FileCount + 1
' Load List box
' Sheet1.Range("A1").Value2 = path & FileName & vbTab & _
FileDateTime(path & FileName) ' Include Modified Date
FileName = Dir() ' Get next file.
Wend
' If there are sub-directories..
If nDir > 0 Then
' Recursively walk into them
For i = 0 To nDir - 1
FindFiles = path & "\" & FileName
Next i
End If
AbortFunction:
Exit Function
sysFileERR:
If Right(DirName, 4) = ".sys" Then
Resume sysFileERRCont ' Known issue with pagefile.sys
Else
MsgBox "Error: " & Err.Number & " - " & Err.Description, , _
"Unexpected Error"
Resume AbortFunction
End If
End Function
Sub Find_Files()
Dim SearchPath As String, FindStr As String, SearchPath1 As String
Dim FileSize As Long
Dim NumFiles As Integer, NumDirs As Integer
Dim Filenames As String, Filenames1 As String
Dim r As Range
'Screen.MousePointer = vbHourglass
'List2.Clear
For Each cell In Range("SS")
SearchPath = Sheet3.Range("B2").Value2
SearchPath1 = Sheet3.Range("B3").Value2
FindStr = Cells(cell.Row, "H").Value
Filenames = FindFiles(SearchPath, FindStr)
Filenames1 = FindFiles(SearchPath1, FindStr)
'Sheet1.Range("B1").Value2 = NumFiles & " Files found in " & NumDirs + 1 & _
" Directories"
Cells(cell.Row, "F").Value = Filenames
Cells(cell.Row, "G").Value = Filenames1
'Format(FileSize, "#,###,###,##0") & " Bytes"
'Screen.MousePointer = vbDefault
Next cell
End Sub
Any thoughts will be highly appreciated.
I realize this question is very old, but it is unanswered. Here is a quick method for finding multiple files and their paths. VBA's DIR function isn't really very handy, but CMD's DIR function is well optimized and has a plethora of command line switches to make it return only files (or even just folders) that match your criteria. The trick is to call DIRfrom a WScript shell so that the output can be parsed by VBA.
For example, this snippet of code will find every file on your system that starts with config.
Dim oShell As Object 'New WshShell if you want early binding
Dim cmd As Object 'WshExec if you want early binding
Dim x As Integer
Const WshRunning = 0
Set oShell = CreateObject("Wscript.Shell")
Set cmd = oShell.Exec("cmd /c ""Dir c:\config* /a:-d /b /d /s""")
Do While cmd.Status = WshRunning
DoEvents
Loop
Debug.Print cmd.StdOut.ReadAll
Set oShell = Nothing
Set cmd = Nothing