VBA Email Loop for excel reporting - vba

I created a macro that would run a report for a selected indivdual and send that person an email with that package. This report is meant for roughly 20 people, but it has been tedious to run the report for each person and then send it.
I was wondering if there was a way to type names in cells of the people I want to run the report to and have excel loop through each one and send that report to the selected individual and then loop to the next one.
Is this possible, and if so how would I go about creating this macro.
Thank you for your aid

Perhaps you can adjust the code below for your needs. It will send the contents of a textbox on the ActiveSheet to a list of emails in column A. To use it you have to set up your sending email account in Outlook.
Option Explicit
'how to send an email to a list of recipients based on data
'stored in a workbook. The recipient email addresses must
'be in column A, and the body text of the email must be in
'the first text box on the active sheet.
Sub Sample()
Dim olApp As Object, olMailItm As Object, i As Integer, j As Integer
Dim r As Range, s As String, numRows As Integer, numCols As Integer
Dim Dest As Variant, emailAddr As String, txtBox As Shape
'Create the Outlook application and the empty email.
Set olApp = CreateObject("Outlook.Application")
Set olMailItm = olApp.CreateItem(0)
Set txtBox = ActiveSheet.Shapes.AddTextbox(msoTextOrientationHorizontal, _
200, 100, 400, 100)
'.TextFrame.TextRange.Text = "Test Box"
'Using the email, add multiple recipients, using a list of addresses in column A.
Set r = Range("B1")
s = "": numCols = 4: numRows = 4
For j = 1 To numCols
For i = 1 To numRows
If i > 1 Then s = s & vbTab
s = s & r.Offset(j, i)
Next i
s = s & vbCr
Next j
txtBox.TextFrame2.TextRange.Characters.Text = s
With olMailItm
emailAddr = ""
For i = 1 To WorksheetFunction.CountA(Columns(1))
If emailAddr = "" Then
emailAddr = Cells(i, 1).Value
Else
emailAddr = emailAddr & ";" & Cells(i, 1).Value
End If
Next i
'Do additional formatting on the BCC and Subject lines, add the body text from the spreadsheet, and send.
.BCC = emailAddr
.Subject = "FYI"
'.body = txtBox.Text
.body = ActiveSheet.TextBoxes(1).Text
.Send
End With
'Clean up the Outlook application.
Set olMailItm = Nothing
Set olApp = Nothing
End Sub

Related

Export details of categorised emails to Excel

I found the below script online and tried to modify. I would like to check the Color Category instead of flagged emails.
So as an example, it would not check if an email is flagged and then export the details to excel, but it would export all and add a Column 6 about the Category (name) the email is marked.
Here is the code for processing the emails in Outlook
Sub ProcessMailFolders(ByVal objCurrentFolder As Outlook.Folder)
Dim i As Long
Dim objMail As Outlook.MailItem
Dim objFlaggedMail As Outlook.MailItem
Dim nLastRow As Integer
Dim objSubfolder As Outlook.Folder
For i = 1 To objCurrentFolder.Items.Count
If objCurrentFolder.Items(i).Class = olMail Then
'Export the information of each flagged email to Excel
Set objMail = objCurrentFolder.Items(i)
If objMail.IsMarkedAsTask = True And objMail.FlagStatus <> olFlagComplete Then
Set objFlaggedMail = objMail
With objExcelWorksheet
nLastRow = .Range("A" & .Rows.Count).End(xlUp).Row + 1
.Range("A" & nLastRow) = objFlaggedMail.Subject
.Range("B" & nLastRow) = objFlaggedMail.TaskStartDate
.Range("C" & nLastRow) = objFlaggedMail.TaskDueDate
.Range("D" & nLastRow) = objFlaggedMail.SenderName
.Range("E" & nLastRow) = objFlaggedMail.To
End With
End If
End If
Next i
If objCurrentFolder.Folders.Count > 0 Then
For Each objSubfolder In objCurrentFolder.Folders
Call ProcessMailFolders(objSubfolder)
Next
End If
End Sub
The code referring to Excel I was able to modify, but not with checking the categorisation instead of flagged emails.
You need to alter the 'if' statement. Mail Items have a property called categories which returns a string.
Change:
If objMail.IsMarkedAsTask = True And objMail.FlagStatus <> olFlagComplete Then
To:
If objMail.Categories = ***Insert Category Name In Quotes*** Then

Do not ignore duplicate email addresses for VBA

In this code, the script will exclude duplicate email addresses. I want the opposite, as I want to include duplicate email addresses and send them each a separate e-mail. I do not know what part of the code to modify to get the intended result.
'**********You MUST DO THIS FIRST**********
'On the Tools menu, click References.
'In the Available References list, click to select the 'Microsoft Outlook 9.0 Object Library check box. Click OK.
'--- Set up the Outlook objects.
Dim objOutlook As Outlook.Application
Dim objOutlookMsg As Outlook.MailItem
Dim objOutlookRecip As Outlook.Recipient
Dim objOutlookAttach As Outlook.Attachment
Dim body As String
Dim T As Integer
Dim Y As Integer
'--- Declare our global variables to be used in each subroutine.
Dim CustomerAddress As String
Dim CustomerMessage As String
Sub MailItNow()
'--- Declare our variables.
Dim X As Integer
Dim TempCustomerAddress As String
ActiveWorkbook.Sheets("day1").Select
Range("A1").Select
'--- Prevent screen redraws until the macro is finished.
Application.ScreenUpdating = False
'--- Sets which row to start searching for e-mail addresses and names.
X = 2
'--- Begin looping through all the e-mail addresses in column A until
' a blank cell is hit.
While ActiveWorkbook.Sheets("day1").Range("I" & X).Text <> ""
'--- Increment X until a different e-mail address is found.
While TempCustomerAddress = CustomerAddress
X = X + 1
CustomerAddress = ActiveWorkbook.Sheets("day1").Range("I" & X).Text
Wend
'--- Add the e-mail address to a global variable.
CustomerAddress = ActiveWorkbook.Sheets("day1").Range("I" & X - 1).Text
'--- Run the subroutine to send the message.
'--- This is required to prevent a name which does not resolve to
' an e-mail address from hanging the app.
On Error Resume Next
' Create the Outlook session.
Set objOutlook = CreateObject("Outlook.Application")
' Create the message.
Set objOutlookMsg = objOutlook.CreateItemFromTemplate("C:\Users\me\new.oft")
f = ActiveWorkbook.Sheets("day1").Range("B" & X - 1)
g = ActiveWorkbook.Sheets("day1").Range("C" & X - 1)
h = ActiveWorkbook.Sheets("day1").Range("E" & X - 1)
j = ActiveWorkbook.Sheets("day1").Range("D" & X - 1)
k = ActiveWorkbook.Sheets("day1").Range("F" & X - 1)
l = ActiveWorkbook.Sheets("day1").Range("G" & X - 1)
m = ActiveWorkbook.Sheets("day1").Range("H" & X - 1)
n = ActiveWorkbook.Sheets("day1").Range("I" & X - 1)
o = ActiveWorkbook.Sheets("day1").Range("J" & X - 1)
With objOutlookMsg
' Add the To recipient(s) to the message.
Set objOutlookRecip = .Recipients.Add(CustomerAddress)
objOutlookRecip.Type = olTo
.HTMLBody = Replace(.HTMLBody, "Field1", f)
.HTMLBody = Replace(.HTMLBody, "Field2", g)
.HTMLBody = Replace(.HTMLBody, "Field3", h)
.HTMLBody = Replace(.HTMLBody, "Field4", j)
.HTMLBody = Replace(.HTMLBody, "Field5", k)
.HTMLBody = Replace(.HTMLBody, "Field6", l)
.HTMLBody = Replace(.HTMLBody, "Field7", m)
.HTMLBody = Replace(.HTMLBody, "Field8", n)
.HTMLBody = Replace(.HTMLBody, "Field9", o)
.Importance = olImportanceHigh 'High importance
' Add attachments to the message.
If Not IsMissing(AttachmentPath) Then
Set objOutlookAttach = .Attachments.Add(AttachmentPath)
End If
' Resolve each Recipient's name.
For Each objOutlookRecip In .Recipients
objOutlookRecip.Resolve
If Not objOutlookRecip.Resolve Then
Exit Sub
End If
Next
.Send '--- Send the message.
End With
'--- Remove the message and Outlook application from memory.
Set objOutlookMsg = Nothing
Set objOutlook = Nothing
Wend
End Sub
As you can see, there is a need to replace certain information within the e-mail template.
For one, do not loop each cell in your column. This is very inefficient. I would recommend you place in an array, then if you must you can loop that.
Also, while declaring workbook/worksheet/range objects is technically optional, it's far from being recommended that you not do this. For starters, if done correctly (as in using meaningful variable names), this can assist in making your code easier to read.
Sub test()
' For the love of Pete, declare your objects!!
Dim ws As Worksheet, rngI As Range
Set ws = ThisWorkbook.Worksheets("day1")
Set rngI = ws.UsedRange.Columns("I")
' This is your array that contains your emails
Dim emailArr() As Variant, Email As Variant
emailArr = rngI.Value
' Loop through each email and do what you need to do with it
For Each Email In emailArr
Set objOutlook = CreateObject("Outlook.Application")
'everything you do with this email goes here
Next
End Sub

Creating dictionary. Error invalid use of Me keyword

this is my code. I have column C that has duplicate names and column B that has unique IDs I need to find which unique IDs match with what names and send an email to the names and paste the unique IDs in the email. I am getting an error on the first Me.Cells.
Sub sendEmails()
Dim dict_emails As Scripting.dictionary
Set dict_emails = New Scripting.dictionary
Dim objOutlook As Object
Dim objMailMessage As Object
Set objOutlook = CreateObject("Outlook.Application")
Dim row As Range
Dim table As ListObject
Dim row_index As Long
Dim strEmail As String
Dim strExeptionID As String
ActiveWorkbook.Sheets("New 0-30").Select
Set table = ActiveSheet.ListObjects("New_030_Table")
For row_index = 1 To table.DataBodyRange.Rows.Count
strEmail = table.DataBodyRange(row_index, 3).Value
strExceptionID = table.DataBodyRange(row_index, 2).Value
If Not dict_emails.Exists(strEmail) Then
' first time we have seen this name
dict_emails.Add strEmail, strExceptionID
Else
dict_emails(strEmail) = dict_emails(strEmail) & vbCrLf & strExceptionID
End If
Next
Dim var_key As Variant
For Each var_key In dict_emails.Keys
Set objMailMessage = objOutlook.CreateItem(0) ' create new mail
With objMailMessage
.To = "" & var_key
.CC = ""
.BCC = ""
.Subject = "Exceptions Set to Expire in Less Than 30 Days"
.Body = "You have the following exceptions set to expire: " & vbCrLf & dict_emails(var_key)
.Save ' save as draft
End With
Next
End Sub
I was in same issue and I foung solution !!
but anyone will not believe in reference list "Microsoft Scripting Runtime" set priority to top 3rd. and it will start working and error will be gone.

Get cell info from another column in the row

How do I make it so the email address for the recipient name is taken from a different column.
I have the names written out in a column and I want to check the date in the same row for each person and if its 1 month out then send an email to that person. I can only reference one specific cell but I need it for each row as it iterates down the P column.
Sub Workbook_Open()
Dim Cell As Range
Dim objDate As Date
For Each Cell In Range("P3:P4").Cells
If Cell.Value <= Date + 30 Then
'MsgBox "Going to expire in 1 month"
Dim appOutlook As Outlook.Application
Dim mitOutlookMsg As Outlook.MailItem
Dim recOutlookRecip As Outlook.Recipient
' Step 1: Initialize an Outlook session.
Set appOutlook = CreateObject("Outlook.Application")
' Step 2: Create a new message.
Set mitOutlookMsg = appOutlook.CreateItem(olMailItem)
With mitOutlookMsg
' Step3: Add the To recipient(s) to message.
Set recOutlookRecip = .Recipients.Add(Cells(3, 2))
recOutlookRecip.Type = olTo
'Set valid properties like Subject, Body, and Importance of the message.
.Subject = "Test123"
'.Body = "Test"
.BodyFormat = olFormatHTML
.HTMLBody = " TEST EMAIL "
.Importance = olImportanceHigh 'High importance
' Resolve every Recipient's name
For Each recOutlookRecip In .Recipients
recOutlookRecip.Resolve
If Not recOutlookRecip.Resolve Then
mitOutlookMsg.Display
End If
Next
.Send
End With
Set mitOutlookMsg = Nothing
Set appOutlook = Nothing
Else
End If
Next Cell
End Sub
I think what you're looking for is:
Range.Offset(row, col)
For example:
For Each Cell In Range("P3:P4").Cells
'cell.Value refers to P3:P4
myDate = cell.Value
'cell.Offset(0, 1).Value refers to the column one to the right of cell
myName = cell.Offset(0, 1).Value
Next cell

Adding a Cell value into the HTML body of an Email in Excel

I have to order reports on accounts daily and then send an email with all of the reports but it has to be formatted a certain way. I finally made an Excel macro to order the reports but I am trying to make the macro also email the reports. Here is what I have so far.
Sub Email()
Dim OutApp As Object
Dim OutMail As Object
Dim Email As String
Dim ws As Worksheet
Set ws = Worksheets("Data")
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
K = 2
Do While ws.Cells(K, 1) <> ""
ws.Cells(K, 5) = "ACCT:" & ws.Cells(K, 1).Value
K = K + 1
Loop
Email = "Hello, <br><br>" & _
"The following reports were ordered today: <br><br>" & _
"<br> ws.Cells(2, 5) & _
'"<br> ACCT:" & ws.cells(1, 2) & _
"<br><br> Thank you." & _
"<br><br><br> <i> Please note Call if you have any questions </i>" & _
With OutMail
.to = "me#me.com"
.CC = ""
.BCC = ""
.Subject = "Statements Ordered"
.HTMLBody = Email
.Send
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
What I have it do is take the AC numbers that are in the book in column A and then match it with ACCT: so that cells E:E900 have ACCT: 12345.... but I dont know how to add that cell into the HTML body. Below it I have commented out a 2nd way I tried but also failed and that was to try and match the ACCT: & ws.Cells(1,2).
So Question: is there a way to either use an If then statement inside of the HTMLbody or is there a way to add the cell value inside the HTMLbody?