VBA: Multiply a file (copy) and rename all after list - excel

I had a .bat file that worked but I need this in VBA now.
I tried different approches but only managed to do this with one file at a time. So I keep starting over and over.
So:
I have a file (named 1.pdf)
I have on a excel on Sheet1 (starting with A2) a list of file names
I need VBA to create a folder named ABC (where-ever the Excel macro is located) and multiply 1.pdf as many times as needed and rename the copies with every name in the excel list.
Example:
(i have in the same folder as the macro 1.pdf) and in Excel:
A1
John.pdf
Dog.pdf
Triangle.pdf
After execution this would result in 1.pdf copied and renamed with all of those 3 names uploaded into folder :ABC
In command prompt woud look like:
if not exist "ABC\" mkdir %cd%\ABC\
copy "1.pdf" "ABC"
ren "ABC\1.pdf" "John.pdf"
copy "1.pdf" "ABC"
ren "ABC\1.pdf" "Dog.pdf"
copy "1.pdf" "ABC"
ren "ABC\1.pdf" "Triangle.pdf"

Something like this should work for you:
Sub CopyFileForEachName()
Dim rRenameList As Range
Dim rNameCell As Range
Dim sFileToCopyPath As String
Dim sFolderPath As String
Dim sFileName As String
Dim sExt As String
Dim sNewSubFolder As String
Dim sCopyErr As String
Dim sResultsMsg As String
Dim lSuccessfulCopies As Long
Dim i As Long
'These are invalid characters for the subfolder name (the double quote "" will be evaluated as a single double quote")
Const sInvalidChar As String = "\/:*?""<>|"
If Len(ActiveWorkbook.Path) > 0 Then ChDir ThisWorkbook.Path 'Start in same folder as the active workbook
sFileToCopyPath = Application.GetOpenFilename("All Files, *.*") 'Prompt user to select file to copy
If sFileToCopyPath = "False" Then Exit Sub 'Pressed cancel
sFolderPath = Left(sFileToCopyPath, InStrRev(sFileToCopyPath, Application.PathSeparator)) 'Extract the folder path
sExt = Mid(sFileToCopyPath, InStrRev(sFileToCopyPath, ".")) 'Extract the extension
'Prompt user to select the range of cells that contain the rename list
'Pressing cancel will cause an error, resume next will suppress the error and GoTo 0 will remove the On Error condition
On Error Resume Next
Set rRenameList = Application.InputBox("Select the cells that contain the rename list.", "Rename Cells Selection", Selection.Address, Type:=8)
On Error GoTo 0
If rRenameList Is Nothing Then Exit Sub 'Pressed cancel
'If the list of rename cells is ALWAYS in the same location, you can comment out the above code, and uncomment the following:
'With ActiveWorkbook.Sheets("Sheet1")
' Set rRenameList = .Range("A2", .Cells(.Rows.Count, "A").End(xlUp))
' If .Row < 2 Then Exit Sub 'No data
'End With
'Prompt user to enter the destination subfolder name
'Change the Default parameter to provide a desired default subfolder name
sNewSubFolder = InputBox(Prompt:="Please enter the name of the subfolder that will store the copied and renamed files." & Chr(10) & _
"Note that if the subfolder doesn't already exist, it will be created.", _
Title:="Destination Subfolder", _
Default:="ABC")
If Len(Trim(sNewSubFolder)) = 0 Then Exit Sub 'Pressed cancel
'Verify valid subfolder name
For i = 1 To Len(sInvalidChar)
sNewSubFolder = Replace(sNewSubFolder, Mid(sInvalidChar, i, 1), " ")
Next i
sNewSubFolder = WorksheetFunction.Trim(sNewSubFolder)
If Right(sNewSubFolder, Len(Application.PathSeparator)) <> Application.PathSeparator Then sNewSubFolder = sNewSubFolder & Application.PathSeparator
'Attempt to create the subfolder
Err.Clear
On Error Resume Next
MkDir sFolderPath & sNewSubFolder
On Error GoTo 0
If Err.Number <> 0 Then
'Failed to create the subfolder
'Check if the folder already exists
If Len(Dir(sFolderPath & sNewSubFolder, vbDirectory)) = 0 Then
'Subfolder does NOT exist, the provided subfolder name must be invalid
MsgBox "Unable to create subfolder named [" & Replace(sNewSubFolder, Application.PathSeparator, "") & "] because it is an invalid name." & Chr(10) & "Exiting macro."
Exit Sub
Else
'Subfolder already exists, got error due to duplicate name
Err.Clear
End If
End If
'Loop through each cell and rename the file
For Each rNameCell In rRenameList.Cells
'Make sure to use the extension of the file being copied
If Right(rNameCell.Text, Len(sExt)) = sExt Then
sFileName = Replace(rNameCell.Text, sExt, "")
Else
sFileName = rNameCell.Text
End If
'Attempt to copy and rename the file to the destination subfolder
Err.Clear
On Error Resume Next
FileCopy sFileToCopyPath, sFolderPath & sNewSubFolder & sFileName & sExt
On Error GoTo 0
'Record successes and failures
If Err.Number <> 0 Then
sCopyErr = sCopyErr & Chr(10) & sFileName & sExt
Else
lSuccessfulCopies = lSuccessfulCopies + 1
End If
Next rNameCell
'Build results message
sResultsMsg = "Successfully copied [" & sFileToCopyPath & "] " & lSuccessfulCopies & " times into subfolder [" & sNewSubFolder & "]"
If Len(sCopyErr) > 0 Then
sResultsMsg = sResultsMsg & Chr(10) & Chr(10) & "Failed to copy with the following names: " & Chr(10) & sCopyErr
End If
'Display results message
MsgBox sResultsMsg
End Sub

Related

Can you create a PDF and have a target path such as i have below?

Ok, So i am trying to create a PDf and place it into a a folder that is named after cell E10 in which is side a folder of B18. I am getting a "Compile Error block If Without End If" I have tried both end and exit statements with no luck.
Function Dispatch_PDF() As Boolean ' Copies sheets into new PDF file for e-mailing
Dim Thissheet As String, ThisFile As String, PathName As String
Dim SvAs As String
Dim Tmp As String
Dim FldName As String
' 1. Create the name you want to search for before starting the search
' 2. don't refer to cells by their range names (too cumbersome)
FldName = Cells(10, 5).Value ' actually, it's Cells(10, 5)
Debug.Print FldName ' check the name
If Len(FldName) Then
Tmp = Cells(18, 2).Value
If Len(Tmp) Then
FldName = Tmp & "\" & FldName ' observe how to add the path separator
Debug.Print FldName ' check the name
FldName = ActiveWorkbook.path & "\DISPATCHED WORK ORDERS\" & FldName
Debug.Print FldName
Application.ScreenUpdating = False
' Get File Save Name
Thissheet = ActiveSheet.Name
ThisFile = ActiveWorkbook.Name
PathName = ActiveWorkbook.path
SvAs = PathName & "\DISPATCHED WORK ORDERS\" & FldName & Range("E10").Value & ".pdf"
'Set Print Quality
On Error Resume Next
ActiveSheet.PageSetup.PrintQuality = 600
Err.Clear
On Error GoTo 0
' Instruct user how to send
On Error GoTo RefLibError
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:=SvAs, Quality:=xlQualityStandard, IncludeDocProperties:=False, IgnorePrintAreas:=False, OpenAfterPublish:=True
On Error GoTo 0
SaveOnly:
MsgBox "A copy of this sheet has been successfully saved as a .pdf file: " & Chr(13) & Chr(13) & SvAs & _
"Review the .pdf document. If the document does NOT look good, adjust your printing parameters, and try again."
Dispatch_PDF = True
GoTo EndMacro
RefLibError:
MsgBox "Unable to save as PDF. Reference library not found."
Dispatch_PDF = False
EndMacro:
End Function
Any Suggestions?

Copy, rename and validate success of multiple files and paths in excel

Solution Template SetUp
Been scratching around for the last 5 days here and across the net to find something that works for multiple files. Many a late night/early hours of the morning unsuccessfully piecing together/coding to get a result. Thanks in advance.
The following code is from get-digital-help.com/copyrename-a-file-excel-vba written by Oscar
It works for 1 file, Ive got 8,000 files to do across a deep folder structure so but I'd really like each row to look at a source path, source file name, destination path and destination file:
For each row:
Column A list the source path
Column B lists the source file name
Column C lists to destination path
Column D lists the new file name
Column E writes "Success" or "Fail" validation.
if file name already exists in destination, then "Fail"
If source file doesn't exist, then "Fail"
Nice to have/completely optional!!! :)
Check if source file column A&B exists, = True or False in column F. Where True, then proceed with copy and rename.
If destination file already exist, the fail and column F = duplicate
Leave first row to put in column header names.
Sub CopyRenameFile()
'Dimension variables and declare data types
Dim src As String, dst As String, fl As String
Dim rfl As String
'Save source directory specified in cell A2 to variable src
src = Range("A2")
'Save destination directory specified in cell C2 to variable dst
dst = Range("C2")
'Save file name specified in cell B2 to variable fl
fl = Range("B2")
'Save new file name specified in cell D2 to variable rfl
rfl = Range("D2")
'Enable error handling
On Error Resume Next
'Copy file based on variables src and fl to destination folder based on variable dst and name file based on value in rfl
FileCopy src & "\" & fl, dst & "\" & rfl
'Check if an error has occurred
If Err.Number <> 0 Then
'Show error using message box
MsgBox "Copy error: " & src & "\" & rfl
End If
'Disable error handling
On Error GoTo 0
End Sub
Copy Files Using a File List
This solution consists of three procedures. You run only the first: copyRenameFile. The other two, getOffsetColumn and writeOffsetRange are being called by the first, when necessary.
It is best tested with a new workbook. Insert a module and copy the code into it. Now open your original workbook and copy certain values to e.g. Sheet1 of the new workbook. Since the code is written for Thisworkbook (the workbook containing this code), the original workbook will be safe (will not be written to).
First adjust the values in the constants sections (titled Worksheet and Other). Then test the empty worksheet. Then test with one folder in column A then with more and slowly continue testing with other columns. Possible errors should be suppressed and their messages (descriptions) should appear in VBE's Immediate window (CTRL+G).
As a byproduct of this investigation, I've also added the createFolders function to create folders in one case when MkDir 'cannot', and two procedures to test it.
The Code
Option Explicit
Sub copyRenameFile()
' Initialize error handling.
Const ProcName As String = "copyRenameFile"
On Error GoTo clearError ' Turn on error trapping.
' Worksheet
Const wsName As String = "Sheet1" ' Worksheet Name
Const FirstRow As Long = 2 ' First Row Number
Const LastRowCol As Variant = "A" ' Last Row Column Index
Dim srcCols As Variant ' Source Columns Array
srcCols = VBA.Array("A", "B", "C", "D")
Dim tgtCols As Variant ' Target Columns Array
tgtCols = VBA.Array("E", "F")
' Other
Dim filMsg() As Variant ' File Messages
filMsg = VBA.Array("Fail", "Success")
Dim folMsg() As Variant ' Folder Messages
folMsg = VBA.Array(False, True, "Duplicate")
Dim PathDelimiter As String
PathDelimiter = Application.PathSeparator
Dim wb As Workbook
Set wb = ThisWorkbook ' 'Thisworkbook' is the workbook containing this code.
' Define Last Row Column Range ('rng').
Dim ws As Worksheet
Set ws = wb.Worksheets(wsName)
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, LastRowCol).End(xlUp).Row
If LastRow < FirstRow Then
GoTo FirstRowBelowLastRow
End If
Dim rng As Range
Set rng = ws.Range(ws.Cells(FirstRow, LastRowCol), _
ws.Cells(LastRow, LastRowCol))
' Write Source Column Ranges to Source Jagged Array ('Source').
Dim ubcS As Long
ubcS = UBound(srcCols)
Dim Source As Variant
ReDim Source(0 To ubcS)
Dim Data As Variant
Dim j As Long
For j = 0 To ubcS
getOffsetColumn Data, srcCols(j), rng
Source(j) = Data
Next j
' Define Target Jagged Array ('Target').
Dim ubcT As Long
ubcT = UBound(tgtCols)
Dim ubs As Long
ubs = UBound(Source(0))
Dim Target As Variant
ReDim Target(0 To ubcT)
ReDim Data(1 To ubs, 1 To 1)
For j = 0 To ubcT
Target(j) = Data
Next j
' Declare additional variables for the For Next loop.
Dim i As Long
Dim Copied As Long
Dim srcPath As String
Dim tgtPath As String
' Loop through rows of arrays of Source Jagged Array, check folders,
' check files and finally copy if condition is met. At the same time
' write results to arrays of Target Jagged Array.
' The condition to copy is met when source file exists,
' and target file does not.
For i = 1 To ubs
' Folders
srcPath = Source(0)(i, 1)
If Dir(srcPath, vbDirectory) = "" Then
' Source Folder and Source File do not exist.
Target(0)(i, 1) = filMsg(0)
Target(1)(i, 1) = folMsg(0)
GoTo NextRow
End If
' Source Folder exists.
tgtPath = Source(1)(i, 1)
If Dir(tgtPath, vbDirectory) = "" Then
' Target Folder and Target File do not exist.
Target(0)(i, 1) = filMsg(0)
Target(1)(i, 1) = folMsg(0)
GoTo NextRow
End If
' Source Folder and Target Folder exist.
' Files
srcPath = srcPath & PathDelimiter & Source(2)(i, 1)
If Dir(srcPath) = "" Then
' Source File does not exist.
Target(0)(i, 1) = filMsg(0)
Target(1)(i, 1) = folMsg(0)
GoTo NextRow
End If
' Source File exists.
tgtPath = tgtPath & PathDelimiter & Source(3)(i, 1)
If Dir(tgtPath) <> "" Then
' Target File exists.
Target(0)(i, 1) = filMsg(0)
Target(1)(i, 1) = folMsg(2)
GoTo NextRow
End If
' Source File exists and Target File does not.
Target(0)(i, 1) = filMsg(1)
Target(1)(i, 1) = folMsg(1)
' Copy
FileCopy srcPath, tgtPath
' Count files copied.
Copied = Copied + 1
NextRow:
Next i
' Write values (results) from arrays of Target Jagged Array
' to Target Columns.
For j = 0 To ubcT
writeOffsetRange Target(j), tgtCols(j), rng
Next j
' Inform user.
MsgBox "Copied " & Copied & " files.", vbInformation, "Success"
ProcExit:
Exit Sub
FirstRowBelowLastRow:
Debug.Print "'" & ProcName & "': First row below last row."
GoTo ProcExit
clearError:
Debug.Print "'" & ProcName & "': " & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
On Error GoTo 0 ' Turn off error trapping.
GoTo ProcExit
End Sub
Sub getOffsetColumn(ByRef Data As Variant, _
OffsetColumnIndex As Variant, _
ColumnRange As Range)
' Initialize error handling.
Const ProcName As String = "getOffsetColumn"
On Error GoTo clearError ' Turn on error trapping.
Data = Empty
If ColumnRange Is Nothing Then
GoTo NoRange
End If
Dim ws As Worksheet
Set ws = ColumnRange.Worksheet
If ColumnRange.Rows.Count > 1 Then
Data = ColumnRange.Offset(, ws.Columns(OffsetColumnIndex).Column _
- ColumnRange.Column) _
.Value
Else
ReDim Data(1 To 1, 1 To 1)
Data(1, 1) = ColumnRange.Offset(, ws.Columns(OffsetColumnIndex) _
.Column _
- ColumnRange.Column) _
.Value
End If
ProcExit:
Exit Sub
NoRange:
Debug.Print "'" & ProcName & "': No Range."
GoTo ProcExit
clearError:
Debug.Print "'" & ProcName & "': " & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
On Error GoTo 0 ' Turn off error trapping.
GoTo ProcExit
End Sub
Sub writeOffsetRange(Data As Variant, _
OffsetColumnIndex As Variant, _
ColumnRange As Range)
' Initialize error handling.
Const ProcName As String = "writeOffsetColumn"
On Error GoTo clearError ' Turn on error trapping.
If ColumnRange Is Nothing Then
GoTo NoRange
End If
Dim ws As Worksheet
Set ws = ColumnRange.Worksheet
ColumnRange.Offset(, ws.Columns(OffsetColumnIndex).Column _
- ColumnRange.Column).Value = Data
ProcExit:
Exit Sub
NoRange:
Debug.Print "'" & ProcName & "': No Range."
GoTo ProcExit
clearError:
Debug.Print "'" & ProcName & "': " & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
On Error GoTo 0 ' Turn off error trapping.
GoTo ProcExit
End Sub
The Byproduct
' e.g. "C:\Test" is an existing folder, "C:\Test\Test1" is not.
' When you want to create the folder "C:\Test\Test1\Test2", 'MkDir' will return
' "Run-time error '76': Path Not found", because "C:\Test\Test1" does not exist.
' The 'createFolders' function remedies this by creating as many folders
' as needed. In the previous example it first creates "C:\Test\Test1" and
' only then creates "C:\Test\Test1\Test2" in it.
' The function returns 'True' if the folder previously existed or now exists.
' The function returns 'False' if 'PathString' is invalid.
Function createFolders(PathString As String) As Boolean
' Initialize error handling.
Const ProcName As String = "createFolders"
On Error GoTo clearError ' Turn on error trapping.
' Split Path String ('PathString') by System Path Separator ('Delimiter')
' into 1D zero-based Folders Array 'Folders()'.
Dim Delimiter As String
Delimiter = Application.PathSeparator
Dim Folders() As String
Folders = Split(PathString, Delimiter)
' Define Last Subscript ('LastSS') to be considered, because Path String
' could be ending with a System Path Separator.
Dim LastSS As Long
LastSS = UBound(Folders)
If Folders(LastSS) = "" Then
LastSS = LastSS - 1
End If
' Using Folders Array, write paths to Paths Array ('Paths()').
Dim Paths() As String
ReDim Paths(0 To LastSS)
Paths(0) = Folders(0)
Dim j As Long
If LastSS > 0 Then
For j = 1 To LastSS
Paths(j) = Paths(j - 1) & Delimiter & Folders(j)
Next j
End If
' Create each folder if it does not exist.
For j = 0 To LastSS
If Dir(Paths(j), vbDirectory) = "" Then
MkDir Paths(j)
End If
Next j
' Write result.
createFolders = True
ProcExit:
Exit Function
clearError:
Debug.Print "'" & ProcName & "': " & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
On Error GoTo 0 ' Turn off error trapping.
GoTo ProcExit
End Function
Sub testCreateFolders()
Const PathString As String = "C:\Test\Test1\Test2"
Dim Result As Boolean
Result = createFolders(PathString)
If Result Then
MsgBox "If the path previously didn't exist, now it certainly does."
Else
MsgBox "The supplied path is invalid."
End If
End Sub
Sub testMkDir()
Const PathString As String = "C:\Test\Test1\Test2"
MkDir PathString
End Sub

Search for a string and move files containing string from source folder to destination folder

I have large number of .csv files in a folder and each file has few separation codes in them. Separation code usually will be 5 digit code eg: B82A6.
I have to copy files with a certain separation code and move them to a destination folder.
I am new to VBA. I've been searching for code to modify it to my use.
Sub Test()
Dim R As Range, r1 As Range
Dim SourcePath As String, DestPath As String, SeperationCode As String
SourcePath = "C:\Users\hr315e\Downloads\Nov_03_2019\"
DestPath = "C:\Users\hr315e\Downloads\Target\"
Set r1 = Range("A1", Range("A" & Rows.Count).End(xlUp))
For Each R In r1
SeperationCode = Dir(SourcePath & R)
Do While SeperationCode <> ""
If Application.CountIf(r1, SeperationCode) Then
FileCopy SourcePath & SeperationCode, DestPath & SeperationCode
R.Offset(0, 1).Value = SeperationCode
Else
MsgBox "Bad file: " & SeperationCode & " ==>" & SeperationCode & "<== "
End If
SeperationCode = Dir(SourcePath & "B82A6" & R.Value & "B82A6")
Loop
Next
End Sub
So, here's the code that should work for you.
As you can see, this is a version of code which I linked to you with small updates:
Sub GoThroughFilesAndCopy()
Dim BrowseFolder As String, DestinationFolder As String
Dim FileItem As Object
Dim oFolder As Object
Dim FSO As Object
Dim TempFileName As String
Dim CheckCode As String
Application.ScreenUpdating = False
' selecting the folder with files
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Select the folder with files"
.Show
On Error Resume Next
Err.Clear
BrowseFolder = .SelectedItems(1)
If Err.Number <> 0 Then
MsgBox "You didn't select anything!"
Application.ScreenUpdating = True
Exit Sub
End If
On Error GoTo 0
End With
' or you may hardcode it (data from your post):
'BrowseFolder = "C:\Users\hr315e\Downloads\Nov_03_2019\"
' selecting the destination folder
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Select the the destination folder"
.Show
On Error Resume Next
Err.Clear
DestinationFolder = .SelectedItems(1)
If Err.Number <> 0 Then
MsgBox "You didn't select anything!"
Application.ScreenUpdating = True
Exit Sub
End If
On Error GoTo 0
End With
' or you may hardcode it (data from your post):
'DestinationFolder = "C:\Users\hr315e\Downloads\Target\"
CheckCode = "Some string" ' this is you check code
Set FSO = CreateObject("Scripting.FileSystemObject") ' creating filesystem object
Set oFolder = FSO.getfolder(BrowseFolder) ' creating folder object
For Each FileItem In oFolder.Files 'looking through each file in selected forlder
TempFileName = ""
If UCase(FileItem.Name) Like "*.CSV*" Then 'try opening only .csv files
TempFileName = BrowseFolder & Application.PathSeparator & FileItem.Name ' getting the full name of the file (with full path)
If CheckTheFile(TempFileName, CheckCode) Then ' if the file passes the checking function
If Dir(DestinationFolder & Application.PathSeparator & FileItem.Name) = "" Then 'if the file doesn't exist in destination folder
FileCopy Source:=TempFileName, Destination:=DestinationFolder & Application.PathSeparator & FileItem.Name ' it is copied to destination
Else ' otherwise, there are to options how to deal with it further
'uncomment the part you need below:
' this will Overwrite existing file
'FSO.CopyFile Source:=TempFileName, Destination:=DestinationFolder & Application.PathSeparator & FileItem.Name
' this will get new name for file and save it as copy
'FileCopy Source:=TempFileName, Destination:=GetNewDestinationName(FileItem.Name, DestinationFolder)
End If
End If
End If
Next
Application.ScreenUpdating = True
End Sub
'////////////////////////////////////////////////////////////////////////
Function CheckTheFile(File As String, Check As String) As Boolean
Dim TestLine As String
Dim TestCondition As String
TestCondition = "*" & Check & "*" ' this is needed to look for specific text in the file, refer to Like operator fro details
CheckTheFile = False
Open File For Input As #1 ' open file to read it line by line
Do While Not EOF(1)
Line Input #1, TestLine ' put each line of the text to variable to be able to check it
If TestLine Like TestCondition Then ' if the line meets the condition
CheckTheFile = True ' then function gets True value, no need to check other lines as main condition is met
Close #1 ' don't forget to close the file, beacuse it will be still opened in background
Exit Function ' exit the loop and function
End If
Loop
Close #1 ' if condiotion is not found in file just close the file, beacuse it will be still opened in background
End Function
'////////////////////////////////////////////////////////////////////////
Function GetNewDestinationName(File As String, Destination As String) As String
Dim i As Integer: i = 1
Do Until Dir(Destination & Application.PathSeparator & "Copy (" & i & ") " & File) = "" ' if Dir(FilePath) returns "" (empty string) it means that the file does not exists, so can save new file with this name
i = i + 1 ' incrementing counter untill get a unique name
Loop
GetNewDestinationName = Destination & Application.PathSeparator & "Copy (" & i & ") " & File ' return new file name
End Function
Basically, there is one sub, which is mostly copy-paste from linked topic, and two simple functions.

Getting a file, copying that file, then creating a folder, then pasting that file in the created folder

So basically, I need to transfer pdf file from one folder to another. But the source folder contains thousands of pdfs and i need to transfer about 500+ of them in another folder which I should create as well. So it means, I copy "apple" from source then in the destination folder, I'll create a folder named "apple" then paste the copied "apple" file in the created "apple" folder.
Sub transferpdf()
Application.ScreenUpdating = False
Sheets("Stress Log").Activate
r = 3
'Declare Variables
'Do While Cells(r, 3) <> ""
Dim FSO
Dim sFile As String
Dim sSFolder As String
Dim sDFolder As String
Dim foldname As String
Call create_folder
'Name of new folder
'foldname = Cells(r, 1)
'File name to copy
sFile = Cells(r, 3) & "_R" & Cells(r, 4) & ".pdf"
'Source file path
sSFolder = "\\Fdnet.com\ca_projects\CA_LNGC\000_GENERAL\TRANSFER\TO CSA_From Stress - PERMANENT\"
'Destination file path
sDFolder = "C:\Users\vid14865\Desktop\VLM - Sir Earl\3RC430BB VLM - Stress ISOs\" & foldname
'Create Object
Set FSO = CreateObject("Scripting.FileSystemObject")
'Checking If File Is Located in the Source Folder
If Not FSO.FileExists(sSFolder & sFile) Then
MsgBox [sFile] & " Not Found", vbInformation, "Not Found"
'Copying If the Same File is Not Located in the Destination Folder
ElseIf Not FSO.FileExists(sDFolder & sFile) Then
FSO.CopyFile (sSFolder & sFile), sDFolder, True
MsgBox [sFile] & (" Copied Successfully")
Else
MsgBox [sFile] & " Already Exists In The Destination Folder", vbExclamation, "File Already Exists"
End If
'r = r + 1
'Loop
MsgBox "Finished Creating"
End Sub
Sub create_folder()
Sheets("Stress Log").Activate
r = 3
foldname = Cells(r, 1)
MkDir ("C:\Users\vid14865\Desktop\VLM - Sir Earl\3RC430BB VLM - Stress ISOs\" & foldname)
End Sub
This is what I have so far. This creates the folder and copies the file very well, but then the file is not copied in the folder. It's copied outside the created file.

Excel VBA Search in folder and subfolders and returns multiple files

I have to search and copy a number of files in a folder starting from an Excel list like:
8100 ' cell "A2"
8152 ' cell "A3"
8153 ' cell "A4"
in the source folders there are files named like this:
8153.pdf
100_8152.pdf
102_8153.pdf
8153 (2).pdf
How can I find these files and copy ALL the files that matches in a separate folder? The code returns only one file, but I need ALL the files matching the cell value. I need to extend my research in subfolders organized by years too (ie: "D:\myfolder\2015", "D:\myfolder\2016", etc.).
Thanks to user3598756, I'm now using this code:
Option Explicit
Sub cerca()
Dim T As Variant
Dim D As Variant
T = VBA.Format(VBA.Time, "hh.mm.ss")
D = VBA.Format(VBA.Date, "yyyy.MM.dd")
Dim Source As String
Dim Dest As String
Dim Missed As String
Dim fileFound As String
Dim CodiceCS As Variant
Dim cell As Range
Source = "D:\myfolder\"
Dest = "D:\myfolder\research " & D & " " & T
If Dir(Dest, vbDirectory) = "" Then MkDir Dest '<--| create destination folder if not alerady there
With Worksheets("Cerca") '<-- reference your worksheet with pdf names
For Each cell In .Range("A2", .Cells(.Rows.Count, "A").End(xlUp)).SpecialCells(xlCellTypeConstants) '<-- loop through its column "A" cells with "constant" (i.e. not resulting from formulas) values from row 2 down to last non empty one
CodiceCS = VBA.Left((cell.Value), 4)
fileFound = Dir(Source & "\" & CodiceCS & "\*" & cell.Value & "*.Pdf") '<-- look for a source folder file whose name contains the current cell value
If fileFound <> "" Then '<-- if found...
FileCopy Source & "\" & CodiceCS & "\" & fileFound, Dest & "\" & fileFound '<-- ...copy to destination folder
Else '<--otherwise...
Missed = Missed & cell.Value & vbCrLf '<--... update missing files list
End If
Next cell
End With
If Missed <> "" Then '<-- if there's any missing file
Dim FF As Long
FF = FreeFile
Open (Dest & "\" & "MissingFiles.txt") For Output As #FF
Write #FF, VBA.Left(Missed, Len(Missed) - 2)
Close #FF
End If
MsgBox "OK"
Shell "explorer.exe " + Dest, vbNormalFocus
End Sub
This code will place all the file names in the main folder and subfolders into an array. It then looks through the array for matching values.
I've included an extra couple of lines which I've commented out - these are different options you could do within the code.
Public Sub cerca()
Dim DT As String
Dim Source As String
Dim Dest As String
Dim vFiles As Variant
Dim vFile As Variant
Dim rCell As Range
Dim oFSO As Object
Dim FileFound As Boolean
Dim FF As Long
FF = FreeFile
DT = Format(Now, "yyyy.mm.dd hh.mm.ss")
Set oFSO = CreateObject("Scripting.FileSystemObject")
Source = "D:\myfolder\"
Dest = "D:\myfolder\research " & DT
If Dir(Dest, vbDirectory) = "" Then MkDir Dest
'Get the full path name of all PDF files in the source folder and subfolders.
vFiles = EnumerateFiles(Source, "pdf")
With Worksheets("Cerca")
'Look at each cell containing file names.
For Each rCell In .Range("A1", .Cells(.Rows.Count, "A").End(xlUp))
FileFound = False 'Assume the file hasn't been found.
'Check each value in the array of files.
For Each vFile In vFiles
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Use this line if the file name in the sheet exactly match the file name in the array. '
'8152 and 100_8152.pdf are not a match, 8152 and 8152.pdf are a match. '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
If rCell & ".pdf" = FileNameOnly(vFile) Then
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Use this line if the file name in the sheet should appear in the file name in the array. '
'8152 and 100_8152.pdf are a match, 1852 and 8152.pdf are a match. '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'If InStr(FileNameOnly(vFile), rCell.Value) > 0 Then
'If found copy the file over and indicate it was found.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
'This line will use the rcell value to name the file. '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
oFSO.CopyFile vFile, Dest & "\" & rCell & ".pdf"
''''''''''''''''''''''''''''''''''''''
'This line will not rename the file. '
''''''''''''''''''''''''''''''''''''''
'oFSO.CopyFile vFile, Dest & "\" & FileNameOnly(vFile)
FileFound = True
End If
Next vFile
'Any file names that aren't found are appended to the text file.
If Not FileFound Then
Open (Dest & "\" & "MissingFiles.txt") For Append As #FF ' creates the file if it doesn't exist
Print #FF, rCell ' write information at the end of the text file
Close #FF
End If
Next rCell
End With
End Sub
Public Function EnumerateFiles(sDirectory As String, _
Optional sFileSpec As String = "*", _
Optional InclSubFolders As Boolean = True) As Variant
EnumerateFiles = Filter(Split(CreateObject("WScript.Shell").Exec _
("CMD /C DIR """ & sDirectory & "*." & sFileSpec & """ " & _
IIf(InclSubFolders, "/S ", "") & "/B /A:-D").StdOut.ReadAll, vbCrLf), ".")
End Function
Public Function FileNameOnly(ByVal FileNameAndPath As String) As String
FileNameOnly = Mid(FileNameAndPath, InStrRev(FileNameAndPath, "\") + 1, Len(FileNameAndPath))
End Function

Resources