Eugene Astafiev

How To: Use Restrict method in Outlook to get calendar items

I described how to use Find and FindNext methods against calendar items in my previous post. Today I would like to take closer look at how to deal with calendar items using the Restrict method. In fact, this method can make you tear your hair out because of some aspects or limitations coming from the Outlook Object Model. I’d spent half a day debugging the code and investigating the issue until I found the cause.

Firstly, to retrieve all Outlook appointment items from the folder that meets the predefined condition, you need to sort the items in ascending order and set the IncludeRecurrences to true. You will not catch recurrent appointments if you don’t do this before using the Restrict method!

Secondly, Microsoft doesn’t recommend using the Count property in case you set the IncludeRecurrences property. The Count property may return unexpected results and cause an infinite loop.

Thirdly, I would recommend using the do/while or foreach loops for iterating found items. The for loop can’t be used because the Count property of the Items class may return unexpected results.

The sample code does exactly the same job we did with the Find/FindNext methods in my previous post – collects all 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).

As you remember I took the current time as the start time and midnight as the end time.

C# and Add-in Express:

using System.Text;
using System.Diagnostics;
// ...
private void RestrictCalendarItems(Outlook.MAPIFolder folder)
{
    DateTime dtEnd = new DateTime(DateTime.Now.Year, DateTime.Now.Month,
                                  DateTime.Now.Day, 23, 59, 00, 00);
    string restrictCriteria = "[Start]<=\"" + dtEnd.ToString("g") + "\"" + 
                              " AND [End]>=\"" + DateTime.Now.ToString("g") + "\"";
    StringBuilder strBuilder = null;
    Outlook.Items folderItems = null;
    Outlook.Items resultItems = null;
    Outlook._AppointmentItem appItem = null;
    int counter = default(int);
    object item = null;
    try
    {
        strBuilder = new StringBuilder();
        folderItems = folder.Items;
        folderItems.IncludeRecurrences = true;
        folderItems.Sort("[Start]");
        resultItems = folderItems.Restrict(restrictCriteria);
        item = resultItems.GetFirst();
        do
        {
           if (item != null)
           {
               if (item is Outlook._AppointmentItem)
               {
                   counter++;
                   appItem = item as Outlook._AppointmentItem;
                   strBuilder.AppendLine("#" + counter.ToString() +
                                         "\tStart: " + appItem.Start.ToString() +
                                         "\tSubject: " + appItem.Subject +
                                         "\tLocation: " + appItem.Location);
               }
               Marshal.ReleaseComObject(item);
               item = resultItems.GetNext();
           }
       }
       while (item != null);
       if (strBuilder.Length > 0)
           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);
       if (resultItems != null) Marshal.ReleaseComObject(resultItems);
   }
}

VB.NET and Add-in Express:

Imports System.Text
Imports System.Diagnostics
' ...
Private Sub RestrictCalendarItems(folder As Outlook.MAPIFolder)
    Dim dtEnd As DateTime = New DateTime(DateTime.Now.Year, DateTime.Now.Month, _
                                         DateTime.Now.Day, 23, 59, 0, 0)
    Dim restrictCriteria As String = "[Start]<=""" + dtEnd.ToString("g") + """" + _
                                     " AND [End]>=""" + DateTime.Now.ToString("g") + """"
    Dim strBuilder As StringBuilder = Nothing
    Dim folderItems As Outlook.Items = Nothing
    Dim resultItems As Outlook.Items = Nothing
    Dim appItem As Outlook._AppointmentItem = Nothing
    Dim counter As Integer = 0
    Dim item As Object = Nothing
    Try
        strBuilder = New StringBuilder()
        folderItems = folder.Items
        folderItems.IncludeRecurrences = True
        folderItems.Sort("[Start]")
        resultItems = folderItems.Restrict(restrictCriteria)
        item = resultItems.GetFirst()
        Do
            If Not IsNothing(item) Then
                If (TypeOf (item) Is Outlook._AppointmentItem) Then
                    counter = counter + 1
                    appItem = item
                    strBuilder.AppendLine("#" + counter.ToString() + _
                                          " Start: " + appItem.Start.ToString() + _
                                          " Subject: " + appItem.Subject + _
                                          " Location: " + appItem.Location)
                End If
                Marshal.ReleaseComObject(item)
                item = resultItems.GetNext()
            End If
        Loop Until IsNothing(item)
        If (strBuilder.Length > 0) 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)
        If Not IsNothing(resultItems) Then Marshal.ReleaseComObject(resultItems)
    End Try
End Sub

C# and VSTO:

using System.Diagnostics;
using System.Runtime.InteropServices;
// ...
private void RestrictCalendarItems(Outlook.MAPIFolder folder)
{
    DateTime dtEnd = new DateTime(DateTime.Now.Year, DateTime.Now.Month,
                                  DateTime.Now.Day, 23, 59, 00, 00);
    string restrictCriteria = "[Start]<=\"" + dtEnd.ToString("g") + "\"" +
                              " AND [End]>=\"" + DateTime.Now.ToString("g") + "\"";
    StringBuilder strBuilder = null;
    Outlook.Items folderItems = null;
    Outlook.Items resultItems = null;
    Outlook._AppointmentItem appItem = null;
    int counter = default(int);
    object item = null;
    try
    {
        strBuilder = new StringBuilder();
        folderItems = folder.Items;
        folderItems.IncludeRecurrences = true;
        folderItems.Sort("[Start]");
        resultItems = folderItems.Restrict(restrictCriteria);
        item = resultItems.GetFirst();
        do
        {
            if (item != null)
            {
                if (item is Outlook._AppointmentItem)
                {
                    counter++;
                    appItem = item as Outlook._AppointmentItem;
                    strBuilder.AppendLine("#" + counter.ToString() +
                                          "\tStart: " + appItem.Start.ToString() +
                                          "\tSubject: " + appItem.Subject +
                                          "\tLocation: " + appItem.Location);
                }
                Marshal.ReleaseComObject(item);
                item = resultItems.GetNext();
            }
        }
        while (item != null);
        if (strBuilder.Length > 0)
            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);
        if (resultItems != null) Marshal.ReleaseComObject(resultItems);
    }
}

VB.NET and VSTO:

Imports System.Diagnostics
Imports System.Runtime.InteropServices
' ...
Private Sub RestrictCalendarItems(folder As Outlook.MAPIFolder)
    Dim dtEnd As DateTime = New DateTime(DateTime.Now.Year, DateTime.Now.Month,
                                         DateTime.Now.Day, 23, 59, 0, 0)
    Dim restrictCriteria As String = "[Start]<=""" + dtEnd.ToString("g") + """" + _
                                     " AND [End]>=""" + DateTime.Now.ToString("g") + """"
    Dim strBuilder As StringBuilder = Nothing
    Dim folderItems As Outlook.Items = Nothing
    Dim resultItems As Outlook.Items = Nothing
    Dim appItem As Outlook._AppointmentItem = Nothing
    Dim counter As Integer = 0
    Dim item As Object = Nothing
    Try
        strBuilder = New StringBuilder()
        folderItems = folder.Items
        folderItems.IncludeRecurrences = True
        folderItems.Sort("[Start]")
        resultItems = folderItems.Restrict(restrictCriteria)
        item = resultItems.GetFirst()
        Do
            If Not IsNothing(item) Then
                If (TypeOf (item) Is Outlook._AppointmentItem) Then
                    counter = counter + 1
                    appItem = item
                    strBuilder.AppendLine("#" + counter.ToString() + _
                                          " Start: " + appItem.Start.ToString() + _
                                          " Subject: " + appItem.Subject + _
                                          " Location: " + appItem.Location)
                End If
                Marshal.ReleaseComObject(item)
                item = resultItems.GetNext()
            End If
        Loop Until IsNothing(item)
        If (strBuilder.Length > 0) 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)
        If Not IsNothing(resultItems) Then Marshal.ReleaseComObject(resultItems)
    End Try
End Sub

You can use the Output window in Visual Studio when debugging the code or the DebugView utility to see the results.

See you on our forums and in the e-mail support!

3 Comments

  • 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!

  • Joey says:

    You made my day! I tried for one day now to include recurrencies and filter/restrict the result with some strange results. Including the line “Sort(“[Start]”)” solved the issue completely. WTF… Thx!!!

Post a comment

Have any questions? Ask us right now!