Working with Outlook calendar (appointment and meeting items)
Yeah sure, email is front and center with Outlook. But right behind it and ready to steal the show is the Outlook calendar. If you aren’t looking at email, I bet you are looking at your calendar to see if you can meet at such-and-such time on such-and-such date. It is my opinion that, the appointments residing in our calendar are the culmination of all your emailing efforts.
If you didn’t email, you wouldn’t have appointments.
If you didn’t have appointments, you’d have nothing to email about.
Today, let’s take a look at how work with the items in your Outlook calendar:
- What is an Outlook Calendar item?
- How to enumerate calendar items
- How to create calendar items
- How to list attendees and see their response status
- How to delete calendar items
- How to send meeting responses
- Useful events
Outlook likes to mix things up and use different objects for different purposes (e.g. Explorer and Inspector windows). When it comes to the calendar we have two items to master:
- AppointmentItem :: this is the appointment object that resides in a calendar folder. You can create this via code.
- MeetingItem :: this is a meeting request received by the user. It resides in the inbox… tricky! You cannot create these with code, but you can code against them when they exist.
Now, here are some mind-blowing facts about these two objects:
- An AppointmentItem can become a meeting by adding another person to it and clicking Send.
Once sent, the AppointmentItem travels the Interweb is magically turned into a MeetingItem by the time the intended recipient receives it.
- A MeetingItem contains an AppointmentItem.
- An AppointmentItem does not contain a MeetingItem… even if you add another user to it.
I have a few code samples that show the basics of Outlook calendars but also aren’t too lame. In fact, I daresay they are not lame at all as they can be quite useful. I thought of you, my fellow developer, and I want you to steal this code. It will be here when you need it.
To make this happen, we’ll work with Outlook appointments residing in the default calendar. The code loops through the folder’s items collection and prints out its message class.
VB.NET code example
Friend Sub EnumerateDefaultAppointmentsAndDoSomethingSillyThatIllustratesAPoint( _ calendarType As String) Dim calendar As Outlook.Folder = Nothing Dim calendarItems As Outlook.Items If calendarType = "AppointmentItem" Then calendar = _ OutlookApp.Session.GetDefaultFolder( _ Outlook.OlDefaultFolders.olFolderCalendar) calendarItems = calendar.Items Else 'MeetingItem (are assume that is the case) calendar = _ OutlookApp.Session.GetDefaultFolder( _ Outlook.OlDefaultFolders.olFolderInbox) calendarItems = calendar.Items End If Dim i As Integer = 0 Do Until i = calendarItems.Count Console.WriteLine(calendarItems.MessageClass) 'AppointmentItem = IPM.Appointment 'MeetingRequest = IPM.Schedule.Meeting.Request Loop 'Release COM Objects! If calendarItems IsNot Nothing Then Marshal.ReleaseComObject(calendarItems) If calendar IsNot Nothing Then Marshal.ReleaseComObject(calendar) End Sub
Okay, this is a somewhat lame except that it makes a nice segue into informing you of the different message classes in play when working with the calendars.
|Outlook Item||Message Class|
Using the message class, you quickly filter a folder’s items to the objects you desire. This strategy helps ensure you access only the item types you want… reducing the potential for error. I’ll show you this technique soon.
I stated previously that you can only create AppointmentItems with code (and that you can’t create MeetingItems)… and it’s true. Here is how it’s done:
Friend Sub CreateAppointment(title As String) Dim apptItem As Outlook.AppointmentItem = Nothing apptItem = _ OutlookApp.Session.Application.CreateItem( _ Outlook.OlItemType.olAppointmentItem) With apptItem .Subject = title .Start = DateTime.Now .End = Date.Now.AddHours(1) .Save() End With 'Release COM Objects If apptItem IsNot Nothing Then Marshal.ReleaseComObject(apptItem) End Sub
First we use the CreateItem method to create the AppointmentItem. Then we set a few properties and save it. Done.
How to create a recurring appointment (as a reminder)
This sample kills two birds with one stone. Here, I show you how to create recurring appointment as well as how to set a reminder in Outlook.
Creating a recurring appointment is a bit more involved than you might think it would be. This situation is due to the fact that you need to create a ReccurancePattern object for the appointment. To add a reminder to the appointment, we need to set its ReminderSet property to true.
VB.NET code example
Friend Sub CreateRecurringAppointmentWithReminder(reminderText As String, _ recurring As Boolean) Dim apptItem As Outlook.AppointmentItem = Nothing apptItem = _ OutlookApp.Session.Application.CreateItem( _ Outlook.OlItemType.olAppointmentItem) Dim pattern As Outlook.RecurrencePattern = Nothing With apptItem .Subject = reminderText .Importance = Outlook.OlImportance.olImportanceHigh .Sensitivity = Outlook.OlSensitivity.olPrivate .Start = DateTime.Now .End = Date.Now.AddHours(1) .ReminderMinutesBeforeStart = 15 .ReminderSet = True If recurring Then pattern = .GetRecurrencePattern() pattern.RecurrenceType = Outlook.OlRecurrenceType.olRecursDaily pattern.PatternStartDate = DateTime.Parse(Today().ToString) pattern.PatternEndDate = DateAndTime.DateAdd(DateInterval.Day, 14, Today()) pattern.StartTime = .Start pattern.EndTime = .End End If .Save() End With 'Release COM Objects! If pattern IsNot Nothing Then Marshal.ReleaseComObject(pattern) If apptItem IsNot Nothing Then Marshal.ReleaseComObject(apptItem) End Sub
After creating the AppointmentItem and setting some typical properties, we move create the reminder (ReminderSet = True) and the Recurrence pattern. The appointment will recur everyday from the start and will end fourteen days later. Save and release objects… done!
How to create a meeting invitation
A meeting invitation is an AppointmentItem with attendees. We make this happen by adding recipient objects to an AppointmentItem:
Friend Sub CreateAppointmentWithAttendees(meetingTitle As String, meetingDate As String, _ startTime As String, endTime As String, recipientEmail As String) Dim apptItem As Outlook.AppointmentItem = Nothing Dim recipient As Outlook.Recipient = Nothing If IsDate(meetingDate) And IsDate(startTime) And IsDate(endTime) Then apptItem = _ OutlookApp.Session.Application.CreateItem( _ Outlook.OlItemType.olAppointmentItem) recipient = apptItem.Recipients.Add(recipientEmail) recipient.Type = CType(Outlook.OlMeetingRecipientType.olRequired, Integer) With apptItem .MeetingStatus = Outlook.OlMeetingStatus.olMeeting .Subject = meetingTitle .Start = DateTime.Today & " " & startTime .End = DateTime.Today & " " & endTime End With If apptItem.Recipients.ResolveAll Then apptItem.Send() Else apptItem.Display() End If 'Release the COM! If recipient IsNot Nothing Then Marshal.ReleaseComObject(recipient) If apptItem IsNot Nothing Then Marshal.ReleaseComObject(apptItem) End If End Sub
I chose to make this procedure "steal-able" by adding parameters. I check to ensure the date parameters are, indeed, dates before wasting precious CPU cycles. If they are I create the appointment and use the recipientEmail parameter to add a recipient. I also set the MeetingStatus to olMeeting, this is an important thing to do.
I then resolve the recipients and, if it resolves successfully, send it. If it doesn’t resolve, I display to the user so they can deal with it.
How to create all-day event
This is the last example showing you how to create an Outlook appointment. This one shows how to create an all-day event. These events are the ones that reside at the top of the calendar:
To create one of these, you create an appointment and set AllDayEvent to True.
VB.NET code example
Friend Sub CreateAllDayAppointment(eventTitle As String, startDate As String, _ endDate As String) Dim apptItem As Outlook.AppointmentItem = Nothing If IsDate(startDate) And IsDate(endDate) Then apptItem = _ OutlookApp.Session.Application.CreateItem( _ Outlook.OlItemType.olAppointmentItem) With apptItem .Subject = eventTitle .Start = startDate .End = endDate .AllDayEvent = True .Save() End With End If 'Release COM Objects! If apptItem IsNot Nothing Then Marshal.ReleaseComObject(apptItem) End Sub
I realize I could have combined this sample with another but I wanted to point it out specifically.
When you send a meeting invitation, most people are kind enough to send a reply that lets you know if they will attend (or not). But they don’t have to because Outlook lets you approve or reject the meeting without notifying the organizer. This is rude and forces the organizer to open the meeting on their calendar and check to see who will attend.
Well, how about we, as nice developers, provide a feature that informs the organizer the response status of each requested attendee? Pretty good idea right? Well this is exactly what ListAttendees does.
VB.NET code example
Friend Sub ListAttendees(appointment As Outlook.AppointmentItem) If Not IsNothing(appointment) Then Dim recipients As Outlook.Recipients = appointment.Recipients Dim recipient As Outlook.Recipient = Nothing Dim i As Integer = 0 Do Until i = recipients.Count MessageBox.Show(recipient.Name & " :: Meeting Status = _ " & recipient.MeetingResponseStatus) i = i + 1 Loop 'Release the COM! If recipient IsNot Nothing Then Marshal.ReleaseComObject(recipient) If recipients IsNot Nothing Then Marshal.ReleaseComObject(recipients) End If End Sub
This snippet uses the passed AppointmentItem and grabs its Recipients collection. Next it loops through the collection and displays each Recipient object’s MeetingResponseStatus.
Useful? Yes. Slightly annoying to show a message box for each recipient? Absolutely!
If you create items, you will want to delete items. The DeleteAppointmentItems procedure takes care of unwanted appointments. To me, unwanted appointments are any that list me as an optional attendee. Delete them! Delete them all!
VB.NET code example
Friend Sub DeleteAppointmentItems(attendeeName As String) Dim folder As Outlook.Folder Dim folderItems As Outlook.Items Dim filteredItems As Outlook.Items Dim appt As Outlook.AppointmentItem folder = OutlookApp.ActiveExplorer.CurrentFolder If folder.DefaultItemType = Outlook.OlItemType.olAppointmentItem Then folderItems = folder.Items filteredItems = folderItems.Restrict("[MessageClass] = 'IPM.Appointment'") Dim fRemoved As Boolean = False Dim i As Integer = 1 Do Until i > filteredItems.Count appt = filteredItems.Item(i) Dim optionalAttendees As String = appt.OptionalAttendees If Not optionalAttendees Is Nothing Then If optionalAttendees.Contains(attendeeName) Then filteredItems.Remove(i) fRemoved = True End If End If If fRemoved Then 'We removed an item which lowers the items count. 'Leave i as is (i=i) 'reset boolean fRemoved = False Else i = i + 1 End If Marshal.ReleaseComObject(appt) Loop 'Relase COM Objects! Marshal.ReleaseComObject(filteredItems) Marshal.ReleaseComObject(folderItems) Marshal.ReleaseComObject(folder) End If End Sub
To make it (even more) useful, I parameterized the routine so you can pass a name to use as the search criteria. The routine does this:
- References the default calendar folder.
- Filters the folder’s items collection to ensure we work only with the AppontmentItem.
- Loops through the OptionalAttendees collection and looks for the passed name.
- If it finds a match… it deletes the appointment.
Gone! Hello free time! They won’t miss you anyway… you’re optional.
I mentioned earlier that some people send meeting responses some don’t. Some might receive a bunch and want to process their replies in bulk. This is the scenario I have in mind for the SendMeetingResponses routine.
VB.NET code example
Friend Sub SendMeetingResponses(planToAttend As Boolean) Dim inbox As Outlook.Folder = Nothing Dim meetingItems As Outlook.Items = Nothing Dim filteredItems As Outlook.Items = Nothing Dim typeFilter As String = "[MessageClass] = 'IPM.Schedule.Meeting.Request'" inbox = OutlookApp.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox) meetingItems = inbox.Items filteredItems = meetingItems.Restrict(typeFilter) If filteredItems.Count > 0 Then Dim i As Integer = 1 Do Until i > filteredItems.Count Dim mtgReqItem As Outlook.MeetingItem = _ CType(filteredItems.Item(i), Outlook.MeetingItem) Dim mtgItem As Outlook.MeetingItem = Nothing Dim apptItem As Outlook.AppointmentItem = _ mtgReqItem.GetAssociatedAppointment(True) If Not IsNothing(apptItem) Then If planToAttend Then mtgItem = _ apptItem.Respond(Outlook.OlMeetingResponse.olMeetingAccepted) mtgItem.Send() Else mtgItem = apptItem.Respond(Outlook.OlMeetingResponse.olMeetingDeclined) mtgItem.Send() End If End If If Not mtgItem Is Nothing Then Marshal.ReleaseComObject(mtgItem) If Not mtgReqItem Is Nothing Then Marshal.ReleaseComObject(mtgReqItem) End If If Not apptItem IsNot Nothing Then Marshal.ReleaseComObject(apptItem) i = i + 1 Loop 'Delete all MeetingRequests now Do Until 1 > filteredItems.Count 'Always use Index =1 because each remove lowers the count '1 is always valid. filteredItems.Remove(1) Loop End If 'Release the COM! If filteredItems IsNot Nothing Then Marshal.ReleaseComObject(filteredItems) If meetingItems IsNot Nothing Then Marshal.ReleaseComObject(meetingItems) If inbox IsNot Nothing Then Marshal.ReleaseComObject(inbox) End Sub
MeetingItem objects reside in the inbox. They are not in calendar folders. Therefore, this routine rummages in the inbox folder and grabs its Items collection.
With the collection in-hand we filter to include only meeting requests. Predictably, next comes “The Loop”. For each Outlook meeting request, we do as directed by the planToAttend parameter and send the response. Before ending, the routine deletes the meeting requests from the inbox.
No more clicking each meeting and responding individually. No sir, we can now blindly accept or reject them and get them off our To Do list.
Unlike mail item, appointments don’t have any events specific to them. But, I think the Outlook Application’s ItemSend event is useful. Keep in mind that for Outlook events, you need to an AdxOutlookEvents object to the AddInModule.
No surprise here, this event occurs when an item is sent… either by the user clicking the Send button in an Inspector or by calling the item’s Send method. It’s a great way to automatically include a signature line…
Private Sub adxOutlookEvents_ItemSend(sender As Object, e As ADXOlItemSendEventArgs) _ Handles adxOutlookEvents.ItemSend e.Cancel = False Dim mtgItem As Outlook.MeetingItem = TryCast(e.Item, Outlook.MeetingItem) If mtgItem IsNot Nothing Then mtgItem.Body = "I'LL BRING THE DONUTS!!!" mtgItem.Save() End If End Sub
Everybody likes the guy that brings the donuts to the meeting. You want be that guy (or girl, I don’t mean to be sexist but I hate gender neutral writing).
We’ll stop here. I’ve only begun to scratch the surface. Because it’s enough to cover the basics and get you going with Outlook calendars I’ll hold back and save something for next time.
- Part 1: Outlook add-in development: Outlook Application and base objects
- Part 2: Creating custom Outlook views
- Part 3: Creating custom Outlook forms
- Part 4: Outlook UI – Explorer and Inspector Windows. What is customizable?
- Part 5: Customizing Outlook main menu, context menus and Backstage view
- Part 6: Creating custom Outlook ribbons and toolbars
- Part 7: Advanced view regions for Outlook 2013 – 2003
- Part 8: Advanced form regions for Outlook 2013 – 2003
- Part 9: Working with Outlook Accounts, Stores, Folders and Items
- Part 10: Working with Outlook calendar
- Part 11: Working with Outlook tasks