Get cell info from another column in the row - vba

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

Related

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

VBA Email Loop for excel reporting

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

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.

Sending multiple and and different attachments through VBA and Outlook

I'm by no means an expert and I want to send the multiple and different attachments (e.g. Person1 receives BOTH attch.1 and attach.2; Person2 receives attch.3 and attch. 5 etc).
My code:
Sub SendEmail(what_address As String, subject_line As String, mail_body As String)
Dim dlApp As Outlook.Application
Set olApp = CreateObject("Outlook.Application")
Dim olMail As Outlook.MailItem
Set olMail = olApp.CreateItem(olMailItem)
olMail.To = what_address
olMail.Subject = subject_line
olMail.Body = mail_body
olMail.Send
End Sub
Sub SendMassEmail()
Dim mail_body_message As String
Dim title As String
row_number = 1
Do
DoEvents
row_number = row_number + 1
mail_body_message = Sheet1.Range("D2")
title = Sheet1.Range("B" & row_number)
mail_body_message = Replace(mail_body_message, "replace_name_here", title)
Call SendEmail(Sheet1.Range("A" & row_number), "This is a test", mail_body_message)
Loop Until row_number = Sheet1.Cells(Rows.Count, 1).End(xlUp).Row
End Sub
I think your code requires some work but the snippet below should help with adding multiple attachments. I have tried to add annotations that might be helpful.
Please note that the full path for each attachment must be known.
For example:
C:\TestFolder\TestSubfolder\TestFile.txt
You should be able to use the same looping concept to traverse across columns to handle multiple emails. It would be difficult to suggest the exact looping to be used without knowing the structure of your spreadsheet.
Sub GenerateEmails()
Dim OutApp As Object
Dim OutMail As Object
Dim myRange As Range
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = Outlook.Application.CreateItem(olMailItem)
'This will only generate a single email with multiple attachments.
'You will need another loop or something similar to process multiple emails the loop could
'be similar to the loop below that use offset to go down rows but instead
'you will offest across columns
With OutMail
'I have used hard coded cell ranges to define the values but you can use other
'methods.
.Subject = Range("A1").Value
.To = Range("A2").Value
.CC = Range("A3").Value
.Body = Range("A4").Value
'This is where you list of attachments will start
Set myRange = Range("A5")
'Keep going down one cell until no more attachment values are provided
Do Until myRange.Value = ""
'The value here needs to be the full attachment path including file name and extension
.Attachments.Add (myRange.Value)
'Set the range to be the next cell down
Set myRange = myRange.Offset(1, 0)
Loop
'This displays the email without sending.
.Display
'Once the code is correct you can use the .Send instead to actually send the emails.
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub

Send Email To Recipient List Excel

I want to send an automatically from Excel as it is running reports, but I need it to do a VLOOKUP on the client name and select all email addresses that are assigned to that client. Can you help please?
So I will have a table such as below, on a sheet named Client Emails
Company 1 | example#mail.com
Company 1 | example2#mail.com
Company 2 | somebody#somewhere.com
Company 3 | you#here.com
Company 1 | him#there.com
to make it easier to keep up to date. Right now I have the below code which sends the email correctly, but I would like it to pull the addresses from workbook and not the code as it is easier to update this way.
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = "example#mail.com; example2#mail.com"
.CC = ""
.BCC = ""
.Subject = "Subject"
.Body = "Hello World."
.Attachments.Add ("Attachment")
'.Display
.Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
You could set up a loop to look through the table of email address and concatenate the emails of matching companies into a string variable which you then use for the "to" section.
For example (inserted prior to your with statement):
Dim Lastrow as long
dim myemail as string
dim myrange as Range
'counts the number of rows in use
lastrow = Sheets("Client Emails").Cells(Rows.Count, 1).End(xlUp).Row
For Each myrange In Sheets("Client Emails").Range("A2:A" & lastrow)
If myrange = "Company1" then
myEmail = myEmail & myrange.offset(0,1).value & ";"
End if
Next Myrange
You would replace "Company1" in the above to be the name of the company you were currently emailing.
The in your existing code replace:
.To = Email1, Email2,email3, .........
With
.To = myEmail
company = cells(1,2) ' Assign the source cell value of company name like VLOOKUP reference
a = 2
do while cells(a,1)<>""
if company = cells(a,1) then tolist = cells(a,2) 'IF condition matches, To mail list will be assigned to tolist
a = a +1
loop
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = tolist
.CC = ""
.BCC = ""
.Subject = "Subject"
.Body = "Hello World."
.Attachments.Add ("Attachment")
'.Display
.Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing