This question already has answers here:
Sending emails to multiple recipients using VBA
(2 answers)
Closed 6 years ago.
I am very new to VBA. I have an already developed an Excel worksheet wherein I have an additional task as followed:
I need to create an email button and by clicking on that button, the entire worksheet should be mailed to the given recipients, also allowing me to add an attachment.
Hello Aakash Sehgal,
Sendmail()
Dim OutApp As Object
Dim OutMail As Object
Dim cell As Range
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
On Error GoTo cleanup
For Each cell In Columns("B").Cells.SpecialCells(xlCellTypeConstants)
If cell.Value Like "?*#?*.?*" And _
LCase(Cells(cell.Row, "C").Value) = "yes" Then
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = cell.Value
.Subject = "Aakash Sehgal"
.Body = "Dear " & Cells(cell.Row, "A").Value _
& vbNewLine & vbNewLine & _
"Please contact us to discuss bringing " & _
"your account up to date"
'You can add files also by use:
'.Attachments.Add ("C:\test.txt")
.Send 'Or use Display
End With
On Error GoTo 0
Set OutMail = Nothing
End If
Next cell
cleanup:
Set OutApp = Nothing
Application.ScreenUpdating = True
End Sub
Make a list of following columns in ActiveSheet:
In column A : Names of the people
In column B : E-mail addresses
In column C : yes or no ( if the value is yes it will create a mail)
the macro loop through each row on the Activesheet and if there is a E-mail-address in column B and "yes" in column C it will create a mail with a reminder like the one below for each person. If you have duplicate addresses in the column check out this example.
this is one example how you can make it but if you instead want to add manually the smtp is that possible too take a look here:
Sub SMTP_Mail_SEND()
Dim iMsg As Object
Dim iConf As Object
Dim strbody As String
' Dim Flds As Variant
Set iMsg = CreateObject("CDO.Message")
Set iConf = CreateObject("CDO.Configuration")
' iConf.Load -1 ' CDO Source Defaults
' Set Flds = iConf.Fields
' With Flds
' .Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
' .Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") _
' = "Fill in your SMTP server here"
' .Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
' .Update
' End With
strbody = "Hi there" & vbNewLine & vbNewLine & _
"This is line 1" & vbNewLine & _
"This is line 2" & vbNewLine & _
"This is line 3" & vbNewLine & _
"This is line 4"
With iMsg
Set .Configuration = iConf
.To = "test#test.com"
.CC = ""
.BCC = ""
.From = """daniel"" <daniel#test.com>"
.Subject = "This is a mail generated by use manually smtp mail"
.TextBody = strbody
.Send
End With
End Sub
Source:
http://www.rondebruin.nl/win/s1/cdo.htm
Cheers
XsiSec
Related
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
I have an Excel Document in a Template. Users input information and Save As a new genericized number. They then hit a button that auto populates an email to one of 5 people using Vlookup and based on the cost margin.
The file is Save As'd but the e-mail recipient cannot open the file, it reads invalid location. I can close and reopen the new renamed sheet and drag it into an e-mail. I need to link to the newly saved file's name that appears in the email.
Sub Email_created_Workbook()
Dim OutApp As Object
Dim OutMail As Object
Dim Mess As Object, Recip
Recip = [Sheet1!B28].Value & "; " & [Sheet1!B27].Value
Dim strbody As String
If ActiveWorkbook.Path <> "" Then
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "<font size=""3"" face=""Calibri"">" & _
"Hello,<br><br>" & _
"There is a New PO awaiting your approval :<br><B>" & _
ActiveWorkbook.Name & "</B> is created.<br>" & _
"Click on this link to open the file : " & _
"<A HREF=""file://" & ActiveWorkbook.FullName & _
""">Link to Workbook</A>" & _
"<br><br>Regards," & _
"<br><br>Automated Approval System</font>"
On Error Resume Next
With OutMail
.To = Recip
.CC = ""
.BCC = ""
.Subject = ActiveWorkbook.Name
.HTMLBody = strbody
.Display 'or use .Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
Else
MsgBox "The ActiveWorkbook does not have a path, Save the file first."
End If
End Sub
The file name does adapt in my e-mail, from PO Template, but will not open.
I believe this will help you with your current issue (closing and reopening your file before sending). I've removed the the two lines of your code where you set the Outlook objects to Nothing. To reopen the current file you can use the OnTime function like so:
Sub Email_created_Workbook()
Dim OutApp As Object
Dim OutMail As Object
Dim Mess As Object, Recip
Recip = [Sheet1!B28].Value & "; " & [Sheet1!B27].Value
Dim strbody As String
If ActiveWorkbook.Path <> "" Then
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "<font size=""3"" face=""Calibri"">" & _
"Hello,<br><br>" & _
"There is a New PO awaiting your approval :<br><B>" & _
ActiveWorkbook.Name & "</B> is created.<br>" & _
"Click on this link to open the file : " & _
"<A HREF=""file://" & ActiveWorkbook.FullName & _
""">Link to Workbook</A>" & _
"<br><br>Regards," & _
"<br><br>Automated Approval System</font>"
On Error Resume Next
With OutMail
.To = Recip
.CC = ""
.BCC = ""
.Subject = ActiveWorkbook.Name
.HTMLBody = strbody
.Display 'or use .Send
End With
Application.OnTime Now + TimeValue("00:00:10"), "SendEmail"
ThisWorkbook.Close True 'True= yes, save changes
Else
MsgBox "The ActiveWorkbook does not have a path, Save the file first."
End If
End Sub
Sub SendEmail()
Dim OutApp As Object: Set OutApp = GetObject(, "Outlook.Application") 'Grab current instance of Outlook since we already opened the instance prior to restarting Excel
Dim oInspector As OutApp.Inspector: Set oInspector = OutApp.ActiveInspector
Dim NewMail As OutApp.MailItem: Set NewMail = oInspector.CurrentItem 'Grab currently open New/Compose Mail window
NewMail.Send 'Send Email
End Sub
Let me know if this helps resolve your issue.
Using the object "Outlook.Application", I send an e-mail using VBA Access. In the body, I put a string like this:
Email = "Random things" & Chr(13) _
& "More random things" & Chr(13) _
If I show the string Email in a MsgBox it is displayed correctly, but when I send it, the linebreaks are deleted.
I've tried with:
Chr(13)
vbCrLf
vbCr
But all three have the same result:
Try This:
Sub OutlookEmail()
Dim AppOutlook As Outlook.Application
Set AppOutlook = CreateObject("Outlook.application")
Dim Mail As MailItem
Set Mail = AppOutlook.CreateItem(olMailItem)
Dim Email As String
Email = "Random things" & vbNewLine _
& "More random things" & vbNewLine
'Generate Email
Mail.Subject = "Test Subject"
Mail.To = "Test#test.com"
Mail.Body = Email
Mail.Display
Set Mail = Nothing
Set AppOutlook = Nothing
End Sub
Tested it my self appears to work correctly on my PC.
The code below display the email in Outlook. To send, change .Display to .Send
Sub SendDisplayEmail(strEmailFrom As String, strEmailTo As String, strEmailCC As String, strEmailBCC As String, strSubject As String)
Dim OutApp As Object
Dim OutMail As Object
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0) ' olMailItem
Debug.Print ("From: " & strEmailFrom & ", To: " & strEmailTo & ", cc: " & strEmailCC & ", bcc: " & strEmailBCC & ", file: " & xFile)
On Error Resume Next
OutMail
With OutMail
.to = strEmailTo
.CC = strEmailCC
.BCC = strEmailBCC
.Subject = strSubject
'.Body = "Random things" _
' & vbCrLf & vbCrLf & "More random things." _
.BodyFormat = 2 ' olFormatHTML
.HTMLBody = "<html>Random things<br>More random things.</html>"
'.Body = strBody
'.Save
.Display
'.Send 'or use .Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
You can use the HTMLBody (with .BodyFormat = 2) for a nice formated e-mail or .Body for the plain text e-mail. Note that %0D%0A and dont work in HTMLBody because Outlook parse it.
Ok , so, anyone know if it is possible to send an email reminder from excel to outlook automatically every time the excel sheet gets updated? If so, how that part of the macro would look like? I cant find it online anywhere.
The following code seems to work.
Right click on a worksheet and select 'View code'
and select Change event for Worksheet.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "Hi there" & vbNewLine & vbNewLine & _
"This is line 1" & vbNewLine & _
"This is line 2" & vbNewLine & _
"This is line 3" & vbNewLine & _
"This is line 4"
On Error Resume Next
With OutMail
.To = "someone#someemail.com"
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.Body = strbody
'You can add a file like this
'.Attachments.Add ("C:\test.txt")
.Send 'or use .Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
When I send emails they go out from my personal inbox at work, but I need them to go out from another mailbox that I have access to. I have both mailboxes in my outlook.
Can I send emails from a specific mailbox?
Here is the code I am using. It does not find the 2nd item in my account.
Sub Mail_small_Text_Change_Account()
Dim cel As Range
Dim OutApp As Outlook.Application
Dim OutMail As Outlook.MailItem
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(olMailItem)
strbody = "Hi there" & vbNewLine & vbNewLine & _
"This is line 1" & vbNewLine & _
"This is line 2" & vbNewLine & _
"This is line 3" & vbNewLine & _
"This is line 4"
On Error Resume Next
For Each cel In Range(("C2"), Range("C2").End(xlDown))
With OutMail
.To = cel.Value
'.CC = cel.Offset(0, 3).Value
.Subject = "Benefits Refund"
.Body = strbody
.SendUsingAccount = OutApp.Session.Accounts.Item(2)
.Send 'or use .Display
End With
Next
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Yes. Using a POP mail box, you can specify the user name and password for any account.
.To = "E#E.com"
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.Body = "This is the body"
.SendUsingAccount = OutApp.Session.Accounts.Item(1)