VBA Email unique people based on recordset - vba

I've got the following code I'm using to loop through a recordset and pull names to email. The problem is I want to set this up so it only grabs a person once. If they already exist then I don't want to add them again.
I'm not sure the best way to handle it. I'm assuming maybe a count? but I'm not sure how that would work in this case.
Any help or push in the right direction would be greatly apprecaited!
Set rs = db.OpenRecordset("InSMasterQuery")
With objMail
.To = "<Email#email.com>"
.CC = objOutlookApp.GetNamespace("MAPI").Session.CurrentUser.AddressEntry
With rs
If .EOF And .BOF Then
Else
Merch = ""
Do Until .EOF
Merch = Merch & ";" & ![Merchandiser]
.MoveNext
Loop
objMail.CC = Merch & objOutlookApp.GetNamespace("MAPI").Session.CurrentUser.AddressEntry
objMail.Display
End If
End With
.Subject = "In Season Markdown Request " & strSeason & " From " & Request & ""
.Body = "The following is a In Season Markdown Request from " & Request & " Using Version " & Mid(Cver, 24, 6) & ""
.Attachments.Add myWorkbook.FullName
.Attachments.Add CopyFile.FullName
.Attachments.Add UploadFile.FullName
.Send
End With

Using a Dictionary:
Dim dictMerch As Object, currUsr
'...
'...
Set rs = Db.OpenRecordset("InSMasterQuery")
currUsr = objOutlookApp.GetNamespace("MAPI").Session.CurrentUser.AddressEntry
With objMail
.To = "<Email#email.com>"
.CC = currUsr
With rs
If Not .EOF And Not .BOF Then
Set dictMerch = CreateObject("Scripting.Dictionary")
Merch = ""
Do Until .EOF
dictMerch(.Fields("Merchandiser").Value) = True 'add to dictionary FIXED
.MoveNext
Loop
objMail.CC = Join(dictMerch.Keys, ";") & ";" & currUsr
objMail.Display
End If
End With
.Subject = "In Season Markdown Request " & strSeason & " From " & Request & ""
.Body = "The following is a In Season Markdown Request from " & Request & " Using Version " & Mid(Cver, 24, 6) & ""
.attachments.Add myWorkbook.FullName
.attachments.Add CopyFile.FullName
.attachments.Add UploadFile.FullName
.Send
End With

Related

multiple recipients in email but send mail through loop

For i = LBound(reviewer_names) To UBound(reviewer_names)
reviwer_strg = reviewer_names(i)
assigned_to_strg = assigned_to_names(LBound(assigned_to_names))
For j = 6 To 15
st1 = ThisWorkbook.Sheets("Master").Range("H" & j).Value
If (reviwer_strg = st1) Then
reviewer_email_id = ThisWorkbook.Sheets("Master").Range("I" & j).Value
Set olMail = olApp.CreateItem(olMailItem)
olMail.To = reviewer_email_id
olMail.Recipients.Add (reviewer_email_id)
olMail.Subject = "Task for Review;" & client_name & ";" & title
str1 = "Dear " & reviewer & ", " & "<br>" & "Please see the following for review." & "<br>"
str2 = "Task : " & title & "<br>" & "Client Name : " & client_name & "<br>" & "Due Date : " & due_date & "<br><br>"
str3 = "Document Location : " & "" & document_location & "" & "<br>"
str4 = "Backup Location : " & "" & backup_location & "" & "<br><br>"
str5 = "Awaiting your Feedback." & "<br>" & "Regards, " & "<br>" & assigned_to_strg
olMail.HTMLBody = "<BODY style=font-size:10pt;font-family:Verdana>" & str1 & str2 & str3 & str4 & str5 & "</BODY>"
olMail.Send
End If
Next
Next i
I am sending emails by extracting email-ids from a column in excel, by comparing the names entered in a cell.
Cells from where I am extracting the names.
"Assigned to" and "Reviewer" Columns which is used to compare the names entered in the cells and the names in the columns. from this I am picking up the corresponding email id and sending mail.
The emails that I am sending are through loops. Hence everytime a mail is sent, the olMail.To picks up a single email id, and sends email to all the reviewers it matches in the column. But the recipients shows only the email id of the current recipient. I want to show all the email ids to which the email is sent, but send emails to each reviewer. ( Like mail to multiple addresses). The problem is that if I add all the email ids that are matched, in olMail.To, it gives me an error since it cannot contain more than one email id at a time.
How to do it?
It's a good idea to review the documentation for any procedures you're using with which you aren't completely familiar.
The To property returns or sets a semicolon-delimited String list of display names for the To recipients for the Outlook item. This property contains the display names only. The To property corresponds to the MAPI property PidTagDisplayTo. The Recipients collection should be used to modify this property.
(Source)
The Recipients collection contains a collection of Recipient objects for an Outlook item. Use the Add method to create a new Recipient object and add it to the Recipients object.
(Source)
Example:
ToAddress = "test#test.com"
ToAddress1 = "test1#test.com"
ToAddress2 = "test#test.com"
MessageSubject = "It works!."
Set ol = CreateObject("Outlook.Application")
Set newMail = ol.CreateItem(olMailItem)
newMail.Subject = MessageSubject
newMail.RecipIents.Add(ToAddress)
newMail.RecipIents.Add(ToAddress1)
newMail.RecipIents.Add(ToAddress2)
newMail.Send
(Source)
This is the solution code in case someone needs it :
For i = LBound(reviewer_names) To UBound(reviewer_names) - 1
reviwer_strg = reviewer_names(i)
assigned_to_strg = assigned_to_names(LBound(assigned_to_names))
For j = 6 To 15
st1 = ThisWorkbook.Sheets("Master").Range("H" & j).Value
If (reviwer_strg = st1) Then
reviewer_email_id = ThisWorkbook.Sheets("Master").Range("I" & j).Value
Set olMail = olApp.CreateItem(olMailItem)
olMail.Subject = "Task for Review;" & client_name & ";" & title
str1 = "Dear " & reviewer & ", " & "<br>" & "Please see the following for review." & "<br>"
str2 = "Task : " & title & "<br>" & "Client Name : " & client_name & "<br>" & "Due Date : " & due_date & "<br><br>"
str3 = "Document Location : " & "" & document_location & "" & "<br>"
str4 = "Backup Location : " & "" & backup_location & "" & "<br><br>"
str5 = "Awaiting your Feedback." & "<br>" & "Regards, " & "<br>" & assigned_to_strg
olMail.HTMLBody = "<BODY style=font-size:10pt;font-family:Verdana>" & str1 & str2 & str3 & str4 & str5 & "</BODY>"
For x = LBound(reviewer_names) To UBound(reviewer_names)
recipient_strg = reviewer_names(x)
Debug.Print x & reviewer_names(x)
For y = 6 To 15
st2 = ThisWorkbook.Sheets("Master").Range("H" & y).Value
If (recipient_strg = st2) Then
recipient_email_id = ThisWorkbook.Sheets("Master").Range("I" & y).Value
olMail.Recipients.Add (recipient_email_id)
End If
Next y
Next x
olMail.Send
End If
Next
Next i
MsgBox ("Email has been sent !!!")
End If
Please look at the example below. I think this will do all you want, and more.
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)
The Macro will loop through each row in "Sheet1" and if there is a E-mail address in column B
and file name(s) in column C:Z it will create a mail with this information and send it.
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
See the link below for more details.
https://www.rondebruin.nl/win/s1/outlook/amail6.htm

How to insert an existing signature block into Outlook .htmlbody from Word VBA [duplicate]

This question already has answers here:
How to add default signature in Outlook
(15 answers)
Closed 6 years ago.
I have completed this code to populate the body of an Outlook email, however, I do not know how I can use my existing signature block already created in Outlook. When I create a new, reply or forward email, my signature is there, but when I create the email with this code it does not appear. What I'm trying to accomplish here is to have my signature (or any signature for that matter) appear into the email created by this code.
Private Sub emailbutton_Click()
'No-option email sending
Dim OL As Object
Dim EmailItem As Object
Dim Doc As Document
Application.ScreenUpdating = False
Set OL = CreateObject("Outlook.Application")
Set EmailItem = OL.CreateItem(olMailItem)
Set Doc = ActiveDocument
If VName.Value = "" Then
Doc.SaveAs ("Quotation_Blank 2016")
Else
Doc.SaveAs2 ("QFORM" & "_" & JNumber.Value & "_" & VName.Value)
End If
With EmailItem
.Subject = "QFORM" & "_" & JNumber.Value & "_" & VName.Value
'HTMLbody
msg = "<b><font face=""Times New Roman"" size=""3"" color=""blue"">INTEGRATED ASSEMBLY </font></b><br>" _
& " 1200 Woodruff Rd.<br>" _
& " Suite A12<br>" _
& " Greenville, SC 29607<br><br>" _
& "We have recently released subject project, which will contain assemblies to be outsourced. You have been selected to build these assemblies according to the attachment.<br><br>" _
& "As part of this process, please review the quotion form attached and inidcate your acceptance. If adjustments and-or corrections are required please feel free to contact us for quick resolution.<br><br>" _
& "<b><font face=""Times New Roman"" size=""3"" color=""Red"">NOTE: </font></b>" _
& "The information on attached quotation form is not a contract and only an estimate of predetermined costs per hourly rate for outsource assemblies. <br><br>" _
& "*******For your records you may wish to print out the completed quote form. <br><br>" _
& "Thank you, <br><br>" _
& "<b>HARTNESS INTERNATIONAL </b><br>" _
& "H1 Production Control" & vbNewLine & Signature
.HTMLBody = msg
If VName.Value = "INTEGRATED ASSEMBLY" Then
.To = "XXX.com;"
.CC = "XXX.com;" & "XXX.com;"
.Importance = olImportanceNormal 'Or olImportanceHigh Or olImportanceLow
.Attachments.Add Doc.FullName
.Display
ElseIf VName.Value = "LEWALLEN" Then
.To = "XXX.com;"
.CC = "XXX.com;" & "XXX.com;"
.Importance = olImportanceNormal 'Or olImportanceHigh Or olImportanceLow
.Attachments.Add Doc.FullName
.Display
End If
End With
Application.ScreenUpdating = True
Set Doc = Nothing
Set OL = Nothing
Set EmailItem = Nothing
End Sub
I think you need to call the .HTMLBody again after you insert msg.
So for example:
.HTMLBody = msg & .HTMLBody
Should get the signature. I'm not deep enough into programming to know why though.
Do you have Option Explicit set in your module?
I don't see where you've set Signature or declared it so it's probably empty and not giving you an error message.
I think you need to retrieve it first by pulling in the blank Body
Something like this should work
With EmailItem
.Display
signature = .body
.Subject = "QFORM" & "_" & JNumber.Value & "_" & VName.Value
' and so on ..
`
The code was successful with inputting a with statement to display the EmailItem - along with recalling .HTMLBody following the msg.. Please see full code below.
Private Sub emailbutton_Click()
'No-option email sending
Dim OL As Object
Dim EmailItem As Object
Dim Doc As Document
Application.ScreenUpdating = False
Set OL = CreateObject("Outlook.Application")
Set EmailItem = OL.CreateItem(olMailItem)
Set Doc = ActiveDocument
With EmailItem
.Display
End With
Signature = EmailItem.body
With EmailItem
.Subject = "QFORM" & "_" & JNumber.Value & "_" & VName.Value
'HTMLbody
msg = "<b><font face=""Times New Roman"" size=""4"" color=""blue"">INTEGRATED ASSEMBLY </font></b><br>" _
& " 1200 Woodruff Rd.<br>" _
& " Suite A12<br>" _
& " Greenville, SC 29607<br><br>" _
& "We have recently released subject project, which will contain assemblies to be outsourced. You have been selected to build these assemblies according to the attachment. <br><br>" _
& "As part of this process, please review the quotation form attached and indicate your acceptance. If adjustments and-or corrections are required, please feel free to contact us for quick resolution. <br><br>" _
& "<b><font face=""Times New Roman"" size=""4"" color=""Red"">NOTE: </font></b>" _
& "The information on attached quotation form is not a contract and only an estimate of predetermined costs per hourly rate for outsource assemblies. <br><br>" _
& "*******For your records you may wish to print out the completed quote form. <br><br>" _
& "Thank you, <br><br>" _
& "<b>HARTNESS INTERNATIONAL </b><br>" _
& "H1 Production Control <br>" _
& vbNewLine & Signature
.HTMLBody = msg & .HTMLBody
If VName.Value = "INTEGRATED ASSEMBLY" Then
.To = "ryan#integratedassembly.com;"
.CC = "jfournier#hartness.com;" & "jmarshone#hartness.com;"
.Importance = olImportanceNormal 'Or olImportanceHigh Or olImportanceLow
.Attachments.Add Doc.FullName
.Display
ElseIf VName.Value = "LEWALLEN" Then
.To = "jessica.andrews#patriot-automation.com;"
.CC = "jfournier#hartness.com;" & "jmarshone#hartness.com;"
.Importance = olImportanceNormal 'Or olImportanceHigh Or olImportanceLow
.Attachments.Add Doc.FullName
.Display
End If
End With
If VName.Value = "" Then
Doc.SaveAs ("Quotation_Blank 2016")
Else
Doc.SaveAs2 ("QFORM" & "_" & JNumber.Value & "_" & VName.Value)
End If
Application.ScreenUpdating = True
Set Doc = Nothing
Set OL = Nothing
Set EmailItem = Nothing
End Sub

I want to set up my email reminder on a bi-weekly basis in access

I need help creating some code that will send email reminders once every two weeks. I already have code that send email reminders, but it sends the emails once everyday. That can be very annoying to the users
Here is my vba code from access:
Function GenerateEmail(MySQL As String)
'On Error GoTo Exit_Function:
Dim oOutLook As Outlook.Application
Dim oEmailAddress As MailItem
Dim MyEmpName As String
Dim MyEquip As String
Dim MyModel As String
Dim MyAsset As String
Dim MySerial As String
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset(MySQL)
If rs.RecordCount > 0 Then
rs.MoveFirst
Do Until rs.EOF
If IsNull(rs!EmailAddress) Then
rs.MoveNext
Else
If oOutLook Is Nothing Then
Set oOutLook = New Outlook.Application
End If
Set oEmailAddressItem = oOutLook.CreateItem(olMailItem)
With oEmailAddressItem
MyEmpName = DLookup("EmpName", "Employees", "[EmpID]= " & rs!EmpName)
MyEquip = rs!EquipmentType
MyModel = rs!ModelNo
MyAsset = rs!AssetNo
MySerial = rs!SerialNo
.To = "another#.com;another#.com;another#.com"
.Subject = "Calibration that's due between 1 to 11 months"
.Body = "Calibration ID: " & rs!RecordID & vbCr & _
"Location: " & rs!CalLocation & vbCr & _
"Requirement: " & rs!CalRequirement & vbCr & _
"Employee: " & MyEmpName & vbCr & _
"Name: " & MyEquip & vbCr & _
"Serial No.: " & MySerial & vbCr & _
"Model No.: " & MyModel & vbCr & _
"Asset No.: " & MyAsset & vbCr & _
"Due Date : " & rs!CalUpcomingDate & vbCr & vbCr & _
"This email is auto generated. Please Do Not Replay!"
'MyEmpName = DLookup("EmpName", "Employees", "[EmpID]= " & rs!EmpName)
'.To = rs!EmailAddress
'.Subject = "Task due in between 1st and 11th month reminder for " & MyEmpName
'.Body = "Task ID: " & rs!RecordID & vbCr & _
'"Task Name: " & rs!TaskName & vbCr & _
'"Employees: " & MyEmpName & vbCr & _
' "Task Due: " & rs!CalUpcomingDate & vbCr & vbCr & _
'"This email is auto generated from Task Database. Please Do Not Replay!"
.Display
'.Send
' rs.Edit
' rs!DateEmailSent = Date
' rs.Update
End With
Set oEmailAddressItem = Nothing
Set oOutLook = Nothing
rs.MoveNext
End If
Loop
Else
'do nothing
End If
rs.Close
Exit_Function:
Exit Function
End Function
It looks like you had the right idea once - and #Gustav pointed out the solution.
You first need to uncomment out the lines:
' rs.Edit
' rs!DateEmailSent = Date
' rs.Update
Then change what happens when you process each email address:
Suggested new look of your program:
rs.MoveFirst
Do Until rs.EOF
If Not IsNull(rs!EmailAddress) Then
' Only Send Emails if never been sent before - or past 14 days since last one'
If (IsNull(rs!DateEmailSent)) Or DateDiff("d", rs!DateEmailSent, Date) >= 14 Then
If oOutLook Is Nothing Then
Set oOutLook = New Outlook.Application
End If
Set oEmailAddressItem = oOutLook.CreateItem(olMailItem)
' ... rest of email processing '
' .................... '
.Display
.Send
' Make sure to record that reminder was sent '
rs.Edit
rs!DateEmailSent = Date
rs.Update
' Only do this if this has been set '
Set oEmailAddressItem = Nothing
End If
End If
rs.MoveNext
Loop
' Do this at end '
Set oOutLook = Nothing

Runtime error if contact in Outlook doesn't exist

When I complete a piece of work I email it to certain people. It depends on the work who gets it.
If any person in the list leaves, changes job or has an email change the code will bug out saying
Run Time error -2147467259(80004005), Outlook Does Not Recognise One Or More Names
If I manually copy the email addresses in the list and pop them into Outlook and send I'll get an email back saying the user doesn't exist or has been changed.
I have tried On Error Resume Next and On Error Goto. I have added MS Outlook 14.0 Object Libary, SharePoint Social Provider, Social Provider Extensibility and Outlook View control from the references.
The code bugs out on the .send
Sub EMailer()
Application.ScreenUpdating = False
strfilepath = "\\DFZ70069\Data\199711009\workgroup\Res Plan Team\Performance Management\Specialised Reporting\Debit & Credit Reporting\Masters\Sent Reports\"
strArea = "Recipients" '..........................................................................................
'Get list of recipients for email
For Each cell In Worksheets("EMails").Range(sRange)
If cell.Value = "" Then GoTo Continue
strmaillist = strmaillist & cell.Value + ";"
Continue:
Next
[B1].Value = strmaillist
If bMyEmail = True Then
strmaillist = strmaillist & MyEmailAddress
End If
'Display email list
Dim AckTime As Integer, InfoBox As Object
Set InfoBox = CreateObject("WScript.Shell")
AckTime = 1
Select Case InfoBox.Popup("Sending " & sReportName & " emails to " & vbNewLine & strArea, _
AckTime, "Message Box", 0)
Case 1, -1
End Select
'SEND EMAIL
'set up Body of email............
strbody = "Please find attached " & sReportName & " Report " & " _" & strDate & vbLf & vbLf & _
strComments & vbLf & _
strComments2 & vbLf & _
"" & vbLf & _
eMailName & vbLf & _
"MI & Performance Reporting Team" & vbLf & _
sline2 & vbLf & _
sline3 & vbLf & vbLf & _
sLine4
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.to = strmaillist
.CC = ""
.BCC = ""
.Subject = sReportName & " Report " & strDate
.HTMLBody = "Set to HTML" & vbLf & vbLf & ""
.Body = strbody
.Attachments.Add (strfilepath & sTemplateName)
.send ' bugs out here
End With
Set OutMail = Nothing
Set OutApp = Nothing
ThisWorkbook.Activate
Sheets("Sheet1").Select
Application.ScreenUpdating = True: Application.ScreenUpdating = False
Sheets("Sheet1").Select
Range(sRange2).Value = sConclusion '.
Application.ScreenUpdating = True: Application.ScreenUpdating = False
End Sub
You can try to check the validity of the recipient before sending, by using the .Resolve method of the Recipient object. Only valid recipients can be kept in the Recipient list of the mail item.
You might try this:
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.Subject = sReportName & " Report " & strDate
.HTMLBody = "Set to HTML" & vbLf & vbLf & ""
.Body = strbody
.Attachments.Add (strfilepath & sTemplateName)
For Each cell In Worksheets("EMails").Range(sRange)
If cell.Value <> "" Then
set r = .Recipients.Add(cell.value)
If Not r.Resolve then r.Delete '<~~ Removes invalid recipients
End If
Next
.send
End With

Clear Email Attachment for the next loop

I am trying to send attachments to an email list with the following codes. The emails successfully sent but the second email address will get the attachments together with the attachment of the first email address and so for the third email address will get the first and second's attachments.
My question is: Is there any way to clear the attachment before the attachment actually added? I tried to search but no luck.
Please guide me on this, thank you.
Set rsInvoices = db.OpenRecordset("SELECT * FROM Invoices WHERE InvMonth = " & Month(dtPeriod) & " AND InvYear = " & Year(dtPeriod))
selectQuery = "SELECT Email FROM Student WHERE ID = "
On Error GoTo CloseReportHandler
If Not (rsInvoices.EOF And rsInvoices.BOF) Then
Do Until rsInvoices.EOF = True
DoCmd.OpenReport strReportName, acViewPreview, , "Invoice.SID = " & Chr(34) & rsInvoices!SID & Chr(34) & " AND Invoice.InvYear = " & rsInvoices!InvYear & " AND Invoice.InvMonth = " & rsInvoices!InvMonth
fileName = "Invoice-" & rsInvoices!SID & "-" & rsInvoices!InvYear & "-" & rsInvoices!InvMonth & ".pdf"
selectQuery = selectQuery + rsInvoices!SID
Set rsStudents = db.OpenRecordset("SELECT Email FROM Student WHERE ID = " & Chr(34) & rsInvoices!SID & Chr(34))
studEmail = rsStudents!Email
DoCmd.OutputTo acOutputReport, , acFormatPDF, path + fileName, False
DoCmd.Close acReport, "Invoice"
With cdomsg
.To = studEmail
.From = "xxx#example.com"
.subject = "Test Email"
.TextBody = "Hello"
.AddAttachment path + fileName
Set .Configuration = cdoconf
.Send
End With
MoveNextInvoice:
rsInvoices.MoveNext
Loop
Set cdomsg = Nothing
End If
CloseReportHandler:
Select Case Err
Case 2501
'MsgBox ("here")
Resume MoveNextInvoice
Case Else
MsgBox (Err.Description)
End Select
Set cdomsg = Nothing
'Kill (path + "*.pdf")
rsInvoices.Close
End Sub
You could do one of two things:
Place an .Attachments.DeleteAll statement immediately before the .AddAttachment statement, or
Create the CDO.Message object (Set cdomsg = ...), send it, and Set cdomessage = Nothing all inside the Do Until loop so you use a fresh CDO.Message object for each iteration.