How To: Retrieve Outlook calendar items using Find and FindNext methods
In my previous articles I described how to use the Find and FindNext methods of the Items class against mail and contact items. Today we will have a closer look at calendar items. For example, how can we collect all Outlook appointments the user has assigned for the rest of the day? The Find and FindNext methods can help us in this task. As you may remember, Microsoft suggests using these methods because they are faster than Restrict in case you have a small number of items in the collection.
In the sample code I am going to get all the appointments that are:
- currently in the process (were started earlier);
- going to begin and end at the specified time (in the middle of our timeline);
- start before the end border and end after the specified time (outside of the specified time).
Let’s take the current time as the start time and midnight as the end time, i.e. collect all the appointments assigned for the rest of the day.
Here is a sample code that collects the appointments and outputs the Subject, Organizer and Location properties to the Debug window. You can use the Output window in Visual Studio when debugging the code or the DebugView utility to see the results.
C# and Add-in Express:
using System.Text; using System.Diagnostics; // ... private void FindActiveAppointments(Outlook.MAPIFolder folder) { string dateTimeStart = DateTime.Now.ToString("MM/dd/yyyy hh:mm tt"); DateTime dt = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 00, 00); string dateTimeEnd = dt.ToString("MM/dd/yyyy hh:mm tt"); string searchCriteria = "[Start]<=\"" + dateTimeEnd + "\"" + " AND [End]>=\""+ dateTimeStart +"\""; StringBuilder strBuilder = null; int counter = default(int); Outlook._AppointmentItem appItem = null; Outlook.Items folderItems = null; object resultItem = null; try { folderItems = folder.Items; folderItems.IncludeRecurrences = true; folderItems.Sort("[Start]"); if (folderItems.Count > 0) { resultItem = folderItems.Find(searchCriteria); if (resultItem != null) { strBuilder = new StringBuilder(); do { if (resultItem is Outlook._AppointmentItem) { counter++; appItem = resultItem as Outlook._AppointmentItem; strBuilder.AppendLine("#" + counter.ToString() + "\tSubject: " + appItem.Subject + "\tOrganizer: " + appItem.Organizer + "\tLocation: " + appItem.Location); } Marshal.ReleaseComObject(resultItem); resultItem = folderItems.FindNext(); } while (resultItem != null); } } if (strBuilder != null) Debug.WriteLine(strBuilder.ToString()); else Debug.WriteLine("There is no match in the " + folder.Name + " folder."); } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message); } finally { if (folderItems != null) Marshal.ReleaseComObject(folderItems); } }
VB.NET and Add-in Express:
Imports System.Text Imports System.Diagnostics ' ... Private Sub FindActiveAppointments(folder As Outlook.MAPIFolder) Dim dateTimeStart As String = DateTime.Now.ToString("MM/dd/yyyy hh:mm tt") Dim dt As DateTime = New DateTime(DateTime.Now.Year, DateTime.Now.Month, _ DateTime.Now.Day, 23, 59, 0, 0) Dim dateTimeEnd As String = dt.ToString("MM/dd/yyyy hh:mm tt") Dim searchCriteria As String = "[Start]<=""" + dateTimeEnd + """ AND [End]>=""" + _ dateTimeStart + """" Dim strBuilder As StringBuilder = Nothing Dim counter As Integer = 0 Dim appItem As Outlook._AppointmentItem = Nothing Dim folderItems As Outlook.Items = Nothing Dim resultItem As Object = Nothing Try folderItems = folder.Items folderItems.IncludeRecurrences = True folderItems.Sort("[Start]") If (folderItems.Count > 0) Then resultItem = folderItems.Find(searchCriteria) If Not IsNothing(resultItem) Then strBuilder = New StringBuilder() Do If (TypeOf (resultItem) Is Outlook._AppointmentItem) Then counter += 1 appItem = resultItem strBuilder.AppendLine("#" + counter.ToString() + _ " Subbject: " + appItem.Subject + _ " Organizer: " + appItem.Organizer + _ " Location: " + appItem.Location) End If Marshal.ReleaseComObject(resultItem) resultItem = folderItems.FindNext() Loop Until IsNothing(resultItem) End If End If If Not IsNothing(strBuilder) Then Debug.WriteLine(strBuilder.ToString()) Else Debug.WriteLine("There is no match in the " + _ folder.Name + " folder.") End If Catch ex As Exception System.Windows.Forms.MessageBox.Show(ex.Message) Finally If Not IsNothing(folderItems) Then Marshal.ReleaseComObject(folderItems) End If End Try End Sub
The code for VSTO and Add-in Express based add-ins is the same. Just remember two simple things when switching between these 2 kinds of add-ins:
- To declare required namespaces at the beginning of the file.
- To use the Application property and OutlookApp property in VSTO and Add-in Express based add-ins respectively to get an instance of the Application.
C# and VSTO:
using System.Runtime.InteropServices; using System.Diagnostics; // ... private void FindActiveAppointments(Outlook.MAPIFolder folder) { string dateTimeStart = DateTime.Now.ToString("MM/dd/yyyy hh:mm tt"); DateTime dt = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 00, 00); string dateTimeEnd = dt.ToString("MM/dd/yyyy hh:mm tt"); string searchCriteria = "[Start]<=\"" + dateTimeEnd + "\"" + " AND [End]>=\"" + dateTimeStart + "\""; StringBuilder strBuilder = null; int counter = default(int); Outlook._AppointmentItem appItem = null; Outlook.Items folderItems = null; object resultItem = null; try { folderItems = folder.Items; folderItems.IncludeRecurrences = true; folderItems.Sort("[Start]"); if (folderItems.Count > 0) { resultItem = folderItems.Find(searchCriteria); if (resultItem != null) { strBuilder = new StringBuilder(); do { if (resultItem is Outlook._AppointmentItem) { counter++; appItem = resultItem as Outlook._AppointmentItem; strBuilder.AppendLine("#" + counter.ToString() + "\tSubject: " + appItem.Subject + "\tOrganizer: " + appItem.Organizer + "\tLocation: " + appItem.Location); } Marshal.ReleaseComObject(resultItem); resultItem = folderItems.FindNext(); } while (resultItem != null); } } if (strBuilder != null) Debug.WriteLine(strBuilder.ToString()); else Debug.WriteLine("There is no match in the " + folder.Name + " folder."); } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message); } finally { if (folderItems != null) Marshal.ReleaseComObject(folderItems); } }
VB.NET and VSTO:
Imports System.Runtime.InteropServices Imports System.Diagnostics ' ... Private Sub FindActiveAppointments(folder As Outlook.MAPIFolder) Dim dateTimeStart As String = DateTime.Now.ToString("MM/dd/yyyy hh:mm tt") Dim dt As DateTime = New DateTime(DateTime.Now.Year, DateTime.Now.Month, _ DateTime.Now.Day, 23, 59, 0, 0) Dim dateTimeEnd As String = dt.ToString("MM/dd/yyyy hh:mm tt") Dim searchCriteria As String = "[Start]<=""" + dateTimeEnd + """ AND [End]>=""" + _ dateTimeStart + """" Dim strBuilder As StringBuilder = Nothing Dim counter As Integer = 0 Dim appItem As Outlook._AppointmentItem = Nothing Dim folderItems As Outlook.Items = Nothing Dim resultItem As Object = Nothing Try folderItems = folder.Items folderItems.IncludeRecurrences = True folderItems.Sort("[Start]") If (folderItems.Count > 0) Then resultItem = folderItems.Find(searchCriteria) If Not IsNothing(resultItem) Then strBuilder = New StringBuilder() Do If (TypeOf (resultItem) Is Outlook._AppointmentItem) Then counter += 1 appItem = resultItem strBuilder.AppendLine("#" + counter.ToString() + _ " Subbject: " + appItem.Subject + _ " Organizer: " + appItem.Organizer + _ " Location: " + appItem.Location) End If Marshal.ReleaseComObject(resultItem) resultItem = folderItems.FindNext() Loop Until IsNothing(resultItem) End If End If If Not IsNothing(strBuilder) Then Debug.WriteLine(strBuilder.ToString()) Else Debug.WriteLine("There is no match in the " + _ folder.Name + " folder.") End If Catch ex As Exception System.Windows.Forms.MessageBox.Show(ex.Message) Finally If Not IsNothing(folderItems) Then Marshal.ReleaseComObject(folderItems) End If End Try End Sub
See you on our forums and in the e-mail support!
8 Comments
how can i find the Organizer e – mail address from AppointmentItem object?
like appItem.Organizer
only appItem.Organizer_Email???
Hello Noam,
The Organizer property of the AppointmentItem class returns a string representing the name of the organizer. It looks like you need to find the corresponding entry in the Address book of your Outlook profile.
Hi,
I am using the above code you have shared. The program runs in to error at times, please help. Error – “Your server administrator has limited the number of items you can open simultaneously. try closing messages you have opened or removing attachments and images from unsent messages you are composing”
thanks
Praveen
Hello Praveen,
The error message suggests that you talk to your administrator. That sort of restriction cannot be bypassed programmatically.
Hello, just a quick note that there’s a type in your example, [Start]< = should be <=. Thanks.
Hi Josh,
Thank you for pointing out this misprint. Fixed!
Hi,
I need to retrieve appointment items along with recurrences from a very populated calendar. So I need to use the Find/FindNext approach to speed up things.
But I only able to include recurrences if I use a raw foreach loop over all items which is very slow.
Certainly I understand that I need to add Sort(“[Start]”) before setting Items.IncludeRecurrences to true. The strange thing is that after setting Items.IncludeRecurrences = true, the value of the property keeps to be false in the debugger.
Any idea what may I do wrong? Thank you.
Hello Hudgi,
There’s an example showing how to use Items.IncludeRecurrences; see the second example at https://msdn.microsoft.com/en-us/library/office/ff866969.aspx. Note that it uses Items.Restrict. At https://msdn.microsoft.com/en-us/library/office/ff869597.aspx, they write: The Find or FindNext methods are faster than filtering if there are a small number of items. The Restrict method is significantly faster if there is a large number of items in the collection, especially if only a few items in a large collection are expected to be found.
After you apply Restrict, you can just loop through the Items collection; find more details on Items.Restrict.