Loop to send an email for each row - excel

I can not get Excel to see row three as a separate line of data. My code is adding all the attachments from row three to the email with information generated from row two.
How can I loop through rows 2 to the last row with data?
I am trying to send an email using the information filled in each cell of each row. I am using this current code since it is the only way I can get a signature line to work.
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Sheet1")
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Dim I As Integer
Dim last_row As Integer
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
last_row = Application.WorksheetFunction.CountA(sh.Range("A:A"))
For I = 2 To last_row
.display
.SentOnBehalfOfName = sh.Range("A" & I).Value
.To = sh.Range("B" & I).Value
.CC = sh.Range("C" & I).Value
.Subject = sh.Range("D" & I).Value
.HTMLBody = strbody & "<br>" & .HTMLBody
If sh.Range("F" & I).Value <> "" Then
.attachments.Add sh.Range("F" & I).Value
End If
If sh.Range("G" & I).Value <> "" Then
.attachments.Add sh.Range("G" & I).Value
End If
If sh.Range("H" & I).Value <> "" Then
.attachments.Add sh.Range("H" & I).Value
End If
I don't think the last part of the code is worth much it is just strbody =. I originally wanted the body to be a variable. That presented the problem of not being able to use a signature line.

I think what you had in mind was perhaps as shown below. The code creates an email text, including some snippets from the worksheet, which can then be assigned to the HTMLbody.
Dim Txt As String
Dim Line As String
Dim C As Long
Txt = "Dear Sir," & vbNewLine & vbNewLine & _
"Please take note of the following." & vbNewLine
Line = ""
For C = 6 To 8
With sh.Cells(i, C)
If Len(.Value) Then
If Len(Line) Then Line = Line & ", "
Line = Line & .Value
End If
End With
Next C
If Len(Line) Then Txt = Txt & Line & vbNewLine
Txt = Txt & "Please get back to me ASAP." & vbNewLine & vbNewLine
Txt = Txt & " Regards" & vbNewLine & "John Doe"

Related

Send bulk emails with multiple attachments to multiple recipients

I found this code to send bulk emails to multiple recipients by Outlook with Excel VBA.
What should I add to it to send two attachments not one?
Sub Send_Multiple_Email()
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Sheet3")
Dim oa As Object
Dim msg As Object
Set oa = CreateObject("outlook.Application")
Dim i As Integer
Dim last_row As Integer
last_row = Application.WorksheetFunction.CountA(sh.Range("A:A"))
For i = 2 To last_row
Set msg = oa.createitem(0)
msg.to = sh.Range("A" & i).Value
msg.Subject = sh.Range("B" & i).Value
msg.body = sh.Range("c" & i).Value
If sh.Range("D" & i).Value <> "" Then
msg.attachments.Add sh.Range("D" & i).Value
End If
msg.display
Next i
MsgBox "mails sent"
End Sub
Add information to E2 till the end row and add there what you want to attach like , what is done with D.
And you can add more columns f G H I J K .. with more attachments
If the cell is empty, no attachment is added
If sh.Range("D" & i).Value <> "" Then
msg.attachments.Add sh.Range("D" & i).Value
End If
If sh.Range("E" & i).Value <> "" Then
msg.attachments.Add sh.Range("E" & i).Value
End If
msg.display

Send all Due to date and names in one email

Hello Everyone i was wondering if anyone can help me resolve my problem., i have got code which i found from the net which is working absolutely perfect however only problem is that when there is more than one due date in the column it will send email each time instead of sending all due date and names in One email at same time. Names it is on column A, Expiry Date it is in column E, and email stamp as sent in Column F, below its the code.
Private Sub Workbook_Open()
Dim Email As String, Subj As String, Msg As String, wBox As String
Dim RowNo As Long, i As Long, ky As Variant, cad As Variant
Dim wsEmail As Worksheet, OutApp As Object, OutMail As Object, dic As Object
Set wsEmail = ThisWorkbook.Sheets("Tracker")
Set dic = CreateObject("scripting.dictionary")
With wsEmail
For RowNo = 2 To .Cells(.Rows.Count, "A").End(xlUp).Row
If .Cells(RowNo, "E") <> "" Then
If .Cells(RowNo, "F") = "" And .Cells(RowNo, "E") <> "" And .Cells(RowNo, "E") <= Date + 60 Then
If dic.exists(.Cells(RowNo, "F").Value) Then
dic(.Cells(RowNo, "A").Value) = dic(.Cells(RowNo, "A").Value) & RowNo & "|"
Else
dic(.Cells(RowNo, "A").Value) = RowNo & "|"
End If
End If
End If
Next
For Each ky In dic.keys
cad = Left(dic(ky), Len(dic(ky)) - 1)
cad = Split(cad, "|")
wBox = ""
dBox = ""
For i = 0 To UBound(cad)
wBox = wBox & " " & wsEmail.Cells(cad(i), "A")
dBox = wsEmail.Cells(cad(i), "E")
.Cells(cad(i), "F") = "Sent"
.Cells(cad(i), "G") = Environ("username")
.Cells(cad(i), "H") = "E-mail sent on: " & Now()
Next
On Error Resume Next
Set OutApp = GetObject("Outlook.Application")
On Error GoTo 0
If OutApp Is Nothing Then Set OutApp = CreateObject("Outlook.Application")
Do: Loop Until Not OutApp Is Nothing
Set OutMail = OutApp.CreateItem(0)
With OutMail
Subj = wBox & Space(1) & "from will expire soon"
Msg = "Hi" & vbCrLf & vbCrLf _
& "This is an automated e-mail to let you know that" & wBox & Space(1) & " will expire as follow;" & vbCrLf & vbCrLf _
& "Expiry date:" & dBox & vbCrLf & vbCrLf & "Many Thanks " & vbCrLf _
& vbCrLf & "Kind Regards" & vbCrLf & vbCrLf & Environ("username")
.To = "Sent to"
.CC = ""
.BCC = ""
.Subject = Subj
.ReadReceiptRequested = False
.Body = Msg
.Display
End With
mystring = ("Email has been sent for below staff;") & _
vbCrLf & vbCrLf & ky
MsgBox mystring
Set OutApp = Nothing
Set OutMail = Nothing
Next
End With
End Sub
is there any way to do this?
This should get you started.
Read the code's comments and adjust it to fit your needs.
Private Sub SendEmails()
Dim trackerSheet As Worksheet
Set trackerSheet = ThisWorkbook.Worksheets("CTCTracker")
Dim lastRow As Long
lastRow = trackerSheet.Cells(trackerSheet.Rows.Count, "A").End(xlUp).Row
Dim trackerRange As Range
Set trackerRange = trackerSheet.Range("A5:A" & lastRow)
' Declare boolean to check if there are any expiring names
Dim anyExpiring As Boolean
Dim nameCell As Range
For Each nameCell In trackerRange
' Check: 1) There is a expiring date
' 2) Email not sent yet
' 3) Expiring date less than today + 60 días
If nameCell.Offset(0, 4).Value <> "" And _
nameCell.Offset(0, 5).Value = "" And _
nameCell.Offset(0, 4).Value <= Date + 60 Then
' Store names and expiring dates into array
Dim infoArray() As Variant
Dim counter As Long
ReDim Preserve infoArray(counter)
infoArray(counter) = Array(nameCell.Value, nameCell.Offset(0, 4).Value)
counter = counter + 1
' Stamp action log
nameCell.Offset(0, 5).Value = "Sent"
nameCell.Offset(0, 6).Value = Environ$("username")
nameCell.Offset(0, 7).Value = "E-mail sent on: " & Now()
' To be able to check later
anyExpiring = True
End If
Next nameCell
' Exit if there are not expiring contacts
If Not anyExpiring Then
MsgBox "There are not expiring contacts"
Exit Sub
End If
' Prepare message
Dim namesList As String
For counter = 0 To UBound(infoArray)
namesList = namesList & infoArray(counter)(0) & vbTab & vbTab & " | " & vbTab & vbTab & infoArray(counter)(1) & vbNewLine
Next counter
Dim emailBodyTemplate As String
emailBodyTemplate = "This is an automated e-mail to let you know that the following CTC will expire as follow:" & vbCrLf & vbCrLf & _
"Name" & vbTab & vbTab & vbTab & " | " & vbTab & vbTab & vbTab & " CTC Expiry date" & vbCrLf & _
"<namesList>" & vbCrLf & vbCrLf & _
"Many Thanks " & vbCrLf & _
vbCrLf & "Kind Regards" & vbCrLf & vbCrLf & Environ("username")
Dim emailBody As String
emailBody = Replace(emailBodyTemplate, "<namesList>", namesList)
' Start outlook (late bound)
Dim outApp As Object
On Error Resume Next
Set outApp = GetObject("Outlook.Applicatin")
On Error GoTo 0
' If outlook is not running, start an instance
If outApp Is Nothing Then Set outApp = CreateObject("Outlook.Application")
Do: Loop Until Not outApp Is Nothing
' Compose email
Dim outMail As Object
Set outMail = outApp.CreateItem(0)
With outMail
.To = "Sent to"
.CC = ""
.BCC = ""
.Subject = "CTC will expire soon"
.ReadReceiptRequested = False
.Body = emailBody
.Display
End With
' Display message to user
Dim staffMessage As String
staffMessage = ("Email has been sent for below staff")
MsgBox staffMessage
' Clean up
Set outApp = Nothing
Set outMail = Nothing
End Sub
Let me know if it works

Can values in a column (such as names) be used in an email body string?

My goal: An Excel spreadsheet with VBA code, where
- User ID in Column A is used for the sending address.
- user's first name in Column B is used in the greeting line of the email body.
What I have: I created multiple emails with an email body for each User ID in Column A.
What I cannot figure out: How to use the name from Column B in the email body.
For every email:
Here is the code thus far, asterisks have been used to replace email text.
Sub SendEmail()
Dim i As Integer, Mail_Object, Email_Subject, o As Variant, lr As Long
Dim strbody As String
lr = Cells(Rows.Count, "A").End(xlUp).Row
Set Mail_Object = CreateObject("Outlook.Application")
strbody = "Hello " & vbNewLine & _
"***********************" & vbNewLine & vbNewLine & _
"***********************" & vbNewLine & _
"***********************" & vbNewLine & vbNewLine & _
"***********************" & vbNewLine & _
"***********************" & vbNewLine
For i = 2 To lr
With Mail_Object.CreateItem(o)
.Subject = Range("C2").Value
.To = Range("A" & i).Value
.Body = strbody
.SentOnBehalfOfName = "*****"
'.Send
.display 'disable display and enable send to send automatically
End With
Next i
'MsgBox "E-mail successfully sent", 64
'Application.DisplayAlerts = False
Set Mail_Object = Nothing
End Sub
Just add the value from cell(2,i) to .body in the loop like below
`Sub SendEmail()
Dim i As Integer, Mail_Object, Email_Subject, o As Variant, lr As Long
Dim strbody As String, Strbody1 as String
lr = Cells(Rows.Count, "A").End(xlUp).Row
Set Mail_Object = CreateObject("Outlook.Application")
strbody = "Hello "
strbody1 = vbNewLine & _
"***********************" & vbNewLine & vbNewLine & _
"***********************" & vbNewLine & _
"***********************" & vbNewLine & vbNewLine & _
"***********************" & vbNewLine & _
"***********************" & vbNewLine
For i = 2 To lr
With Mail_Object.CreateItem(o)
.Subject = Range("C2").Value
.To = Range("A" & i).Value
.Body = strbody & Range("B" & i).Value & strbody2
.SentOnBehalfOfName = "*****"
'.Send
.display 'disable display and enable send to send automatically
End With
Next i
'MsgBox "E-mail successfully sent", 64
'Application.DisplayAlerts = False
Set Mail_Object = Nothing
End Sub`
Will give my comment as an answer:
First, do the Excel activities at once, storing what's needed in variables so you're not changing focus back and fourth between Excel/Outlook:
Public toString as String
Private Sub excelActivities()
with thisworkbook.sheets("NAME")
dim lr as long
lr = .Cells(.Rows.Count, "A").End(xlUp).Row
dim i as long
for i = 2 to lr
toString = toString & ";" & .Cells(i,1).Value
next i
end with
End Sub
Then you can use your Excel values, stored as variables, when performing your Outlook activities... could be two separate subroutines called in series:
Sub generateEmail()
excelActivities
outlookActivities
End Sub
Your outlookActivities would include creating the email, adding the .To = toString, etc.

Change Reference Column in Email

I am attempting to adapt the code to use column "J" as the reference column but with little success. I am not sure what I am missing to have the code use column "J" instead of column "A". Everything works as expected, the code just still references column "A" to get the email address to send to.
Sub EmailItems()
'Creates emails, attaches items, and choice to send automatically or have them pop up for your
review. Delete the "'" in front of .Send in order to send automatically
Dim MailDest As String
Dim subj As String
Dim att As Variant
Dim OutLookApp As Object
Dim OutLookMailItem As Object
Dim lastRow As Long
lastRow = ThisWorkbook.Worksheets("Email").Cells(Rows.Count, "J").End(xlUp).Row
For i = 2 To lastRow
Set OutLookApp = CreateObject("Outlook.application")
Set OutLookMailItem = OutLookApp.CreateItem(0)
Set Attach = OutLookMailItem.Attachments
With OutLookMailItem
.SentOnBehalfOfName = [O6]
.To = Cells(i, 1).Value
.Subject = [O5]
.Body = [O7] & vbNewLine & vbNewLine & [O9] & vbNewLine & vbNewLine & [O11] & vbNewLine &
vbNewLine & [O13] & vbNewLine & [O14] & vbNewLine & [O15] & vbNewLine & [O16]
On Error Resume Next
For Each att In Split(Cells(i, 2).Value, ",")
Attach.Add [O2] & att & [O3]
Next
.Display
On Error GoTo 0
'.Send
End With
Next
End Sub
Use the code below:
Sub EmailItems()
'Creates emails, attaches items, and choice to send automatically or have them pop up for your
review. Delete the "'" in front of .Send in order to send automatically
Dim MailDest As String
Dim subj As String
Dim att As Variant
Dim OutLookApp As Object
Dim OutLookMailItem As Object
Dim lastRow As Long
lastRow = ThisWorkbook.Worksheets("Email").Cells(Rows.Count, "J").End(xlUp).Row
For i = 2 To lastRow
Set OutLookApp = CreateObject("Outlook.application")
Set OutLookMailItem = OutLookApp.CreateItem(0)
Set Attach = OutLookMailItem.Attachments
With OutLookMailItem
.SentOnBehalfOfName = [O6]
.To = Cells(i, 10).Value
.Subject = [O5]
.Body = [O7] & vbNewLine & vbNewLine & [O9] & vbNewLine & vbNewLine & [O11] & vbNewLine &
vbNewLine & [O13] & vbNewLine & [O14] & vbNewLine & [O15] & vbNewLine & [O16]
On Error Resume Next
For Each att In Split(Cells(i, 2).Value, ",")
Attach.Add [O2] & att & [O3]
Next
.Display
On Error GoTo 0
'.Send
End With
Next
End Sub

merge email subject and body if recipient email is same

I am using below code to send email from excel when user press the button. it works fine. i actually want to fine tune this because right now what is happening is when in Column C there is a duplicate email and in column N it is all yes separate emails are generated. what i want to do is if there is a duplicate email in column C one email should be generated with subject and body from the duplicate rows
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
'On Error Resume Next
LastRow = Range("C" & Rows.Count).End(xlUp).Row
For Each Cell In Range("C8:C" & LastRow)
If WorksheetFunction.CountIf(Range("C8:C" & Cell.Row), Cell) = 1 Then
If Cells(Cell.Row, 14) = "Yes" Then
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Dear " & Cells(Cell.Row, 2) & vbNewLine & vbNewLine & _
Cells(Cell.Row, 7) & " " & Cells(Cell.Row, 6) & vbNewLine & _
"were issue to you for project " & Cells(Cell.Row, 8) & vbNewLine & vbNewLine & vbNewLine & vbNewLine & _
"This is a system generated email and doesn't require signature"
On Error Resume Next
With xOutMail
.To = Cells(Cell.Row, 3)
.CC = Cells(Cell.Row, 5)
.BCC = ""
.Subject = Cells(Cell.Row, 7) & " " & Cells(Cell.Row, 6) & " Issued to " & Cells(Cell.Row, 4)
.Body = xMailBody
'.Attachments.Add ActiveWorkbook.FullName
.Display
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End If
End If
Next Cell
You can try:
Option Explicit
Public Sub Get_Unique_Count_Paste_Array()
Dim Ob As Object
Dim rng As Range
Dim LR As Long
Dim str As String
With Worksheets("Sheet1")
LR = .Range("C" & Rows.Count).End(xlUp).Row
Set Ob = CreateObject("scripting.dictionary")
For Each rng In .Range("C8:C" & LR)
str = Trim(rng.Value)
If Len(str) > 0 Then
Ob(str) = Ob(str) + 1
If Ob(str) = 1 Then '<= Check how many times email address appears in the array & if it s appears only one time then..
MsgBox str '<= Insert your code here
End If
End If
Next rng
End With
End Sub

Resources