Email Body Loop Values - excel

I am attempting to loop through a column (n=96) in my worksheet, when it comes across a value <10 I would like the macro to open outlook and email offset values (four columns across) from the values it found.
I've generated a working example though it seems to be limited to only one example I've tested. I think I am approaching it from the wrong angle.
Sub SendReminderMail()
Dim p As Long
Dim OutLookApp As Object
Dim OutLookMailItem As Object
Dim iCounter As Integer
Dim MailDest As String
'If MsgBox("Are you sure?", vbYesNo) = vbNo Then Exit Sub
Set OutLookApp = CreateObject("Outlook.application")
Set OutLookMailItem = OutLookApp.CreateItem(0)
p = 2
Do Until Trim$(Cells(p, 1).Value) = ""
If Cells(p, 1).Value <= 10 Then
Set OutLookMailItem = OutLookApp.CreateItem(0)
With OutLookMailItem
.To = "Emailaddress etc"
.Subject = "Reminder: " & Cells(1, 7).Value
.Body = Cells(p, 1).Offset(0, 4).Value
.Display
End With
End If
p = p + 1
Loop
End Sub
How do I set it up to loop through all the <10 values and tell it to paste the offset values into the body of the email?

I think that you need to split this into two blocks of code.
First block would iterate through rows, check criteria and, if needed, call the second one, so the mail sending Sub, passing by necessary parameters.
Someting similar to the below code:
Sub SendReminderMail(ByVal MailSubject As String, mailBody As String)
Dim p As Long
Dim OutLookApp As Object
Dim OutLookMailItem As Object
Dim iCounter As Integer
Dim MailDest As String
'If MsgBox("Are you sure?", vbYesNo) = vbNo Then Exit Sub
Set OutLookApp = CreateObject("Outlook.application")
Set OutLookMailItem = OutLookApp.CreateItem(0)
Set OutLookMailItem = OutLookApp.CreateItem(0)
With OutLookMailItem
.To = "Emailaddress etc"
.Subject = MailSubject
.Body = mailBody
.Display
End With
End Sub
Sub IterateThroughRows()
Dim p As Integer
Dim Sht As Worksheet
Dim MailSubject As String
Dim mailBody As String
Set Sht = ThisWorkbook.Sheets("SheetName")
p = 2
Do Until Sht.Cells(p, 1).Value = ""
If Cells(p, 1).Value <= 10 Then
mailBody = mailBody + " | " + Sht.Cells(p, 1).Offset(0, 4).Value
End If
p = p + 1
Loop
Call SendReminderMail(MailSubject, mailBody)
MailSubject = "Reminder: " & Sht.Cells(1, 7).Value
End Sub

Related

How to copy text from a textbox in excel to paste it into an email. VBA

I'm trying to improve the macro for sending files to clients.
Everything was fine until the boss decided that the email text should be left in the correct format. Previously, the macro took the text from a cell. I am now trying to change this so that the email text retains the format. Highlights, hyperlinks etc.
I have changed the original macro several times according to what I found on the internet but I keep getting an error. Unfortunately I am just starting with VBA and I am already lost here.
I would be very grateful for your help.
Keep the format of a text box in excel and insert it in an email body
enter image description here
enter image description here
Sub Mail()
Dim wb As Workbook
Dim OutApp As Object
Dim OutMail As Object
Dim olInsp As Object
Dim xlSheet As Worksheet
Dim wdDoc As Object
Dim oRng As Object
Set wb = Workbooks("BankDetails.xlsm")
Set ws = wb.Sheets("MessageBody")
Set ws1 = wb.Sheets("Data")
Set ws2 = wb.Sheets("Batch")
Set xlSheet = ActiveWorkbook.Sheets("MessageBody")
xlSheet.TextBoxes("TextBox 1").Copy
Dim i As Long
Dim i2 As Long 'For the number of passes (?)
lastRow = ws2.Cells(ws2.Rows.Count, "A").End(xlUp).Row
For i = 2 To lastRow
klient = ws2.Cells(i, "A")
zalacznik1 = ws.Cells(4, "B") & ws.Cells(5, "B")
zalacznik2 = ws.Cells(4, "B") & ws.Cells(6, "B")
zalacznik3 = ws.Cells(4, "B") & ws.Cells(7, "B")
Set OutApp = CreateObject("Outlook.Application")
'Create Item Outlook Element
Set OutMail = OutApp.CreateItem(0)
With OutMail
'Sender e-mail address
.SentOnBehalfOfName = ws.Cells(1, "B")
'E-mail address of the recipient, can also be several with ; separate
'.To = ws2.Cells(i, "B")
.BodyFormat = 3
.BCC = ws2.Cells(i, "B")
'from column C
.Subject = ws2.Cells(i, "C")
'The text to send in column D
'Maximum 1024 characters
'The text is accepted without formatting
'.body = body
'Add attachements w. reference to column B in sheets1 / MessageBody
.Attachments.Add (zalacznik1)
.Attachments.Add (zalacznik2)
.Attachments.Add (zalacznik3)
Set olInsp = .GetInspector
Set wdDoc = olInsp.WordEditor
Set oRng = wdDoc.TextBoxes
oRng.collapse 1
oRng.Paste
'Here the mail is displayed
.Display
'Here the e-mail is immediately placed in the outbox
'.Send
End With
'Empty object variables
Set OutApp = Nothing 'CreateObject("Outlook.Application")
Set OutMail = Nothing 'OutApp.CreateItem(0)
Set olInsp = Nothing
Set wdDoc = Nothing
Set oRng = Nothing
'Turn on pause
'Outlook can't process the orders quickly enough, hence the pause
Application.Wait (Now + TimeValue("0:00:02"))
' ws2.Cells(i, "D") = "Done"
ws2.Cells(i, "D").Value = "Done, " & Now()
Next i
End Sub
By using the WordEditor you have access to a big part of MS Words Object model, including it's Range object, so you can use its PasteSpecial method.
In the below code I also made a few other minor changes such as taking the Outlook.Application object out of the loop (why would you open and close Outlook every time?) and using the existing Outlook.Application object if it's already open.
Sub Mail()
Dim wb As Workbook
Dim OutApp As Object
Dim OutMail As Object
Dim xlSheet As Worksheet
Dim wdDoc As Object
Dim oRng As Object
Set wb = Workbooks("BankDetails.xlsm")
Set ws = wb.Sheets("MessageBody")
Set ws1 = wb.Sheets("Data")
Set ws2 = wb.Sheets("Batch")
Set xlSheet = ActiveWorkbook.Sheets("MessageBody")
xlSheet.TextBoxes("TextBox 1").Copy
Dim i As Long
Dim i2 As Long 'For the number of passes (?)
lastRow = ws2.Cells(ws2.Rows.Count, "A").End(xlUp).Row
On Error Resume Next
Set outApp = GetObject(, "Outlook.Application")
On Error GoTo 0
If outApp Is Nothing Then
Set outApp = CreateObject("Outlook.Application")
End If
For i = 2 To lastRow
klient = ws2.Cells(i, "A")
zalacznik1 = ws.Cells(4, "B") & ws.Cells(5, "B")
zalacznik2 = ws.Cells(4, "B") & ws.Cells(6, "B")
zalacznik3 = ws.Cells(4, "B") & ws.Cells(7, "B")
'Create Item Outlook Element
Set OutMail = OutApp.CreateItem(0)
With OutMail
'Sender e-mail address
.SentOnBehalfOfName = ws.Cells(1, "B")
'E-mail address of the recipient, can also be several with ; separate
'.To = ws2.Cells(i, "B")
.BodyFormat = 3
.BCC = ws2.Cells(i, "B")
'from column C
.Subject = ws2.Cells(i, "C")
.Display 'Needs to be displayed before opening Word Inspector
Set wdDoc = .GetInspector.WordEditor
'The text to send in column D
'Maximum 1024 characters
ws2.Cells(i, "D").Copy
wdDoc.Paragraphs.first.Range.PasteSpecial 16 'wdFormatOriginalFormatting
'.body = body
'Add attachements w. reference to column B in sheets1 / MessageBody
.Attachments.Add zalacznik1
.Attachments.Add zalacznik2
.Attachments.Add zalacznik3
' Set oRng = wdDoc.TextBoxes
' oRng.collapse 1
' oRng.Paste
'Here the e-mail is immediately placed in the outbox
'.Send
End With
'Empty object variables
Set OutMail = Nothing 'OutApp.CreateItem(0)
Set olInsp = Nothing
Set wdDoc = Nothing
Set oRng = Nothing
'Turn on pause
'Outlook can't process the orders quickly enough, hence the pause
Application.Wait (Now + TimeValue("0:00:02"))
' ws2.Cells(i, "D") = "Done"
ws2.Cells(i, "D").Value = "Done, " & Now()
Next i
End Sub

Is there a function to skip outfiltered rows when running a code in VBA?

I have developed a template with which I can automate invoice reminders by outputting emails. Currently the code loops through the list outputting an email for each individual row (= each individual invoice). I would like to update the code so that it skips outfiltered rows in the excel doc to make it more efficient and easier in use.
My code is as follows:
Sub Send_email_fromtemplate()
Dim edress As String
Dim cc1, cc2, cc3 As String
Dim group As String
Dim number As String
Dim outlookapp As Object
Dim outlookmailitem As Object
Dim r As Long
Dim olInsp As Object
Dim wdDoc As Object
Dim oRng As Object
r = 3
Do While Sheet1.Cells(r, 1) <> ""
Set outlookapp = CreateObject("Outlook.Application")
'call your template
Set outlookmailitem = outlookapp.CreateItemFromTemplate([location])
outlookmailitem.Display
edress = Sheet1.Cells(r, 7)
cc1 = Sheet1.Cells(r, 8)
cc2 = Sheet1.Cells(r, 9)
cc3 = Sheet1.Cells(r, 10)
group = Sheet1.Cells(r, 4)
number = Sheet1.Cells(r, 3).Value
With outlookmailitem
.To = edress
.cc = cc1 & ";" & cc2 & ";" & cc3
.bcc = ""
.Subject = "First invoice reminder " & group
Set olInsp = .GetInspector
Set wdDoc = olInsp.WordEditor
Set oRng = wdDoc.Range
With oRng.Find
Do While .Execute(FindText:="{{Number}}")
oRng.Text = number
Exit Do
Loop
End With
Set xInspect = outlookmailitem.GetInspector
.Display
'.send
End With
'clear your email address
edress = ""
r = r + 1
Loop
'clear your fields
Set outlookapp = Nothing
Set outlookmailitem = Nothing
Set wdDoc = Nothing
Set oRng = Nothing
End Sub
I've tried to solve the problem using a Range function and ActiveSheet.UsedRange.SpecialCells(xlCellTypeVisible), but as the template will be filled with a variable number of rows (each time I send reminders) this is causing troubles, as the range differs each time.
Please, try the next updated code. As I said in my above comment, it is able to calculate the last row on A:A, then create a range from visible rows of the filtered area and iterate between its rows:
Sub Send_email_fromtemplate()
Dim edress As String, cc1 As String, cc2 As String, cc3 As String
Dim group As String, number As String
Dim outlookapp As Object, outlookmailitem As Object, olInsp As Object
Dim wdDoc As Object, xInspect As Object
Dim oRng As Object, lastR As Long, rngVis As Range, r As Range
lastR = Sheet1.Range("A" & Sheet1.rows.count).End(xlUp).row 'last row on A:A
On Error Resume Next 'this is necessary in case of no any filtered visible cell
Set rngVis = Sheet1.Range("A3:J" & lastR).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If rngVis Is Nothing Then MsgBox "No visible filtered values in the necessary range...": Exit Sub
Set outlookapp = CreateObject("Outlook.Application") 'you should set it only ones, outside of the iteration...
For Each r In rngVis.rows 'iterate between the discontinuous (visible cells) rows
'call your template
Set outlookmailitem = outlookapp.CreateItemFromTemplate([Location])
outlookmailitem.Display
edress = r.cells(1, 7) 'extract the necessary values from the iterated row
cc1 = r.cells(1, 8)
cc2 = r.cells(1, 9)
cc3 = r.cells(1, 10)
group = r.cells(1, 4)
number = r.cells(1, 3).Value
With outlookmailitem
.To = edress
.cc = cc1 & ";" & cc2 & ";" & cc3
.BCC = ""
.Subject = "First invoice reminder " & group
Set olInsp = .GetInspector
Set wdDoc = olInsp.WordEditor
Set oRng = wdDoc.Range
With oRng.Find
Do While .Execute(FindText:="{{Number}}")
oRng.Text = number
Exit Do
Loop
End With
Set xInspect = outlookmailitem.GetInspector
.Display
'.send
End With
'clear your email address
edress = ""
Next r
'clear memory of used objects:
Set outlookapp = Nothing: Set outlookmailitem = Nothing
Set wdDoc = Nothing: Set oRng = Nothing
End Sub
Please, send some feedback after testing it.

Sending multiple emails using data from excel cells using VBA

I've got a spreadsheet of clients with their client name, email address, contact and admin listed.
I want to be able to send an individual email to each client using the data from the rows that the client is listed.
I've got some VBA that I've written (parts obtained from other people) but it's trying to add all the email addresses to the to field and every other field is pulling all the data instead of the relevant row.
I'm fairly new to this VBA stuff and would greatly appreciate some help.
How can I make it draft individual emails per client with the information from just the row the client is listed.
Example data:
Column B has client names from row 3 down
Column C has email addresses from row 3 down
Column E has contact name from row 3 down
Column G has admin name from row 3 down
Here's the VBA:
Option Explicit
Sub AlexsEmailSender()
Dim OutApp As Object
Dim OutMail As Object
Dim lngLastRow As Long
Dim rngMyCell As Range
Dim objEmailTo As Object
Dim strEmailTo As String
Dim objCCTo As Object
Dim strCCTo As String
Dim objContact As Object
Dim strContact As String
Dim objAdmin As Object
Dim strAdmin As String
Dim strbody As String
Dim objClient As Object
Dim strClient As String
Dim strToday As Date
strToday = Date
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'Make sure emails are unique
Set objEmailTo = CreateObject("Scripting.Dictionary")
lngLastRow = Worksheets("Sheet1").Cells(Rows.Count, "C").End(xlUp).Row
For Each rngMyCell In Worksheets("Sheet1").Range("C3:C" & lngLastRow)
If Len(rngMyCell) > 0 Then
If objEmailTo.Exists(CStr(rngMyCell)) = False Then
objEmailTo.Add CStr(rngMyCell), rngMyCell
End If
End If
Next rngMyCell
strEmailTo = Join(WorksheetFunction.Transpose(WorksheetFunction.Transpose(objEmailTo.Items)), ";")
'Make sure cc emails are unique
Set objCCTo = CreateObject("Scripting.Dictionary")
lngLastRow = Worksheets("Sheet1").Cells(Rows.Count, "D").End(xlUp).Row
For Each rngMyCell In Worksheets("Sheet1").Range("D3:D" & lngLastRow)
If Len(rngMyCell) > 0 Then
If objCCTo.Exists(CStr(rngMyCell)) = False Then
objCCTo.Add CStr(rngMyCell), rngMyCell
End If
End If
Next rngMyCell
strCCTo = Join(WorksheetFunction.Transpose(WorksheetFunction.Transpose(objCCTo.Items)), ";")
'Make sure contacts are unique
Set objContact = CreateObject("Scripting.Dictionary")
lngLastRow = Worksheets("Sheet1").Cells(Rows.Count, "E").End(xlUp).Row
For Each rngMyCell In Worksheets("Sheet1").Range("E3:E" & lngLastRow)
If Len(rngMyCell) > 0 Then
If objContact.Exists(CStr(rngMyCell)) = False Then
objContact.Add CStr(rngMyCell), rngMyCell
End If
End If
Next rngMyCell
strContact = Join(WorksheetFunction.Transpose(WorksheetFunction.Transpose(objContact.Items)), ";")
'Make sure admins are unique
Set objAdmin = CreateObject("Scripting.Dictionary")
lngLastRow = Worksheets("Sheet1").Cells(Rows.Count, "G").End(xlUp).Row
For Each rngMyCell In Worksheets("Sheet1").Range("G3:G" & lngLastRow)
If Len(rngMyCell) > 0 Then
If objAdmin.Exists(CStr(rngMyCell)) = False Then
objAdmin.Add CStr(rngMyCell), rngMyCell
End If
End If
Next rngMyCell
strAdmin = Join(WorksheetFunction.Transpose(WorksheetFunction.Transpose(objAdmin.Items)), ";")
'Make sure clients are unique
Set objClient = CreateObject("Scripting.Dictionary")
lngLastRow = Worksheets("Sheet1").Cells(Rows.Count, "B").End(xlUp).Row
For Each rngMyCell In Worksheets("Sheet1").Range("B3:B" & lngLastRow)
If Len(rngMyCell) > 0 Then
If objClient.Exists(CStr(rngMyCell)) = False Then
objClient.Add CStr(rngMyCell), rngMyCell
End If
End If
Next rngMyCell
strClient = Join(WorksheetFunction.Transpose(WorksheetFunction.Transpose(objClient.Items)), ";")
Application.ScreenUpdating = True
strbody = "Dear " & strContact & "," & vbNewLine & vbNewLine & _
"Say Hello World!" & vbNewLine & vbNewLine & _
"Kind Regards," & vbNewLine & _
"Mr A Nother"
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = strEmailTo
.CC = strCCTo
.BCC = ""
.Subject = strToday & " - Agreement"
.Body = strbody
'.Attachments.Add
.Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
To Answer Your Question:
I think the reason you are only seeing one email is because you only created one OutMail object. If you want to loop, you need to set the object = nothing before you can create a new one:
Set OutMail = Nothing
It also looks like you are creating a single dictionary that has all of the emails pushed together in the email field, the names pushed together, etc. You need a way to loop through each email you want to send. You could create an array of dictionaries, create a collection of objects, or loop through a range where the data is kept. Looping through a range sounds like it would be the least complicated in this case.
The pseudocode/code looks like this:
'instantiate the outlook object. Use:
Set OutApp = CreateObject("Outlook.Application")
'Create your array of dictionaries or return a range with the data
'Let's call it listOfEmails
For each email in listOfEmails:
'instantiate the mail object. Use:
Set OutMail = OutApp.CreateItem(0)
'The block that creates the email:
With OutMail
.To = strEmailTo
.CC = strCCTo
.BCC = ""
.Subject = strToday & " - Agreement"
.Body = strbody
'.Attachments.Add
.Display
End With
'destroy the object when you are done with that particular email
Set OutMail = Nothing
Next email
Set OutApp = Nothing
Some General Advice:
Breaking your code into smaller pieces can help make things easier to fix and read. It also makes it more reusable for both this project and future projects.
I'm including this feedback because it also makes for easier questions to answer on here.
For example:
A function to check if Outlook is open:
Function isOutlookOpen() As Boolean
'returns true or false if Outlook is open
Dim OutApp As Object
On Error Resume Next
Set OutApp = CreateObject("Outlook.Application")
If OutApp Is Nothing Then
isOutlookOpen = False
Else: isOutlookOpen = True
End If
On Error GoTo 0
End Function
A subroutine to send the email that you can call from another sub:
Sub sendEmail(ByVal recTO As String, ByVal subjectContent As String, ByVal bodyContent As String)
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = recTO
'.CC = ""
'.BCC = ""
.subject = subjectContent
.body = bodyContent '.HTMLBody
.display
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
A function to return a range of data:
Function dataRange() As Range
'Returns the range where the data is kept
Dim ws As Worksheet
Dim dataRng As Range
Dim lastRow As Integer
Dim rng As Range
Set ws = Workbooks("outlookEmail.xlsm").Sheets("dataSheetName")
lastRow = Cells(Rows.Count, 2).End(xlUp).Row
'still select where the data should go if the data range is empty
If lastRow = 2 Then
lastRow = lastRow + 1
End If
Set dataRange = Range("B3", "G" & lastRow)
End Function
A subroutine to bring it all together:
Sub main()
'This sub does more than one thing, but I'm asuming it's extremely custom ans still relatively short
Dim data As Range
Dim subj As String
Dim recEmail As String
Dim body As String
Dim Row As Range
'check if data exists. Exit the sub if there's nothing
Set data = dataRange
If dataRange.Cells(1, 1).Value = "" Then
MsgBox "Data is empty"
Exit Sub
End If
'Loop through the data and send the email.
For Each Row In data.Rows
'Row is still a range object, so you can access the ranges inside of it like you normally would
recEmail = Row.Cells(1, 2).Value
If recEmail <> "" Then 'if the email is not blank, send the email
subj = Format(Date, "mm.dd.yy") & " - Agreement"
body = "Dear " & Row.Cells(1, 4).Value & "," & vbNewLine & vbNewLine & _
"Say Hello World!" & vbNewLine & vbNewLine & _
"Kind Regards," & vbNewLine & _
"Mr A Nother"
Call sendEmail(recEmail, subj, body)
End If
Next Row
End Sub
Very Importantly:
Thank you to Ron De Bruin for teaching me all about sending emails from Outlook using code in Excel VBA
First of all, add
Option Explicit
above all code.
Then correct the errors.
Then:
https://stackoverflow.com/help/mcve
You want to use Excel VBA to achieve Outlook mail delivery?
if so, You can use the following method to get the email address in range.
You can not be so troublesome. You have simpler code to implement.
Sub Send_Email()
Dim rng As Range
For Each rng In Range("C1:C4")
Call mymacro(rng)
Next rng
End Sub
Private Sub mymacro(rng As Range)
Dim OutApp As Object
Dim OutMail As Object
Dim MailBody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
MailBody = "hello"
On Error Resume Next
With OutMail
.To = rng.Value
.CC = ""
.BCC = ""
.Subject = Sheet1.Cells(rng.Row, 1).Value
.Body = Sheet1.Cells(rng.Row, 2).Value
.Display
'.Send
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub
I use the mymacro method to create a message and send it.
I loop through the email addresses("C1:C4").And call mymacro method to send an email to this address.

Email a single attachment from folder of files each to a different person

I have a folder with 50 files and I have a list of 50 email addresses. Each file goes to a different email address. Is there a way to write a macro that performs this task?
The problem with the set of code below is two-fold:
1) I have 3 COLUMNS of data in an Excel file: One for subject, one for email address to send to, and the third for the FILE PATH of where the attachment to be attached is stored.
The code below does not allow for a pre-determined set of subject arguments. It also uses ROWS?? for the filepath field instead of a column like it does for send to? So confusing.
Sub Send_Files()
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
Here is quick example, assuming col A = Email, Col B = Subject & Col C = Path
Option Explicit
Public Sub Example()
Dim olApp As Object
Dim olMail As Object
Dim olRecip As Object
Dim olAtmt As Object
Dim iRow As Long
Dim Recip As String
Dim Subject As String
Dim Atmt As String
iRow = 2
Set olApp = CreateObject("Outlook.Application")
Dim Sht As Worksheet
Set Sht = ThisWorkbook.Worksheets("Sheet1")
Do Until IsEmpty(Sht.Cells(iRow, 1))
Recip = Sht.Cells(iRow, 1).Value
Subject = Sht.Cells(iRow, 2).Value
Atmt = Sht.Cells(iRow, 3).Value ' Attachment Path
Set olMail = olApp.CreateItem(0)
With olMail
Set olRecip = .Recipients.Add(Recip)
.Subject = Subject
.Body = "Hi "
.Display
Set olAtmt = .Attachments.Add(Atmt)
olRecip.Resolve
End With
iRow = iRow + 1
Loop
Set olApp = Nothing
End Sub

How to create a to string?

I am trying to create an Outlook email for multiple recipients.
I have two sheets 1 and 2.
I want the code in sheet 1 column B to look into Sheet 2 column A and pick up all the email addresses matched the codes and create an email with list recipients in tostring and do repeat task for second code till its empty.
Also attach files corresponding to that code in column c in sheet 1.
Its in the Sheet 2 column B
I have clients' names in sheet 1 column B and there is corresponding names in sheet 2 Column A and email addresses in Column B.
I created below code. How do I create a to string in VBA?
Sub GenerateEmail()
i = 2 ' selects row 2 ,since row 1 ,i am keeping for titles
Dim wbBook As Excel.Workbook
Dim doText As DataObject
Dim wsSheet As Excel.Worksheet
Dim x As Variant
Dim myemail As String
Dim myrange As Range
Dim n As Range
Dim sm2 As Range
Set wbBook = ThisWorkbook
Set sm2 = ThisWorkbook.Sheets("Sheet 2").Range("A2:A1000")
Set sm1 = ThisWorkbook.Sheets("Sheet 1").Range("B2:B1000")
Do Until ThisWorkbook.Sheets("Sheet 1").Cells(i, "B").Value = ""
EmailTo = tostring
BCC = ThisWorkbook.Sheets("Sheet 1").Range("J3").Value
Subj = ThisWorkbook.Sheets("Sheet 1").Range("J4").Value
Path = "N:\Folder 1\Folder 2\Folder 3\Folder 3\Result\"
FileName = ThisWorkbook.Sheets("Sheet 1").Cells(i, 3)
SM = ThisWorkbook.Sheets("Sheet 1").Cells(i, 2)
x = Replace(Range("Content1").Value, "<PROJECTION DATE1>", Format(Range("GenerationMonth").Value, "mmmm"))
x = x & Replace(Range("Content2").Value, "<PROJECTION DATE2>", Format(Range("GenerationMonth").Value, "mmmm-yyyy"))
x = x & ThisWorkbook.Sheets("Sheet 3").Range("Content3").Value
Msg = x
Application.ScreenUpdating = False
Application.StatusBar = "Preparing email..."
Application.DisplayAlerts = False
'Variables for MS Outlook.
'Variables for MS Outlook.
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.SentOnBehalfOfName = "Cleint1#Hotmail.com"
.To = EmailTo
.BCC = "Cleint1#Hotmail.com"
.Subject = "This is my subject" & Format(DateAdd("m", -1, Date), "mmmm yyyy")
.Attachments.Add Path & FileName
.Display
.BodyFormat = olFormatPlain
.Body = Msg
'send
End With
i = i + 1
Set doText = Nothing
Application.CutCopyMode = False
Loop
Cells(7, "J").Value = "Outlook msg count =" & i - 1
Set OutMail = Nothing
Set OutApp = Nothing
Application.DisplayAlerts = False
Application.ScreenUpdating = False
'Workbooks(MyFile).Close
End Sub
This is one way to start your loop and get the "To:" variable.
I comment out most of the code because I don't have your workbook and the code would not work in my situation.
Sub DoItEmail()
'Dim doText As DataObject
Dim x As Variant
Dim myemail As String
Dim myrange As Range
Dim n As Range
Dim sm2 As Range
Dim OutApp As Object
Dim OutMail As Object
'==================================================================
Dim sh As Worksheet, ws As Worksheet, wb As Workbook
Dim Rws As Long, Rng As Range, c As Range
Dim Rws2 As Long, Rng2 As Range, b As Range, SndTo As String
Set sh = Sheets("Sheet1")
Set ws = Sheets("Sheet2")
Application.ScreenUpdating = 0
With sh
Rws = .Cells(.Rows.Count, "A").End(xlUp).Row
Set Rng = .Range("A2:A" & Rws)
End With
With ws
Rws2 = .Cells(.Rows.Count, "C").End(xlUp).Row
Set Rng2 = .Range("C2:C" & Rws2)
End With
For Each c In Rng.Cells
For Each b In Rng2.Cells
If b = c Then
SndTo = b.Offset(0, 1) 'this would be your "to:" variable
'MsgBox SndTo & " is the To: variable"
'EmailTo = tostring
BCC = sh.Range("J3").Value
Subj = sh.Range("J4").Value
'Path = "N:\Folder 1\Folder 2\Folder 3\Folder 3\Result\"
'FileName = sh.Cells(i, 3)
'SM = sh.Cells(i, 2)
' x = Replace(Range("Content1").Value, "<PROJECTION DATE1>", Format(Range("GenerationMonth").Value, "mmmm"))
' x = x & Replace(Range("Content2").Value, "<PROJECTION DATE2>", Format(Range("GenerationMonth").Value, "mmmm-yyyy"))
' x = x & ThisWorkbook.Sheets("Sheet 3").Range("Content3").Value
' Msg = x
Application.ScreenUpdating = False
'Application.StatusBar = "Preparing email..."
Application.DisplayAlerts = False
'Variables for MS Outlook.
'Variables for MS Outlook.
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.SentOnBehalfOfName = "Cleint1#Hotmail.com"
.To = SndTo
.BCC = "Cleint1#Hotmail.com"
.Subject = "This is my subject: " & Format(DateAdd("m", -1, Date), "mmmm yyyy")
'.Attachments.Add Path & FileName
.Display
.BodyFormat = olFormatPlain
.Body = Msg
'send
End With
i = i + 1
Set doText = Nothing
Application.CutCopyMode = False
Cells(7, "J").Value = "Outlook msg count =" & i
Set OutMail = Nothing
Set OutApp = Nothing
Application.DisplayAlerts = False
Application.ScreenUpdating = False
'Workbooks(MyFile).Close
End If
Next b
Next c
Application.StatusBar = False
End Sub

Resources