Eugene Astafiev

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!

21 Comments

  • noam says:

    how can i find the Organizer e – mail address from AppointmentItem object?
    like appItem.Organizer
    only appItem.Organizer_Email???

  • Eugene Astafiev says:

    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.

  • Praveen says:

    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

  • Andrei Smolin (Add-in Express Team) says:

    Hello Praveen,

    The error message suggests that you talk to your administrator. That sort of restriction cannot be bypassed programmatically.

  • Josh says:

    Hello, just a quick note that there’s a type in your example, [Start]< = should be <=. Thanks.

  • Dmitry Kostochko (Add-in Express Team) says:

    Hi Josh,

    Thank you for pointing out this misprint. Fixed!

  • Hudgi says:

    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.

  • Andrei Smolin (Add-in Express Team) says:

    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.

  • Akansh Bhanot says:

    Hi ,

    I’m also using the same code for getting the subject ,location of the appointment but it return null for both of them .

    I created a project in VS 2019 and getting error in reteriving the values

    add_Appointment.Location = appItem.Location;
    add_Appointment.Subject=appItem.Subject

  • Andrei Smolin (Add-in Express Team) says:

    Hello Akansh,

    I assume you use that code on a newly created or recently modified appointment. I’d suggest that you save it before accessing these properties.

  • Akansh Bhanot says:

    I tried to saved it but no success though i’m creating my own outlook plugin .

    In which while creating appointment i get the details from it which user added like Title ,Location .

    But while try to access it it gives null value but i’m getting value of startdate & end date

    Please find the below code for your reference

    Outlook.AppointmentItem appItem = application.CreateItem(
    Outlook.OlItemType.olAppointmentItem) as Outlook.AppointmentItem;
    if (appItem != null)
    {
    add_Appointment.Subject = appItem.Subject ;// getting value null
    add_Appointment.StartDate = appItem.Start;
    add_Appointment.EndDate = appItem.End;
    add_Appointment.Location = appItem.Location;// getting value null

    }

    Could you please help or suggest

  • Andrei Smolin (Add-in Express Team) says:

    Hello Akansh,

    The behavior above is expected. To get something from the Subject of a newly created item, you should previously assign a value to the Subject.

  • Akansh Bhanot says:

    But if i assign a title value and set the location of the appointment after i click on my custom button then it should provide those details when i retrive the value from the appointment form .

    Why the location value is coming null.

  • Akansh Bhanot says:

    When i type “Test” in Title and added start date & end date with the location and then click on my custom button then it should display Test as the subject value

  • Andrei Smolin (Add-in Express Team) says:

    Hello Akansh,

    It should show the new value. It may not show it in two cases: 1) you haven’t saved the item, 2) you get a wrong item e.g. you create a new item instead of getting the existing one.

  • Akansh Bhanot says:

    I tried to save it in a property .

    But that property value also coming null and location too .

    I’m getting value for Start date,end date , IsAllDayEvent & Owner.

    But not the subject and Location .

    Like in above code if i open a appointment form update Title , Location , Start & end date

    So i assigning the value of title in my label.

  • Akansh Bhanot says:

    So despite of using
    Outlook.AppointmentItem appItem = application.CreateItem(
    Outlook.OlItemType.olAppointmentItem) as Outlook.AppointmentItem;

    What can i use for get the existing appointment .

  • Andrei Smolin (Add-in Express Team) says:

    Hello Akansh,

    CreateItem creates a new item. To get an existing item shown in an inspector window, you get the Inspector object corresponding to that window and get Inspector.CurrentItem.

  • Akansh Bhanot says:

    Thanks Andrei .

    But when i click on my button to add task the active explorer get the object of the custom created form.

    So how can i get the previous explorer object of task form ?

  • Akansh Bhanot says:

    Thanks Andrei .

    But when i click on my button to add task the active explorer get the object of the custom created form.

    So how can i get the previous explorer object of task form ?

    Cause i open task form and add all the details then click on my custom button which open a window form .

  • Andrei Smolin (Add-in Express Team) says:

    Hello Akansh,

    I assume you talk about active inspector, not active explorer; explorer shows a list of emails, tasks, etc. When you create an Outlook item e.g. via Application.CreateItem, there’s no inspector window. At this point, you create an inspector object in two ways: 1) you can call MailItem.GetInspector – this creates an inspector window and returns an Outlook.Inspector object corresponding to that window; 2) you can call MailItem.Display – this creates an Outlook inspector showing that email; then you get the Inspector object in a number of ways: MailItem.GetInspector or OutlookApp.ActiveInspector;

Post a comment

Have any questions? Ask us right now!