VBA - Sending Emails Through Outlook Based on Cell Data - vba

I've been failing miserably trying to write code for this, so I'd be happy if someone could help me create a macro in excel. I'm looking to send a bunch of users access credentials through outlook based off data I add to excel. Specifically, I have two worksheets:
1) Email Information (all static)
This contains:
Email Subject in cell C5
Email Body in Cell C6 (Essentially this says Hello, your user credentials are below)
Additional Email Body in Cell C7 (This portion would say something along the lines of "please let us know if you have any questions") Both cells C6 and C7 can of course be updated to include any language
2) User Information (number of users can vary)
This contains:
Column A - First Name
Column B - Last Name
Column C - Full Name (Not really needed)
Column D - Email Address
Column E - Password
Ideally, the macro would be able to look at the user information and create a new, separate email from outlook for every email address from column D with the following format:
Email To: email addresses in cell D2 until last email (User Information worksheet)
Email Subject: Cell C5 in Email information worksheet
"Hi" Firstname value from column A in User Information worksheet
Email Body Part 1 from cell C6 in Email Information worksheet
Username: which is the email address from column D (same as email recipient)
Password: from column E in User Information worksheet
Email Body PArt 2 from cell C7 in Email Information worksheet
Hope someone has the time to help me out.
Thanks in advance!!
EDIT
Thanks for the help, Barry. Here is my code as I'm trying to reference two different worksheets. Can you let me know what I'm doing wrong?
Sub GenerateEmail()
Dim sEmailBodyp1 As String
Dim sEmailBodyp2 As String
Dim sEmailSubject As String
Dim sEmailTo As String
Dim sFirstName As String
Dim sPassword As String
Dim OutApp As Object
Dim OutMail As Object
Dim EmailSheet As Worksheet
Dim UserSheet As Worksheet
Dim UsedRange As Range
Set EmailSheet = Sheets("Email Information")
Set UserSheet = Sheets("User Information")
Set sEmailSubject = EmailSheet.Cells("C5")
Set sEmailBodyp1 = EmailSheet.Cells("C6")
Set sEmailBodyp2 = EmailSheet.Cells("C7")
Set UsedRange = UserSheet.UsedRange
For Each Row In UsedRange.Rows
sFirstName = Row.Columns(1)
sEmailTo = Row.Columns(4)
sPassword = Row.Columns(5)
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = sEmailTo
.Subject = sEmailSubject
.Body = "Hi " + sFirstName + "," + vbCrLf + vbCrLf + sEmailBodyp1 + vbCrLf + vbCrLf + "Username: " + sEmailTo + vbCrLf + "Password: " + sPassword + vbCrLf + vbCrLf + sEmailBodyp2
.Display
End With
Set OutMail = Nothing
Next
Set OutApp = Nothing
End Sub

Based on discussions this is my edit for this solution.
Excel Macro
Public Sub GenerateEmail()
Dim sEmailBodyp1 As String
Dim sEmailBodyp2 As String
Dim sEmailSubject As String
Dim sEmailTo As String
Dim sFirstName As String
Dim sPassword As String
Dim OutApp As Object
Dim OutMail As Object
Dim EmailSheet As Worksheet
Dim UserSheet As Worksheet
Dim UsedRange As Range
Set EmailSheet = Sheets("Email Information")
Set UserSheet = Sheets("User Information")
sEmailSubject = EmailSheet.Range("C5").Value
sEmailBodyp1 = EmailSheet.Range("C6").Value
sEmailBodyp2 = EmailSheet.Range("C7").Value
Set UsedRange = UserSheet.UsedRange
For Each Row In UsedRange.Rows.Offset(1, 0).Resize(UsedRange.Rows.Count - 1, UsedRange.Columns.Count)
sFirstName = Row.Columns(1)
sEmailTo = Row.Columns(4)
sPassword = Row.Columns(5)
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = sEmailTo
.Subject = sEmailSubject
.Body = "Hi " + sFirstName + "," + vbCrLf + vbCrLf + sEmailBodyp1 + vbCrLf + vbCrLf + "Username: " + sEmailTo + vbCrLf + "Password: " + sPassword + vbCrLf + vbCrLf + sEmailBodyp2
.Display
End With
Set OutMail = Nothing
Next
Set OutApp = Nothing
End Sub

Related

How to paste the whole range from Excel to Lotus as bitmap?

I wrote a macro that works out quite well. I'm able to copy and paste given range (to be precise a pivot table) as bitmap but the problem is that not the whole are is copied, only a part of a table.
Here is the code, what's wrong with pasting? Why can't I copy the whole table?
Public Sub Lotus_Mail()
Dim NSession As Object
Dim NUIWorkSpace As Object
Dim NDatabase As Object
Dim NDoc As Object
Dim NUIdoc As Object
Dim Subject As String
Dim SendTo As String, CopyTo As String
Dim pivots As Range
Dim Month As String
Dim text1 As Range
Dim text2 As Range
Dim i As Integer
Dim arrHUBs(1 To 8) As String
arrHUBs(1) = "a"
arrHUBs(2) = "b"
arrHUBs(3) = "c"
arrHUBs(4) = "d"
arrHUBs(5) = "e"
arrHUBs(6) = "f"
arrHUBs(7) = "g"
arrHUBs(8) = "h"
Week = DatePart("ww", Date, vbMonday, vbFirstFourDays)
Month = MonthName(DatePart("m", Date), False)
On Error Resume Next
For x = 1 To 8
SendTo = Application.WorksheetFunction.VLookup(arrHUBs(x), Sheets("Mail").Range("A2:C9"), 2, 0)
CopyTo = Application.WorksheetFunction.VLookup(arrHUBs(x), Sheets("Mail").Range("A2:C9"), 3, 0)
Subject = "Summary " & arrHUBs(x) & " - " & Month & ": week " & Week
'area to select (pivot table)
rows = Sheets("sheet").Cells(Rows.Count, 21).End(xlUp).Row
columns = Sheets("sheet").Cells(6, Columns.Count).End(xlToLeft).Column
Set pivots = Sheets("sheet").Range(Cells(4, 19), Cells(wiersz, kolumna))
'Set pivots = Sheets("sheet").PivotTables("Pivot1") ???this line doesn't work, any other way to select pivot and paste to Lotus?
Set text1 = Sheets("Mail").Range("A12")
Set text2 = Sheets("Mail").Range("A13")
'Lotus step by step
Set NSession = CreateObject("Notes.NotesSession")
Set NUIWorkSpace = CreateObject("Notes.NotesUIWorkspace")
Set NDatabase = NSession.GetDatabase("", "")
If Not NDatabase.IsOpen Then NDatabase.OPENMAIL
'creating mail
Set NDoc = NDatabase.CreateDocument
With NDoc
.SendTo = SendTo
.CopyTo = CopyTo
.Subject = Subject
'Email body text, including a placeholder which will be replaced by Excel table
.body = text1 & vbLf & vbLf & _
"{IMAGE_PLACEHOLDER}" & vbLf
.Save True, False
End With
'Edit the new document using Notes UI to copy and paste pivot table into it
Set NUIdoc = NUIWorkSpace.EDITDocument(True, NDoc)
With NUIdoc
Sheets("sheet").Select
'Find the placeholder in the Body item
.GotoField ("Body")
.FINDSTRING "{IMAGE_PLACEHOLDER}"
'.DESELECTALL 'Uncomment to leave the placeholder in place (cells are inserted immediately before it)
'Copy pivot table (being a range) as a bitmap to the clipboard and paste into the email
pivots.CopyPicture xlBitmap
.Paste 'maybe any paste special option exists?
Application.CutCopyMode = False
'.Send
'.Close
End With
Set NSession = Nothing
Next x
End Sub
Thank you for your answers

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.

Can't send multiple Outlook Messages

I can send a single Outlook message using Excel VBA. However, I want to loop through my rows and send an email for each row that meets a certain condition.
Unfortunately, when I put the email code in a for loop only one email gets sent or none at all (depending on how I structure the code).
Is there something about calling Outlook multiple times that I should know?
Private Sub CommandButton1_Click()
Dim OutApp As Object
Dim OutMail As Object
Dim myValue As Variant
Dim contactRange As Range
Dim cell As Range
Dim toAddy As String, nextAddy As String
Dim i As Integer
Set contactRange = Me.Range("ContactYesNo")
myValue = InputBox("Enter body of email message.")
For Each cell In contactRange
If Range(Cells(cell.Row, cell.Column).Address).Value = "Yes" Then
nextAddy = Range(Cells(cell.Row, cell.Column).Address).Offset(0, 5).Value
toAddy = nextAddy & ", " & toAddy
End If
Next cell
If Len(toAddy) > 0 Then
toAddy = Left(toAddy, Len(toAddy) - 2)
End If
For i = 0 To 1 'short loop for testing purposes
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = toAddy
.CC = ""
.BCC = ""
.Subject = "test email"
.Body = myValue
.Send
End With
Set OutMail = Nothing
Set OutApp = Nothing
Next i
End Sub
Take the CreateObject line out of the loop:
Set OutApp = CreateObject("Outlook.Application")
For i = 0 To 1 'short loop for testing purposes
Set OutMail = OutApp.CreateItem(0)
...
I've tried to clean up your logic stream but there are many unanswered questions due to the lack of sample data, explicit error messages and output.
Private Sub CommandButton1_Click()
Dim outApp As Object
Dim outMail As Object
Dim myValue As Variant
Dim contactRange As Range
Dim cell As Range
Dim toAddy As String, nextAddy As String
Dim i As Integer
Set outApp = CreateObject("Outlook.Application")
Set contactRange = Me.Range("ContactYesNo")
myValue = InputBox("Enter body of email message.")
With Worksheets(contactRange.Parent.Name) '<~~ surely you know what worksheet you are on..!?!
For Each cell In contactRange
If cell.Value = "Yes" Then 'no need to define a range by the range's address
nextAddy = cell.Offset(0, 5).Value 'again, no need to define a range by the range's address
toAddy = nextAddy & ";" & toAddy 'use a semi-colon to concatenate email addresses
End If
Next cell
End With
If Len(toAddy) > 0 Then
toAddy = Left(toAddy, Len(toAddy) - 2) 'I have no idea why you need to shorten the toAddy by 2
'only send mail where one or more addresses exist
For i = 0 To 1 'short loop for testing purposes
Set outMail = outApp.CreateItem(0)
With outMail
.To = toAddy
.CC = ""
.BCC = ""
.Subject = "test email"
.Body = myValue
.Send
End With
Set outMail = Nothing
Next i
End If
Set outApp = Nothing
End Sub
OK, so I re-wrote the code based on the feedback. I used a loop to send emails one at a time instead of concatenating the addresses together as I wanted to personalize each email. I also needed to create a form to handle the input as inputbox only accepts 256 characters.
A form was pretty much required as I needed to capture the subject line, message body, salutation, path the to the attachment etc.:
Private Sub CommandButton1_Click()
Dim subject As String, msg As String, path As String
subject = TextBox1.Value
msg = TextBox2.Value & vbCrLf & vbCrLf & "Sincerely," & vbCrLf & TextBox4.Value & vbCrLf & TextBox5
path = TextBox3.Value
UserForm1.Hide
Module1.sendEmail subject, msg, path
End Sub
I placed the email code in Module1. Note, be sure to set the .sentOnBehalfOfName attribute or Outlook will simply pick an account which may not be the one you want if you have multiple accounts registered:
Public Sub sendEmail(subject As String, msg As String, path As String)
Dim outApp As Object
Dim outMail As Object
Dim contactRange As Range, cell As Range
Dim toAddy As String, emailMsg As String
Dim count As Integer
Set outApp = CreateObject("Outlook.Application")
Set contactRange = Range("ContactYesNo")
With Worksheets("IT consulting")
For Each cell In contactRange
If cell.Value = "Yes" Then
count = count + 1
toAddy = cell.Offset(0, 6).Value
emailMsg = "Dear " & cell.Offset(0, 2).Value & "," & vbCrLf & vbCrLf & msg
Set outMail = outApp.CreateItem(0)
With outMail
.SentOnBehalfOfName = "me#someemail.com"
.To = toAddy
.CC = ""
.BCC = ""
.subject = subject
.Body = emailMsg
.Attachments.Add path
'.Display
.Send
End With
'log the action
cell.Offset(0, 1).Value = Now & vbCrLf & cell.Offset(0, 1).Value
End If
Set outMail = Nothing
Next cell
End With
Set outApp = Nothing
MsgBox "total emails sent: " & count
End Sub

How do I loop through a specific folder in outlook

What would be the VBA code for looping through a specific folder in outlook 2010 that is NOT the default inbox nor a subfolder of the inbox?
Dim ns As Outlook.NameSpace
Dim folder As MAPIFolder
Set ns = Session.Application.GetNamespace("MAPI")
Set folder = Please help me :-)
Thank you for any hint and help, greetings Ionic
Change
Set ns = Session.Application.GetNamespace("MAPI")
To
Set ns = Session.Application.GetNamespace("MAPI").PickFolder
This will prompt you to select the folder.
Here's a full routine that I wrote some time ago that may be of assistance, bear in mind this was written so that it could be run from Excel but should provide you with the syntax that you need:
Sub GetMail()
'// This sub is designed to be used with a blank worksheet. It will create the header
'// fields as required, and continue to populate the email data below the relevant header.
'// Declare required variables
'-------------------------------------------------------------
Dim olApp As Object
Dim olFolder As Object
Dim olMailItem As Object
Dim strTo As String
Dim strFrom As String
Dim dateSent As Variant
Dim dateReceived As Variant
Dim strSubject As String
Dim strBody As String
Dim loopControl As Variant
Dim mailCount As Long
Dim totalItems As Long
'-------------------------------------------------------------
'//Turn off screen updating
Application.ScreenUpdating = False
'//Setup headers for information
Range("A1:F1").Value = Array("To", "From", "Subject", "Body", "Sent (from Sender)", "Received (by Recipient)")
'//Format columns E and F to
Columns("E:F").EntireColumn.NumberFormat = "DD/MM/YYYY HH:MM:SS"
'//Create instance of Outlook
Set olApp = CreateObject("Outlook.Application")
'//Select folder to extract mail from
Set olFolder = olApp.GetNamespace("MAPI").PickFolder
'//Get count of mail items
totalItems = olFolder.items.Count
mailCount = 0
'//Loop through mail items in folder
For Each loopControl In olFolder.items
'//If loopControl is a mail item then continue
If TypeName(loopControl) = "MailItem" Then
'//Increase mailCount
mailCount = mailCount + 1
'//Inform user of item count in status bar
Application.StatusBar = "Reading email no. " & mailCount & " of " & totalItems
'//Get mail item
Set olMailItem = loopControl
'//Get Details
With olMailItem
strTo = .To
'//If strTo begins with "=" then place an apostrophe in front to denote text format
If Left(strTo, 1) = "=" Then strTo = "'" & strTo
strFrom = .Sender
'//If sender displays name only, show name followed by email address e.g.(Bloggs, Joe < j.bloggs#mail.com >)
If InStr(1, strFrom, "#") < 1 Then strFrom = strFrom & " - < " & .SenderEmailAddress & " >"
dateSent = .SentOn
dateReceived = .ReceivedTime
strSubject = .Subject
strBody = .Body
End With
'//Place information into spreadsheet
'//import information starting from last blank row in column A
With Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
.Value = strTo
.Offset(0, 1).Value = strFrom
.Offset(0, 2).Value = strSubject
'//Check for previous replies by looking for "From:" in the body text
'//Check for the word "From:"
If InStr(0, strBody, "From:") > 0 Then
'//If exists, copy start of email body, up to the position of "From:"
.Offset(0, 3).Value = Mid(strBody, 1, InStr(1, strBody, "From:") - 1)
Else
'//If doesn't exist, copy entire mail body
.Offset(0, 3).Value = strBody
End If
.Offset(0, 4).Value = dateSent
.Offset(0, 5).Value = dateReceived
End With
'//Release item from memory
Set olMailItem = Nothing
End If
'//Next Item
Next loopControl
'//Release items from memory
Set olFolder = Nothing
Set olApp = Nothing
'//Resume screen updating
Application.ScreenUpdating = True
'//reset status bar
Application.StatusBar = False
'//Inform user that code has finished
MsgBox mailCount & " messages copied successfully.", vbInformation, "Complete"
End Sub
Okay, I've found it myself.
Set folder = ns.GetDefaultFolder(olFolderInbox).Parent.Folders(NAME OF THE FOLDER)
Than you for your help guys !

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?