I have a VBA for copying images from one folder to another based on image names. You can check macro in work in attached. Code is:
Option Explicit
Sub CopyFiles()
Dim iRow As Integer ' ROW COUNTER.
Dim sSourcePath As String
Dim sDestinationPath As String
Dim sFileType As String
Dim bContinue As Boolean
bContinue = True
iRow = 2
' THE SOURCE AND DESTINATION FOLDER WITH PATH.
sSourcePath = "C:\Users\nhatc_000\Desktop\01010101\"
sDestinationPath = "C:\Users\nhatc_000\Desktop\02020202\"
sFileType = ".jpg" ' TRY WITH OTHER FILE TYPES LIKE ".pdf".
' LOOP THROUGH COLUMN "A" TO PICK THE FILES.
While bContinue
If Len(Range("A" & CStr(iRow)).Value) = 0 Then ' DO NOTHING IF THE COLUMN IS BLANK.
MsgBox "Images have been moved. Thank you!" ' DONE.
bContinue = False
Else
' CHECK IF FILES EXISTS.
If Len(Dir(sSourcePath & Range("A" & CStr(iRow)).Value & sFileType)) = 0 Then
Range("B" & CStr(iRow)).Value = "Does Not Exists"
Range("B" & CStr(iRow)).Font.Bold = True
Else
Range("B" & CStr(iRow)).Value = "On Hand"
Range("B" & CStr(iRow)).Font.Bold = False
If Trim(sDestinationPath) <> "" Then
Dim objFSO
Set objFSO = CreateObject("scripting.filesystemobject")
' CHECK IF DESTINATION FOLDER EXISTS.
If objFSO.FolderExists(sDestinationPath) = False Then
MsgBox sDestinationPath & " Does Not Exists"
Exit Sub
End If
'*****
' HERE I HAVE INCLUDED TWO DIFFERENT METHODS.
' I HAVE COMMENTED THE SECOND METHOD. TO THE SEE THE RESULT OF THE
' SECOND METHOD, UNCOMMENT IT AND COMMENT THE FIRST METHOD.
' METHOD 1) - USING "CopyFile" METHOD TO COPY THE FILES.
objFSO.CopyFile Source:=sSourcePath & Range("A" & CStr(iRow)).Value & _
sFileType, Destination:=sDestinationPath
' METHOD 2) - USING "MoveFile" METHOD TO PERMANENTLY MOVE THE FILES.
'objFSO.MoveFile Source:=sSourcePath & Range("B" & CStr(iRow)).Value & _
sFileType, Destination:=sDestinationPath
'*****
End If
End If
End If
iRow = iRow + 1 ' INCREMENT ROW COUNTER.
Wend
End Sub
However, I need 2 more things to add to this code:
When I enter the name of the file to be copied, I also want to copy
files that have the same name PLUS extension _01/_02/.../_07 if
those exist.
I want macro to look not only inside specified folder but also in
subfolders inside the folder and subfolders inside the subfolder
etc.
Can anyone help?
Thanks!
What you need is some Recursive Subs to find all the similar filenames based on the Range value.
Here I will approach this goal with below code with a couple of steps:
For each Range value (stored as a Key in Dictionary), find all the file names (exact and similar as Item in Dictionary). Joining each finding with "|" (an illegal file name character).
Process the Dictionary items after all files and sub folders from Source Path
For each Item in the dictionary of a key, see if existing file in destination folder. Append " (i)" to destination file name if already exists.
Copy the destination file to destination folder.
While copying, it returns the
Stop looping when first Empty cell is encountered
NOTE: Code not been tested, only compiled fine
Option Explicit
' THE SOURCE AND DESTINATION FOLDER WITH PATH.
Private Const sSourcePath = "C:\Users\nhatc_000\Desktop\01010101\"
Private Const sDestinationPath = "C:\Users\nhatc_000\Desktop\02020202\"
Private Const sFileType = "jpg" ' TRY WITH OTHER FILE TYPES LIKE ".pdf".
Private Const DIV = "|" ' A character that's not legal file name
Private objFSO As Object, objDict As Object
Sub CopyFilesAlike()
Dim lRow As Long, sName As String
Set objFSO = CreateObject("Scripting.FileSystemObject")
If Not objFSO.FolderExists(sSourcePath) Then
MsgBox "Source folder not found!" & vbCrLf & sSourcePath, vbCritical + vbOKOnly
GoTo I_AM_DONE
End If
If Not objFSO.FolderExists(sDestinationPath) Then
MsgBox "Destination folder not found!" & vbCrLf & sDestinationPath, vbCritical + vbOKOnly
GoTo I_AM_DONE
End If
' Proceed when both Source and Destination folders found
Set objDict = CreateObject("Scripting.Dictionary")
lRow = 2
Do Until IsEmpty(Cells(lRow, "A")) ' Stop on first empty cell in Column A from lRow
' Get Main file name to look up
sName = Cells(lRow, "A").Value
' Look for files (exact and alikes from sub folders) to add to dictionary
LookForFilesAlike sName, objFSO.GetFolder(sSourcePath)
' Copy files
If objDict.Count = 0 Then
Cells(lRow, "B").Value = "No files found."
Else
Cells(lRow, "B").Value = objDict.Count & " filenames(s) found." & vbLf & CopyFiles
End If
' Clear the Dictionary for next Name
objDict.RemoveAll
' Increment row counter
lRow = lRow + 1
Loop
Set objDict = Nothing
I_AM_DONE:
Set objFSO = Nothing
End Sub
Private Sub LookForFilesAlike(ByVal sName As String, ByVal objFDR As Object)
Dim oFile As Object, oFDR As Object
' Add files of current folder to dictionary if name matches
For Each oFile In objFDR.Files
If InStr(1, oFile.Name, sName, vbTextCompare) = 1 Then ' Names beginning with sName
' Check the extension to match
If LCase(objFSO.GetExtensionName(oFile)) = LCase(sFileType) Then
If objDict.Exists(oFile.Name) Then
' Append Path to existing entry
objDict.Item(oFile.Name) = objDict.Item(oFile.Name) & DIV & oFile.Path
Else
' Add Key and current path
objDict.Add oFile.Name, oFile.Path
End If
End If
End If
Next
' Recurse into each sub folder
For Each oFDR In objFDR.SubFolders
LookForFilesAlike sName, oFDR
Next
End Sub
Private Function CopyFiles() As String
Dim i As Long, oKeys As Variant, oItem As Variant, iRepeat As Integer, sName As String, sOut As String
sOut = ""
' Process the items for each key in Dictionary
Set oKeys = objDict.Keys ' <- Add "Set " before oKeys
For i = 0 To objDict.Count
For Each oItem In Split(objDict.Item(oKeys(i)), DIV)
' Determine the filename in destination path
If objFSO.FileExists(sDestinationPath & objFSO.GetFileName(oItem)) Then
' Same file name alreay found, try append " (i)"
iRepeat = 0
Do
iRepeat = iRepeat + 1
sName = objFSO.GetBaseName(oItem) & " (" & iRepeat & ")" & objFSO.GetExtensionName(oItem)
Loop While objFSO.FileExists(sDestinationPath & sName)
sName = sDestinationPath & sName
Else
' First file to be copied to destination folder
sName = sDestinationPath
End If
' Copy the source file to destination file
If Len(sOut) = 0 Then
sOut = oItem & DIV & sName
Else
sOut = sOut & vbLf & oItem & DIV & sName
End If
objFSO.CopyFile oItem, sName
Next
Next
CopyFiles = sOut
End Function
Related
I am working on the code which successfully copies the file (based on partial name list) from one folder to another. However i just would like to request if there is any possible way where the code can also read the extension of file before copy. For example column A contains the name of files and Column Column B contains extensions of each file, therefore the code should first read the file name and then extensions and if it matches then it should copy otherwise skips. I have the files with the following extension.
XML
PDF
TXT
ZIP
RAR
PDF
also the code i have is mentioned below
Sub moveFilesFromListPartial()
Const sPath As String = "E:\Uploading\Source"
Const dPath As String = "E:\Uploading\Destination\Destination_2\!Destination_3"
Const fRow As Long = 2
Const Col As String = "B"
' Reference the worksheet.
Dim ws As Worksheet: Set ws = Sheet2
' Calculate the last row,
' i.e. the row containing the last non-empty cell in the column.
Dim lRow As Long: lRow = ws.Cells(ws.Rows.Count, Col).End(xlUp).Row
' Validate the last row.
If lRow < fRow Then
MsgBox "No data in column range.", vbCritical
Exit Sub
End If
' Early Binding - needs a reference
' to 'Tools > References > Microsoft Scripting Runtime' (has intelli-sense)
Dim fso As Scripting.FileSystemObject
Set fso = New Scripting.FileSystemObject
' Late Binding - needs no reference (no intelli-sense)
'Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
' Validate the source folder path.
Dim sFolderPath As String: sFolderPath = sPath
If Right(sFolderPath, 1) <> "\" Then sFolderPath = sFolderPath & "\"
If Not fso.FolderExists(sFolderPath) Then
MsgBox "The source folder path '" & sFolderPath _
& "' doesn't exist.", vbCritical
Exit Sub
End If
' Validate the destination folder path.
Dim dFolderPath As String: dFolderPath = dPath
If Right(dFolderPath, 1) <> "\" Then dFolderPath = dFolderPath & "\"
If Not fso.FolderExists(dFolderPath) Then
MsgBox "The destination folder path '" & dFolderPath _
& "' doesn't exist.", vbCritical
Exit Sub
End If
Dim r As Long ' current row in worksheet column
Dim sFilePath As String
Dim sPartialFileName As String
Dim sFileName As String
Dim dFilePath As String
Dim sYesCount As Long ' source file moved
Dim sNoCount As Long ' source file not found
Dim dYesCount As Long ' source file exists in destination folder
Dim BlanksCount As Long ' blank cell
For r = fRow To lRow
sPartialFileName = CStr(ws.Cells(r, Col).Value)
If Len(sPartialFileName) > 3 Then ' the cell is not blank
' 'Begins with' sPartialFileName
sFileName = Dir(sFolderPath & sPartialFileName & "*")
' or instead, 'Contains' sPartialFileName
'sFileName = Dir(sFolderPath & "*" & sPartialFileName & "*")
Do While sFileName <> ""
If Len(sFileName) > 3 Then ' source file found
sFilePath = sFolderPath & sFileName
dFilePath = dFolderPath & sFileName
If Not fso.FileExists(dFilePath) Then ' the source file...
fso.CopyFile sFilePath, dFilePath ' ... doesn't exist...
sYesCount = sYesCount + 1 ' ... in the destination
Else ' the source file exists in the destination folder
dYesCount = dYesCount + 1
End If
Else ' the source file doesn't exist
sNoCount = sNoCount + 1
End If
sFileName = Dir
Loop
Else ' the cell is blank
BlanksCount = BlanksCount + 1
End If
Next r
End Sub
I will be really thankful
Please, use the next updated code. It uses my suggestion from my above comment. It works only if the file partial name exists in "A:A" column and extension in "B:B":
Sub moveFilesFromListPartial()
Const sPath As String = "E:\Uploading\Source"
Const dPath As String = "E:\Uploading\Destination\Destination_2\!Destination_3"
Const fRow As Long = 2
Const Col As String = "A", colExt As String = "B"
' Reference the worksheet.
Dim ws As Worksheet: Set ws = Sheet2
' Calculate the last row,
' i.e. the row containing the last non-empty cell in the column.
Dim lRow As Long: lRow = ws.cells(ws.rows.count, Col).End(xlUp).row
' Validate the last row.
If lRow < fRow Then
MsgBox "No data in column range.", vbCritical
Exit Sub
End If
' Early Binding - needs a reference
' to 'Tools > References > Microsoft Scripting Runtime' (has intelli-sense)
Dim fso As Scripting.FileSystemObject
Set fso = New Scripting.FileSystemObject
' Late Binding - needs no reference (no intelli-sense)
'Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
' Validate the source folder path.
Dim sFolderPath As String: sFolderPath = sPath
If Right(sFolderPath, 1) <> "\" Then sFolderPath = sFolderPath & "\"
If Not fso.FolderExists(sFolderPath) Then
MsgBox "The source folder path '" & sFolderPath _
& "' doesn't exist.", vbCritical
Exit Sub
End If
' Validate the destination folder path.
Dim dFolderPath As String: dFolderPath = dPath
If Right(dFolderPath, 1) <> "\" Then dFolderPath = dFolderPath & "\"
If Not fso.FolderExists(dFolderPath) Then
MsgBox "The destination folder path '" & dFolderPath _
& "' doesn't exist.", vbCritical
Exit Sub
End If
Dim r As Long ' current row in worksheet column
Dim sFilePath As String
Dim sPartialFileName As String
Dim sFileName As String
Dim dFilePath As String
Dim sYesCount As Long ' source file moved
Dim sNoCount As Long ' source file not found
Dim dYesCount As Long ' source file exists in destination folder
Dim BlanksCount As Long ' blank cell
Dim sExt As String 'extension (dot inclusive)
For r = fRow To lRow
sPartialFileName = CStr(ws.cells(r, Col).Value)
sExt = CStr(ws.cells(r, colExt).Value)
If Len(sPartialFileName) > 3 Then ' the cell is not blank
' 'Begins with' sPartialFileName
sFileName = Dir(sFolderPath & sPartialFileName & "*" & sExt)
Do While sFileName <> ""
If Len(sFileName) > 3 Then ' source file found
sFilePath = sFolderPath & sFileName
dFilePath = dFolderPath & sFileName
If Not fso.FileExists(dFilePath) Then ' the source file...
fso.CopyFile sFilePath, dFilePath ' ... doesn't exist...
sYesCount = sYesCount + 1 ' ... in the destination
Else ' the source file exists in the destination folder
dYesCount = dYesCount + 1
End If
Else ' the source file doesn't exist
sNoCount = sNoCount + 1
End If
sFileName = Dir
Loop
Else ' the cell is blank
BlanksCount = BlanksCount + 1
End If
Next r
End Sub
Please, send some feedback after testing it.
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
Can anyone please help me update the below VBA Code which I found in the below website, I changed the MyPath to loop through the rows but somehow it only merged the first folder in loop and it is not merging the next folder in the given rows.
http://www.vbaexpress.com/forum/showthread.php?47310-Need-code-to-merge-PDF-files-in-a-folder-using-adobe-acrobat-X/page3
Option Explicit
Sub Main()
Dim DestFile As String ' <-- change to suit
Dim MyPath As String, MyFiles As String
Dim a() As String, i, j, numRows As Long, f As String
' Choose the folder or just replace that part by: MyPath = Range("E3")
'With Application.FileDialog(msoFileDialogFolderPicker)
'.InitialFileName = "C:\Temp\"
'.AllowMultiSelect = False
' If .Show = False Then Exit Sub
'MyPath = .SelectedItems(1)
' DoEvents
'End With
Dim ws As Worksheet
Dim wb As Workbook
Set wb = ThisWorkbook
Set ws = wb.Worksheets("ForProcessing")
numRows = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
For j = 5 To numRows
MyPath = ws.Cells(j, 1).Value
DestFile = ws.Cells(j, 2).Value & " Rev " & ws.Cells(j, 6).Value & ".pdf"
' Populate the array a() by PDF file names
If Right(MyPath, 1) <> "\" Then MyPath = MyPath & "\"
ReDim a(1 To 2 ^ 14)
f = Dir(MyPath & "*.pdf")
While Len(f)
If StrComp(f, DestFile, vbTextCompare) Then
i = i + 1
a(i) = f
End If
f = Dir()
Wend
' Merge PDFs
If i Then
ReDim Preserve a(1 To i)
MyFiles = Join(a, ",")
Application.StatusBar = "Merging, please wait ..."
Call MergePDFs(MyPath, MyFiles, DestFile)
Application.StatusBar = False
Else
MsgBox "No PDF files found in" & vbLf & MyPath, vbExclamation, "Canceled"
End If
Next j
End Sub
Sub MergePDFs(MyPath As String, MyFiles As String, Optional DestFile As String = "MergedFile.pdf")
' ZVI:2013-08-27 http://www.vbaexpress.com/forum/showthread.php?47310-Need-code-to-merge-PDF-files-in-a-folder-using-adobe-acrobat-X
' Reference required: VBE - Tools - References - Acrobat
Dim a As Variant, i As Long, n As Long, ni As Long, p As String
Dim AcroApp As New Acrobat.AcroApp, PartDocs() As Acrobat.CAcroPDDoc
If Right(MyPath, 1) = "\" Then p = MyPath Else p = MyPath & "\"
a = Split(MyFiles, ",")
ReDim PartDocs(0 To UBound(a))
On Error GoTo exit_
If Len(Dir(p & DestFile)) Then Kill p & DestFile
For i = 0 To UBound(a)
' Check PDF file presence
If Dir(p & Trim(a(i))) = "" Then
MsgBox "File not found" & vbLf & p & a(i), vbExclamation, "Canceled"
Exit For
End If
' Open PDF document
Set PartDocs(i) = CreateObject("AcroExch.PDDoc")
PartDocs(i).Open p & Trim(a(i))
If i Then
' Merge PDF to PartDocs(0) document
ni = PartDocs(i).GetNumPages()
If Not PartDocs(0).InsertPages(n - 1, PartDocs(i), 0, ni, True) Then
MsgBox "Cannot insert pages of" & vbLf & p & a(i), vbExclamation, "Canceled"
End If
' Calc the number of pages in the merged document
n = n + ni
' Release the memory
PartDocs(i).Close
Set PartDocs(i) = Nothing
Else
' Calc the number of pages in PartDocs(0) document
n = PartDocs(0).GetNumPages()
End If
Next
If i > UBound(a) Then
' Save the merged document to DestFile
If Not PartDocs(0).Save(PDSaveFull, p & DestFile) Then
MsgBox "Cannot save the resulting document" & vbLf & p & DestFile, vbExclamation, "Canceled"
End If
End If
exit_:
' Inform about error/success
If Err Then
MsgBox Err.Description, vbCritical, "Error #" & Err.Number
ElseIf i > UBound(a) Then
MsgBox "The resulting file is created:" & vbLf & p & DestFile, vbInformation, "Done"
End If
' Release the memory
If Not PartDocs(0) Is Nothing Then PartDocs(0).Close
Set PartDocs(0) = Nothing
' Quit Acrobat application
AcroApp.Exit
Set AcroApp = Nothing
End Sub
I'm getting the first pdf combined as per the code, however, when it reads the next row this code
MyFiles = Join(a, ",")
The MyFiles value is having two comma before the set of PDF files that needed to be merged like this >>> ",,name1.pdf,name2.pdf"
If anyone can help me update this code will very much appreciated.
Thanks,
Mielkew
I am using this to try and copy photos that exist in the list within a list in excel. it seems check but doesn't see anything in the source folder and returns the "Does N" from the code below. I have enabled macros and the folders don't see locked. any help would be much appriciated
Option Explicit
Sub CopyFiles()
Dim iRow As Integer ' ROW COUNTER.
Dim sSourcePath As String
Dim sDestinationPath As String
Dim sFileType As String
Dim bContinue As Boolean
bContinue = True
iRow = 1
' THE SOURCE AND DESTINATION FOLDER WITH PATH.
sSourcePath = "C:\Users\username\Desktop\source\"
sDestinationPath = "C:\Users\username\Desktop\TARGET\"
sFileType = ".jpg" ' TRY WITH OTHER FILE TYPES LIKE ".pdf".
' LOOP THROUGH COLUMN "A" TO PICK THE FILES.
While bContinue
If Len(Range("A" & CStr(iRow)).Value) = 0 Then ' DO NOTHING IF THE COLUMN IS BLANK.
MsgBox "Process executed" ' DONE.
bContinue = False
Else
' CHECK IF FILES EXISTS.
If Len(Dir(sSourcePath & Range("A" & CStr(iRow)).Value & sFileType)) = 0 Then
Range("B" & CStr(iRow)).Value = "Does N"
Range("B" & CStr(iRow)).Font.Bold = True
Else
Range("B" & CStr(iRow)).Value = "On Hand"
Range("B" & CStr(iRow)).Font.Bold = False
If Trim(sDestinationPath) <> "" Then
Dim objFSO
Set objFSO = CreateObject("scripting.filesystemobject")
' CHECK IF DESTINATION FOLDER EXISTS.
If objFSO.FolderExists(sDestinationPath) = False Then
MsgBox sDestinationPath & " Does Not Exists"
Exit Sub
End If
'*****
' HERE I HAVE INCLUDED TWO DIFFERENT METHODS.
' I HAVE COMMENTED THE SECOND METHOD. TO THE SEE THE RESULT OF THE
' SECOND METHOD, UNCOMMENT IT AND COMMENT THE FIRST METHOD.
' METHOD 1) - USING "CopyFile" METHOD TO COPY THE FILES.
objFSO.CopyFile Source:=sSourcePath & Range("A" & CStr(iRow)).Value & _
sFileType, Destination:=sDestinationPath
' METHOD 2) - USING "MoveFile" METHOD TO PERMANENTLY MOVE THE FILES.
'objFSO.MoveFile Source:=sSourcePath & Range("A" & CStr(iRow)).Value & _
sFileType, Destination:=sDestinationPath
'*****
End If
End If
End If
iRow = iRow + 1 ' INCREMENT ROW COUNTER.
Wend
End Sub
You shouldn’t be creating a new FileSystemObject on every iteration. Also, the destination folder can only be checked once - no need to check it every time.
See below your code with a few changes.
Option Explicit
Sub CopyFiles()
On Error GoTo Errproc
Const sSourcePath As String = "C:\Users\username\Desktop\source\"
Const sDestinationPath As String = "C:\Users\username\Desktop\TARGET\"
Const sFileType As String = ".jpg"
'validate destination folder
If Len(Dir(sDestinationPath)) = 0 Then
MsgBox "Destination path does not exist..."
Exit Sub
End If
Dim iRow As Integer
iRow = Range("A" & Rows.Count).End(xlUp).Row
Dim rr As Range, r As Range
Set rr = Range("A1:A" & iRow)
Dim objFSO As Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
For Each r In rr
With objFSO
If Not .FileExists(sSourcePath & r.Value & sFileType) Then
r.Offset(0, 1).Value = "Does N"
r.Offset(0, 1).Font.Bold = True
Else
r.Offset(0, 1).Value = "On Hand"
r.Offset(0, 1).Font.Bold = False
objFSO.CopyFile sSourcePath & r.Value & sFileType, sDestinationPath, True 'Overwrite
'objFSO.MoveFile Source:=sSourcePath & r.Value & sFileType , Destination:=sDestinationPath
End If
End With
Next r
Leave:
Set objFSO = Nothing
On Error GoTo 0
Exit Sub
Errproc:
MsgBox Err.Description, vbCritical
Resume Leave
End Sub
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