Send email with attachments VBA - vba

I have been having trouble getting this code to run, the idea is that it picks up every email in column C, and attaches the file path in cell D1.
However it keeps falling over with error
"Run time error 91 - Object variable or With block variable not set".
I have attempted to copy and adapt this code from https://www.rondebruin.nl/win/s1/outlook/amail6.htm
Sub Send_WeeklyUpdatePack()
'Working in Excel 2000-2016
'For Tips see: http://www.rondebruin.nl/win/winmail/Outlook/tips.htm
Dim OutApp As Object
Dim OutMail As Object
Dim sh As Worksheet
Dim cell As Range
Dim FileCell As Range
Dim rng As Range
Dim SourceFile As String
Dim DestinationFile As String
Dim strto As String
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
ThisWorkbook.Sheets("Weekly Update Directory").Range("D1") = ThisWorkbook.Sheets("Automation").Range("D22") 'Picks up correct filepath
Set sh = Sheets("Weekly Update Directory")
Set OutApp = CreateObject("Outlook.Application")
For Each cell In sh.Columns("C").Cells.SpecialCells(xlCellTypeConstants)
If cell.Value Like "?*#?*.?*" Then
strto = strto & cell.Value & ";"
End If
Next cell
If Len(strto) > 0 Then strto = Left(strto, Len(strto) - 1)
'Enter the path/file names in the C:Z column in each row
Set rng = sh.Cells(cell.Row, 1).Range("D1") 'ERROR HERE
If cell.Value Like "?*#?*.?*" And _
Application.WorksheetFunction.CountA(rng) > 0 Then
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = strto
.Subject = "Weekly update pack"
.Body = "Hi all," & vbNewLine & vbNewLine & "Please find attached the updated weekly pack." & vbNewLine & vbNewLine & "Kind Regards," & vbNewLine & vbNewLine & "VBA Noob"
'& cell.Offset(0, -1).Value
For Each FileCell In rng.SpecialCells(xlCellTypeConstants)
If Trim(FileCell) <> "" Then
If Dir(FileCell.Value) <> "" Then
.Attachments.Add FileCell.Value
End If
End If
Next FileCell
.Display 'Or use .Display/.Send
End With
Set OutMail = Nothing
End If
Set OutApp = Nothing
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
End Sub
I'm relatively new to VBA (2 weeks) so an explanation/nudge in the right direction would be greatly appreciated

I amended the code as below and it appears to run, although I am not sure why so any comments to explain what was causing the issue would be greatly apprecaited by myself and future readers.
Sub Send_WeeklyUpdatePack()
'Working in Excel 2000-2016
'For Tips see: http://www.rondebruin.nl/win/winmail/Outlook/tips.htm
Dim OutApp As Object
Dim OutMail As Object
Dim sh As Worksheet
Dim cell As Range
Dim FileCell As Range
Dim rng As Range
Dim SourceFile As String
Dim DestinationFile As String
Dim strto As String
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
ThisWorkbook.Sheets("Weekly Update Directory").Range("D1") = ThisWorkbook.Sheets("Automation").Range("D22")
Set sh = Sheets("Weekly Update Directory")
Set OutApp = CreateObject("Outlook.Application")
For Each cell In sh.Columns("C").Cells.SpecialCells(xlCellTypeConstants)
If cell.Value Like "?*#?*.?*" Then
strto = strto & cell.Value & ";"
End If
Next cell
If Len(strto) > 0 Then strto = Left(strto, Len(strto) - 1)
'Enter the path/file names in the C:Z column in each row
Set rng = ThisWorkbook.Sheets("Weekly Update Directory").Range("D1")
'Set rng = ThisWorkbook.sh.Range("D1")
'If cell.Value Like "?*#?*.?*" And
'Application.WorksheetFunction.CountA(rng) > 0 Then
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = strto
.Subject = "Weekly update pack"
.Body = "Hi all," & vbNewLine & vbNewLine & "Please find attached the updated weekly pack." & vbNewLine & vbNewLine & "Kind Regards," & vbNewLine & vbNewLine & "VBA Noob"
'& cell.Offset(0, -1).Value
For Each FileCell In rng.SpecialCells(xlCellTypeConstants)
If Trim(FileCell) <> "" Then
If Dir(FileCell.Value) <> "" Then
.Attachments.Add FileCell.Value
End If
End If
Next FileCell
.Display 'Or use .Display/.Send
End With
Set OutMail = Nothing
'End If
Set OutApp = Nothing
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
End Sub
thanks

Related

Sending Emails from Excel - No Errors but no Output

I am currently working on a macro that should create an email with variable recipients and details within the body of the email depending on input into the relevant row on the worksheet. It should generate an email per row where 'To do' is present in column P.
I currently have a sub coded with everything I think I need and when I run the macro no errors appear, unfortunately it does not open any template emails as intended either.
I'll admit that my VBA is basic at best but any assistance with the below would be great.
Sub Sendmail()
Dim OutApp As Object
Dim OutMail As Object
Dim cell As Range
Dim ClientEmail As Range
Dim PlannerName As String
Dim Salutation As Range
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
On Error GoTo cleanup
For Each cell In Columns("F").Cells.SpecialCells(xlCellTypeConstants)
If cell.Value = "Planner1 Initials" And _
LCase(Cells(cell.Row, "P").Value) = "To do" Then
Set ClientEmail = LCase(Cells(cell.Row, "H").Value)
PlannerName = "Planner1 Name"
Set Salutation = LCase(Cells(cell.Row, "D").Value)
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "Planner1#email.com"
.Subject = "Annual Review"
.Body = "send email to" & vbNewLine & vbNewLine & _
"Dear" & xClientSaluation & vbNewLine & vbNewLine & _
"body" & vbNewLine & _
"Best wishes" & vbNewLine & vbNewLine & _
"" & PlannerName
.Display
End With
ElseIf cell.Value = "Planner2 Initials" And _
LCase(Cells(cell.Row, "P").Value) = "To do" Then
Set ClientEmail = LCase(Cells(cell.Row, "H").Value)
PlannerName = "Planner2 Name"
Set Salutation = LCase(Cells(cell.Row, "D").Value)
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "Planner2#email.com"
.Subject = "Annual Review"
.Body = "send email to" & vbNewLine & vbNewLine & _
"Dear" & xClientSaluation & vbNewLine & vbNewLine & _
"body" & vbNewLine & _
"Best wishes" & vbNewLine & vbNewLine & _
"" & PlannerName
.Display
End With
ElseIf cell.Value = "Planner3 Initials" And _
LCase(Cells(cell.Row, "P").Value) = "To do" Then
Set ClientEmail = LCase(Cells(cell.Row, "H").Value)
PlannerName = "Planner3 Name"
Set Salutation = LCase(Cells(cell.Row, "D").Value)
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "Planner3#email.com"
.Subject = "Annual Review"
.Body = "send email to" & vbNewLine & vbNewLine & _
"Dear" & xClientSaluation & vbNewLine & vbNewLine & _
"Body " & vbNewLine & _
"Best wishes" & vbNewLine & vbNewLine & _
"" & PlannerName
.Display
End With
End If
Next cell
cleanup:
Set OutApp = Nothing
Application.ScreenUpdating = True
End Sub
Appreciate that you likely don't need to repeat for each different set of initials as I have done above but was struggling to set a range without an object error.
The data held in the worksheet columns for context
F = Client Owner Initials
P = If an email needs to be sent, input either No, To Do, Yes or n/a
D = Client's salutation
Thanks,
BIG TWON
Thanks to Krib below, I am now getting Object required error on the following line, I imagine this will repeat throughout:
Set ClientEmail = LCase(Cells(cell.Row, "H").Value)
I think I can see three issues:
LCase(Cells(cell.Row, "P").Value) = "To do" Then
LCase will be seeing "to do", not "To do" so your main block(s) will never run.
Change them to:
LCase(Cells(cell.Row, "P").Value) = "to do" Then
Also, as per your recent update, the line:
Set ClientEmail = LCase(Cells(cell.Row, "H").Value)
Is trying to load the .Value of a cell into ClientEmail
Unfortunately, you have declared it a Range:
Dim ClientEmail As Range
From the looks of your code, you should be declaring it As String. But remember, you don't Set strings. You just load to them e.g:
ClientEmail = LCase(Cells(cell.Row, "H").Value)
Further to above point, you also do:
Dim Salutation As Range
and
Set Salutation = LCase(Cells(cell.Row, "D").Value)
Which should be:
Dim Salutation As String
and..
Salutation = LCase(Cells(cell.Row, "D").Value)
So to wrap up..
Your declarations should look like this:
Dim OutApp As Object
Dim OutMail As Object
Dim cell As Range
Dim ClientEmail As String
Dim PlannerName As String
Dim Salutation As String
Your IF statement(s) should look like this (change PlannerX each time):
If cell.Value = "Planner1 Initials" And LCase(Cells(cell.Row, "P").Value) = "to do" Then
And your variable settings should look like this (again, change PlannerX each time):
ClientEmail = LCase(Cells(cell.Row, "H").Value)
PlannerName = "Planner1 Name"
Salutation = LCase(Cells(cell.Row, "D").Value)
Maybe this will help you out...
Sub Send_Files()
'Working in Excel 2000-2016
'For Tips see: http://www.rondebruin.nl/win/winmail/Outlook/tips.htm
Dim OutApp As Object
Dim OutMail As Object
Dim sh As Worksheet
Dim cell As Range
Dim FileCell As Range
Dim rng As Range
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set sh = Sheets("Sheet1")
Set OutApp = CreateObject("Outlook.Application")
For Each cell In sh.Columns("B").Cells.SpecialCells(xlCellTypeConstants)
'Enter the path/file names in the C:Z column in each row
Set rng = sh.Cells(cell.Row, 1).Range("C1:Z1")
If cell.Value Like "?*#?*.?*" And _
Application.WorksheetFunction.CountA(rng) > 0 Then
Set OutMail = OutApp.CreateItem(0)
With OutMail
.to = cell.Value
.Subject = "Testfile"
.Body = "Hi " & cell.Offset(0, -1).Value
For Each FileCell In rng.SpecialCells(xlCellTypeConstants)
If Trim(FileCell) <> "" Then
If Dir(FileCell.Value) <> "" Then
.Attachments.Add FileCell.Value
End If
End If
Next FileCell
.Send 'Or use .Display
End With
Set OutMail = Nothing
End If
Next cell
Set OutApp = Nothing
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
End Sub
Make a list in Sheets("Sheet1") with :
In column A : Names of the people
In column B : E-mail addresses
In column C:Z : Filenames like this C:\Data\Book2.xls (don't have to be Excel files)
https://www.rondebruin.nl/win/s1/outlook/amail6.htm

Get data from multiple cells

I'm using VBA code from Ron de Bruin that sends every sheet with an email address to the address in a specified cell. It's meant to send the sheet as an attachment.
I want to get data from multiple cells, to put in the body of the email.
I commented out the parts that send the attachment and sent an email that contained data from one cell in the body of the email.
I cannot get data from multiple cells. The email arrives blank.
Sub Mail_Every_Worksheet()
'Working in Excel 2000-2016
'For Tips see: http://www.rondebruin.nl/win/winmail/Outlook/tips.htm
Dim sh As Worksheet
Dim wb As Workbook
Dim FileExtStr As String
Dim FileFormatNum As Long
Dim TempFilePath As String
Dim TempFileName As String
Dim OutApp As Object
Dim OutMail As Object
TempFilePath = Environ$("temp") & "\"
If Val(Application.Version) < 12 Then
'You use Excel 97-2003
FileExtStr = ".xls": FileFormatNum = -4143
Else
'You use Excel 2007-2016
FileExtStr = ".xlsm": FileFormatNum = 52
End If
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set OutApp = CreateObject("Outlook.Application")
For Each sh In ThisWorkbook.Worksheets
If sh.Range("B1").Value Like "?*#?*.?*" Then
sh.Copy
Set wb = ActiveWorkbook
TempFileName = "Sheet " & sh.Name & " of " _
& ThisWorkbook.Name & " " & Format(Now, "dd-mmm-yy h-mm-ss")
Set OutMail = OutApp.CreateItem(0)
With wb
.SaveAs TempFilePath & TempFileName & FileExtStr, FileFormat:=FileFormatNum
On Error Resume Next
With OutMail
.To = sh.Range("B1").Value
.CC = ""
.BCC = ""
.Subject = "Monthly Shirt Sales"
Dim cell As Range
Dim strbody As String
For Each cell In
ThisWorkbook.Sheets("Sheet1").Range("A4:A36")
strbody = strbody & cell.Value & vbNewLine
Next
'.Attachments.Add wb.FullName
'You can add other files also like this
'.Attachments.Add ("C:\test.txt")
.Send 'or use .Display
End With
On Error GoTo 0
.Close savechanges:=False
End With
Set OutMail = Nothing
Kill TempFilePath & TempFileName & FileExtStr
End If
Next sh
Set OutApp = Nothing
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
It works to send the data from one cell when I replace
Dim cell As Range
Dim strbody As String
For Each cell In ThisWorkbook.Sheets("Sheet1").Range("A4:A36")
strbody = strbody & cell.Value & vbNewLine
Next
with this:
.Body = sh.Range("A4").Value
so I thought that using this would work:
.Body = sh.Range("A4:B36").Value
but it also does not get data and sends a blank email.
How do I get data from multiple cells?
You need to loop through the range and combine the values in the range like in the following example;
Dim strbody As String
For Each cell In sh.Range("A1:B2")
strbody = strbody & cell.Value & vbNewLine
Next cell
Then include the strbody in you outlook with statement
With OutMail
.To = sh.Range("B1").Value
.CC = ""
.BCC = ""
.Subject = "Monthly Shirt Sales"
.Body = strbody
.send 'or use .Display
End With

Send bulk mail using Excel VBA

Was working on a project which will be sending bulk mail to different people if the conditions are met.
Conditions :
Column U contains the final status (Open or WIP) (will not send if Closed no matter if current date is larger)
Column Q contains Closure date. Which when compared to current date, if less then automatic shooting mails to people.
I had tried to do with for loop but its giving shooting 4 mails with same To and CC. And not going to the next row to compare.
Thank you in advance.
Code as below:
Dim rng As Range
Dim OutApp As Object
Dim OutMail As Object
Dim StrBody As String
Dim x As Variant
Dim arr1 As Variant
Dim i As Long, r As Long
On Error Resume Next
arr1 = Worksheets("Data").Range("Q2:Q" & Range("Q" & Rows.Count).End(xlUp).row).Value
i = 1
For Each x In arr1
For r = 1 To 2
If x < Now() Then
If Sheets("Data").Worksheets("Data").Cells(i, "U").Value = "Open" Then
Set rng = Nothing
On Error Resume Next
'Only the visible cells in the selection
Set rng = Selection.SpecialCells(xlCellTypeVisible)
'You can also use a fixed range if you want
Set rng = Sheets("Checklist").Range("A2:B25").SpecialCells(xlCellTypeVisible)
On Error GoTo 0
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
If Worksheets("Data").Cells(i, "C").Value = "Operation_Support" And Worksheets("Data").Cells(i, "E").Value = "Quality_Assurance" Then
StrBody = "Hi," & "<br>" & _
.To = "a"
.CC = "b"
.BCC = ""
.Subject = ""
.HTMLBody = StrBody & RangetoHTML(rng)
.Attachments.Add ActiveWorkbook.FullName
' You can add other files by uncommenting the following line.
'.Attachments.Add ("C:\test.txt")
.Display
'.Send
ElseIf Worksheets("Data").Cells(i, "C").Value = "Operation_Support" And Worksheets("Data").Cells(i, "E").Value = "Analytics" Then
StrBody = "Hi," & "<br>" & _
"PFB the process details which requires your attention." & "<br>" & _
"The review for this process has crossed over due." & "<br>" & _
"Please ask the process owner to review the Process Manuals and Maps." & "<br><br><br>"
.To = "c"
.CC = "d"
.BCC = ""
.Subject = "Process Manual and Maps Review is Overdue"
.HTMLBody = StrBody & RangetoHTML(rng)
.Attachments.Add ActiveWorkbook.FullName
' You can add other files by uncommenting the following line.
'.Attachments.Add ("C:\test.txt")
.Display
'.Send
End If
End With
i = i + 1
Exit For
End If
End If
Next r
On Error GoTo 0
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Set OutMail = Nothing
Set OutApp = Nothing
Next x
End Sub
Solved: This will solve the problem above.
Sub Data_RoundedRectangle1_Click()
Dim OutApp As Object
Dim OutMail As Object
Dim rng As Range
For i = 2 To Cells(Rows.Count, 1).End(xlUp).row
If Cells(i, 21).Value = "Open" And Cells(i, 17).Value <= Now() Then
Set rng = Nothing
On Error Resume Next
'Only the visible cells in the selection
Set rng = Selection.SpecialCells(xlCellTypeVisible)
'You can also use a fixed range if you want
Set rng = Sheets("Data").Range("C1:V5").SpecialCells(xlCellTypeVisible)
On Error GoTo 0
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
If Cells(i, 3).Value = "Operation_Support" And Cells(i, 5).Value = "Quality_Assurance" Then
StrBody = "Hi," & "<br>" & _
"PFB the process details which requires your attention." & "<br>" & _
"The review for this process has crossed overdue." & "<br>" & _
"Please ask the process owner to review the Process Manuals and Maps." & "<br><br><br>"
.To = "a"
.CC = "b"
.BCC = ""
.Subject = ""
.HTMLBody = StrBody & RangetoHTML(rng)
.Attachments.Add ActiveWorkbook.FullName
' You can add other files by uncommenting the following line.
'.Attachments.Add ("C:\test.txt")
.Display
'.Send
ElseIf Cells(i, 3).Value = "Operation_Support" And Cells(i, 5).Value = "Analytics" Then
StrBody = "Hi," & "<br>" & _
"PFB the process details which requires your attention." & "<br>" & _
"The review for this process has crossed over due." & "<br>" & _
"Please ask the process owner to review the Process Manuals and Maps." & "<br><br><br>"
.To = "c"
.CC = "s"
.BCC = ""
.Subject = ""
.HTMLBody = StrBody & RangetoHTML(rng)
.Attachments.Add ActiveWorkbook.FullName
' You can add other files by uncommenting the following line.
'.Attachments.Add ("C:\test.txt")
.Display
'.Send
End If
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End If
Next i
End Sub

VBA code for emailing a selection from the worksheet to a provider

I wrote code that breaks up a report filled with providers into individual reports for each provider then saved them into a folder on my desktop to be emailed to the providers.
Now I'd like to add some code that would automatically email these providers for me but would let me take a look first before being sent. Here's my old code.
Sub VendorSeperate()
Application.DisplayAlerts = False
wb1 = ActiveWorkbook.Name
SaveFolder397 = Format(Now(), "mm.dd.yy hh mm ss AM/PM")
SaveFolder400 = "C:\Users\johndoe\Desktop\Test\" & SaveFolder397
On Error Resume Next
MkDir SaveFolder400
On Error GoTo 0
[A2].Select
ActiveWindow.FreezePanes = True
batchdate = Format(Cells(2, 1), "mm.dd.yy") & " Sent " & Format(Now(), "mm.dd.yy")
LR1 = Columns(1).Find("*", SearchDirection:=xlPrevious).Row
For I = 2 To LR1 + 2
If Cells(I, 1) = "" And Cells(I - 1, 1) <> "" Then
providername = Trim(Cells(I - 1, 7))
ActiveSheet.Copy
Cells.AutoFilter Field:=7, Criteria1:="<>*" & providername & "*", Operator:=xlAnd
Rows("2:" & LR1 + 100).SpecialCells(xlCellTypeVisible).Delete
Cells.AutoFilter
ActiveWindow.ScrollColumn = 1
ActiveWindow.ScrollRow = 1
ActiveWorkbook.SaveAs Filename:=SaveFolder400 & "\JD2.0 " & providername & " Ck Batch Date " & batchdate & ".xlsx", FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
ActiveWorkbook.Close
Workbooks(wb1).Activate
End If
Next I
End Sub
This is a really Simple Code to send an Email with Outlook. Maybe this can Help you.
Sub mail()
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.to = "abc#abc.ch"
.CC = ""
.BCC = ""
.Subject = "Subject line"
.Body = "Email text."
.Attachments.Add ActiveWorkbook.FullName
.Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub

Create mail with text in body

The first part of the code will not create the email ever since I added the strBody line and all.
I got the code from Ron de Bruin's site and added some things to it to adjust it for my needs.
Sub Send_Row()
'For Tips see: http://www.rondebruin.nl/win/winmail/Outlook/tips.htm
'Don't forget to copy the function RangetoHTML in the module.
'Working in Excel 2000-2013
Dim OutApp As Object
Dim OutMail As Object
Dim cell As Range
Dim rng As Range
Dim Ash As Worksheet
Dim StrBody As String
Set Ash = ActiveSheet
On Error GoTo cleanup
Set OutApp = CreateObject("Outlook.Application")
StrBody = "Hello " & cel.Offset(, -1) & "<br>" & "<br>" & _
"We regret to inform you that there was an issue with the January interface file and your elections were not" & "<br>" & _
"processed correctly. In order to rectify this situation, we will issue new logs " & "<br>" & _
"you will not experience a big hit to time:" & "<br>" & "<br>" & _
"Please Check Proposed Adjustment Schedule below" & "<br>" & _
"Please contact ." & "<br>" & "<br>" & _
"Again, our sincere apologies for the mishaps with the interface file and any inconvenience this may have caused you." & "<br><br><br>"
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
For Each cell In Ash.Columns("B").Cells.SpecialCells(xlCellTypeConstants)
If cell.Value Like "?*#?*.?*" _
And LCase(cell.Offset(0, 1).Value) = "yes" Then
'Change the filter range and filter Field if needed
'It will filter on Column B now (mail addresses)
Ash.Range("A1:J200").AutoFilter Field:=2, Criteria1:=cell.Value
With Ash.AutoFilter.Range
On Error Resume Next
Set rng = .SpecialCells(xlCellTypeVisible)
On Error GoTo 0
End With
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = cel.Offset(0, -1).Value
.Subject = "Benefits Deductions"
.HTMLBody = StrBody & RangetoHTML(rng)
.Display 'Or use .Send
End With
On Error GoTo 0
Set OutMail = Nothing
Ash.AutoFilterMode = False
End If
Next cell
cleanup:
Set OutApp = Nothing
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
End Sub
On the first line of the StrBody = ..., you use a variable named cel, which seems to be undefined, this is probably what is throwing your program off.