none
Last recurring instance of an appointment is not found using VSTO RRS feed

  • Question

  • Hello,

    In some instances the last recurrence of an appointment series is not found.   

    In this example I have a recurring appointment named "TEST APPOINTMENT" that occurs daily at 1:30pm for 7 days consecutive days.  

    The start of the recurring series is on 10/8/2013 and ends on 10/14/2013

    I am able to find all 7 recurring instances if I search between 10/8 - 10/15.

    Trace Output:

    AppointmentQueue.PrepareUploadDataSet [10/8/2013 to 10/15/2013] 
    Searching for recurring appts: 10/8/2013 3:30 PM 
    Searching for recurring appts: 10/9/2013 3:30 PM 
    Searching for recurring appts: 10/10/2013 3:30 PM 
    Searching for recurring appts: 10/11/2013 3:30 PM 
    Searching for recurring appts: 10/12/2013 3:30 PM 
    Searching for recurring appts: 10/13/2013 3:30 PM 
    Searching for recurring appts: 10/14/2013 3:30 PM 
    Searching for recurring appts: 10/8/2013 10:00 AM 
    Searching for recurring appts: 10/9/2013 10:00 AM 
      Recurrence Appt Found: Client Team Weekly Meeting 
    Searching for recurring appts: 10/10/2013 10:00 AM 
    Searching for recurring appts: 10/11/2013 10:00 AM 
    Searching for recurring appts: 10/12/2013 10:00 AM 
    Searching for recurring appts: 10/13/2013 10:00 AM 
    Searching for recurring appts: 10/14/2013 10:00 AM 
    Searching for recurring appts: 10/8/2013 2:00 PM 
    Searching for recurring appts: 10/9/2013 2:00 PM 
    Searching for recurring appts: 10/10/2013 2:00 PM 
    Searching for recurring appts: 10/11/2013 2:00 PM 
    Searching for recurring appts: 10/12/2013 2:00 PM 
    Searching for recurring appts: 10/13/2013 2:00 PM 
    Searching for recurring appts: 10/14/2013 2:00 PM 
      Recurrence Appt Found: Manhattan Engineering Update 
    Searching for recurring appts: 10/8/2013 1:30 PM 
      Recurrence Appt Found: TEST APPOINTMENT 
    Searching for recurring appts: 10/9/2013 1:30 PM 
      Recurrence Appt Found: TEST APPOINTMENT 
    Searching for recurring appts: 10/10/2013 1:30 PM 
      Recurrence Appt Found: TEST APPOINTMENT 
    Searching for recurring appts: 10/11/2013 1:30 PM 
      Recurrence Appt Found: TEST APPOINTMENT 
    Searching for recurring appts: 10/12/2013 1:30 PM 
      Recurrence Appt Found: TEST APPOINTMENT 
    Searching for recurring appts: 10/13/2013 1:30 PM 
      Recurrence Appt Found: TEST APPOINTMENT 
    Searching for recurring appts: 10/14/2013 1:30 PM 
      Recurrence Appt Found: TEST APPOINTMENT 

    I am able to find the second to the last recurrence if I search between 10/13 - 10/14.

    Trace Output:

    AppointmentQueue.PrepareUploadDataSet [10/13/2013 to 10/14/2013] 
    Searching for recurring appts: 10/13/2013 3:30 PM 
    Searching for recurring appts: 10/13/2013 10:00 AM 
    Searching for recurring appts: 10/13/2013 2:00 PM 
    Searching for recurring appts: 10/13/2013 1:30 PM 
      Recurrence Appt Found: TEST APPOINTMENT 

    However, I cannot find the last recurrence if I search between 10/14 - 10/15.    

    Trace Output:

    AppointmentQueue.PrepareUploadDataSet [10/14/2013 to 10/15/2013] 
    Searching for recurring appts: 10/14/2013 3:30 PM 
    Searching for recurring appts: 10/14/2013 10:00 AM 
    Searching for recurring appts: 10/14/2013 2:00 PM 
      Recurrence Appt Found: Manhattan Engineering Update 

    How come this happens?

    Here is the code below:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml.Linq;
    using Outlook = Microsoft.Office.Interop.Outlook;
    using Office = Microsoft.Office.Core;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    
    namespace RecurrenceItemProblem
    {
        public partial class ThisAddIn
        {
            Outlook.Folder m_calendar;
    
            private void ThisAddIn_Startup(object sender, System.EventArgs e)
            {
                m_calendar = (Outlook.Folder)Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
    
                DateTime now = DateTime.Now;          
                {
                    DateTime start = new DateTime(now.Year, now.Month, 14);            
                    DateTime end = new DateTime(now.Year, now.Month, 15);
                    PrepareUploadDataSet(m_calendar, start, end);
                }
            }
    
            public void PrepareUploadDataSet(Outlook.Folder calendarFolder, DateTime startDate, DateTime endDate)
            {
                Outlook.Items olItems = null;
                Debug.WriteLine(String.Format("AppointmentQueue.PrepareUploadDataSet [{0} to {1}]", startDate.ToShortDateString(), endDate.ToShortDateString()));
    
                try
                {
                    string filter =
             String.Format("[Start] >= \"{0}\" AND [Start] <= \"{1}\"", startDate.ToShortDateString(), endDate.ToShortDateString());
    
                    olItems = calendarFolder.Items;
                    olItems.IncludeRecurrences = true;
                    Outlook.Items listItems = olItems.Restrict(filter) as Outlook.Items;
    
                    if (listItems != null)
                    {
                        Outlook.AppointmentItem apptItem = null; 
                
                        //For a collection of outlook items start index must be "1" not "0".  if you start at 0 you'll get an array index out of bounds exception.
                        //For more info see http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.items.aspx
                        for (int i = 1; i <= listItems.Count; i++)
                        {
                            try
                            {
                                apptItem = (Outlook.AppointmentItem)listItems[i];
                                if (apptItem != null)
                                {
                                    if (apptItem.IsRecurring)
                                    {
                                        Outlook.RecurrencePattern pattern = apptItem.GetRecurrencePattern();
                                        DateTime date = new DateTime(startDate.Year, startDate.Month, startDate.Day, apptItem.Start.Hour, apptItem.Start.Minute, apptItem.Start.Second);
                                        while (date <= endDate)
                                        {
                                            //Unfortunately the GetOccurence function throws an exception if the date passed in
                                            //does not match the exact date and time of an appointment within the pattern series. 
                                            try
                                            {
                                                Debug.WriteLine("Searching for recurring appts: " + date.ToShortDateString() + " " + date.ToShortTimeString());
                                                Outlook.AppointmentItem recurrenceItem = pattern.GetOccurrence(date);
                                                if (recurrenceItem != null)
                                                {
                                                    Debug.WriteLine("  Recurrence Appt Found: " + recurrenceItem.Subject);
                                                }
                                                else
                                                {
                                                    //1-100981606 if the object returned from pattern.GetOccurrence is null OR there is an exception when calling
                                                    //pattern.GetOccurrence we need to cycle through the Outlook.Exceptions collection to see if there is a 
                                                    //recurring meeting that was modified. Thus we throw an exception here so that it enters exception handler code
                                                    throw new Exception();
                                                }
                                            }
                                            catch (Exception)
                                            {
                                                //1-100981606 an exception most likely means that a single recurring meeting within a recurrence series has been
                                                //modified.  We need to cycle through the Outlook.Exceptions collection to get the actual recurrence that has changed.
    
                                                try
                                                {
                                                    System.Collections.IEnumerator iter = pattern.Exceptions.GetEnumerator();
                                                    while (iter.MoveNext())
                                                    {
                                                        Outlook.Exception exception = iter.Current as Outlook.Exception;
                                                        if (exception != null)
                                                        {
                                                            Outlook.AppointmentItem recurrenceItem = exception.AppointmentItem;
                                                            if (!exception.Deleted)
                                                            {
                                                                if (recurrenceItem != null)
                                                                {
                                                                    if (recurrenceItem.Start.Month == date.Month &&
                                                                       recurrenceItem.Start.Day == date.Day &&
                                                                        recurrenceItem.Start.Year == date.Year)
                                                                    {
                                                                        Debug.WriteLine("  Recurrence Appt Found: " + recurrenceItem.Subject);                                                
                                                                    }
                                                                    else
                                                                    {
                                                                        Marshal.ReleaseComObject(recurrenceItem);
                                                                    }
                                                                }
                                                            }
    
                                                            Marshal.ReleaseComObject(exception);
                                                        }
                                                    }
                                                }
                                                catch (Exception)
                                                {
                                                }
                                            }
    
                                            date = date.AddDays(1);
                                        }
    
                                        Marshal.ReleaseComObject(pattern);
                                        pattern = null;
                                    }
                                 
                                }
    
                            }
                            catch (Exception e)
                            {
                                //Not sure why but sometimes just checking to 
                                //see if an appointment is recurring causes an 
                                //exception to be thrown.  
                                //Appointment item seems to be invalid or something
                                Debug.WriteLine("Exception occurred in AppointmentQueue.PrepareUploadDataSet e=" + e.ToString());
                            }
                        }
    
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Exception occurred in AppointmentQueue.PrepareUploadDataSet ex=" + ex.ToString());
                }
                finally
                {
                    if (olItems != null)
                    {
                        Marshal.ReleaseComObject(olItems);
                        olItems = null;
                    }
    
                    //Garbage collection needed to fix defect 1-84083497
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                }
            }
                   
    
    
            private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
            {
            }
    
            #region VSTO generated code
    
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InternalStartup()
            {
                this.Startup += new System.EventHandler(ThisAddIn_Startup);
                this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
            }
            
            #endregion
        }
    }


    • Edited by alexkfh Tuesday, October 8, 2013 4:27 PM
    Tuesday, October 8, 2013 4:23 PM

All replies

  • Hi,

    Thank you for posting in the MSDN Forum.

    I'm trying to involve some senior engineers into this issue and it will take some time. Your patience will be greatly appreciated.

    Sorry for any inconvenience and have a nice day!

    Best regards,
    Fei


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, October 10, 2013 9:54 AM
    Moderator
  • Thanks Fei, please do update me as soon as possible.  
    Thursday, October 10, 2013 3:11 PM
  • For restrictions like that you also should set sorting off in addition to including recurrences. Also, you usually would set the filter to use Start and End dates.

    It might help if you look at the article about searching using dates at http://www.outlookcode.com/article.aspx?id=30. It's all VBA code there, but it's simple to convert that into C#.


    Ken Slovak MVP - Outlook

    Thursday, October 10, 2013 3:19 PM
    Moderator