Attach Multiple files via VBA - vba

Can someone please help me edit below script to add multiple files listed on 3rd column (Column C) of the spreadsheet?
My current macro looks for one file at a time and sends out individual emails. I need it to look for multiple files name (in listed folder path) listed in column C (3rd Column) and it does this until it reaches the empty cell.
My current scrip is below where you will see it looks for one file at a time.
Sub AttachandSendEmail()
Dim obMail As Outlook.MailItem
Dim irow As Integer
Dim dpath As String
Dim pfile As String
'file path
dpath = "C:\Users\filelocation"
'looping through all the files and sending an mail
irow = 1
Do While Cells(irow, 3) <> Empty
'pikcing up file name from column C
pfile = Dir(dpath & "\*" & Cells(irow, 3) & "*")
'checking for file exist in a folder and if its a pdf file
If pfile <> "" And Right(pfile, 3) = "pdf" Then
Set obMail = Outlook.CreateItem(olMailItem)
With obMail
.To = "email#comapny.com"
.Subject = "O/S Blanace"
.BodyFormat = olFormatPlain
.Body = "Please see attached files"
.Attachments.Add (dpath & "\" & pfile)
.Send
End With
End If
'go to next file listed on the C column
irow = irow + 1
Loop
End Sub

Try this, it sends one message with all files attached.
Set obMail = Outlook.CreateItem(olMailItem)
With obMail
.To = "email#comapny.com"
.Subject = "O/S Blanace"
.BodyFormat = olFormatPlain
.Body = "Please see attached files"
Do While Cells(irow, 3) <> Empty
'pikcing up file name from column C
pfile = Dir(dpath & "\*" & Cells(irow, 3) & "*")
'checking for file exist in a folder and if its a pdf file
If pfile <> "" And Right(pfile, 3) = "pdf" Then
.Attachments.Add (dpath & "\" & pfile)
End If
'go to next file listed on the C column
irow = irow + 1
Loop
.Send
End With

Related

Wildcard for file path for adding attachments

I want to add attachments from a specific folder. I specified the file's path and two keywords which are fixed.
There are more characters to complete the file path after 'filename2' and before 'pmonth' which are not fixed and hence I need to use wildcard (*).
The code gives
'Couldn't find file'
I have gone through various threads and tried solutions. None works for what I want.
For ctr = 2 To lastrow
filename1 = Cells(ctr, 1).Value
filename2 = Cells(ctr, 3).Value
Set OutMail = OutApp.CreateItemFromTemplate(str_template)
path = "C:\Users\nikunj.v.tripathi\Desktop\" & filename1 & "_" & filename2 & " -" & "*" & pmonth & " " & syear & ".xlsx"
With OutMail
.Attachments.Add path ' <----- this line gives error
.To = Cells(ctr, 10).Value
.cc = Cells(ctr, 11).Value
.htmlbody = Replace(.htmlbody, "#Month#", smonth)
.htmlbody = Replace(.htmlbody, "#CLIENT NAME#", Cells(ctr, 1).Value
.Save
End With
Next ctr
To use the Dir function effectively in this case, you'll need the path and the file name as two separate variables. Assuming you add another variable called filename, you could then utilise the following code...
...
path = "C:\Users\nikunj.v.tripathi\Desktop\"
filename = filename1 & "_" & filename2 & " -" & "*" & pmonth & " " & syear & ".xlsx"
...
filename = Dir(path & filename) ' Dir returns the filename of the first file matching
' the criteria, or returns an empty string if no match.
Do Until filename = ""
.Attachments.Add path & filename
filename = Dir ' Using Dir again returns the next file matching
' the criteria, or returns an empty string if no match.
Loop
Of course - Attachments.Add adds a single attachment and returns the Attachment object. How can it possibly add multiple attachments?
You can use Scripting.FileSystemObject to loop through all files in a folder and add one attachment at a time. See, for example
https://devblogs.microsoft.com/scripting/how-can-i-get-a-list-of-all-the-files-in-a-folder-and-its-subfolders/

Delete files in a folder that are not found in Excel Spreadsheet

I developed a code that loops through files and folders' names found in an Excel Spreadsheet, finds them in a folder and deletes them.
The problem is that there are some files and folders that don't appear on the spreadsheet, but still need to be deleted.
My goal is to have more free space.
Someone suggested i copied the folder list into another column, match the file names and then delete the ones that don't match.
I'd prefer automation, though.
Any suggestions?
Thanks in advance!
Code:
Sub DeleteSpecificFilesAndFolders()
'This module deletes Extracted Files folders, Flat Files folders and Final Flat Files (.txt format)
Const path = "C:\Users\N\Desktop\Kill_function_test\Test folder for deleting\"
Dim r As Range
Dim r2 As Range
Dim folderpath As String
Dim folderpath_1 As String
Dim fso As FileSystemObject
Set fso = New Scripting.FileSystemObject
Set r2 = Cells(2, 1)
Do Until r2 = ""
folderpath = path & r2 & "\" & "Extracted Files"
'Checks if the folder exists and then deletes it.
If fso.FolderExists(folderpath) Then
fso.DeleteFolder (folderpath)
End If
'Checks if the folder exists and then deletes it
folderpath_1 = path & r2 & "\" & "Flat Files"
If fso.FolderExists(folderpath_1) Then
fso.DeleteFolder (folderpath_1)
End If
Set r2 = r2.Offset(1, 0)
DoEvents
Loop
'Loops through and deletes the "INACTIVE" Final Flat Files (.txt)
Set r = Cells(1, 5)
Do Until r = ""
If UCase(r.Value) = "INACTIVE" Then
'Checks if the extracted flat file exists.
If Dir(path & r.Offset(0, -4) & "\" & "Final Flat Files" & "\" & r.Offset(0, 1) & ".txt") <> "" Then
Kill path & r.Offset(0, -4) & "\" & "Final Flat Files" & "\" & r.Offset(0, 1) & ".txt"
End If
End If
Set r = r.Offset(1, 0)
Loop
End Sub
Try the code below. I used the Dir() command/function. This allows you to obtain all the folder/files that exists in a path.
Sub DeleteSpecificFilesAndFolders()
'This module deletes Extracted Files folders, Flat Files folders and Final Flat Files (.txt format)
Const path = "C:\Users\N\Desktop\Kill_function_test\Test folder for deleting\"
Dim r As Range
Dim folderpath As String
Dim folderpath_1 As String
Dim FolderName As String
Dim fso As FileSystemObject
Set fso = New Scripting.FileSystemObject
FolderName=Dir(Path & "*", vbDirectory)
While FolderName <> ""
if Not FolderName like "*.*" then 'This is because when using Dir(,vbdirectory) you can get . and .. or if files exist
folderpath = path & FolderName & "\" & "Extracted Files"
'Checks if the folder exists and then deletes it.
If fso.FolderExists(folderpath) Then
fso.DeleteFolder (folderpath)
End If
'Checks if the folder exists and then deletes it
folderpath_1 = path & FolderName & "\" & "Flat Files"
If fso.FolderExists(folderpath_1) Then
fso.DeleteFolder (folderpath_1)
End If
end if
FolderName=Dir() 'This will set FolderName to the next folder
DoEvents
wend
'Loops through and deletes the "INACTIVE" Final Flat Files (.txt)
Set r = Cells(1, 5)
Do Until r = ""
If UCase(r.Value) = "INACTIVE" Then
'Checks if the extracted flat file exists.
If Dir(path & r.Offset(0, -4) & "\" & "Final Flat Files" & "\" & r.Offset(0, 1) & ".txt") <> "" Then
Kill path & r.Offset(0, -4) & "\" & "Final Flat Files" & "\" & r.Offset(0, 1) & ".txt"
End If
End If
Set r = r.Offset(1, 0)
Loop
End Sub
Hope this helps

Runtime Error - Cannot find this file; verify name & file path correct (Excel / VBA)

Running into error message in title when attempting to link attachments to email. The attachments are stored in Folder Names respective to the "type" of company, which is why I'm attempting to add a for loop to retrieve "type" from spreadsheet.
Sub mailTest()
Dim olApp As Outlook.Application
Dim olMail As Outlook.MailItem
Dim olAttachmentLetter As Outlook.Attachments
Dim fileLocationLetter As String
Dim dType As String
For i = 2 To 3
Set olApp = New Outlook.Application
Set olMail = olApp.CreateItem(olMailItem)
Set olAttachmentLetter = olMail.Attachments
fileLocationLetter = "C:\...\user\Desktop\FileLocation"
letterName = "TestLetter1"
dType = Worksheets("Test1").Cells(i, 2).Value
mailBody = "Hello " _
& Worksheets("Test1").Cells(i, 4) _
& "," _
& Worksheets("BODY").Cells(2, 1).Value _
& Worksheets("BODY").Cells(3, 1).Value _
& Worksheets("BODY").Cells(4, 1).Value & " " & dType _
& Worksheets("BODY").Cells(5, 1).Value & " TTT" & dType & "xx18" _
& Worksheets("BODY").Cells(6, 1).Value _
& Worksheets("BODY").Cells(7, 1).Value
With olMail
.To = Worksheets("Test1").Cells(i, 5).Value
.Subject = Worksheets("Test1").Cells(i, 3).Value & " - "
.HTMLBody = "<!DOCTYPE html><html><head><style>"
.HTMLBody = .HTMLBody & "body{font-family: Calibri, ""Times New Roman"", sans-serif; font-size: 13px}"
.HTMLBody = .HTMLBody & "</style></head><body>"
.HTMLBody = .HTMLBody & mailBody & "</body></html>"
''Adding attachment
.Attachments.Add fileLocationLetter & letterName & ".pdf"
.Display
'' .Send (Once ready to send)
End With
Set olMail = Nothing
Set olApp = Nothing
Next
End Sub
What am I doing wrong here? The file is stored in 'C:...\user\Desktop\FileLocation\TestLetter1.pdf'
Thank you kindly.
You are missing the \ between the fileLocation and the letterName. Thus, either write this:
.Attachments.Add fileLocationLetter & "\" & letterName & ".pdf"
or this:
fileLocationLetter = "C:\...\user\Desktop\FileLocation\"
With much help from #Vityata, figured it out.
Essentially being able to make two attachments, one is static with known file name, the second attachment's name is dependent on stored cell value. The workaround was to break the path/name of the file as stored strings. Maybe there's an easier way, but this worked for me!
Code used:
Sub mailTest()
Dim olApp As Outlook.Application
Dim olMail As Outlook.MailItem
'' Identify Attachments
Dim olAttachmentLetter As Outlook.Attachments
Dim olAttachmentSSH As Outlook.Attachments
'' Identify Attachment Locations / Paths
Dim fileLocationLetter As String
Dim fileLocationSSH As String
Dim fileLocationSSHi As String
Dim fileLocationSSHii As String
'' Type Variable, referencing cell in worksheet where "Type" is stored (in loop below)
Dim dType As String
'' Creating the loop - Replace 4 with end of rows. Will eventually create code to automatically identify the last cell with stored value
For i = 2 To 4
Set olApp = New Outlook.Application
Set olMail = olApp.CreateItem(olMailItem)
Set olAttachmentLetter = olMail.Attachments
Set olAttachmentSSH = olMail.Attachments
''File Location for Letter
fileLocationLetter = "C:\...\Directory"
''File Location for Excel sheet - Need 3 fields as file name is dynamic based on loop value
fileLocationSSH = "C:\...\Directory\Excel Files"
fileLocationSSHi = "Beginning of File name..."
fileLocationSSHii = " ... End of File name"
letterName = "Name of PDF attachment"
dType = Worksheets("Test1").Cells(i, 2).Value
''Body of Email - Each new line represents new value (linking to hidden worksheet in Excel doc)
mailBody = "Hello " _
& Worksheets("Test1").Cells(i, 4) _
& "," _
& Worksheets("BODY").Cells(2, 1).Value _
& Worksheets("BODY").Cells(3, 1).Value _
& Worksheets("BODY").Cells(4, 1).Value & " " & dType _
& Worksheets("BODY").Cells(5, 1).Value _
& Worksheets("BODY").Cells(6, 1).Value _
& Worksheets("BODY").Cells(7, 1).Value
With olMail
.To = Worksheets("Test1").Cells(i, 5).Value
.Subject = Worksheets("Test1").Cells(i, 3).Value
.HTMLBody = "<!DOCTYPE html><html><head><style>"
.HTMLBody = .HTMLBody & "body{font-family: Calibri, ""Times New Roman"", sans-serif; font-size: 13px}"
.HTMLBody = .HTMLBody & "</style></head><body>"
.HTMLBody = .HTMLBody & mailBody & "</body></html>"
'' Adding attachments, referencing file locations and amending file name if needed
.Attachments.Add fileLocationLetter & "\" & letterName & ".pdf"
.Attachments.Add fileLocationSSH & "\" & dType & "\" & fileLocationSSHi & dType & fileLocationSSHii & ".xlsx"
.Display
'' .Send (Once ready to send)
End With
Set olMail = Nothing
Set olApp = Nothing
Next
End Sub

Unable to search/loop through subfolders

Can any one help why I can't pickup file from sub-folders?
My code will locate locate and attach the file to an email if the file is in the main folder, but not if the file is located in sub-folders.
Code Sample:
Set obMail = Outlook.CreateItem(olMailItem)
With obMail
.to = "email#comapny.com"
.Subject = "O/S Blanace"
.BodyFormat = olFormatPlain
.Body = "Please see attached files"
iRow = 24 'initialize row index from 24
Do While Cells(iRow, 1) <> Empty
'picking up file name from column A
pFile = Dir(dPath & "\*" & Cells(iRow, 1) & "*")
'checking for file exist in a folder and if its a pdf file
If pFile <> "" And Right(pFile, 3) = "pdf" Then
.Attachments.Add (dPath & "\" & pFile)
End If
'go to next file listed on the A column
iRow = iRow + 1
Loop
.Send
End With
The Dir function doesn't traverse subfolders. It traverses the path you give it, not the tree structure. It also resets when called so calling recursively is not an option.
So if you pass it "C:\Test\" you can use it to traverse Test; if cell contains "C:\Test\NextTest\", you can use it to iterate over NextTest.
What you can do is use a Collection to hold each directory and explore recursively in that way.
For an example of how to do this see the following from How To Traverse Subdirectories with Dir
Sub TraversePath(path As String)
Dim currentPath As String, directory As Variant
Dim dirCollection As Collection
Set dirCollection = New Collection
currentPath = Dir(path, vbDirectory)
'Explore current directory
Do Until currentPath = vbNullString
Debug.Print currentPath
If Left(currentPath, 1) <> "." And _
(GetAttr(path & currentPath) And vbDirectory) = vbDirectory Then
dirCollection.Add currentPath
End If
currentPath = Dir()
Loop
'Explore subsequent directories
For Each directory In dirCollection
Debug.Print "---SubDirectory: " & directory & "---"
TraversePath path & directory & "\"
Next directory
End Sub
Sub Test()
TraversePath "C:\Root\"
End Sub
You can easily adapt this to suit your purposes.

PDF file seach and sending it through outlook

the below code search for the file in the mentioned folder and send the searched file through outlook. But I need to add few more conditions to it.
It should also mention the count of files found in the folder with the same name > duplicate files< and put the count in excel sheet next to the file name.
The below code only search in a respective folder and not in sub-folders. It should search in sub-folders as well inside the folder for the files.
Sub CheckandSend()
Dim obMail As Outlook.MailItem
Dim irow As Integer
Dim dpath As String
Dim pfile As String
`dpath = "xxxx"
`'' loop through all files and send mail
irow = 1
Do While Cells(irow, 1) <> Empty
'' get file name in column A
pfile = Dir(dpath & "\*" & Cells(irow, 1) & "*")
'' check file exist and pdf file
If pfile <> "" And Right(pfile, 3) = "pdf"
Then
Set obMail = Outlook.CreateItem(olMailItem)
With obMail
.To = "xxx#domain.com"
.Subject = "123"
.BodyFormat = olFormatPlain
.Body = "123"
.Attachments.Add (dpath & "\" & pfile)
.Send
End With
End If
irow = irow + 1
Loop
End sub
You could simplify your code to this, which will search the directory (and sub-directories) for all PDF files using Windows scripting and then send each file found.
This handles your second issue, but I don't understand your first issue as:
a) How can you have identically named files in the same folder?
b) You haven't showed what you have tried yourself so far.
Sub SO()
Const masterFolder As String = "C:\Users\Macro Man\Files"
Dim files, file
files = Filter(Split(CreateObject("WScript.Shell").Exec("CMD /C DIR """ & masterFolder & "\*.pdf"" /S /B /A:-D").StdOut.ReadAll, vbCrLf), ".")
For Each file In files
With Outlook.CreateItem(0)
.To = "xxx#domain.com"
.Subject = "123"
.BodyFormat = olFormatPlain
.Body = "123"
.Attachments.Add CStr(file)
.Send
End With
Next
End Sub