Event when a document is added to a calendar item - vba

I want the event that will fire when a document is added to calendar item.
After that I want to handle that document by moving it to another place (network share).
I open the calendar and drag a Word document from Windows Explorer to a date on the calendar then I need that event to handle.
Code I tried:
Public WithEvents aaa As Outlook.AppointmentItem
Public WithEvents bbb As Outlook.DocumentItem
Public WithEvents ccc As Outlook.TaskItem
Public WithEvents ddd As Outlook.JournalItem
Public WithEvents eee As Outlook.Items
Private Sub aaa_AttachmentAdd(ByVal Attachment As Attachment)
End Sub
Private Sub aaa_BeforeAttachmentAdd(ByVal Attachment As Attachment, Cancel As Boolean)
End Sub
Private Sub bbb_AttachmentAdd(ByVal Attachment As Attachment)
End Sub
Private Sub bbb_BeforeAttachmentAdd(ByVal Attachment As Attachment, Cancel As Boolean)
End Sub
Private Sub ccc_AttachmentAdd(ByVal Attachment As Attachment)
End Sub
Private Sub ccc_BeforeAttachmentAdd(ByVal Attachment As Attachment, Cancel As Boolean)
End Sub
Private Sub ddd_AttachmentAdd(ByVal Attachment As Attachment)
End Sub
Private Sub ddd_BeforeAttachmentAdd(ByVal Attachment As Attachment, Cancel As Boolean)
End Sub
Private Sub eee_ItemAdd(ByVal Item As Object)
End Sub

I want to find a proper event that will fire when a document is added to calendar item.
It is not clear how a document is added to the Outlook item. Is it attached as a file? Or a shared link is added to the item?
Anyway, when users attach anything to Outlook items, they must select or open an item and then attach a file there. So, you can handle the SelectionChange event of the Explorer class to be aware which item is currently viewed or selected. And if any file is attached to the selected item you may handle the AppointmentItem.AttachmentAdd event which is when an attachment has been added to an instance of the parent object. The Attachment that was added to the item is passed as a parameter to the event handler.
You may find the Implement a wrapper for inspectors and track item-level events in each inspector article helpful.
If you want to track calendar item changes like shared links to documents added you need to handle the Items.ItemChange event which is fired when an item in the specified collection is changed.

Ah, I forgot the basic thing - to set those WithEvents variables in Application_ItemLoad:
Private Sub Application_ItemLoad(ByVal Item As Object)
If (TypeOf Item Is AppointmentItem) Then
Set aaa = Item
ElseIf (TypeOf Item Is DocumentItem) Then
Set bbb = Item
ElseIf (TypeOf Item Is TaskItem) Then
Set ccc = Item
ElseIf (TypeOf Item Is JournalItem) Then
Set ddd = Item
ElseIf (TypeOf Item Is Items) Then
Set eee = Item
ElseIf (TypeOf Item Is Explorer) Then
Set fff = Item
End If
End Sub

Related

What function executes in VBA when changing a calendar event

I have VBA code in Outlook that adds a calendar event in a google calendar when the event is added in Outlook. The code is also able to delete an event in a google calendar when the event is deleted from Outlook.
I have this code at the top of the VBA code:
Dim WithEvents curCal As Items
Dim WithEvents DeletedItems As Items
Dim newCalFolder As Outlook.Folder
The private sub that adds an event looks like this:
Private Sub curCal_ItemAdd(ByVal Item As Object)
Dim cAppt As AppointmentItem
Dim moveCal As AppointmentItem
....
Item.Save
End Sub
The code that deletes an event looks like this:
Private Sub DeletedItems_ItemAdd(ByVal Item As Object)
' only apply to appointments
If Item.MessageClass <> "IPM.Appointment" Then Exit Sub
' if using a category on copied items, this may speed it up.
If Item.Categories = "moved" Then Exit Sub
...
End Sub
Both of these functions work as expected.
Now I need to code a sub that will execute when the event is modified so I can send the modifications to google.
I assume I need to create Private Sub curCal_xxxxxxxxxxxxxxx(ByVal Item As Object) but I dont know what the xxxxxxxxxxxxxxx would be.
Anybody know what the sub name should be where I can place code that will execute after an Outlook calendar event has been changed?
You may consider using the ItemChange event which is fired when an item in the specified collection is changed:
Private Sub myOlItems_ItemChange(ByVal Item As Object)
Dim prompt As String
If VBA.Format(Item.Start, "h") >= "17" And Item.Sensitivity <> olPrivate Then
prompt = "Appointment occurs after hours. Mark it private?"
If MsgBox(prompt, vbYesNo + vbQuestion) = vbYes Then
Item.Sensitivity = olPrivate
Item.Display
End If
End If
End Sub
But there is no information what exactly has been changed, only the item changed is passed as a parameter.
For that reason you may consider handling the AppointmentItem.PropertyChange event which is fired when an explicit built-in property (for example, Subject) of an instance of the parent object is changed. In that case the name of the property that was changed is passed as a parameter.
Also you may find the MailItem.Write event helpful. It is fired when an object is saved, either explicitly (for example, using the Save or SaveAs methods) or implicitly (for example, in response to a prompt when closing the item's inspector).
Public WithEvents myItem As Outlook.MailItem
Private Sub myItem_Write(Cancel As Boolean)
Dim myResult As Integer
myItem = "The item is about to be saved. Do you wish to overwrite the existing item?"
myResult = MsgBox(myItem, vbYesNo, "Save")
If myResult = vbNo Then
Cancel = True
End If
End Sub
Public Sub Initialize_Handler()
Const strCancelEvent = "Application-defined or object-defined error"
On Error GoTo ErrHandler
Set myItem = Application.ActiveInspector.CurrentItem
myItem.Save
Exit Sub
ErrHandler:
MsgBox Err.Description
If Err.Description = strCancelEvent Then
MsgBox "The event was cancelled."
End If
End Sub

How to popup question, whether to flag, after pressing send button?

Is there a way to ask (popup) if I want to flag the email after I press the send button?
Use the Application.ItemSend event to display a MsgBox asking whether to flag or not.
Then as noted in this question, you'll need to listen to the Items.ItemAdd event on the Sent Items folder and call MarkAsTask on the message passed to the event handler.
So add the following code to ThisOutlookSession - use Alt + F11 to bring up the VB editor.
Private WithEvents Items As Outlook.Items
Private Sub Application_Startup()
Dim SentItems As Folder
Set SentItems = Outlook.Application.GetNamespace("MAPI").GetDefaultFolder(olFolderSentMail)
Set Items = SentItems.Items
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
If TypeOf Item Is Outlook.MailItem Then
Dim property As UserProperty
Set property = Item.UserProperties("FlagForFollowUp")
If property Is Nothing Then Exit Sub
Item.MarkAsTask olMarkThisWeek
Item.Save
End If
End Sub
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
If TypeOf Item Is Outlook.MailItem Then
Dim prompt As String
prompt = "Would you like to flag this item?"
If MsgBox(prompt, vbYesNo + vbQuestion, "Flag item") = vbYes Then
Dim property As UserProperty
Set property = Item.UserProperties.Add("FlagForFollowUp", olYesNo)
property.Value = True
End If
End If
End Sub

Close event not working when opening and closing multiple Task-items

I got the following situation.
Open an outlook task
The open event is executed
Open a second outlook task
The open event is executed
Close the first task
No close event is executed !!!
Close the second task
The close event is executed
Does anybody have a clue what is happening here ?
Did I do some bad programming ? I have placed my code below.
Thank you in advance.
Kind regards,
Wamor
Public WithEvents objInspectors As Outlook.Inspectors
Public WithEvents objJournal As Outlook.JournalItem
Public WithEvents objTask As Outlook.TaskItem
Dim objOldTask As Outlook.TaskItem
Private Sub Application_Startup()
Set objInspectors = Outlook.Inspectors
Set objTask = Nothing
Set objJournal = Nothing
Set objOldTask = Nothing
End Sub
Private Sub objInspectors_NewInspector(ByVal Inspector As Inspector)
If TypeOf Inspector.CurrentItem Is TaskItem Then
Set objTask = Inspector.CurrentItem
End If
If TypeOf Inspector.CurrentItem Is JournalItem Then
Set objJournal = Inspector.CurrentItem
End If
End Sub
Private Sub objTask_Open(Cancel As Boolean)
MsgBox "TaskItem open event"
End Sub
Private Sub objTask_close(Cancel As Boolean)
MsgBox "TaskItem close event"
End Sub
Of course - you have multiple open objects but only a single variable to store a reference to them.
The standard way of dealing with problems like this is to have a wrapper class that has Inspector and the Item (two items - TaskItem and JournalItem in your case) as variables. TaskOpen and TaskClose event handlers will be methods on that wrapper class.
When NewInspector event fires, create an instance of your wrapper class and populate its properties. Add the wrapper class to a global list.
When close event fires, remove the wrapper class from the list.

Is it possible to run an Outlook macro when a new Contact is created/saved?

I have an Outlook macro that edits certain fields in all of my Contacts. Is it possible to auto-trigger this macro to run whenever a new Contact is created/saved?
Add this code to the ThisOutlookSession module:
Private WithEvents objNewContact As Items
Private Sub Application_Startup()
Set objNewContact = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderContacts).Items
End Sub
Private Sub objNewContact_ItemAdd(ByVal Item As Object)
MsgBox Item.CompanyAndFullName & " added"
End Sub
Private Sub objNewContact_ItemChange(ByVal Item As Object)
MsgBox Item.CompanyAndFullName & " changed"
End Sub
Application_StartUp will set objNewContact to watch the contacts folder when you start Outlook.
ItemAdd will fire when you save the contact.
ItemChange will fire when you save an existing contact after changing it.
As the link provided by #Maciej states - The sample code must be placed in a class module and ThisOutlookSession is a class module.

How can I trigger an event when multiple items added at once to Outlook Folder?

I use event handlers in VBA and Outlook frequently. One of them is one which marks any item which is deleted to be marked as read.
Private Sub deletedItems_ItemAdd(ByVal Item As Object)
Application_Startup
On Error Resume Next
Item.UnRead = False
End Sub
Declared via:
Private WithEvents deletedItems As Outlook.Items
and initialized in Application_Startup as:
Dim olNameSpace As Outlook.NameSpace
Set olNameSpace = olApp.GetNamespace("MAPI")
Set deletedItems = olNameSpace.GetDefaultFolder(olFolderDeletedItems).Items
Unfortunately, this does not affect all the items if I delete multiple items at once.
Is there a way I can do something to hijack this process somehow? I looked into using the _beforeDelete event but you have to set the item correctly each time, which if I could do this problem wouldn't exist anyways.
Apparently I wasn't clear - the use case I have is when I delete messages via the delete key from my inbox, drafts, whatever.
You don't have to.
I was curious about your question so I opened up Outlook and wrote this code in ThisOutlookSession:
Private WithEvents items As Outlook.items
Public Sub SetItems()
Set items = Application.GetNamespace("MAPI") _
.GetDefaultFolder(olFolderDeletedItems) _
.items
End Sub
Private Sub items_ItemAdd(ByVal Item As Object)
Dim mail As MailItem
On Error Resume Next
Set mail = Item
Err.Clear
On Error GoTo 0
If Not mail Is Nothing Then
MsgBox mail.Subject
mail.UnRead = False
End If
End Sub
Then I ran SetItems from the immediate pane, went to my inbox and deleted a SMS message - as expected mail was Nothing. Then I deleted a single email, and got the message with the mail's subject.
When I selected two emails and hit Delete, the event was fired once for each selected email, so I saw two message boxes - it just works! :)
The Outlook API doesn't seem to offer an event which would handle all deletions at once.
i have (almost) exactly the same code and it works also for multiple items - only after sleep-mode Outlook seems to forget how to handle deleted items...
Option Explicit
Public WithEvents itDeleted As items
Private Sub Application_Startup()
Set itDeleted = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderDeletedItems).items
End Sub
Private Sub itDeleted_ItemAdd(ByVal Item As Object)
'MsgBox "deleted-sub fired" 'this only for test-purposes
If TypeOf Item Is MailItem Then
Item.UnRead = False
End If
End Sub
I think the difference in the definition of "deletedItems" is the problem; that you are not checking the mailitem-property is also not optimal.
Hope this helps,
Max