Freigeben über


HOW TO: Not allow a user to add multiple items of a meeting at the same time & date in a Calendar list for a user in SharePoint 2010

This post is a contribution from Bharat Rathod, an engineer with the SharePoint Developer Support team.

By default, SharePoint 2010 allows you to add multiple items in the calendar for the same date and time.  Below screenshot shows that Meeting1 and Meeting2 occur at the same date and time for the same user.

image

In real world scenario, we do not let a user have multiple entries of meetings at the same date and time.  For example, Outlook warns the user of the clashes of the meeting that occur at the same date and time.

Here’s a sample feature that will prevent this from occurring in your Calendar list.

The Feature.xml file

 <?xml version="1.0" encoding="utf-8"?>
 <Feature Scope="Site"
   Title="Simple Event Handler Registration"
   Id="853A4952-122D-4F97-8239-A2B02FFFDA68"
   xmlns="https://schemas.microsoft.com/sharepoint/">
   <ElementManifests>
     <ElementManifest Location="Elements.xml"/>
   </ElementManifests>
 </Feature>

The Elements.xml file

 <?xml version="1.0" encoding="utf-8"?>
 <Elements xmlns="https://schemas.microsoft.com/sharepoint/">
   <Receivers ListTemplateId="106">
     <Receiver>
       <Name>doublemeeting</Name>
       <Type>ItemAdding</Type>
       <SequenceNumber>10001</SequenceNumber>
       <Assembly>doublemeeting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=30c59cdee5e7a547</Assembly>
       <Class>doublemeeting.PreventDoubleBooking</Class>
       <Data></Data>
       <Filter></Filter>
     </Receiver>
     <Receiver>
       <Name>doublemeeting</Name>
       <Type>ItemUpdating</Type>
       <SequenceNumber>10001</SequenceNumber>
       <Assembly>doublemeeting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=30c59cdee5e7a547</Assembly>
       <Class>doublemeeting.PreventDoubleBooking</Class>
       <Data></Data>
       <Filter></Filter>
     </Receiver>
   </Receivers>
 </Elements>

And the complete code file

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using Microsoft.SharePoint;
  
 namespace doublemeeting
 {
     public class PreventDoubleBooking : SPItemEventReceiver
     {
         /// <summary>
         /// This event is triggered when the user adds a new item
         /// </summary>
         /// <param name="properties"></param>
         public override void ItemAdding(SPItemEventProperties properties)
         {
             //Our query string variable
             string strQuery = null;
  
             try
             {
                 //Get the Sharepoint site instance
                 using (SPWeb oWebsite = new SPSite(properties.SiteId).OpenWeb(properties.RelativeWebUrl))
                 {
  
                     //Get the collection of properties for the Booking item
                     SPListItemCollection collItems = oWebsite.Lists[properties.ListTitle].Items;
  
                     //Get the Calendar List that we will be querying against
                     SPList calendar = oWebsite.Lists[properties.ListId];
  
                     //Get the internal name of the fields we are querying. 
                     //These are required for the CAML query
                     string start_internal = collItems.List.Fields["Start Time"].InternalName;
                     string end_internal = collItems.List.Fields["End Time"].InternalName;
                     string Category_Internal = collItems.List.Fields["Category"].InternalName;
  
                     //Get the query string parameters
                     string start_str = properties.AfterProperties[start_internal].ToString();
                     string end_str = properties.AfterProperties[end_internal].ToString();
                     string Category_str = properties.AfterProperties[Category_Internal].ToString();
  
                     //Construct a CAML query
                     SPQuery query = new SPQuery();
  
                     //Create the CAML query string that checks to see if the booking we are attemping
                     //to add will overlap any existing bookings
                     strQuery = string.Format(@"
  
     <Where>
     
         <And>
             <Or>
             
                 <Or>
                     <And>
                        <Leq>
                           <FieldRef Name='EventDate' />
                           <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                        </Leq>
  
                        <Gt>
                           <FieldRef Name='EndDate' />
                           <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                        </Gt>
                     </And>
  
                     <And>
                        <Lt>
                           <FieldRef Name='EventDate' />
                           <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                        </Lt>
  
                        <Geq>
                           <FieldRef Name='EndDate' />
                           <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                        </Geq>
                     </And>
                 </Or>
                 
                 <Or>
                     <And>
                        <Leq>
                           <FieldRef Name='EventDate' />
                           <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                        </Leq>
  
                        <Geq>
                           <FieldRef Name='EndDate' />
                           <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                        </Geq>
                     </And>
  
                     <And>
                        <Geq>
                           <FieldRef Name='EventDate' />
                           <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                        </Geq>
  
                        <Leq>
                           <FieldRef Name='EndDate' />
                           <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                        </Leq>
                     </And>
                 </Or>
                 
             </Or>
         
             <Eq>
                 <FieldRef Name='Category' />
                 <Value Type='Choice'>{2}</Value>
             </Eq>
             
         </And>
         
     </Where>
     <OrderBy>
         <FieldRef Name='EventDate' />
     </OrderBy>
 ", start_str, end_str, Category_str);
  
                     //Set the query string for the SPQuery object
                     query.Query = strQuery;
  
                     //Execute the query against the Calendar List
                     SPListItemCollection existing_events = calendar.GetItems(query);
  
                     //Check to see if the query returned any overlapping bookings
                     if (existing_events.Count > 0)
                     {
                         //Cancels the ItemAdd action and redirects to error page
                         properties.Cancel = true;
  
                         //Edit the error message that will display on the error page
                         properties.ErrorMessage += "This booking cannot be made because of one or more bookings in conflict. <BR><BR>";
  
                         //Here you can loop through the results of the query
                         //foreach (SPListItem oListItem in existing_events)
                         //{
                         //   ....
                         //}
  
                         properties.ErrorMessage += "Please go back and schedule a new time.";
                     }
  
                 }
             }
             catch (Exception ex)
             {
                 //Cancels the ItemAdd action and redirects to error page
                 properties.Cancel = true;
  
                 //Edit the error message that will display on the error page
                 properties.ErrorMessage = "Error looking for booking conflicts: " + ex.Message;
             }
  
         }
  
         /// <summary>
         /// This event is triggered when the user edits an calendar item
         /// </summary>
         /// <param name="properties"></param>
         public override void ItemUpdating(SPItemEventProperties properties)
         {
  
             string strQuery = null;
  
             try
             {
  
                 //Get the Sharepoint site instance
                 using (SPWeb oWebsite = new SPSite(properties.SiteId).OpenWeb(properties.RelativeWebUrl))
                 {
  
                     //Get the collection of properties for the Booking item
                     SPListItemCollection collItems = oWebsite.Lists[properties.ListTitle].Items;
  
                     //Get the Calendar List that we will be querying against
                     SPList calendar = oWebsite.Lists[properties.ListId];
  
                     //Get the internal name of the fields we are querying. 
                     //These are required for the CAML query
                     string start_internal = collItems.List.Fields["Start Time"].InternalName;
                     string end_internal = collItems.List.Fields["End Time"].InternalName;
                     string Category_Internal = collItems.List.Fields["Category"].InternalName;
                     string guid_internal = collItems.List.Fields["GUID"].InternalName;
  
                     //Get the query string parameters
                     string start_str = properties.AfterProperties[start_internal].ToString();
                     string end_str = properties.AfterProperties[end_internal].ToString();
                     string Category_str = properties.AfterProperties[Category_Internal].ToString();
                     string guid_str = properties.AfterProperties[guid_internal].ToString();
  
                     //Construct a CAML query
                     SPQuery query = new SPQuery();
  
                     //Create the CAML query string that checks to see if the booking we are attemping
                     //to change will overlap any existing bookings, OTHER THAN ITSELF
                     strQuery = string.Format(@"
  
     <Where>
         <And>
         
             <And>
                 <Or>
                 
                     <Or>
                         <And>
                            <Leq>
                               <FieldRef Name='EventDate' />
                               <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                            </Leq>
  
                            <Gt>
                               <FieldRef Name='EndDate' />
                               <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                            </Gt>
                         </And>
  
                         <And>
                            <Lt>
                               <FieldRef Name='EventDate' />
                               <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                            </Lt>
  
                            <Geq>
                               <FieldRef Name='EndDate' />
                               <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                            </Geq>
                         </And>
                     </Or>
                     
                     <Or>
                         <And>
                            <Leq>
                               <FieldRef Name='EventDate' />
                               <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                            </Leq>
  
                            <Geq>
                               <FieldRef Name='EndDate' />
                               <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                            </Geq>
                         </And>
  
                         <And>
                            <Geq>
                               <FieldRef Name='EventDate' />
                               <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                            </Geq>
  
                            <Leq>
                               <FieldRef Name='EndDate' />
                               <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                            </Leq>
                         </And>
                     </Or>
                     
                 </Or>
             
                 <Eq>
                     <FieldRef Name='Category' />
                     <Value Type='Choice'>{2}</Value>
                 </Eq>
                 
             </And>
         
             <Neq>
                 <FieldRef Name='GUID' />
                 <Value Type='GUID'>{3}</Value>
             </Neq>
         
         </And>
         
     </Where>
     
     <OrderBy>
         <FieldRef Name='EventDate' />
     </OrderBy>
 ", start_str, end_str, Category_str, guid_str);
  
                     //Set the query string for the SPQuery object
                     query.Query = strQuery;
  
                     //Execute the query against the Calendar List
                     SPListItemCollection existing_events = calendar.GetItems(query);
  
                     //Check to see if the query returned any overlapping bookings
                     if (existing_events.Count > 0)
                     {
  
                         //Cancels the ItemAdd action and redirects to error page
                         properties.Cancel = true;
  
                         //Edit the error message that will display on the error page
                         properties.ErrorMessage += "This booking cannot be made because of one or more bookings in conflict. <BR><BR>";
  
                         //Here you can loop through the results of the query
                         //foreach (SPListItem oListItem in existing_events)
                         //{
                         //   ....
                         //}
  
                         properties.ErrorMessage += "Please go back and schedule a new time.";
                     }
  
                 }
             }
             catch (Exception ex)
             {
  
                 //Cancels the ItemAdd action and redirects to error page
                 properties.Cancel = true;
  
                 //Edit the error message that will display on the error page
                 properties.ErrorMessage = "Error looking for booking conflicts: " + ex.Message;
             }
  
         }
  
     }
 }

Below are the source code and the feature file samples for your reference.

Feature: DoubleMeeting Feature

Sample source code: DoubleMeetingSource

Hope this post was helpful!

Comments

  • Anonymous
    January 01, 2003
    @TrevoR2300: You should be able to implement the same in a SP 2010 Foundation. For more details of Event Receivers in SP 2010 Foundation, you can refer this MSDN link:-msdn.microsoft.com/.../gg749858(v=office.14).aspx

  • Anonymous
    January 01, 2003
    Hi Can you tell me please how can intall it in a sharepoint foundation? Thanks

  • Anonymous
    January 01, 2003
    @Anahr: so, this is a custom Event Receiver solution which we are deploying. We would also need to modify the Feature.xml associated with the Feature and the Element.xml & code-behind files for the Event Receiver as mentioned above. For more details onto how to create a sample Event Receiver solution, you can refer this MSDN link:-  msdn.microsoft.com/.../gg252010(v=office.14).aspx

  • Anonymous
    January 01, 2003
    See if this helps - www.ehow.com/how_5905423_publish-existing-outlook-calendar-sharepoint.html.

  • Anonymous
    August 03, 2012
    Many thanks for this post. This will allow me to use this in my office environment. I am just checking with you; is there any way we can link Outlook 2010 - room booking calendar with sharepoint calendar. Just a check. Cheers Sathya

  • Anonymous
    August 27, 2013
    Can you please provide some guidance on how this is deployed?

  • Anonymous
    June 09, 2014
    Nice solution, but it will not work for new recurring events. You need to extract the RecurrenceData and parse it....

  • Anonymous
    March 08, 2015
    This code does not validate duplicate recurring event occurrences. Appreciate if you can help on this....