I wonder whether someone could help me please.
I'm trying to write a script which send multiple emails to addressees on a spreadsheet, with various other pieces of information.
I've started to use a solution from Ron de Bruin (below).
Sub Email()
Dim OutApp As Object
Dim OutMail As Object
Dim cell As Range
Dim Src As Worksheet
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
Set Src = ThisWorkbook.Sheets("List")
On Error GoTo cleanup
Src.Select
For Each cell In Columns("C").Cells.SpecialCells(xlCellTypeConstants)
If cell.Value Like "?*#?*.?*" Then
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = cell.Value
.Subject = "Splunk Access"
.Body = "Hi " & Cells(cell.Row, "A").Value _
& vbNewLine & vbNewLine & _
"I have created an account: Production." & _
vbNewLine & vbNewLine & _
"Your username and password for this environment is:" & _
vbNewLine & vbNewLine & _
"Username: " & Cells(cell.Row, "B").Value & _
vbNewLine & _
"Password: " & Cells(cell.Row, "E").Value & _
vbNewLine & vbNewLine & _
"Please log in at your earliest convenience and change your password to a more secure one. " & _
vbNewLine & vbNewLine & _
"You can do this by clicking on your name on the top menu and select ‘Edit Account’." & _
vbNewLine & vbNewLine & _
"You can use this link to get to the log in page for this environment: " & _
vbNewLine & vbNewLine & _
"PROD: right/en-US/account/logout " & _
vbNewLine & vbNewLine & _
"Many thanks and kind regards"
.send
End With
On Error GoTo 0
Set OutMail = Nothing
End If
Next cell
cleanup:
Set OutApp = Nothing
Application.ScreenUpdating = True
End Sub
This script works, but I then receive the 'Outlook' security ,message, which with over 100 recipients, isn't practical to keep pressing "Ok" to send the email.
So following more research I changed:
.send
to
.Display
Application.Wait (Now + TimeValue("0:00:01"))
Application.SendKeys "%"
But the problem I have is that the email is created, but isn't sent. Again not practical to keep pressing "Send" for over 100 users.
I then tried a CDO solution, but I ran into problems with the SMTP address because I'm using my works Microsoft Exchange which I'm not an administrator for, and so don't have any of the SMTP details.
I just wondered whether someone may be able to look a this please, and offer some guidance on how I can create the macro to run automatically.
Many thanks and kind regards
Chris
All,
I managed to get this working with the following:
Sub Email()
Dim OutApp As Object
Dim OutMail As Object
Dim cell As Range
Dim Src As Worksheet
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
Set Src = ThisWorkbook.Sheets("List")
On Error GoTo cleanup
Src.Select
For Each cell In Columns("C").Cells.SpecialCells(xlCellTypeConstants)
If cell.Value Like "?*#?*.?*" Then
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = cell.Value
.Subject = "Access"
.Body = "Hi " & Cells(cell.Row, "A").Value _
& vbNewLine & vbNewLine & _
"I have created an account for you" & _
vbNewLine & vbNewLine & _
"Your username and password for this environment is:" & _
vbNewLine & vbNewLine & _
"Username: " & Cells(cell.Row, "B").Value & _
vbNewLine & _
"Password: " & Cells(cell.Row, "E").Value & _
vbNewLine & vbNewLine & _
"Please log in at your earliest convenience and change your password to a more secure one. " & _
vbNewLine & vbNewLine & _
"You can do this by clicking on your name on the top menu and select 'Edit Account'." & _
vbNewLine & vbNewLine & _
"You can use this link to get to the log in page for this environment: " & _
vbNewLine & vbNewLine & _
"PROD: https://right/en-US/account/logout " & _
vbNewLine & vbNewLine & _
"Many thanks and kind regards"
' .send
.Display
Application.Wait (Now + TimeValue("0:00:02"))
Application.SendKeys "%s"
Application.SendKeys "+o"
End With
On Error GoTo 0
Set OutMail = Nothing
End If
Next cell
cleanup:
Set OutApp = Nothing
Application.ScreenUpdating = True
End Sub
I found through further testing, that a automatic pop up appeared when the 'Send' button was clicked by this command Application.SendKeys "%s", so I added Application.SendKeys "+o2, to automatically click "OK".
Kind regards
Chris
try
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.Calculation = xlCalculationManual
this is of course using .Send
make sure to turn them back on at end of sub
I am using the code below which is basically taken a screenshot of an userform and paste it in an outlook application. The macro is working fine.
What I am trying to achieve is to put an email introduction and then after paste the screenshot, but I am not able to do it properly because the screenshot is not being put after the text.
This is my code
Sub Screenshotemail()
Dim doc As Object, rng As Range
Application.SendKeys "(%{1068})"
DoEvents
'ActiveSheet.Paste
With CreateObject("Outlook.Application").CreateItem(0)
Set doc = .GetInspector.WordEditor
doc.Range(0, 0).Paste
.display
.To = ""
.CC = ""
.Body = "Dear All, " & Chr(10) & Chr(10) & "I kindly remind you that forecasts for program " & Chr(10) & Chr(10) _
& "Please enter your forecast at the link below." _
& Chr(10) & Chr(10) & lien & Chr(10) & Chr(10) & "Best Regards,"
.Subject = "Test:"
.Importance = olImportanceHigh
End With
End Sub
Is there a way to make it work?
My friend, It take me a few hours but i guess it works
just use, htmlbody instead body, and concat the htmlbody after your messagge
reference
Write before paste table in Outlook - Excel VBA
Sub Screenshotemail()
Dim doc As Object, rng As Range
Dim wdDoc As Object
Dim wdRange As Range
Application.SendKeys "(%{1068})"
DoEvents
Set wdDoc = CreateObject("Word.Application")
'ActiveSheet.Paste
With CreateObject("Outlook.Application").CreateItem(0)
Set doc = .GetInspector.WordEditor
doc.Range(0, 0).Paste
.display
.To = ""
.CC = ""
.htmlbody = "Dear All, " & Chr(10) & Chr(10) & "I kindly remind you that forecasts for program " & Chr(10) & Chr(10) _
& "Please enter your forecast at the link below." _
& Chr(10) & Chr(10) & lien & Chr(10) & Chr(10) & "Best Regards," & .htmlbody
.Subject = "Test:"
.Importance = olImportanceHigh
End With
End Sub
So I have a db with two tables. One, "Recipients", contains individuals names or distro list names, their department within the company, and their email address. The second, "Sites", contains information about different locations where the company has offices. The data in these two tables are not related.
I want to click a button on the Sites form that linked to the data in the Sites table to email information about the site in the record that is displayed to everyone in the Recipients table, based on their section or position. For example, the email is sent to everyone in the Sales department, and the supervisors and managers would be CC'd,
I have the VBA script completed except for looking up the e-mail addresses and populating the To and CC address fields. I could hard code the e-mail addresses, but I am building this for other members of my office to use, and would like them to be able to update the e-mail list when an employee leaves, gets added or is replaced without having to learn how to interpret the code. Everything else is working satisfactorily.
I am using Office 365, my script is below.
Private Sub Command106_Click()
'Set up outlook
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
'Create message
strbody = "<p style='font-size:15'>" & "All," & "<br>" & _
"<br>" & _
"Please see the office information below for " & Me.CompanySiteID.Value & "." & "<br>" & _
"<br>" & _
"Address: " & " " & Me.Address.Value & "<br>" & _
"City: " & " " & Me.City.Value & "<br>" & _
"State: " & " " & Me.State.Value & "<br>" & _
" Size: " & " " & Me. Size.Value & "<br>" & _
On Error Resume Next
With OutMail
.Display
.to = ""
.CC = ""
.BCC = ""
.Subject = " Office Information below for " & Me.CompanySiteID.Value
.HTMLBody = strbody & .HTMLBody
'.Send
End With
'Delete any temp files created
Kill strPath & strFName
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Using Outlook, I flag an email if it contains a job for me to do. When I've completed the job I mark the email complete (by changing the flag to a tick). I would like to automatically send a reply telling the initial sender the job has been done.
I found the below code which seems like it would do half of what I want but instead of "John Smith" I want it to use the sender's email address and preferably contain the initial email as it would if I sent a reply.
Public WithEvents olItems As Outlook.Items
Private Sub Application_Startup()
Set olItems = Session.GetDefaultFolder(olFolderTasks).Items
End Sub
Private Sub olItems_ItemChange(ByVal Item As Object)
Dim obApp As Outlook.Application
Dim olMail As Outlook.MailItem
Dim Recip As String
'Replace "test" as per your needs
If InStr(LCase(Item.Subject), "test") > 0 And Item.Complete = True Then
'Replace with your desired contact
Recip = "John Smith"
If MsgBox("Do you want to send a report to " & Recip & " ?", vbYesNo + vbQuestion, "Confirm Sending Report") = vbYes Then
Set obApp = Outlook.Application
Set olMail = obApp.CreateItem(olMailItem)
With olMail
.To = Recip
.Subject = "Complete: " & Item.Subject
.Body = "Dear Mr. Smith" & vbCrLf & "I've completed this task in " & DateDiff("d", Item.CreationTime, Now) & " day" & Chr(40) & "s" & Chr(41) & "." & vbCrLf & vbCrLf & "Task Name: " & Item.Subject & vbCrLf & "Start Date: " & Item.StartDate & vbCrLf & "Due Date: " & Item.DueDate & vbCrLf & "Creation Time: " & Item.CreationTime & vbCrLf & "Completed Time: " & Now & vbCrLf & vbCrLf & "Task Details: " & vbCrLf & Item.Body
.ReadReceiptRequested = True
'To directly send it,use ".Send" instead
.Display
End With
End If
End If
End Sub
Instead of creating a new mail item in the code:
Set olMail = obApp.CreateItem(olMailItem)
You can just reply to the existing one preserving the message body and recipients inplace:
Set olMail = Item.Reply()
Note, you can also use the MailItem.ReplyAll method which creates a reply to all original recipients from the original message.
Public WithEvents olItems As Outlook.Items
Private Sub Application_Startup()
Set olItems = Session.GetDefaultFolder(olFolderTasks).Items
End Sub
Private Sub olItems_ItemChange(ByVal Item As Object)
Dim obApp As Outlook.Application
Dim olMail As Outlook.MailItem
Dim Recip As String
'Replace "test" as per your needs
If InStr(LCase(Item.Subject), "test") > 0 And Item.Complete = True Then
'Replace with your desired contact
Recip = "John Smith"
If MsgBox("Do you want to send a report to " & Recip & " ?", vbYesNo + vbQuestion, "Confirm Sending Report") = vbYes Then
Set olMail = Item.Reply
With olMail
.Subject = "Complete: " & Item.Subject
.Body = "Dear Mr. Smith" & vbCrLf & "I've completed this task in " & DateDiff("d", Item.CreationTime, Now) & " day" & Chr(40) & "s" & Chr(41) & "." & vbCrLf & vbCrLf & "Task Name: " & Item.Subject & vbCrLf & "Start Date: " & Item.StartDate & vbCrLf & "Due Date: " & Item.DueDate & vbCrLf & "Creation Time: " & Item.CreationTime & vbCrLf & "Completed Time: " & Now & vbCrLf & vbCrLf & "Task Details: " & vbCrLf & Item.Body
.ReadReceiptRequested = True
'To directly send it,use ".Send" instead
.Display
End With
End If
End If
End Sub
I've successfully written two macros to automate e-mailing based on cell values within a sheet (basically as a reminder system). The ranges overlap and one sub is intended to send an e-mail when cells reach a value of 0, the other is a smaller range of cells and is meant to send an e-mail when cells report a range between 1 and 5 (inclusive).
I can get the subs to work individually no problem, but my incredibly limited knowledge has been flummoxed when attempting to merge the two. Either it doesn't work at all, or it only part works.
If anyone could help me I'd be incredibly grateful as I'm at something of a loss! The code for the two subs is as follows:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Cells.Count > 1 Then Exit Sub
If Not Application.Intersect(Range("D122:D128,D131:D133,D138,D140,D144,D188,D191:D192,D217:D220,D294,D159:D167"), Target) Is Nothing Then
If IsNumeric(Target.Value) And Target.Value > 0 Then
If IsNumeric(Target.Value) And Target.Value < 6 Then
zRow = Target.Row
zValno = Cells(zRow, "B")
zValname = Cells(zRow, "C")
zValInno = Cells(zRow, "D")
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = ""
strbody = strbody & "Please be advised that " & zValno & " (" & zValname & ") " & "is now low. This value is now " & zValInno & "."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
On Error Resume Next
With OutMail
.to = "abc#anyoldemail.com"
.CC = ""
.BCC = ""
.Subject = "LOW VALUE: " & zValno & " is now low."
.Body = strbody
.Attachments.Add ("C:\reportlog.txt")
.Send
End With
On Error GoTo 0
zSent = zSent + 1
saywhat = "processing " & zSent & " of " & zCount
Application.StatusBar = saywhwat
Application.StatusBar = ""
Set OutMail = Nothing
Set OutApp = Nothing
End If
End If
End If
End Sub
And
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Cells.Count > 1 Then Exit Sub
If Not Application.Intersect(Range("D4:D100,G4:G100,J4:J99"), Target) Is Nothing Then
If IsNumeric(Target.Value) And Target.Value < 1 Then
zRow = Target.Row
zValno = Cells(zRow, "B")
zValname = Cells(zRow, "C")
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = ""
strbody = strbody & "Please be advised that " & zValno & " (" & zValname & ") " & "is now reporting nil."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
On Error Resume Next
With OutMail
.to = "abc#anyoldemail.com"
.CC = ""
.BCC = ""
.Subject = "NULL ALERT: " & zValno & " is now reporting nil."
.Body = strbody
.Attachments.Add ("C:\reportlog.txt")
.Send
End With
On Error GoTo 0
zSent = zSent + 1
saywhat = "processing " & zSent & " of " & zCount
Application.StatusBar = saywhwat
Application.StatusBar = ""
Set OutMail = Nothing
Set OutApp = Nothing
End If
End If
End Sub
This is the brute force approach, but I think your code could be shortened as there are commonalities
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Cells.Count > 1 Then Exit Sub
If Not Application.Intersect(Range("D122:D128,D131:D133,D138,D140,D144,D188,D191:D192,D217:D220,D294,D159:D167"), Target) Is Nothing Then
If IsNumeric(Target.Value) And Target.Value > 0 Then
If IsNumeric(Target.Value) And Target.Value < 6 Then
zRow = Target.Row
zValno = Cells(zRow, "B")
zValname = Cells(zRow, "C")
zValInno = Cells(zRow, "D")
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = ""
strbody = strbody & "Please be advised that " & zValno & " (" & zValname & ") " & "is now low. This value is now " & zValInno & "."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
On Error Resume Next
With OutMail
.to = "abc#anyoldemail.com"
.CC = ""
.BCC = ""
.Subject = "LOW VALUE: " & zValno & " is now low."
.Body = strbody
.Attachments.Add ("C:\reportlog.txt")
.Send
End With
End If
End If
ElseIf Not Application.Intersect(Range("D4:D100,G4:G100,J4:J99"), Target) Is Nothing Then
If IsNumeric(Target.Value) And Target.Value < 1 Then
zRow = Target.Row
zValno = Cells(zRow, "B")
zValname = Cells(zRow, "C")
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = ""
strbody = strbody & "Please be advised that " & zValno & " (" & zValname & ") " & "is now reporting nil."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
On Error Resume Next
With OutMail
.to = "abc#anyoldemail.com"
.CC = ""
.BCC = ""
.Subject = "NULL ALERT: " & zValno & " is now reporting nil."
.Body = strbody
.Attachments.Add ("C:\reportlog.txt")
.Send
End With
End If
End If
On Error GoTo 0
zSent = zSent + 1
saywhat = "processing " & zSent & " of " & zCount
Application.StatusBar = saywhwat
Application.StatusBar = ""
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
With a few modifications, try the combined code below for both Worksheet_Change events.
I've added a Variable EmailType that checks if the modified cells passed one of the 2 criteria’s, and then gets a value of 1 or 2.
Afterwards, according to the EmailType it modifies the email parameters.
Code
Private Sub Worksheet_Change(ByVal Target As Range)
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Dim mailSubject As String '<-- added this String variable to differ on 2 scenarios
Dim EmailType As Long '<-- use variable to see if passed the 2 criterias in the original code
EmailType = 0 '<-- init value
If Target.Cells.Count > 1 Then Exit Sub
If Not Application.Intersect(Range("D122:D128,D131:D133,D138,D140,D144,D188,D191:D192,D217:D220,D294,D159:D167"), Target) Is Nothing Then
If IsNumeric(Target.Value) And Target.Value > 0 And Target.Value < 6 Then
EmailType = 1 '<-- Email Type = 1
End If
End If
If Not Application.Intersect(Range("D4:D100,G4:G100,J4:J99"), Target) Is Nothing Then
If IsNumeric(Target.Value) And Target.Value < 1 Then
EmailType = 2 '<-- Email Type = 2
End If
End If
If EmailType = 0 Then Exit Sub '< didn't pass any of the criterias >> Exit Sub
zValno = Range("B" & Target.Row)
zValname = Range("C" & Target.Row)
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
Select Case EmailType
Case 1
zValInno = Cells("D" & Target.Row) '<-- this value exists on for Email Type 1
mailSubject = "LOW VALUE: " & zValno & " is now low." '<-- mail subject for email type 1
strbody = ""
strbody = strbody & "Please be advised that " & zValno & " (" & zValname & ") " & "is now low. This value is now " & zValInno & "."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
Case 2
mailSubject = "NULL ALERT: " & zValno & " is now reporting nil." '<-- mail subject for email type 2
strbody = ""
strbody = strbody & "Please be advised that " & zValno & " (" & zValname & ") " & "is now reporting nil."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
strbody = strbody & vbCr & vbCr
strbody = strbody & "Blah, blah, blah."
End Select
' ======= from here untill the end the same code, just using different values found per Email Type =======
On Error Resume Next
With OutMail
.to = "abc#anyoldemail.com"
.CC = ""
.BCC = ""
.Subject = mailSubject
.Body = strbody
.Attachments.Add ("C:\reportlog.txt")
.Send
End With
On Error GoTo 0
zSent = zSent + 1
saywhat = "processing " & zSent & " of " & zCount
Application.StatusBar = saywhat
Application.StatusBar = ""
Set OutMail = Nothing
Set OutApp = Nothing
End Sub