Look up instance of potentially recurring calendar event

In my last post I described how to redirect to a publishing page in order to use it as display form for a calendar.

It caused the problem of having to look up the right instance of the calendar event (in case of recurrence) ourselves. If we just implement an ordinary display form SPContext does the lookup for us.

I poked around in the SDK to find a method which could look up an item from a list based on the RecurrenceID, but without any luck. I knew SPContext did this so I fired up Reflector to see how SPContext did this and found GetInstanceItem which did what I wanted, but tightly coupled to the SPContext’s current List and then it was also a private method.

Despite the DRY principle I had to reimplement the same function.

After a look of the implementation in SPContext.GetInstanceItem it turned out that it might be a good idea to optimize the code a bit during the reimplementation, as SPContext’s version retrieves all instances of all calendar events for the full month in question a loops through these in order to find the right one. My implementation only loops thought all instances for the right event for the right day (usually one).

Here is my function for reference:

private SPListItem GetInstanceItem(SPList list, sting recurrenceId)
{
    int pos = recurrenceId.IndexOf(".");
    int id = int.Parse(recurrenceId.Substring(0, pos == -1 ? recurrenceId.Length : pos));
    SPListItem rootItem = list.Items.GetItemById(id);
    if (pos == -1 ||
        (int)rootItem[SPBuiltInFieldId.EventType] != 1)
    {
        // This is a non recurring item
        //
        return rootItem;
    }
    string format = "<Where>" +
        "<And>" +
        "<DateRangesOverlap>" +
        "<FieldRef Name=\"{0}\" />" +
        "<FieldRef Name=\"{1}\" />" +
        "<FieldRef Name=\"{2}\" />" +
        "<Value Type=\"DateTime\"><Today /></Value>" +
        "</DateRangesOverlap>" +
        "<Eq>" +
        "<FieldRef Name=\"{3}\" />" +
        "<Value Type=\"Counter\">{4}</Value>" +
        "</Eq>" +
        "</And>" +
        "</Where>";
    SPQuery query = new SPQuery();
    SPFieldCollection fields = list.Fields;
    query.Query = string.Format(format,
        fields[SPBuiltInFieldId.StartDate].InternalName,
        fields[SPBuiltInFieldId.EndDate].InternalName,
        fields[SPBuiltInFieldId.RecurrenceID].InternalName,
        fields[SPBuiltInFieldId.ID].InternalName,
        id);
    query.ViewAttributes = " Type=\"CALENDAR\" RecurrenceRowset=\"TRUE\" ";
    query.MeetingInstanceId = -2;
    query.ExpandRecurrence = true;
    string dateString = recurrenceId.Substring(recurrenceId.LastIndexOf(".") + 1);
    dateString = dateString.Substring(0, dateString.IndexOf("T"));
    query.CalendarDate = DateTime.Parse(dateString);
    SPListItemCollection items = list.GetItems(query);
    foreach (SPListItem item in items)
    {
        if (item.RecurrenceID == recurrenceId)
        {
            return item;
        }
    }
    return null;
}
comments powered by Disqus