Sending email based on cell values - excel

Is there a more efficient way to send email reminders based on a cell value that changes frequently?
'This is the main function
Sub notify()
Dim rng As Range
For Each rng In Range("F3:F14")
If (rng.Value = 1) Then
Call mymacro
End If
Next rng
End Sub
'-----------------------------------------------------------------------
'This is the function that sends an email when called by the main function
Private Sub mymacro()
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Hi there" & vbNewLine & vbNewLine & _
"This is line 1" & vbNewLine & _
"This is line 2"
On Error Resume Next
With xOutMail
.To = "email address"
.CC = ""
.BCC = ""
.Subject = "test succeeded"
.Body = xMailBody
.Display 'or use .Send
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub
Both codes are in the same module of my worksheet. The code sends an email (through Outlook) to the user. For example, if F3 and F7 evaluate to true, two emails will be sent to the user.
How can I, if the same situation occurs (F3 and F7 evaluate to true), the two email sent to the user would specify which cell evaluated to true. In other words, each email sent would be different in pointing out which specific cell evaluated to true.
Also, would the code be able to rerun if the data inside the cell ("F3:F14") is updated?

On refresh of query, the code should check each cell from F3 to F14 and see if it is equal to 1, if so, it will email user the cell location.
UPDATE:
'Need to be in the sheet code:
Private Sub Worksheet_Change(ByVal Target As Range)
Call notify
End Sub
Sub notify()
Dim rng As Range
For Each rng In Range("F3:F14")
If (rng.Value = 1) Then
Call mymacro(rng.Address)
End If
Next rng
End Sub
Private Sub mymacro(theValue 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 = "Hi there" & vbNewLine & vbNewLine & _
"The value that changed is in cell: " & theValue
On Error Resume Next
With xOutMail
.To = "email address"
.CC = ""
.BCC = ""
.Subject = "test succeeded"
.Body = xMailBody
.Display 'or use .Send
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub

Related

Send an email if the cell contains the word "expired"

I would like to use excel to send an email to the email address in column C from C5-C42 when the corresponding cell in column F contains the text "expired". I've been at this for over four days. I appreciate any help I can get.
I also keep getting a run-time error 424.
Below is my code:
Private Sub CommandButton1_Click()
If Target.Cells.Count > 1 Then Exit Sub
If Not Application.Intersect(Range("F5:F42"), Target) Is Nothing Then
If IsNumeric(Target.Value) And Target.Value = "Expired" Then
Call Mail_small_Text_Outlook
End If
End If
End Sub
Sub Mail_small_Text_Outlook()
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "Hi there" & vbNewLine & vbNewLine & _
"Your certification has expired." & vbNewLine & _
"Please contact an admin."
On Error Resume Next
With OutMail
.To = "emailaddress#net.com"
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.Body = strbody
.Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Try this:
Private Sub CommandButton1_Click()
Dim c As Range
For Each c In Range("F5:F42")
If c.Value2 = "Expired" Then Call Mail_small_Text_Outlook(c.Offset(0, -3).Value2)
Next c
End Sub
This first routine is triggered by the command button click. It cycles through each cell in range F5:F42. If the cell has "Expired" as a value, it calls the mail routine, and passes to it the value contained in column C (by using the F column address -3 columns)
Sub Mail_small_Text_Outlook(emailAddress As String)
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "Hi there" & vbNewLine & vbNewLine & _
"Your certification has expired." & vbNewLine & _
"Please contact an admin."
On Error Resume Next
With OutMail
.To = emailAddress
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.Body = strbody
.Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
The mail routine accepts an email address as a parameter and hopefully you'll notice it replaces the generic "email address.com" you had on the .To line
Please be aware that currently the code is creating a new instance of Outlook for every time it needs to send an e-mail, without closing it. I think you can quit Outlook simply with the line OutApp.Quit so try sticking that in at the end of the Mail_small_Text_Outlook routine

Need help using VBA to prompt an email send when product quantity gets too low

I am trying to use VBA to prompt the user to send an email to the administrator when the quantity of a products dips below the Reorder Quantity. All the parts are listed in a table in Excel and the Total Quantity column is next to the reorder quantity column. I have some code written, but I can't get the conditions to work to allow the email to pop up when the QTY drops below the Reorder QTY. My code is below. The issue I am having is that when the qty drops below the RO quantity, nothing is happening. Any advice? DISCLAIMER I am brand new to VBA, so I am sorry if this code is jibberish.
Private Sub Reorder_Change(ByVal Target As Range)
On Error Resume Next
If Target.Cells.Count > 1 Then Exit Sub
Dim xRg As Range
Set xRg = Intersect(Range("I5:I100"), Target)
If xRg Is Nothing Then Exit Sub
If IsNumeric(Target.Value) And Target.Value <= Application.WorksheetFunction.VLookup(Target.Value, Sheets("Inventory List").Range("I5:J52"), 2, False) Then
Call Mail_small_Text_Outlook
End If
End Sub
Sub Mail_small_Text_Outlook()
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Part needs to be reordered" & vbNewLine & vbNewLine & _
"Part Number: " & vbNewLine & _
"This is line 2"
On Error Resume Next
With xOutMail
.To = "ES ADMIN"
.CC = ""
.BCC = ""
.Subject = "Reorder parts!"
.Body = xMailBody
.Display 'or use .Send
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub

How to send email in loop?

I'm trying to send an email to selected recipient(s) based on if a cell in Excel meets specific criteria, in this instance "yes".
The code will only send to the first user in the range that it sees the "yes" criteria being met.
Sub Read_Emails()
' SET Outlook APPLICATION OBJECT.
Dim objOutlook As Object
Set objOutlook = CreateObject("Outlook.Application")
' CREATE EMAIL OBJECT.
Dim objEmail As Object
Set objEmail = objOutlook.CreateItem(olMailItem)
For Each cell In Columns("N").Cells.SpecialCells(xlCellTypeConstants)
If cell.Value Like "?*#?*.?*" And _
LCase(Cells(cell.Row, "R").Value) = "yes" Then
With objEmail
.To = cell.Value
.CC = ""
.Subject = "Subject here"
.BodyFormat = olFormatHTML
.HTMLBody = "Hello," & "<p>" & "Message here."
.Send
End With
End If
Next cell
Set objEmail = Nothing
Set objOutlook = Nothing
End Sub
I was able to troubleshoot this myself using https://www.rondebruin.nl/win/s1/outlook/bmail5.htm.
Code below for those interested in similar problem:
Dim OutApp As Object
Dim OutMail As Object
Dim cell As Range
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
On Error GoTo cleanup
For Each cell In Columns("L").Cells.SpecialCells(xlCellTypeConstants)
If cell.Value Like "?*#?*.?*" And _
LCase(Cells(cell.Row, "P").Value) = "yes" Then
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = cell.Value
.Subject = "Subject here"
.Body = "Hello " & Cells(cell.Row, "K").Value & "," _
& vbNewLine & vbNewLine & _
"Message here."
'You can add files also like this
'.Attachments.Add ("C:\test.txt")
.Send 'Or use Display
End With
On Error GoTo 0
Set OutMail = Nothing
End If
Next cell
cleanup:
Set OutApp = Nothing
Application.ScreenUpdating = True
End Sub

Send an automatic email from within Excel if a formula value met a condition

Could you please help me to automatically send an email from Excel only when the formula value in column M (=IF(VAL.EMPTY(K15);"";MAX(K15-Today();0))>200. Unfortunately the Sheet1 code triggers the email code if the condition is met (>200) in formula value cell in column M if the date in column K is altered manually or by writing manually Not Sent in column N. Instead my goal would be:
1) to understand why this code in sheet1 doesn't send the email automatically as supposed to do (the only thing it does is to put Sent in column N without sending the email. This make me think that this code works)
2) to find the way to send the email automatically without changing anything manually in the cells in my sheet1.
H I J K L M N
Date Score Description Next Due Status Days till
expiration
15 28/09/2017 13 Medium Risk 25/07/2018 Valid 284 Sent
16 11/10/2017 13 Medium Risk 10/08/2018 Valid 300 Sent
'Sheet1 (FormulaValueChange)
Private Sub Worksheet_Calculate()
Dim FormulaRange As Range
Dim NotSentMsg As String
Dim MyMsg As String
Dim SentMsg As String
Dim MyLimit As Double
NotSentMsg = "Not Sent"
SentMsg = "Sent"
'Above the MyLimit value it will run the macro
MyLimit = 200
'Set the range with the Formula that you want to check
Set FormulaRange = Me.Range("M15:M16")
On Error GoTo EndMacro:
For Each FormulaCell In FormulaRange.Cells
With FormulaCell
If IsNumeric(.Value) = False Then
MyMsg = "Not numeric"
Else
If .Value > MyLimit Then
MyMsg = SentMsg
If .Offset(0, 1).Value = NotSentMsg Then
Call Mail_with_outlook1(FormulaCell)
End If
Else
MyMsg = NotSentMsg
End If
End If
Application.EnableEvents = False
.Offset(0, 1).Value = MyMsg
Application.EnableEvents = True
End With
Next FormulaCell
ExitMacro:
Exit Sub
EndMacro:
Application.EnableEvents = True
MsgBox "Some Error occurred." _
& vbLf & Err.Number _
& vbLf & Err.Description
End Sub
'Mail Code
Option Explicit
Public FormulaCell As Range
Sub Mail_with_outlook1(FormulaCell As Range)
Dim OutApp As Object
Dim OutMail As Object
Dim strto As String, strcc As String, strbcc As String
Dim strsub As String, strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strto = "tom#something.abc"
strcc = ""
strbcc = ""
strsub = "Assessement reminders"
strbody = "Thanks a lot"
With OutMail
.To = strto
.CC = strcc
.BCC = strbcc
.Subject = strsub
.Body = strbody
'You can add a file to the mail like this
'.Attachments.Add ("C:\test.txt")
.Display ' or use .Send
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
You can do it this way.
Sub Mail_small_Text_Outlook()
'For Tips see: http://www.rondebruin.nl/win/winmail/Outlook/tips.htm
'Working in Excel 2000-2016
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "Hi there" & vbNewLine & vbNewLine & _
"Cell A1 is changed" & vbNewLine & _
"This is line 2" & vbNewLine & _
"This is line 3" & vbNewLine & _
"This is line 4"
On Error Resume Next
With OutMail
.To = "ron#debruin.nl"
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.Body = strbody
'You can add a file like this
'.Attachments.Add ("C:\test.txt")
.Display 'or use .Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
https://www.rondebruin.nl/win/s1/outlook/bmail9.htm

How to skip current cell in a for each loop

In excel I have the following code which sends out emails for every cell that contains an email address in column K.
This would work except for the header in the table isn't an email address, so it breaks the code. I tried to skip the header by specifying "if cell.value = CONTACT METHOD, which is the header name text, then go to Next cell"
but this causes a "Next without for" error.
Sub Mail_small_Text_Outlook()
'For Tips see: http://www.rondebruin.nl/win/winmail/Outlook/tips.htm
'Working in Office 2000-2013
Dim OutApp As Object
Dim OutMail As Object
Dim cell As Range
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
On Error GoTo cleanup
For Each cell In Columns("K").Cells.SpecialCells(xlCellTypeConstants)
If cell.Value Like "*#*" Then
finaladdress = cell.Value
Else
finaladdress = cell.Value & "#email.smsglobal.com"
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = finaladdress
.Subject = "Reminder"
.Body = "Dear " & Cells(cell.Row, "A").Value _
& vbNewLine & vbNewLine & _
"Please contact us to discuss bringing " & _
"your account up to date"
'You can add files also like this
'.Attachments.Add ("C:\test.txt")
.Display
End With
On Error GoTo 0
Set OutMail = Nothing
End If
Next cell
cleanup:
Set OutApp = Nothing
Application.ScreenUpdating = True
End Sub
If your goal is to skip cell K1 in looping down column K then:
For Each cell In Columns("K2:K" & Rows.Count).Cells.SpecialCells(xlCellTypeConstants)
You can enclose the code within the FOR/EACH loop within a separate IF statement, as below:
Sub Mail_small_Text_Outlook()
'For Tips see: http://www.rondebruin.nl/win/winmail/Outlook/tips.htm
'Working in Office 2000-2013
Dim OutApp As Object
Dim OutMail As Object
Dim cell As Range
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
On Error GoTo cleanup
For Each cell In Columns("K").Cells.SpecialCells(xlCellTypeConstants)
If cell.Value = "CONTACT METHOD" Then
'Do Nothing, or Enter code here
Else
If cell.Value Like "*#*" Then
finaladdress = cell.Value
Else
finaladdress = cell.Value & "#email.smsglobal.com"
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = finaladdress
.Subject = "Reminder"
.Body = "Dear " & Cells(cell.Row, "A").Value _
& vbNewLine & vbNewLine & _
"Please contact us to discuss bringing " & _
"your account up to date"
'You can add files also like this
'.Attachments.Add ("C:\test.txt")
.Display
End With
On Error GoTo 0
Set OutMail = Nothing
End If
End If
Next cell
cleanup:
Set OutApp = Nothing
Application.ScreenUpdating = True
End Sub

Resources