Automated emails based on data in Excel sheet - excel

I need to send and email based on the expiry date of different machines.
I want to include all the expired machines in one email, as opposed to multiple emails.
The Excel sheet includes expiration date in column "I", the name of the machine in column "B", and has a function that calculates if my machines are "calibrated", "expired", or "near expiration", in column "P".
Private Sub Workbook_Open()
Dim Instrument As String
Dim Status As String
Status = Range("P6").Value
If IsNull(Status) = True Then Exit Sub
If Status = "Expiring Soon" Then
Instrument = Range("B6").Value
Mail_Expiring_Soon_Outlook Instrument
End If
If Status = "Expired" Then
Instrument = Range("B6").Value
Mail_Expired_Outlook Instrument
End If
End Sub
Sub Mail_Expiring_Soon_Outlook(Instrument As String)
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Attention" & vbNewLine & vbNewLine & _
"The " & Instrument & " calibration is due within 30 days." & vbNewLine & vbNewLine & _
"Please arrange calibration."
On Error Resume Next
With xOutMail
.To = ""
.CC = ""
.BCC = ""
.Subject = "Calibration Due within 30 days"
.Body = xMailBody
.Display
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub
Sub Mail_Expired_Outlook(Instrument As String)
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Warning!" & vbNewLine & vbNewLine & _
"The " & Instrument & " calibration is expired." & vbNewLine & vbNewLine & _
"Please arrange calibration."
On Error Resume Next
With xOutMail
.To = ""
.CC = ""
.BCC = ""
.Subject = "Warning! Calibration is Expired"
.Body = xMailBody
.Display
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub

If I've understood what you're aiming for, you could simply loop through all the rows adding machine names to one of two variables depending on the status.
You could use something like the following...
Private Sub Workbook_Open()
Dim ExpiringSoon As String
Dim Expired As String
Dim Subject As String
Dim Body As String
Dim Row As Long
' Loop through rows, from row 2 until the last used row in column B
For Row = 2 To Cells(Rows.Count, "B").End(xlUp).Row
Select Case Cells(Row, "P")
Case "Expiring Soon"
ExpiringSoon = ExpiringSoon & Cells(Row, "B") & vbNewLine
Case "Expired"
Expired = Expired & Cells(Row, "B") & vbNewLine
End Select
Next
If ExpiringSoon <> "" Then
Subject = "Calibration Due within 30 days"
Body = "Attention" & vbNewLine & vbNewLine & _
"Calibration is due within 30 days for the following machines:" & vbNewLine & _
ExpiringSoon & vbNewLine & _
"Please arrange calibration."
Send_Mail Subject, Body
End If
If Expired <> "" Then
Subject = "Warning! Calibration is Expired"
Body = "Warning!" & vbNewLine & vbNewLine & _
"Calibration is expired for the following machines:" & vbNewLine & _
Expired & vbNewLine & _
"Please arrange calibration."
Send_Mail Subject, Body
End If
End Sub
Sub Send_Mail(Subject As String, Body As String)
On Error Resume Next
With CreateObject("Outlook.Application").CreateItem(0)
.Subject = Subject
.BodyFormat = 1
.Body = Body
.Display
End With
End Sub

Private Sub Workbook_Open()
Dim Instrument1 As String
Dim Instrument2 As String
Dim ws As Worksheet
Dim Status As String
Set ws = Sheets("DAQ Fault Log")
lr = ws.Range("A" & Rows.Count).End(xlUp).Row
' MsgBox "This code ran at Excel start!"
' On Error Resume Next
' If Target.Cells.Count > 1 Then Exit Sub
counter1 = 0
counter2 = 0
On Error Resume Next
For i = 2 To lr
Status = ws.Range("P" & i).Value
If Status = "Expiring Soon" Then
Instrument1 = Instrument1 & ws.Range("B" & i).Value & ", "
counter1 = counter1 + 1
End If
If Status = "Expired" Then
Instrument2 = Instrument2 & ws.Range("B" & i).Value & ", "
counter2 = counter2 + 1
End If
Next i
If counter1 > 0 And counter1 = 1 Then Mail_Expiring_Soon_Outlook Left(Instrument1, Len(Instrument1) - 2)
If counter1 > 0 And counter1 > 1 Then Mail_Expiring_Soon_Outlook Left(Instrument1, Len(Instrument1) - 1)
If counter2 > 0 And counter2 = 1 Then Mail_Expired_Outlook Left(Instrument2, Len(Instrument2) - 2)
If counter2 > 0 And counter2 > 1 Then Mail_Expired_Outlook Left(Instrument2, Len(Instrument2) - 1)
End Sub
Sub Mail_Expiring_Soon_Outlook(Instrument1 As String)
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Attention" & vbNewLine & vbNewLine & _
"The " & Instrument1 & " calibration is due within 30 days." & vbNewLine & vbNewLine & _
"Please arrange calibration."
On Error Resume Next
With xOutMail
.to = ""
.CC = ""
.BCC = ""
.Subject = "Calibration Due within 30 days"
.Body = xMailBody
.Display 'or use .Send
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub
Sub Mail_Expired_Outlook(Instrument2 As String)
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Warning!" & vbNewLine & vbNewLine & _
"The " & Instrument2 & " calibration is expired." & vbNewLine & vbNewLine & _
"Please arrange calibration."
On Error Resume Next
With xOutMail
.to = ""
.CC = ""
.BCC = ""
.Subject = "Warning! Calibration is Expired"
.Body = xMailBody
.Display 'or use .Send
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub

Related

Including Relative Cell References in Email Body

Trying to write code to email information based on one cell, to include other cells values from that same row within the email body. If the Cells(x,11) = Pending, then am wanting to include other information (relative to that cell) in the email body; looking to include the contents of cells -9, and also -7. Thanks so much in advance.
Sub EmailPendings()
Dim xOutApp As Object
Dim xOutMail As Object
Dim xOutMailAttach As String
Dim xMailBody As String
On Error Resume Next
FirstCell = 0
x = 6
While Cells(x, 1).Value <> ""
If Cells(x, 11).Value = "Pending" Then
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Hi Team" & vbNewLine & vbNewLine & _
"The following items are pending final approval, and is expected soon. Please proceed with Team assignment." & vbNewLine & vbNewLine & _
"Additional details are included below" & vbNewLine & _
Cells(x, 11).Value = "Pending" _
.FormulaR1C1 = "=(RC[-9],0)" & vbNewLine & _
Range ("C43") & vbNewLine & _
Range("C44") & vbNewLine & _
Range("C45") & vbNewLine & _
"Best,"
On Error Resume Next
With xOutMail
.To = ""
.CC = ""
.BCC = ""
.Subject = "Assignments Needed From Team Review: " & Date
.Body = xMailBody
.Display 'or use .Send
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
exitHandler:
Exit Sub
errHandler:
MsgBox "Could not create email"
Resume exitHandler
End If
'Go to next line
x = x + 1
Wend

How to import table and mail it using Excel?

I am trying to send a table via email using Excel VBA Code. The Code is working good but it does not allow me to send data in the form of the table. The structure of the sheet is as under.
I want to send the table to start with Sr. NO. I am using the below code which is working perfectly. But it sends only data in the form of values rather than a table.
Sub Send_EmailFinal()
Dim xRg As Range
Dim I, J As Long
Dim xAddress As String
Dim xEmailBody As String
Dim xMailOut As Outlook.MailItem
Dim xOutApp As Outlook.Application
On Error Resume Next
xAddress = ActiveWindow.RangeSelection.Address
Set xRg = Range("H5:L32")
If xRg Is Nothing Then Exit Sub
Application.ScreenUpdating = False
Set xOutApp = CreateObject("Outlook.Application")
Set xMailOut = xOutApp.CreateItem(olMailItem)
For I = 1 To xRg.Rows.Count
For J = 1 To xRg.Columns.Count
xEmailBody = xEmailBody & " " & xRg.Cells(I, J).Value
Next
xEmailBody = xEmailBody & vbNewLine
Next
xEmailBody = "Hi" & vbLf & vbLf & " body of message you want to add" & vbLf & vbLf & xEmailBody & vbNewLine
With xMailOut
.subject = "Test"
.To = ""
.CC = ""
.subject = "Productivity Report"
.body = xEmailBody
.Display
'.Send
End With
Set xMailOut = Nothing
Set xOutApp = Nothing
Application.ScreenUpdating = True
End Sub
Please check it and guide me where I am doing wrong. Thanks
Create a function to build the HTML and the code in your sub can be minimal.
Option Explicit
Sub Send_EmailFinal()
Dim xMailOut As Outlook.MailItem
Dim xOutApp As Outlook.Application
Set xOutApp = CreateObject("Outlook.Application")
Set xMailOut = xOutApp.CreateItem(olMailItem)
With xMailOut
.BodyFormat = olFormatHTML
.To = "###"
.CC = ""
.Subject = "Productivity Report"
.HTMLBody = ToHTML(ActiveSheet.Range("H5:L32"))
.Display
'.Send
End With
Set xMailOut = Nothing
Set xOutApp = Nothing
End Sub
Function ToHTML(rng As Range) As String
Dim row As Range, cell As Range
Dim n As Long, s As String
s = "<p>Good Afternoon</p><p>Please see your productivity for lastweek, " & _
"any questions or concerns please let me or Claudia know</p>"
' table header
s = s & "<table border=""1"" width=""50%"" cellspacing=""0"" cellpadding=""3"" align=""center"">" & _
"<tr align=""center"" bgcolor=""#CCCCCC"">"
Set row = rng.Rows(1)
For Each cell In row.cells
s = s & "<th>" & cell & "</th>"
Next
s = s & "</tr>" & vbCrLf
' data
For n = 2 To rng.Rows.Count
Set row = rng.Rows(n)
' skip blank lines
If Len(row.cells(1, 1)) > 0 Then
s = s & "<tr align=""center"">"
For Each cell In row.cells
s = s & "<td>" & cell & "</td>"
Next
s = s & "</tr>" & vbCrLf
End If
Next
ToHTML = s & "</table>"
End Function
For my limited applications, I am sending more basic emails that do not require the use of the Outlook object.
Try the following code that sends whatever is selected on your screen.
In a new workbook write something in several cells, select them then run the code (do not expect somebody to answer the from that email address).
Sub EmailSelectedRange()
ActiveWorkbook.EnvelopeVisible = True
With ActiveSheet.MailEnvelope
.Item.To = "ThisIsAFakeEmailAddress#ThisIsAFakeEmailAddress.com"
.Item.Subject = "This is the subject of the email"
.Introduction = "This is a text in the email"
.Item.Send
End With
End Sub

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

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

Adding conditions and optional input to an e-mail sending macro

I have a slight issue with a macro. It works fine at the moment, but I need to add some code to do the following but don't know at what point to add it:
If for each cell in Column C that there is a blank cell to look for the email address on the same row but 10 columns over to the right in Column M
In the start of the body "Hi There (Column B content)
In the body of the email I would like for the macro to insert the contents from column F like this: "Please choose the following option (Column F content)
Any Ideas on how I can modify the code to include these options please.
Thank you for your time.
Sub Send_Email()
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Dim cel As Range
Dim SigString As String
Dim Signature As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
SigString = Environ("appdata") & _
"\Microsoft\Signatures\GBS.txt"
If Dir(SigString) <> "" Then
Signature = GetBoiler(SigString)
Else
Signature = ""
End If
For Each cel In Range(("C2"), Range("C2").End(xlDown))
strbody = "Hi there" & vbNewLine & vbNewLine & _
"My name Is William, Please choose the following option ..." & vbNewLine & _
"I work at Fair" & vbNewLine & _
"Bye" & vbNewLine & _
"WH"
On Error Resume Next
With OutMail
.To = cel.Value
.CC = cel.Offset(0, 10).Value
'.BCC = ""
.Subject = "Choose you plan"
.Body = strbody & vbNewLine & vbNewLine & Signature
.Display
'.Attachments.Add ("C:\test.txt")
'.Send
End With
On Error GoTo 0
Next cel
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Try this one:
Sub Send_Email()
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Dim cel As Range
Dim SigString As String
Dim Signature As String
Dim lastrow As Long
Set OutApp = CreateObject("Outlook.Application")
SigString = Environ("appdata") & _
"\Microsoft\Signatures\GBS.txt"
If Dir(SigString) <> "" Then
Signature = GetBoiler(SigString)
Else
Signature = ""
End If
lastrow = Cells(Rows.Count, 3).End(xlUp).Row
For Each cel In Range("C2:C" & lastrow)
strbody = "Hi there" & cel.Offset(, -1) & vbNewLine & vbNewLine & _
"My name Is William, Please choose the following option ..." & vbNewLine & _
cel.Offset(, 3) & _
"I work at Fair" & vbNewLine & _
"Bye" & vbNewLine & _
"WH"
On Error Resume Next
With OutApp.CreateItem(0)
If cel.Value <> "" Then
.To = cel.Value
.CC = cel.Offset(0, 10).Value
Else
.To = cel.Offset(0, 10).Value & ", " & Join(Application.Index(cel.Offset(, -2).Resize(, 4).Value, 0), ", ")
End If
'.BCC = ""
.Subject = "Choose you plan"
.Body = strbody & vbNewLine & vbNewLine & Signature
.Display
'.Attachments.Add ("C:\test.txt")
'.Send
End With
On Error GoTo 0
Next cel
Set OutApp = Nothing
End Sub

Resources