Gunnar Peipman's ASP.NET blog

ASP.NET, C#, SharePoint, SQL Server and general software development topics.

Sponsors

News

 
 
 
DZone MVB

Links

Social

Creating SharePoint global calendar

Creating global calendar that shows data from different calendars is something that SharePoint doesn’t have out-of-box. Using site data query and calendar view control we can easily create global calendar and make it show data from lists we want.

data-from-multiple-calendars

Before you start you should create two calendars to SharePoint site where you want to show global calendar. I tested my code on MOSS 2007 but it should also work on WSS 3.0. If you want to get done fast then you can create new web part and paste all these methods to web part class. Don’t forget to change list GUID-s before deploying your code.

Creating the calendar control

As a first thing let’s update CreateChildControls method. We don’t write calendar creation code here because in this method we want things to be simple and clear.


/// <summary>

/// Called by the ASP.NET page framework to notify server controls

/// that use composition-based implementation to create any child

/// controls they contain in preparation for posting back or
/// rendering.

/// </summary>

protected override void CreateChildControls()

{

    base.CreateChildControls();

 

    try

    {

        AddCalendar();

    }

    catch (Exception ex)

    {

        Controls.Add(new LiteralControl("<b>Error</b> "));

        Controls.Add(new LiteralControl(ex.ToString()));

    }

 

}


As a next thing let’s add code for AddCalendar method. In this method we control the process of calendar creation. We need reference to current web and then we play with data. GetQueryData returns us DataTable and GetCalendarItems converts this DataTable to SPCalendarItemCollection. Then we detect calendar view type (day view, week view,  month view) by request variables and as a last thing we bind data to calendar and add calendar to web part controls collection.


/// <summary>

/// Adds the calendar to web part.

/// </summary>

private void AddCalendar()

{

    var web = SPContext.Current.Web;

    var results = GetQueryData(web);

    var items = GetCalendarItems(web, results);

 

    var calView = new SPCalendarView();

    calView.ViewType = GetCalendarType(Page.Request["CalendarPeriod"]);

    calView.DataSource = items;

    calView.DataBind();

    Controls.Add(calView);

}


Quering lists

Now let’s ask data for calendar. We have to create SPSiteDataQuery that is able to query all the lists in site or site collection. This is a little bit tricky class and you can read about it blog posting SPSiteDataQuery Samples for WSS v3 from thekid.me.uk blog. We will write now our GetQueryData method that creates site data query and returns results. We are able to get these results only as DataTable. Why separate method? Just look at this method – it is pretty long.


/// <summary>

/// Executes the query against the web and returns
/// results as DataTable.

/// </summary>

/// <param name="web">The web that is queried.</param>

/// <returns>Query results as DataTable.</returns>

private DataTable GetQueryData(SPWeb web)

{

    var query = new SPSiteDataQuery();

 

    query.Lists = @"<Lists>

                        <List ID='{56F5E040-D547-4BF5-8C99-F019D54F9997}' />

                        <List ID='{92A87CB9-E39B-4C2D-B37D-5721E6C7FECD}' />

                    </Lists>";

 

    query.Query = @"<Where>

                        <Gt>

                            <FieldRef Name='ID' />

                            <Value Type='Number'>0</Value>

                        </Gt>

                    </Where>";

 

    query.Webs = "<Webs Scope='SiteCollection' />";

 

    query.ViewFields = "<FieldRef Name='Title' />";

    query.ViewFields+= "<FieldRef Name='ID' />";

    query.ViewFields+= "<FieldRef Name='EventDate' />";

    query.ViewFields+= "<FieldRef Name='EndDate' />";

    query.ViewFields+= "<FieldRef Name='Location' />";

    query.ViewFields+= "<FieldRef Name='Description' />";

    query.ViewFields+= "<FieldRef Name='fRecurrence' />";

 

    query.RowLimit = 100;

 

    return web.GetSiteData(query);

}


NB! The first block of XML is lists definition. Replace GUID-s of lists with GUID-s of your lists! Also don’t remove row limit. You can change the value but if you remove it then you get no results.

Transforming results

GetSiteData returns results as DataTable. SPCalendarView accepts DataTable as data source but it shows calendar empty. We need SPCalendarItemCollection to get results to calendar. For this conversion we write the method GetCalendarItems. This method takes DataTable returned by GetSiteData and returns results as SPCalendarItemCollection.

The code for calendar actions is borrowed from Tom Stegeman blog posting Using SPCalendarView to show items in a calendar.


/// <summary>

/// Gets the collection of calendar items based on site
/// data query results.

/// </summary>

/// <param name="web">The web that was queried.</param>

/// <param name="results">The results of query.</param>

/// <returns>Collection of calendar items accepted by
/// calendar component
</returns>

private SPCalendarItemCollection GetCalendarItems(SPWeb web, DataTable results)

{

    var items = new SPCalendarItemCollection();

    foreach (DataRow row in results.Rows)

    {

        var listGuid = new Guid(row["ListId"] as string);

        var list = web.Lists[listGuid];

 

        SPCalendarItem item = new SPCalendarItem();

 

        foreach (SPForm form in list.Forms)

            if (form.Type == PAGETYPE.PAGE_DISPLAYFORM)

            {

                item.DisplayFormUrl = form.ServerRelativeUrl;

                break;

            }

 

        item.ItemID = row["ID"] as string;

        item.StartDate = DateTime.Parse(row["EventDate"] as string);

        item.EndDate = DateTime.Parse(row["EndDate"] as string);

        item.hasEndDate = true;

        item.Title = row["Title"] as string;

        item.Location = row["Location"] as string;

        item.Description = row["Description"] as string;

        item.IsAllDayEvent = (int.Parse(row["fAllDayEvent"] as string) != 0);

        item.IsRecurrence = (int.Parse(row["fRecurrence"] as string) != 0);

        item.CalendarType = Convert.ToInt32(SPCalendarType.Gregorian);

        items.Add(item);

    }

 

    return items;

}


This method has one little trick. We need URL template to assign it to DisplayFormUrl. When calendar is rendered then parameter ID will be added to this URL.

Why we don’t ask it from list and then use it as constant? Okay, results are coming from more than one list. Each list has separate display form and therefore separate display form URL. To get correct URL-is it is good idea to ask them directly from list Forms collection.

Detecting calendar type

As a last thing we have to add one utility method to our web part class. We need to know what view calendar has to show. There three views:

  • day view,
  • week view,
  • month view.

When we switch view then view type is given to calendar over query string. As query string is something that everybody can easily change we need to make sure that we assign correct view type to calendar. Otherwise exception will be thrown.


/// <summary>

/// Gets the type of the calendar view.

/// </summary>

/// <param name="type">The type to be checked.</param>

/// <returns>Correct view type of calendar.</returns>

private static string GetCalendarType(string type)

{

    if (type == null)

        type = string.Empty;

 

    switch (type.ToLower())

    {

        case "day":

            return "day";

        case "week":

            return "week";

        case "timeline":

            return "timeline";

        default:

            return "month";

    }

}


How it’s time to compile the code and deploy it to server. If you or I have make no mistakes in code then you should see familiar SharePoint calendar that shows results from more than one calendar.

Calendar based on site data query

You can click on image to see how it looks full size. Training info comes from list Calendar and meeting information comes from Rooms Calendar.

Happy SharePointing!

Posted: Jan 24 2009, 12:53 PM by DigiMortal | with 62 comment(s)
Filed under:

Comments

Links (1/25/2009) « Steve Pietrek - Everything SharePoint said:

Pingback from  Links (1/25/2009) &laquo; Steve Pietrek - Everything SharePoint

# January 25, 2009 8:11 PM

Christopher Steen said:

Link Listing - January 26, 2009

# January 27, 2009 1:46 AM

Christopher Steen said:

Sharepoint New Release of the SmartTools for SharePoint Project [Via: Jan Tielens ] Creating SharePoint...

# January 27, 2009 1:47 AM

Kirk said:

Is there a download of this calendar to test with? If not, would you mind explaining a few details? Do you start with a generic WebPart in Visual Studio or do you base it on a standard SharePoint Calendar and extend it?

I get the idea you're doing but I've never had to create a SharePoint control until now, so a few pointers would set me straight.

Great info!

# March 5, 2009 1:44 PM

DigiMortal said:

I plan to write a web part if find some time for that. If you want to do it by yourself then extending or wrapping SharePoint calendar is easiest way to go, I think.

# March 5, 2009 4:52 PM

Trevor said:

I am new to the SharePoint world.  Could anyone tell me which files these various methods (such as CreateChildControls, etc.) are located so I can edit them?

Thanks!!!

# March 6, 2009 11:01 AM

DigiMortal said:

Trevor, I created simple WebPart using Visual Studio.

# March 7, 2009 7:19 AM

James said:

has any one made this into a Webpart that they could send me?

I understand the theory but in practice havent got a clue where to start.

Thanks in advance

# March 16, 2009 2:41 PM

DigiMortal said:

Hi James! I have got no time to develop web part for global calendar yet. When I get time I will create this web part for sure.

# March 17, 2009 6:09 AM

Recurring events said:

hi,

I developed global calendar (showing all calendar events from whole site collection). BUT it does not display recurring events right way - it shows them as all-day events with correct start date however end date is e.g. year 2028. It seems like property IsRecurrence does not work well...

# April 2, 2009 5:44 AM

DigiMortal said:

I think you have to ask more fields from calendars because recurrence information is kept as XML on certain fields. Try to get recurrence information to your calendar results and let's see then what happens.

# April 2, 2009 5:54 AM

smultronpop@hotmail.com said:

I´m having trouble convering system.data.datatable to microsoft.sharepoint.webcontrols.datatablesourceview in the return web.GetSiteData(query); line

# April 24, 2009 9:00 AM

DigiMortal said:

Can you show me your code or paste full exception with trace here?

# April 24, 2009 9:09 AM

smultronpop@hotmail.com said:

worked it out, just had to check my code.

# April 28, 2009 8:30 AM

Julien said:

Hello,

I was wondering how this could be implemented in our SharePoint site directly trough the web browser since we do not have access to the server and we do net have any software to program with.

Thank tou

# June 10, 2009 9:32 AM

DigiMortal said:

Hello!

You can do something like this using JavaScript, AJAX and SharePoint web services although I don't recommend this solution. It is better to write your own web part, install it on your server and use it.

# June 10, 2009 9:42 AM

Recurring events said:

to DigiMortal>>>

The problem with showning reccuring events correctly is not in data i got or did not get from a source. Event i put correct data into spcalendar (e.g. item.IsAllDayEvent = false;

       item.IsRecurrence = true;

)

the calendar view is broken - it shows all day events instead of recuuring events i have set in the code...

# June 15, 2009 10:43 AM

Umair Khan said:

Great blog... very simple... Thanks...

I have created the webpart using sharepoint webpart template in VS 2005 (did some changes to code to get it work in VS 2005).

Furthermore i have added a toolpart to accept comma(,) delimited urls to calendar lists on the site collection. Which allows users to set the web part directly from sharepoint eliminating the need to open code if you have to add more calendars.

Let me know if any one needs it or with permission from Gunnar Peipman we can have it here as attachment.

# July 1, 2009 4:14 AM

DigiMortal said:

Umair, it is very okay if you send your web part here. You can send files to gunnar [at] developers-team com

# July 3, 2009 3:26 AM

hana said:

Thanx for this blog - it was a big help! now a question, I'm trying to create a color coded calendar but it seems like the background color property only works if the event is a "full day event", otherwise it just ignores the class. any ideas?

thank you for your time,

# August 4, 2009 1:43 AM

DigiMortal said:

Hi hana!

Just to get better understanding of a problem - is the background color you set written out to html too? Just trying to make sure if this problem is related to calendar component or is it stylesheets issue.

# August 4, 2009 2:45 AM

hana said:

thanx for answering!

the background color I'm using is written in my custom theme CSS file. now, I see it's working for events that are marked as full day events but for some odd reason it just doesn't 'catch' onto regular events. (I also checked with my idev tool and I see that although during debug it shows giving the item my class, when it displays the calendar it goes back to it's original class)

I'm really stuck with this and can't seem to find a way around, this has to be ready by next week and I'm so nervous- please could you help me?

again I appreciate you time and effort,

# August 6, 2009 7:50 AM

DB said:

Great post. I am also having issues with the calendar not displaying the recurring events correctly. Did anyone ever figure this out? If the event repeats every Monday for two months, instead of having a separate item on each day that the event occurs, I end up where it looks like the event begins on a date and then runs for the next two months every day.

# August 20, 2009 1:33 PM

DigiMortal said:

Thanks for good word, DB :)

Handling recurring events is pretty problematic topic and problems stated here are not the easy ones. I will put up this code to my development environment again and try out what I can do to make this code completely to work.

I promise no dates because I'm busy with my SharePoint and other projects but if I achieve something that maybe useful to you then I will let you know through this blog.

# August 20, 2009 3:28 PM

jfischer said:

hi,

first thanks for this nice tutorial.

but i have an exception at

item.IsAllDayEvent = (int.Parse(row["fAllDayEvent"] as string) != 0);

The Exception:

System.FormatException: The input string has the wrong format. At System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal) At System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info) At System.Int32.Parse(String s) At GlobalCalendar.WebPart1.GetCalendarItems(SPWeb web, DataTable results) At GlobalCalendar.WebPart1.AddCalendar() At GlobalCalendar.WebPart1.CreateChildControls()

Could anyone help me please?!

Thanks, best regards

jfischer

# August 25, 2009 5:30 AM

DigiMortal said:

Try to do it this way:

item.IsAllDayEvent = (int.Parse(row["fAllDayEvent"].ToString()) != 0);

or

item.IsAllDayEvent = ((int)row["fAllDayEvent"] != 0);

# August 26, 2009 6:26 PM

maanda said:

Hi all,

So has anyone figured out the recurring events problem. I am stuck with it too.

Thanks

# August 27, 2009 2:00 AM

budi said:

ok nice and it's worked!, well how to syncronize this global calendar with oulook ?

# September 10, 2009 11:45 AM

DigiMortal said:

Hi budi!

As far as I know it is not very easy to synchronize this calendar to Outlook because it doesn't exist as list in SharePoint. One dirty hack that comes to my mind is to use timer job and hidden calendar that is synchronized with other calendars. But I don't think it is good solution.

# September 12, 2009 1:28 AM

links for 2009-09-18 « Jet Grrl said:

Pingback from  links for 2009-09-18 &laquo; Jet Grrl

# September 18, 2009 8:36 PM

Juna said:

May I know if the recurring events display issues solved?

# September 23, 2009 12:15 AM

SharePoint Global Calendar « Adonis Latham said:

Pingback from  SharePoint Global Calendar &laquo; Adonis Latham

# October 4, 2009 6:03 PM

Rich Browne said:

REGARDING RECURRING EVENTS

Hi Guys,

I've been working on a calendar feature for an external website using multiple calendar lists as a data source and to settle the argument, this implementation will not work with recurring calendar events.

The reason is that recurring events are actually only one list item which represents the 'set', and the recurrance rule is stored as a property of that list item. Using SPQuery you can return these recurrences using the 'DateRangesOverlap' caml method, but unfortunately SPSiteDataQuery does not have this functionality so you will only get the list item that represents the 'set' back as a result (this is why you are seeing all day events that stretch for months - this is the range of your recurrence set).

The only solution I found to this problem is that you have to run an SPQuery for every recurrence set that SPSiteDataQuery retrieves, and add the results to your final results DataTable.

This is a god-awful implementation that reeks of last minute hackage from Microsoft goons, and we can only hope that it is properly implemented in vNext.

# October 6, 2009 3:09 PM

Jur said:

Great !

It worked, but, what about if I need to change the fields in the view??

I mean, if instead of seeing the Title, in the MonthView, I want to view another field.

Thanks Man!!

# December 9, 2009 2:33 PM

mr.x said:

Hi, first off, kudos to the author. This is perfect and exactly what I need. This may sound stupid, but I'm pretty confused about how to do this. From the sounds of it I need to start Visual Studio, and create a new  simple WebPart (which i guess is available as a template). Then once I copy and paste the codes above into the appropriate sections and make the appropriate adjustments I save it and install on the server running the sharepoint? How do I go about doing that? Do I just run it or something? Sorry I don't have visual studio at work and I need to go home to do this that's why I'm asking.

Also, we have sharepoint 2.0, is this still going to work? And we have a main sharepoint site with a calendar that is already being used by the company, I just want to pull data from that calendar to my group's calendar (which hasn't been created yet), do I need to do anything differently from what is mentioned above?

I'm sorry for asking too many questions but I would really like to have this working. Thanks

# January 29, 2010 12:27 PM

Saravana said:

Calendaring roll-ups of the IT SharePoint subsites to its top level site calendars

The top-level  calendars seem to be functioning as far as reflecting (and updating in real-time) the subsites subsequent calendar information

The one snag we have run into is that anytime a calendar item is marked as "recurring" it turns it into an all-day event, and stretches the meeting notice across the whole calendar.

For example: Subsite Calendar lists a monthly PM meeting occurring the 2nd Thurs. of every month from 12:30pm-2pm. Once marked 'recurring' and submitted, the entire calendar shows the meeting stretched across each day, each month, each year to the end of the set recurrence (whether a set date or # of recurrences, or no end date to recurrence at all).

This view ONLY affects the top-level calendars; subsite calendars are NOT affected in any way.

Any single-entry calendars without recurrences display normally.

Note: exactly I followed the Code in the Site: weblogs.asp.net/.../creating-sharepoint-global-calendar.aspx. is there anything I need to add to code to resolve this issue.

I appreciate your responses.

# February 8, 2010 10:15 AM

Dishaniti said:

From where I can download the complete code?

# February 16, 2010 8:36 PM

DigiMortal said:

Source is not available (yet). As soon as I have time to work with it I will publish it here.

# February 18, 2010 7:33 AM

Avikumar said:

I like your code and want to implement on production server. Before this I have 1 question i.e. How can I show user/role specific events in calendar. Let say if user belong to owner group he can see all the events, if user is belong to contributor he can see only his events.

How can I add this?

# February 18, 2010 10:51 PM

Roby said:

I am pretty sure that Gunnar is working on the RECURRING EVENTS issue.

But could you suggest a temporary workaround for this problem. In simple terms is there a way to just query the list collection with the events that are recurring and displaying them as such. In the lines of using the SPQuery object to filter out the items based on a certain CAML query.

I am pretty sure there are people with vibrant ideas.

Thanks,

# February 19, 2010 2:59 PM

DigiMortal said:

This recurring events issue needs some deeper investigation. You should be able to find recurring events by some field value they have in common.

# February 19, 2010 9:50 PM

fera said:

Sorry, I'm a newbie in sharepoint. May I know how should I do if I want to open sharepoint site using visual studio 2008 and entry the code that you show in this site.

Thank you.

# April 14, 2010 7:39 AM

Charlie said:

How do you get the ListID's of a calendar for the GetQueryData function?

# April 15, 2010 7:27 PM

avikumar said:

I tried your code, calendar is displaying properly, but calendar events are not populating. I checked UID, it is also correct? Let me know I am missing anything?

Is this possible that we can pull items from various custom lists, rahter calendar type list?

Please advise

# May 25, 2010 1:28 AM

aisabuz said:

Thanks for nice article

To: Charle

You can get ID by Title by the following code

using (SPSite site = new SPSite("http://localhost/"))

{

   using (SPWeb web = site.OpenWeb())

   {   //You Calendar or Any List Title            

       string calendar = "Calendar";

       SPList list = null;

       foreach (SPList currentList in web.Lists)

       {

          if (currentList.Title.Equals(calendar,

                      StringComparison.InvariantCultureIgnoreCase))

           {

               list = currentList;  Console.WriteLine(list.ID.ToString());  

                break;

            }

        }                        

  }

}

# July 16, 2010 8:56 AM

ankit said:

Really nice article. It really worked for me. But can i do this way..means can i select calendar form drop down list and the selected calendar will be merged to global calendar.

Quick reply will be appreciated.

Thanks

Ankit

# August 11, 2010 1:15 AM

Keith Kelly said:

I see this webpart loses the toolbar at the top.

I've played around all day with SPList and Toolbar classes and I can get a toolbar to display using the listGUID but this will display as many toolbars as there are lists/calendars on my site.

I want this webpart to replace the default Calendar webpart for the Global Calendar with a toolbar so users can create appointments in the main global calendar still (but are able to view all appointemnts in other sites still) and possibly integrate the combined calendars into Outlook.

Thanks, I'm a novice at this and I've spent all day on it googling without success :)

# October 5, 2010 5:10 PM

Vishal said:

Hi,

Did anyone find solution for recurring events?, I am facing issues with that, otherwise Webpart is working great.. Thanks for the post

# February 7, 2011 11:46 AM

PeterGa said:

Hi all

I have another version of solution for Recurring Events

You will search for fReccurence=1 and you will find all that are reccurent and you will need too get RecurrenceData field and after then you will need to manually parse this XML data to find if this event have appointment in your date range. I think better as to query each Calendar in Site collection.

Also one possible solution too.

# March 7, 2011 3:53 AM

Yogesh said:

This code will work in sharepoint 2010 if you add the below line of code

calView.EnableV4Rendering = false;

# June 9, 2011 4:05 PM

sahana said:

Does anybody know if this solution works for SharePoint 2010?

# September 13, 2011 7:08 PM

DigiMortal said:

Hi! I haven't made tests on SP2010 and I don't know how this solution works on it.

# September 16, 2011 6:34 AM

Ed W said:

All -

I've seen some great discussion on ways to do this and know some of you have developed web parts for it.  I'm new to Sharepoint, arriving headlong into MOSS and wondering if anyone wants to be generous enough to send me a web part that might do the trick that I can adapt?

# November 3, 2011 9:09 PM

R.G said:

I want to remove Expand All, Collapse All, Day, week, Month etc from calendar view. Also need to remove click event on item. How it can be done?

# November 23, 2011 4:23 AM

Sunil said:

Actually i developed a web part by using your code and the problem i am facing is that the events are not being displayed on the calendar and i see only the same calendar what we have in SharePoint 2010.

# November 28, 2011 2:27 AM

Sunil said:

Hi

I prepared the web part in visual studio 2010 and deployed it to the SharePoint 2010 site page and the calendar is displayed but the events from the calendars are not being displayed..

So can anyone suggest me what to do...?????

# November 28, 2011 7:34 AM

sunilprakash7 said:

Hi,

I had created the Web Part in Visual Studio 2010 and deployed into the SharePoint 2010 Site page and the calendar is also displayed,but the problem is that  the events from the calendars are not displayed in the web part.

So i need some suggestion...

# November 28, 2011 7:39 AM

Ajit said:

Hi All,

I had created same Web Part in Studio 2010 and deployed into the SharePoint 2010 Site.Now here only calendar is displayed,but the problem is that  the events from the calendars are not displayed in the web part.

Here i am fetching data from the TaskList.Not from the calender.I replace startdate with eventdate.

Can anyone help me??

# December 28, 2011 7:29 AM

Kris said:

Hi all, is there anyway to create this in a sharepoint environment rather than visual studio, I have visual studio 2008 version but it will not allow me to connect to sharepoint? I have sharepoint designer also, so if it can be done there then even better, all help is much appreciated :-)

# January 5, 2012 10:38 AM

Madhu said:

Hi,

I used your code in my custom calendar web part creation

its working good.

but i need add events for  particular dates and display what i added events that dates.

how can add the events in your calendar code.

please explain me.i am spent lot of time for this.

Thanks,

Madhu.

# March 15, 2012 3:20 AM

susheel said:

hi itried the steps which u have mentioned, i am able to display the webpart but when i clcik on the views i.e, day, week , month nothing is working, even the month icons also not working can u help me out.

regards,

susheel

# June 13, 2012 12:45 AM

Mani said:

For RECURRING EVENTS:

======================

Gotcha.. For recurring events issue, i have found a solution , as instructed in the msdn..

Need to change the SPquery little bit as given below,

googledotnet.blogspot.sg/.../recurring-events-not-working-in.html

Thanks

# November 16, 2012 2:08 AM