VBA - Remove Seconds from NOW function - excel

I have something that notify me an hour before it happens. For that, I use the NOW function in VBA as I need it to check for the Date as well.
The problem is the script runs every 20 seconds so I can't have it consider seconds for the NOW function.
Is there a way to remove those? To have only like (DAY,MONTH,YEAR,HOUR,MINUTE)?
Something along those lines:
MyLimit = NOW(DAY,MONTH,YEAR,HOUR,MINUTE)
For Each FormulaCell In FormulaRange.Cells
With FormulaCell
If .Value = MyLimit Then
Call Notify
Here is the script in which I attempt to detect the date and time.
Option Explicit
Public Function AutoRun()
Application.OnTime Now + TimeValue("00:00:20"), "TaskTracker2"
End Function
Public Sub TaskTracker2()
Dim FormulaCell As Range
Dim FormulaRange As Range
Dim NotSentMsg As String
Dim MyMsg As String
Dim SentMsg As String
Dim SendTo As String
Dim CCTo As String
Dim BCCTo As String
Dim MyLimit As Date
NotSentMsg = "Not Sent"
SentMsg = "Sent"
SendTo = Range("D2")
CCTo = Range("E2")
BCCTo = Range("F2")
MyLimit = Format((Now), "DD/MM/YYYY HH:MM")
Set FormulaRange = Range("E5:E35")
On Error GoTo EndMacro:
For Each FormulaCell In FormulaRange.Cells
With FormulaCell
If .Value = MyLimit Then
MyMsg = SentMsg
If .Offset(0, 1).Value = NotSentMsg Then
strTO = SendTo
strCC = CCTo
strBCC = BCCTo
strSub = "[Task Manager] Reminder that you need to: " & Cells(FormulaCell.Row, "A").Value
strBody = "Hello Sir, " & vbNewLine & vbNewLine & _
"This email is to notify that you that your task : " & Cells(FormulaCell.Row, "A").Value & " with the following note: " & Cells(FormulaCell.Row, "B").Value & " is nearing its Due Date." & vbNewLine & "It would be wise to complete this task before it expires!" & _
vbNewLine & vbNewLine & "Truly yours," & vbNewLine & "Task Manager"
If sendMail(strTO, strSub, strBody, strCC) = True Then MyMsg = SentMsg
End If
Else
MyMsg = NotSentMsg
End If
Application.EnableEvents = False
.Offset(0, 1).Value = MyMsg
Application.EnableEvents = True
End With
Next FormulaCell
AutoRun
ExitMacro:
Exit Sub
EndMacro:
Application.EnableEvents = True
MsgBox "Some Error occurred." _
& vbLf & Err.Number _
& vbLf & Err.Description
End Sub

To strip the seconds off Now, you can use some maths or to-and-from text conversion.
CDate(format(Now, "dd-mmm-yyyy hh:mm"))
'... or,
CLng(Now * 1440)/1440
Both of those return a true, numerical datetime value with the seconds stripped off. They do not average the seconds to the nearest minute; simply remove them.

You could just round MyLimit to the nearest minute:
MyLimit = Round(Now * 1440, 0) / 1440
Consider, when comparing it to the contents of a cell, that you might need to use a <= or >= comparison to avoid problems if the time changes at the "wrong" time for an equality to hold true.

Another method would be this:
MyLimit = now-second(now)/60/60/24
second(now) returns the seconds, and the /60/60/24 converts it to days, which every date and time is stored in. Use this or Jeeped's answer, any one of these should work.
Edit:
To avoid the tiny but existing possibility of error, use this:
MyLimit = now
MyLimit =MyLimit -second(MyLimit)/60/60/24

Try limit = Format((Now), "DD/MM/YYYY HH:MM")

Use the Date function instead of the NOW function
https://msdn.microsoft.com/en-us/library/aa227520(v=VS.60).aspx
UPDATE

I usually just go with the function =TIME(HOUR(NOW()),MINUTE(NOW()),0)

Alternative approach per VBA Office 2010 and later:
Dim DateWithoutSeconds : DateWithoutSeconds = DateAdd("s",-Second(Now),Now)
Notice that the minus (-) removes the seconds.
More info at https://msdn.microsoft.com/en-us/library/office/gg251759.aspx

Related

Copy row from one sheet to another when a cell value is negative

I have code in which if column I, it will look at that value and then send an email if it matches any of my limits. Then I have also included a refresh anytime I edit another column.
This code is in ThisWorkbook
Private Sub Workbook_Open()
Call Worksheet_Calculated
End Sub
This is my code in Sheet1 that will run the operation if anything in column G changes.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address Like "$F$*" Then
Call Worksheet_Calculated
End If
End Sub
This code is in a module. It checks to see if any value in column I is any of of the MyLimit Values, if it is, in column I, it will say sent or not sent. If sent, an email will be generated.
Option Explicit
Public Sub Worksheet_Calculated()
Dim FormulaRange As Range
Dim NotSentMsg As String
Dim MyMsg As String
Dim SentMsg As String
Dim MyLimita As Double
Dim MyLimitb As Double
Dim MyLimitc As Double
Dim MyLimitd As Double
NotSentMsg = "Not Sent"
SentMsg = "Sent"
'Above the MyLimit value it will run the macro
MyLimita = 100
MyLimitb = 50
MyLimitc = 10
MyLimitd = 1
'Set the range with Formulas that you want to check
'This is the column that shows how many days left
Set FormulaRange = Range("H5:H25")
On Error GoTo EndMacro:
For Each FormulaCell In FormulaRange.Cells
With FormulaCell
If IsNumeric(.Value) = False Then
MyMsg = ""
ElseIf (.Value = MyLimita Or .Value = MyLimitb Or .Value = MyLimitc Or .Value = MyLimitd) Then
MyMsg = SentMsg
If .Offset(0, 1).Value = NotSentMsg Then
Call Mail_with_outlook(FormulaCell)
End If
Else
MyMsg = NotSentMsg
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
The above code will call another module which will populate the email that I would like to send.
Option Explicit
Public FormulaCell As Range
Public Sub Mail_with_outlook(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)
'Change the parenthesis for column that the email is in
strto = Cells(FormulaCell.Row, "K").Value
strcc = ""
strbcc = ""
strsub = "Payment Notification (PO --Enter PO # Here--)"
'Change the parenthesis for the Column that the POC is in
strbody = "Hi " & Cells(FormulaCell.Row, "J").Value & vbNewLine & vbNewLine & _
"This is a reminder to pay for a licensing/maintenance bill in: " & Cells(FormulaCell.Row, "H").Value & " days." & _
vbNewLine & vbNewLine & "Line 2" & _
vbNewLine & "Line 3" & _
vbNewLine & "Line 4" & _
vbNewLine & "Line 5" & _
vbNewLine & "Line 6"
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
I want to continue running this code on start up and whenever column G is edited, but only in Sheet1.
I want when column I is negative to copy that entire row into sheet2.

VBE Start macro on startup and then after that, once a certain column (G) is edited everyday

In VBE, I have a spreadsheet where if the column 'I' reaches 'MyLimit_', then i will automatically get an email. I am trying to make this code run only when I change a certain column (G).
This code is for the sheet.
In column I, I am looking at the these values to see if they equal my limit. if they do, it will trigger and email being generated.
Option Explicit
Private Sub Worksheet_Calculate()
Dim FormulaRange As Range
Dim NotSentMsg As String
Dim MyMsg As String
Dim SentMsg As String
Dim MyLimita As Double
Dim MyLimitb As Double
Dim MyLimitc As Double
Dim MyLimitd As Double
NotSentMsg = "Not Sent"
SentMsg = "Sent"
'Above the MyLimit value it will run the macro
MyLimita = 100
MyLimitb = 50
MyLimitc = 10
MyLimitd = 1
'Set the range with Formulas that you want to check
'This is the column that shows how many days left
Set FormulaRange = Me.Range("I5:I25")
On Error GoTo EndMacro:
For Each FormulaCell In FormulaRange.Cells
With FormulaCell
If IsNumeric(.Value) = False Then
MyMsg = ""
ElseIf .Value = MyLimita Then
MyMsg = SentMsg
If .Offset(0, 1).Value = NotSentMsg Then
Call Mail_with_outlook
End If
ElseIf .Value = MyLimitb Then
MyMsg = SentMsg
If .Offset(0, 1).Value = NotSentMsg Then
Call Mail_with_outlook
End If
ElseIf .Value = MyLimitc Then
MyMsg = SentMsg
If .Offset(0, 1).Value = NotSentMsg Then
Call Mail_with_outlook
End If
ElseIf .Value = MyLimitd Then
MyMsg = SentMsg
If .Offset(0, 1).Value = NotSentMsg Then
Call Mail_with_outlook
End If
Else
MyMsg = NotSentMsg
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
This code is what I put into the module. This is basically all the code I used to generate my email and then populate with the appropriate info.
Option Explicit
Public FormulaCell As Range
Sub Mail_with_outlook()
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)
'Change the parenthesis for column that the email is in
strto = Cells(FormulaCell.Row, "L").Value
strcc = ""
strbcc = ""
strsub = "Payment Notification (PO --Enter PO # Here--)"
'Change the parenthesis for the Column that the POC is in
strbody = "Hi " & Cells(FormulaCell.Row, "K").Value & vbNewLine & vbNewLine & _
"This is a reminder to pay for a licensing/maintenance bill in: " & Cells(FormulaCell.Row, "I").Value & " days." & _
vbNewLine & vbNewLine & "Line 2" & _
vbNewLine & "Line 3" & _
vbNewLine & "Line 4" & _
vbNewLine & "Line 5" & _
vbNewLine & "Line 6"
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 run a code automatically when the workbook is opened by calling it from the Workbook_Open() procedure.
The Worksheet_Change(ByVal Target As Range) procedure fires every time there's a chance, and then you can use the Address property of Target to see if the change was within Column G.
In the ThisWorkbook module:
Private Sub Workbook_Open()
Call YourProcedureName
End Sub
In a Sheet module:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address Like "$G$*" Then
Call YourProcedureName
End If
End Sub
In a regular module:
Public Sub YourProcedureName()
'Your code here
End Sub

Sending an email for values that exceed a limit

When I try to execute the following code, the debugger is highlighting the line strbody which decides which cells get output to the email.
I'm not sure how to activate the FormulaCell so that when a value is exceeded in a column this row will be able to used to enter information to the email.
Option Explicit
Public FormulaCell As Range
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 = 1
'Set the range with Formulas that you want to check
Set FormulaRange = Me.Range("B3:B197")
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_outlook2
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
MACRO
Option Explicit
Public FormulaCell As Range
Sub Mail_with_outlook1()
'For mail code examples visit my mail page at:
'http://www.rondebruin.nl/sendmail.htm
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 = "ron#something.abc"
strcc = ""
strbcc = ""
strsub = "Customers"
strbody = "Hi Ron" & vbNewLine & vbNewLine & _
"The total Customers of all stores this week is : " & Cells(FormulaCell.row, "B").Value & _
vbNewLine & vbNewLine & "Good job"
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
Sub Mail_with_outlook2()
'For mail code examples visit my mail page at:
'http://www.rondebruin.nl/sendmail.htm
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 = "MAIL#EMAIL.CO.UK"
strcc = ""
strbcc = ""
strsub = "S888 OVERDUE"
strbody = "THIS S888 IS NOW OVERDUE" & Cells(FormulaCell.row, "A").Value & vbNewLine & vbNewLine & _
"Your total of this week is : " & Cells(FormulaCell.row, "K:Q").Value & _
vbNewLine & vbNewLine & "HURRY UP!!"
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
as Vityata already stated, the expression Cells(FormulaCell.row, "K:Q").Value isn't valid
if you need a reference to cells in column K to Q in the same row as FormulaCell Range then use
Worksheetfunction.Sum(Intersect(FormulaCell.EntireRow, Range("K:Q")))
So if you wanted to return the sum of those cells then use
strbody = "THIS S888 IS NOW OVERDUE" & Cells(FormulaCell.row, "A").Value & vbNewLine & vbNewLine & _
"Your total of this week is : " & Worksheetfunction.Sum(Intersect(FormulaCell.EntireRow, Range("K:Q"))) & _
vbNewLine & vbNewLine & "HURRY UP!!"
But there I see a hidden bug in your code where you use Public FormulaCell As Range both in Worksheet_Calculate() event handler and in your "MACRO" Module
By doing so, in you're instantiating two different Range variables, one attached to the worksheet event handler and one to the MACRO module, and without explicitly qualifying them up to their Parent object you would reference the Range variable in the currently "active" VBA module.
So, in your code before executing Call Mail_with_outlook2 statement, any FormulaCell would reference the current iterator Range variable of your For Each FormulaCell In FormulaRange.Cells loop. But as soon as the program execution gets into Mail_with_outlook2() the "resident" FormulaCell variable is still to be set and so it's Nothing
Long story short you have two choices:
get rid of Public FormulaCell As Range in MACRO module and explicitly qualify all FormulaCell references up to the Sheet object where the Worksheet_Calculate() resides
for example, assuming "Sheet1" is the name of this latter, then you'd write:
strbody = "Hi Ron" & vbNewLine & vbNewLine & _
"The total Customers of all stores this week is : " & Cells(Worksheets("Sheet1").FormulaCell.Row, "B").value & _
vbNewLine & vbNewLine & "Good job"
get rid of all Public FormulaCell As Range in both Worksheet and MACRO module and have Mail_with_outlook1() sub accept a "FormulaCell" Range parameter
so in Worksheet_Calculate(), instead of:
Call Mail_with_outlook2
you'd have:
Mail_with_outlook2 FormulaCell
and in Mail_with_outlook1(), instead of:
Sub Mail_with_outlook1()
you'd have
Sub Mail_with_outlook1(FormulaCell As Range)
The error is in this here:
Cells(FormulaCell.row, "K:Q").Value Depending on what you need, try like this:
Cells(FormulaCell.Row, "K").Value
Range("K" & FormulaCell.Row & ":Q" & FormulaCell.Row).Values
Or something else.
In general, whenever you think that the error is somewhere you know, try to make the code as smaller as possible and to see whether it runs. In your case something small is this one:
Public Sub TestMe()
Dim strBody As String
For Each FormulaCell In Range("A1:A2")
strBody = "Hi Ron" & vbNewLine & vbNewLine & _
"The total Customers of all stores this week is : " _
& Cells(FormulaCell.Row, "B").Value & _
vbNewLine & vbNewLine & "Good job"
Debug.Print strBody
Next FormulaCell
End Sub

Application.Ontime Cancel Fails to Method 'ONTIME' of Object 'Application'

I am completely lost so any help will be greatly appreciated.
I am attempting to cancel 2 scheduled event that are triggered when the Workbook is opened, and repeated using the Application.Ontime method.
I know that to terminate the OnTime schedule loop, you must provide the exact time that it is scheduled to run and that having multiple Application.OnTime tasks requires multiple variables.
This is why I have set two Public variables (Header of the document below Options Explicit):
Dim dTime as Date
Dim dTime2 as Date
The scheduler use these Variables and everything works properly as the code runs every minute.
dTime's value is set inside the TaskTracker function to be:
dTime = Now() + TimeValue("00:01:00")
Application.OnTime dTime, "TaskTracker", , True
dTime2's value is set inside the Autoclear function to be:
dTime2 = Now() + TimeValue("00:01:00")
Application.OnTime dTime, "AutoClear", , True
Despite all this, I get a Method 'ONTIME' of Object'Application' error message when attempting to run the function at the end of the module:
Function AutoDeactivate()
Application.OnTime EarliestTime:=dTime, Procedure:="TaskTracker", _
Schedule:=False
Application.OnTime EarliestTime:=dTime2, Procedure:="AutoClear", _
Schedule:=False
End Function
This is where I absolutely do not get what is going wrong. Triggering the Debug brings me to the OnTime section of each procedure cancel attempt.
Below is the script that contains these elements. Hopefully this will give you guys some insight as to why these event can't be canceled.
Option Explicit
Dim dTime As Date
Dim dTime2 As Date
'------------------------------------------------------------
'This is what checks cells to define if an email notification has to be sent, and what the content of that email should be.
'------------------------------------------------------------
Function TaskTracker()
Dim FormulaCell As Range
Dim FormulaRange As Range
Dim NotSentMsg As String
Dim MyMsg As String
Dim SentMsg As String
Dim SendTo As String
Dim CCTo As String
Dim BCCTo As String
Dim MyLimit As Double
Dim MyLimit2 As Double
dTime = Now() + TimeValue("00:01:00")
NotSentMsg = "Not Sent"
SentMsg = "Sent"
SendTo = ThisWorkbook.Worksheets("Tasks").Range("D2")
CCTo = ThisWorkbook.Worksheets("Tasks").Range("E2")
BCCTo = ThisWorkbook.Worksheets("Tasks").Range("F2")
MyLimit = Date
MyLimit2 = ((Round(Now * 1440, 0) - 30) / 1440)
Set FormulaRange = ThisWorkbook.Worksheets("Tasks").Range("F5:F35")
On Error GoTo EndMacro:
For Each FormulaCell In FormulaRange.Cells
With FormulaCell
If DateValue(CDate(.Value)) = MyLimit Then
MyMsg = SentMsg
If .Offset(0, 1).Value = NotSentMsg Then
strTO = SendTo
strCC = CCTo
strBCC = BCCTo
strSub = "[Task Manager] Reminder that you need to: " & Cells(FormulaCell.Row, "B").Value
If Cells(FormulaCell.Row, "C").Value = "" Then
strBody = "Greetings, " & vbNewLine & vbNewLine & _
"Your task : " & Cells(FormulaCell.Row, "B").Value & " is nearing its Due Date: " & Cells(FormulaCell.Row, "F").Value & "." & vbNewLine & "A wise decision would be to complete this task before it expires!" & _
vbNewLine & vbNewLine & "Truly yours," & vbNewLine & "Task Manager"
Else
strBody = "Hello, " & vbNewLine & vbNewLine & _
"Your task : " & Cells(FormulaCell.Row, "B").Value & " with the mention: " & Cells(FormulaCell.Row, "C").Value & " is nearing its Due Date: " & Cells(FormulaCell.Row, "F").Value & "." & vbNewLine & "A wise decision would be to complete this task before it expires!" & _
vbNewLine & vbNewLine & "Truly yours," & vbNewLine & "Task Manager"
End If
If sendMail(strTO, strSub, strBody, strCC) = True Then MyMsg = SentMsg
End If
Else
MyMsg = NotSentMsg
End If
If .Value = MyLimit2 Then
MyMsg = NotSentMsg
End If
Application.EnableEvents = False
.Offset(0, 1).Value = MyMsg
Application.EnableEvents = True
End With
Next FormulaCell
ExitMacro:
Exit Function
EndMacro:
Application.EnableEvents = True
MsgBox "Some Error occurred." _
& vbLf & Err.Number _
& vbLf & Err.Description
Application.OnTime dTime, "TaskTracker", , True
End Function
'------------------------------------------------------------
'This is the function that clears the rows of Completed Tasks
'------------------------------------------------------------
Function AutoClear()
Dim i As Integer
dTime2 = Now() + TimeValue("00:01:00")
With Tasks
For i = 5 To 35
If .Cells(i, 4).Value Like "Done" And .Cells(i, 5).Value = "1" Then
.Cells(i, 1).ClearContents
.Cells(i, 2).ClearContents
.Cells(i, 3).ClearContents
.Cells(i, 5).ClearContents
.Cells(i, 6).ClearContents
.Cells(i, 4).Value = "Pending"
.Cells(i, 7).Value = "Not Sent"
End If
Next i
End With
Tasks.AutoFilter.ApplyFilter
Application.OnTime dTime2, "AutoClear", , True
End Function
'------------------------------------------------------------
'ThisWorkbook calls this to deactivate the Application.OnTime. This "should" prevent the Excel process from reoppening the worksheets.
'------------------------------------------------------------
Function AutoDeactivate()
On Error Resume Next
Application.OnTime EarliestTime:=dTime, Procedure:="TaskTracker", _
Schedule:=False
Application.OnTime EarliestTime:=dTime2, Procedure:="AutoClear", _
Schedule:=False
End Function
It looks like it was a setup mistake!
Option Explicit
Dim dTime As Date
Dim dTime2 As Date
Application.OnTime dTime, "TaskTracker", , True
Application.OnTime dTime2, "AutoClear", , True
With the AutoDeactivation function called when the workbook closes does work as intended!
Function AutoDeactivate()
On Error Resume Next
Application.OnTime EarliestTime:=dTime, Procedure:="TaskTracker", _
Schedule:=False
Application.OnTime EarliestTime:=dTime2, Procedure:="AutoClear", _
Schedule:=False
End Function
Workbook_BeforeClose:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Call AutoDeactivate
End Sub
What was happening is pretty idiotic. I had an issue with canceling the event at Work, so I took the Excel Sheet home and coded the fix found above. Yet, it still didn't work. Not because there was a mistake in it, but because I didn't have Outlook at home! :P
Not having the Outlook application prevented the event from being rescheduled after running once (resulting in an auto-dismissed ActiveX error message).
So as soon as I took this script back to work (where Outlook is installed) and everything worked properly :)
Marking this as resolved by myself haha.

sending an auto mail from excel based on multiple conditions

I am a VBA novice so thanks in advance for anyone who can help me here. Basically I am using an adapted Ron de Bruin piece of code to automatically send a mail to students when their attendance drops below a certain level as displayed in a particlular excel cell. So far, so good, the Ron de Bruin stuff looks after this.
But there is another criterion which I want to add and that is basically to only send the mail if there is also a letter 'Y' in a different cell in the same row as the attendance.
To summarize, I only want the mail to go to people who fulfill the two criteria, 1)dropping below a certain level, and 2)having a 'Y' in another cell, but the code at the moment only accounts for the first criterion. Huge thanks. Alun (code below)
Option Explicit
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 = 80
'Set the range with Formulas that you want to check
Set FormulaRange = Me.Range("BH279:BH280")
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_outlook2
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
If .Value2 < MyLimit And Not .EntireRow.Find(What:="Y", LookIn:=xlValues, LookAt:=xlWhole) Is Nothing Then Call Mail_with_outlook2
'If you look for the complementer solution, remove the " Not"
You look for the value "Y" in the same row.
I'd recommend setting output variables as well to the mailing macro Call Mail_with_outlook2(emailaddress, name, title, MyValue).

Resources