I have looked into previous answers and tried many variations on the below, but I cannot seem to get it to work.
Basically, the purpose of the script below is to turn Outlook reminders into e-mail messages.
However, I cannot seem to programmatically dismiss the reminders. I've looked into prior answers to these questions (such as this one) and attempted to implement them, but they don't seem to succeed in this configuration.
' declare this object withEvents displaying all the events
Private WithEvents olRemind As Outlook.Reminders
Private Sub Application_Reminder(ByVal Item As Object)
Dim objMsg As MailItem
Dim objRem As Reminder
Dim olRemind As Reminders
Set olRemind = Outlook.Reminders
Set objMsg = Application.CreateItem(olMailItem)
objMsg.To = "*ADDRESS REMOVED FROM EXAMPLE*"
objMsg.subject = "MHReminder: " + Item.subject
objMsg.Body = Item.Body
Set objMsg.SaveSentMessageFolder = Session.GetDefaultFolder(olFolderDeletedItems)
objMsg.Send
Set objMsg = Nothing
End Sub
Private Sub olRemind_BeforeReminderShow(Cancel As Boolean)
For Each objRem In olRemind
If objRem.IsVisible = True Then
objRem.Dismiss
Cancel = True
End If
Exit For
Next objRem
End Sub
I'm a bit more of a "kludge-and-splice" programmer than a true programmer, so would appreciate anyone pointing out my (hopefully obvious) errors.
Thank you ...
You are looking at the first found reminder then quitting with
Exit For
As in the example you found Dismiss Outlook reminder you will need something like
For Each objRem In objRems
If objRem.Caption = "TESTING" Then ' <--
If objRem.IsVisible Then
objRem.Dismiss
End If
Exit For
End If
Next objRem
Cancel parameter in the BeforeReminderShow event handler needs to be ByRef.
Related
I could use assistance modifying the Outlook VBA macro. Any time I reply to an e-mail from any of my multiple e-mail accounts the script will change the sender address to the one specified (i.e. user#domain.com on behalf of group#domain.com). I like this behavior but need help making a change so that this script only runs when I am sending from an email address #domain.com. Essentially I would like the macro to have an if statement specifying if sending from an #domain.com email account then run the macro otherwise if sending from another email account i.e. user#gmail.com do not run the macro.
'================================================================================
'Description: Outlook macro to automatically set a different
' From address.
'
'Comment: You can set the email address at the bottom of the code.
' Uncomment the myOlExp_InlineResponse sub to also make it
' work with the Reading Pane reply feature of Outlook 2013/2016/2019/365.
'
' author : Robert Sparnaaij
' version: 1.1
' website: https://www.howto-outlook.com/howto/setfromaddress.htm
'================================================================================
Dim WithEvents objInspectors As Outlook.Inspectors
Dim WithEvents objMailItem As Outlook.MailItem
Dim WithEvents myOlExp As Outlook.Explorer
Private Sub Application_Startup()
Initialize_handler
End Sub
Public Sub Initialize_handler()
Set objInspectors = Application.Inspectors
Set myOlExp = Application.ActiveExplorer
End Sub
Private Sub objInspectors_NewInspector(ByVal Inspector As Inspector)
If Inspector.CurrentItem.Class = olMail Then
Set objMailItem = Inspector.CurrentItem
If objMailItem.Sent = False Then
Call SetFromAddress(objMailItem)
End If
End If
End Sub
'Uncomment the next 3 lines to enable Outlook 2013/2016/2019/365 Reading Pane Reply
'Private Sub myOlExp_InlineResponse(ByVal objItem As Object)
' Call SetFromAddress(objItem)
'End Sub
Public Sub SetFromAddress(oMail As Outlook.MailItem)
' Set your preferred default From address below.
' Exchange permissions determine if it is actually stamped
' as "Sent On Behalf Of" or "Sent As".
' The address is not properly updated for the InlineResponse
' feature in Outlook 2013/2016/365. This is only a visual bug.
oMail.SentOnBehalfOfName = "delegate#domain.com"
End Sub
Navigate the folder tree up to the email address folder.
This should be objMailItem.Parent.Parent.
Private Sub objInspectors_NewInspector(ByVal Inspector As Inspector)
If Inspector.currentItem.Class = olMail Then
Set objMailItem = Inspector.currentItem
If objMailItem.Sent = False Then
Debug.Print objMailItem.Parent.Parent
If InStr(LCase(objMailItem.Parent.Parent), LCase("#domain.com")) Then
Call SetFromAddress(objMailItem)
End If
End If
End If
End Sub
If you want to handle outgoing emails you need to subscribe to the ItemSend event of the Application class which is fired whenever an Microsoft Outlook item is sent, either by the user through an Inspector (before the inspector is closed, but after the user clicks the Send button) or when the Send method for an Outlook item, such as MailItem, is used in a program.
Public WithEvents myOlApp As Outlook.Application
Public Sub Initialize_handler()
Set myOlApp = Outlook.Application
End Sub
Private Sub myOlApp_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim prompt As String
prompt = "Are you sure you want to send " & Item.Subject & "?"
If MsgBox(prompt, vbYesNo + vbQuestion, "Sample") = vbNo Then
Cancel = True
End If
End Sub
In the event handler you may check out the MailItem.SendUsingAccount property which allows setting an Account object that represents the account under which the MailItem is to be sent. The SendUsingAccount property can be used to specify the account that should be used to send the MailItem when the Send method is called.
Depending on the account set on the mail item you may want to set the MailItem.SentOnBehalfOfName property which returns a string indicating the display name for the intended sender of the mail message. You may need to cancel the default action and re-submit the item anew programmatically.
For anyone who finds this.
This should work if you already have the primary account setup in outlook and the account you want to send from has "send on behalf" or "send as" permission:
Dim WithEvents objInspectors As Outlook.Inspectors
Dim WithEvents objMailItem As Outlook.MailItem
Dim WithEvents myOlExp As Outlook.Explorer
Private Sub Application_Startup()
Initialize_handler
End Sub
Public Sub Initialize_handler()
Set objInspectors = Application.Inspectors
Set myOlExp = Application.ActiveExplorer
End Sub
Private Sub objInspectors_NewInspector(ByVal Inspector As Inspector)
If Inspector.CurrentItem.Class = olMail Then
Set objMailItem = Inspector.CurrentItem
If objMailItem.Sent = False Then
Call SetFromAddress(objMailItem)
End If
End If
End Sub
'Uncomment the next 3 lines to enable Outlook 2013/2016/2019/365 Reading Pane Reply
'Private Sub myOlExp_InlineResponse(ByVal objItem As Object)
'Call SetFromAddress(objItem)
'End Sub
Public Sub SetFromAddress(oMail As Outlook.MailItem)
' Set your preferred default From address below.
' Exchange permissions determine if it is actually stamped
' as "Sent On Behalf Of" or "Sent As".
' The address is not properly updated for the InlineResponse
' feature in Outlook 2013/2016/365. This is only a visual bug.
If oMail.SendUsingAccount = "primary#domain" Then
oMail.SentOnBehalfOfName = "delegate#domain"
End If
End Sub
I am looking for a way that when performing any email action (new email, reply, reply all, forward, etc.) that the CC field gets filled with an email "example#domain.com" before actually sending the email (an Outlook rules adds the CC after sending the email so this does not work)
Reason for adding the CC before the email is sent is so that the user has the ability to remove "examlle#domain.com" if the email is confidential
Any help is greatly appreciated as I have been searching for hours!
I am unsure of your level of VBA experience but here is a question that was asked on Stack Overflow that contains all the basis of what you want to do.
Add CC
The only things to change would be adding the other actions(currently the code use .forward only): New Email, Reply and Reply All.
Be sure to use .Display and not .Send, so that way the email will be displayed and the sender can then edit what he wants before sending the email.
[EDIT]
Option Explicit
Private WithEvents oExpl As Explorer
Private WithEvents oItem As MailItem
Private bDiscardEvents As Boolean
Dim oResponse As MailItem
'to start the macro when outlook starts
Private Sub Application_Startup()
Set oExpl = Application.ActiveExplorer
bDiscardEvents = False
End Sub
Private Sub oExpl_SelectionChange()
On Error Resume Next
Set oItem = oExpl.Selection.Item(1)
End Sub
'on Reply
Private Sub oItem_Reply(ByVal Response As Object, Cancel As Boolean)
Cancel = True
bDiscardEvents = True
Set oResponse = oItem.Reply
afterReply
End Sub
'on Forward
Private Sub oItem_Forward(ByVal Response As Object, Cancel As Boolean)
Cancel = True
bDiscardEvents = True
Set oResponse = oItem.Forward
afterReply
End Sub
'On Reply All
Private Sub oItem_ReplyAll(ByVal Response As Object, Cancel As Boolean)
Cancel = True
bDiscardEvents = True
Set oResponse = oItem.ReplyAll
afterReply
End Sub
Private Sub afterReply()
oResponse.Display
' do whatever here with .to, .cc, .cci, .subject, .HTMLBody, .Attachements.Add, etc.
oResponse.CC = "example#domain.com"
End Sub
Here is the code I put together and tested in my environnement. Just paste it in your VBA editor under ThisOutlookSession. To lauch it click inside the Application_Startup Sub and hit play. It was heavily inspired by another code I found a while back. I do not have the source however. With this everytime you starup Outlook it should start automatically.
#LaZoR_Bear
From some code I found online a while ago to solve this purpose (automatically change the from address on all new emails, replies, reply all, forwards, etc.), I finally figured out the syntax to make it CC on new emails (but your code is still required so thank you again for that).
Code solely to change the from address:
'=================================================================
'Description: Outlook macro to automatically set a different
' From address.
'
'Comment: You can set the email address at the bottom of the code.
' Uncomment the myOlExp_InlineResponse sub to also make it
' work with the Reading Pane reply feature of Outlook 2013/2016/365.
'
' author : Robert Sparnaaij
' version: 1.1
' website: https://www.howto-outlook.com/howto/setfromaddress.htm
'=================================================================
Dim WithEvents objInspectors As Outlook.Inspectors
Dim WithEvents objMailItem As Outlook.MailItem
Dim WithEvents myOlExp As Outlook.Explorer
Private Sub Application_Startup()
Initialize_handler
End Sub
Public Sub Initialize_handler()
Set objInspectors = Application.Inspectors
Set myOlExp = Application.ActiveExplorer
End Sub
Private Sub objInspectors_NewInspector(ByVal Inspector As Inspector)
If Inspector.CurrentItem.Class = olMail Then
Set objMailItem = Inspector.CurrentItem
If objMailItem.Sent = False Then
Call SetFromAddress(objMailItem)
End If
End If
End Sub
'The next 3 lines to enable Outlook 2013/2016/365 Reading Pane Reply
Private Sub myOlExp_InlineResponse(ByVal objItem As Object)
Call SetFromAddress(objItem)
End Sub
Public Sub SetFromAddress(oMail As Outlook.MailItem)
' Set your preferred default From address below.
' Exchange permissions determine if it is actually stamped
' as "Sent On Behalf Of" or "Sent As".
' The address is not properly updated for the InlineResponse
' feature in Outlook 2013/2016/365. This is only a visual bug.
oMail.SentOnBehalfOfName = "example#doman.com"
End Sub
And then with your code added onto it (plus adding oMail.CC = "example#domain.com" to the code above) looks like this:
Option Explicit
Private WithEvents oExpl As Explorer
Private WithEvents oItem As MailItem
Private bDiscardEvents As Boolean
Dim oResponse As MailItem
Dim WithEvents objInspectors As Outlook.Inspectors
Dim WithEvents objMailItem As Outlook.MailItem
Dim WithEvents myOlExp As Outlook.Explorer
Private Sub Application_Startup()
Initialize_handler
Set oExpl = Application.ActiveExplorer
bDiscardEvents = False
End Sub
Public Sub Initialize_handler()
Set objInspectors = Application.Inspectors
Set myOlExp = Application.ActiveExplorer
End Sub
Private Sub objInspectors_NewInspector(ByVal Inspector As Inspector)
If Inspector.CurrentItem.Class = olMail Then
Set objMailItem = Inspector.CurrentItem
If objMailItem.Sent = False Then
Call SetFromAddress(objMailItem)
End If
End If
End Sub
'The next 3 lines to enable Outlook 2013/2016/365 Reading Pane Reply
Private Sub myOlExp_InlineResponse(ByVal objItem As Object)
Call SetFromAddress(objItem)
End Sub
Public Sub SetFromAddress(oMail As Outlook.MailItem)
' Set your preferred default From address below.
' Exchange permissions determine if it is actually stamped
' as "Sent On Behalf Of" or "Sent As".
' The address is not properly updated for the InlineResponse
' feature in Outlook 2013/2016/365. This is only a visual bug.
oMail.SentOnBehalfOfName = "example#domain.com"
oMail.CC = "example#domain.com"
End Sub
Private Sub oExpl_SelectionChange()
On Error Resume Next
Set oItem = oExpl.Selection.item(1)
End Sub
'on Reply
Private Sub oItem_Reply(ByVal Response As Object, Cancel As Boolean)
Cancel = True
bDiscardEvents = True
Set oResponse = oItem.Reply
afterReply
End Sub
'on Forward
Private Sub oItem_Forward(ByVal Response As Object, Cancel As Boolean)
Cancel = True
bDiscardEvents = True
Set oResponse = oItem.Forward
afterReply
End Sub
'On Reply All
Private Sub oItem_ReplyAll(ByVal Response As Object, Cancel As Boolean)
Cancel = True
bDiscardEvents = True
Set oResponse = oItem.ReplyAll
afterReply
End Sub
Private Sub afterReply()
oResponse.Display
' do whatever here with .to, .cc, .cci, .subject, .HTMLBody, .Attachements.Add, etc.
oResponse.CC = "example#domain.com"
End Sub
This macro works fine when used on a "clean" new email. However when I reply or forward an email, I get the VBA
error 91 - Object variable or With block variable not set
Private WithEvents olRemind As Outlook.Reminders
Private Sub Application_Reminder(ByVal Item As Object)
Set olRemind = Outlook.Reminders
If Item.MessageClass <> "IPM.Task" Then
Exit Sub
End If
If Item.Categories <> "Online" Then
Exit Sub
End If
SetOnline
Timed_box (1)
Pause 30
SetOffline
Item.MarkComplete
Set olRemind = Outlook.Reminders
For Each objRem In olRemind
If Item.Categories = "Online" Then
If objRem.IsVisible Then
objRem.Dismiss
Cancel = True
End If
Exit For
End If
Next objRem
End Sub
'Categorize Sent Items
'Place in ThisOutlookSession
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
If TypeOf Item Is Outlook.MailItem And Len(Item.Categories) = 0 Then
Set Item = Application.ActiveInspector.CurrentItem
Item.ShowCategoriesDialog
End If
End Sub
Set Item = Application.ActiveInspector.CurrentItem is the line I need to debug. Thanks
I'm going to guess that the reply or forward is in the pane at the bottom of Outlook, the ActiveInlineResponse pane. I recently modified some code to take that pane into account. If that's the case, something like this might work for you:
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
If TypeOf Item Is Outlook.MailItem And Len(Item.Categories) = 0 Then
If Not Application.ActiveExplorer.ActiveInlineResponse Is Nothing Then
Set Item = Application.ActiveExplorer.ActiveInlineResponse
End If
'If the draft is in it's own window
If OutItem Mail Is Nothing Then
If Not Application.ActiveInspector Is Nothing Then
Set Item = Application.ActiveInspector.CurrentItem
Item.ShowCategoriesDialog
End If
End Sub
This code is untested, and I might not have pasted/modified everything correctly.
Item is passed to ItemSend, you need not find it yourself.
'Categorize Sent Items
'Place in ThisOutlookSession
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
If TypeOf Item Is Outlook.MailItem And Len(Item.Categories) = 0 Then
Item.ShowCategoriesDialog
End If
End Sub
I am having no luck dismissing an Outlook alert programmatically before it displays.
Private Sub Application_Reminder(ByVal Item As Object)
Dim objRem As Reminder
Dim objRems As Reminders
If Item.Subject = "TESTING" Then
'downloadAndSendSpreadReport
Set objRems = Application.Reminders
i = 0
For Each objRem In objRems
i = i + 1
If objRem.Caption = "TESTING" Then
objRems.Remove i
If objRem.IsVisible Then
objRem.Dismiss
End If
Exit For
End If
Next objRem
Item.ReminderSet = False
Item.Delete
'Item.Dismiss
End If
End Sub
I want to use this appointment Item as a trigger to some macro without needing users to manually dismiss the reminder.
Seems to me, when this event is triggered, the reminder item is NOT visible, thus cannot be dismissed
I tried to remove it from the reminders set but this seems to delete the whole event from my calendar. Also, it will still display a STRANGE TITLE reminder not in ASCII.
I tried to set the reminderSet property of the appointment item to false, the reminder property still pops up.
So I am looking for a way to a) dismiss the reminder before it pops automatically/ b). dismiss the reminder after it pops automatically....or any workaround to do a scheduled MACRO in Outlook.
(Please note that I do not have permission to use scheduled job in Windows nor VBS.)
Updates:
Now I have the following code. The reminder is being removed, but it will still pop out a reminder window with a caption like "There is no appointment/reminder" something like this.
The beforeReminderShow event is useful in the sense the Reminder Object isVisible = true
so I can dismiss out.. but the reminders windows will continue to pop up even if there's 0 event.
Private WithEvents olRemind As Outlook.Reminders
Private Sub olRemind_BeforeReminderShow(Cancel As Boolean)
Set objRems = Application.Reminders
For Each objRem In objRems
If objRem.Caption = "TESTING" Then
If objRem.IsVisible Then
objRem.Dismiss
End If
Exit For
End If
Next objRem
End Sub
[Solved] - final edit
The final solution workable (I placed in "ThisOutlookSession" Module).
Hope this helps others.
' declare this object withEvents displaying all the events
Private WithEvents olRemind As Outlook.Reminders
Private Sub Application_Reminder(ByVal Item As Object)
Set olRemind = Outlook.Reminders
' RUN OTHER MACRO HERE
End Sub
Private Sub olRemind_BeforeReminderShow(Cancel As Boolean)
For Each objRem In olRemind
If objRem.Caption = "TESTING" Then
If objRem.IsVisible Then
objRem.Dismiss
Cancel = True
End If
Exit For
End If
Next objRem
End Sub
The only way I know how to do this is as follows.
You need this at the top of your module/class:
Private WithEvents olRemind As Outlook.Reminders
Then when you get your Outlook object you need to do this:
Set olRemind = olApp.Reminders
Where olApp is your Outlook Application object.
Now in your code you need to have this event:
Private Sub olRemind_BeforeReminderShow(Cancel As Boolean)
Once you put the WithEvents at the top then you will be able to see all the events you can use.
Now you can cancel this event and thus not see the reminder window.
If you want to dismiss all the reminders, you can simply implement the following code (declare this object WithEvents displaying all the events):
Private WithEvents olRemind As Outlook.Reminders
Private Sub Application_Reminder(ByVal Item As Object)
Set olRemind = Outlook.Reminders
' RUN OTHER MACRO HERE
End Sub
Private Sub olRemind_BeforeReminderShow(Cancel As Boolean)
Cancel = True
End Sub
I have this code in a class module - as stated to on msdn and on this stackoverflow thread
Public WithEvents objReminders As Outlook.Reminders
Private Sub Application_Startup()
Set objReminders = Application.Reminders
End Sub
Private Sub Application_Reminder(ByVal Item As Object)
Call Send_Email_Using_VBA
MsgBox ("Litigate!")
End Sub
I have tried using the code at the bottom of this thread and that won't launch either.
All I can get is outlook's reminders popup. No breakpoints are ever hit, the Msgbox never shows - even if I remove the function call. I have restarted it several times and I have no result.
Am I missing something important?
You are using WithEvents to handle your Reminder events on the objReminders object, but you are not declaring the subs to match. In my code below, please note the objReminders_... vs. your Application_... subs.
I played with your code in Outlook 2003 (I do not have Office 2007, so I cannot test there), and came up with the following:
Public WithEvents objReminders As Outlook.Reminders
Private Sub objReminders_Snooze(ByVal ReminderObject As Reminder)
Call Send_Email_Using_VBA
MsgBox ("Litigate!")
End Sub
Private Sub Class_Initialize()
Set objReminders = Outlook.Reminders
End Sub
Implemented with this in a normal code module:
Sub test()
Dim rmd As New ReminderClass
rmd.objReminders.Item(1).Snooze 1 'Triggers objReminders_Snooze in class module
rmd.objReminders.Item(2).Snooze 1
End Sub
Now, this is triggering on the Snooze event, which I explicitly call. However, this should also work for you to trigger when the event first comes up (this does not, as far as I can tell, trigger when a reminder wakes from a Snooze). I did not have any reminders set up to test - if you have difficulties beyond this, I will set up a few of my own tests with regard to that.
Private Sub objReminders_ReminderFire(ByVal ReminderObject As Reminder)
Call Send_Email_Using_VBA
MsgBox ("Litigate!")
End Sub
Update:
After playing around with this in 2010, I found the following to work (at least fire, but it seemed to constantly fire):
Private Sub Application_Reminder(ByVal Item As Object)
Call Send_Email_Using_VBA
MsgBox ("Litigate!")
End Sub
This was set up in the ThisOutlookSession object module. Does adding this do anything for you?
It's worth noting that this must be in the ThisOutlookSession code, not a different module
Private Sub objReminders_ReminderFire(ByVal ReminderObject As Reminder)
Call Send_Email_Using_VBA
MsgBox ("Litigate!")
End Sub
The actual ANSWER to this question is the following:
If you are setting recurring appointments, and putting code in the Application_Reminder event on an appointment, the Reminder event will NOT fire unless you specifically set a Reminder period in the drop down within the Appointment itself.
I played with this for days, the event would never fire unless it was a single Appointment - recurring never worked.
Setting a recurring appointment with a Reminder time of 5 minutes and all is working perfectly.
FYI here is some code that I use to send user information (self password reset) reminders on a monthly basis, using email templates stored in a local folder. Works perfectly now. Remember to create your own new category if sending auto-emails called something linke 'Send Mail'. Each appointment must be set to this category and is checked within the Sub.
Private Sub Application_Reminder(ByVal Item As Object)
Dim objMsg As MailItem
On Error Resume Next
'IPM.TaskItem to watch for Task Reminders
If Item.MessageClass <> "IPM.Appointment" Then
Exit Sub
End If
If Item.Categories <> "Send Mail" Then
Exit Sub
End If
'Check which Template for Reminder we need to send by looking for the keyword in the Reminder Appointment
If InStr(Item.Subject, "e-Expenses Password Resets") > 0 Then
Set objMsg = Application.CreateItemFromTemplate("C:\Reminder Emails\e-Expenses Resetting your own password.oft")
ElseIf InStr(Item.Subject, "e-Learning Password Resets") > 0 Then
Set objMsg = Application.CreateItemFromTemplate("C:\Reminder Emails\e-Learning Resetting your own password.oft")
ElseIf InStr(Item.Subject, "EMIS Password Resets") > 0 Then
Set objMsg = Application.CreateItemFromTemplate("C:\Reminder Emails\EMIS Web Resetting your own password.oft")
ElseIf InStr(Item.Subject, "NHS email Password Resets") > 0 Then
Set objMsg = Application.CreateItemFromTemplate("C:\Reminder Emails\NHS Net eMail Resetting your own password.oft")
ElseIf InStr(Item.Subject, "STRATA Password Resets") > 0 Then
Set objMsg = Application.CreateItemFromTemplate("C:\Reminder Emails\STRATA Resetting your own password.oft")
ElseIf InStr(Item.Subject, "VPN Password String Resets") > 0 Then
Set objMsg = Application.CreateItemFromTemplate("C:\Reminder Emails\VPN Resetting your own password.oft")
Else: Exit Sub
End If
'Location is the email address we send to, typically to ALL users
objMsg.To = Item.Location
objMsg.Subject = Item.Subject 'Make the subject of the Appointment what we want to say in the Subject of the email
objMsg.Send
Set objMsg = Nothing
End Sub
Have fun.
Dave Thomas