|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionSharePoint Calendar Lists not only offer standard “1:00-2:30 pm” type entries, but also entries that span multiple days, and all-day items, which have no set start or end time. Retrieving this data means learning something about CAML queries and SharePoint gotchas – and I hope this article saves you some time. OverviewThe “sliding window” calendar web part shows data for 1- 7 contiguous days. The number of days displayed can be configured via the tool pane. If the web part is set to show 3 days, you’ll see today, tomorrow, and the day after that. For example, if today is Wednesday, you’ll see Wednesday-Thursday-Friday; on Thursday, the window “slides” to Thursday-Friday-Saturday. The goal is to display a lot of information in a small amount of space. To that end, only the title of each item is listed and hyperlinked - and when the mouse hovers over an item, a tooltip displays the start and end times, title, location, and description. Retrieving SharePoint list datausing (SPWeb web = SPContext.Current.Site.OpenWeb(listCalendarUrl))
{
SPList list = null;
try { list = web.Lists[listCalendar]; }
catch { }
if (null == list)
return;
DateTime[] weeks;
if (((int)StartDay + NumberOfDays) > 7)
// the time span goes over the weekend
weeks = new DateTime[] { StartDate, StartDate.AddDays(7) };
else
weeks = new DateTime[] { StartDate };
If the sliding window spans the weekend, then we’ll need to look at two weeks’ worth of items, so we’ve stored our target days in the “ foreach (DateTime day in weeks)
{
// include recurring events by using a DateRangesOverlap query
SPQuery queryRecurring = new SPQuery();
queryRecurring.ExpandRecurrence = true;
queryRecurring.CalendarDate = day;
queryRecurring.Query = "<Where><DateRangesOverlap>"
+ "<FieldRef Name=\"EventDate\" /><FieldRef Name=\"EndDate\" />" +
"<FieldRef Name=\"RecurrenceID\" />"
+ "<Value Type=\"DateTime\"><Week />" +
"</Value></DateRangesOverlap></Where>";
SPListItemCollection listItems;
listItems = list.GetItems(queryRecurring);
CAML – Collaborative Application Markup Language. CAML queries are used to retrieve SharePoint data. They look a bit like SQL queries expressed in XML, but in a prefix notation. For schema information on CAML queries, try: Query Schema, and for help with building queries, try: U2U CAML Query Builder and Execution Tool Released. Gotcha: In CAML queries, you must use the name of the column, not the display name, and the real name can be hard to find, especially, if you renamed any columns. To find column names for any SharePoint list, open the list, edit the list settings, and scroll down until you find the list of columns. Click on a column name to view its properties: In the textbox at the right, the column name is “Start Time” - but that is the display name. The real column name is at the end of the URL(!). Look at the rightmost bit of the address bar to see “Field=EventDate”; and “ Back to the CAML query. Recurring events … recur. For example, a seminar that occurs every week for 10 weeks, from 2 – 3 pm on Thursdays. These list items are created at runtime, not stored in the database (like an ordinary event), and a standard query will not return them. The In this example, we’re choosing to look at one week at a time. Let’s take another look at that CAML query in an easier-to-read format: In the A couple of attributes need to be set on the query also: queryRecurring.ExpandRecurrence = true;
queryRecurring.CalendarDate = day;
Set Processing the list items collectionNow that we have the item collection, we need to figure out if each item is an all-day, multi-day, or ordinary item; check if the item’s start date is in our date range, and if so, add it to our sorted list, If it is a multi-day item, there will be only one occurrence, and we’ll need to add the other days manually; but, there may be one each week if the time span bridges the weekend. This raises the possibility of accidentally adding the same items twice, so we’ll save the bool multiday;
bool allday;
foreach (SPListItem item in listItems)
{
DateTime itemStartDate = (DateTime)item["EventDate"];
DateTime itemEndDate = (DateTime)item["EndDate"];
multiday = (itemEndDate - itemStartDate >
new TimeSpan(1, 0, 0, 0)) ? true : false;
allday = (itemEndDate - itemStartDate ==
new TimeSpan(23, 59, 0)) ? true : false;
if (multiday)
// is the calendar start day within
// the Multi-Day span? if so, reset itemStartDay
if (day >= itemStartDate && day <= itemEndDate)
itemStartDate = day;
if (!ItemIsInDateRange(itemStartDate, day, weeks))
continue;
// Create key for assigning to gridrows.
// Example: key for Thursday 8 am would be 08-4;
// key for Monday 3 pm would be 15-1
// Example: key for an All Day item on Friday would be ..-5
// Example: keys for a Multi-Day item spanning
// Thursday-Friday-Saturday: ..-4 ..-5 ..-6
string key = string.Empty;
if (multiday || allday)
key = AllDayHour + "-" +
((int)itemStartDate.DayOfWeek).ToString();
else
{
key = itemStartDate.TimeOfDay.Hours.ToString() + "-" +
((int)itemStartDate.DayOfWeek).ToString();
if (key.Length < 4)
key = "0" + key;
}
string titleText = string.Empty;
if (multiday || allday)
titleText = item["Title"].ToString();
else
titleText = itemStartDate.ToShortTimeString() +
" " + item["Title"].ToString();
string linkUrl = web.Url + "/"
+ item.Url.ToString().Substring(0, item.Url.LastIndexOf("/") + 1)
+ "DispForm.aspx?ID=" + item.RecurrenceID.ToString();
// Example for javascript tooltips:
//string titleLink = "<a href=" + Quote(linkUrl)
// + " onmouseover=\"Tip('" + tip(item, multiday || allday) +
// "')\" onmouseout=\"UnTip()\" >" +
// titleText + "</a>";
string titleLink = "<a href=" + Quote(linkUrl)
+ " title=" + Quote(tip(item, multiday || allday)) +
" >" + titleText + "</a>";
string UniqueID = item.UniqueID + item.RecurrenceID;
if (!processedListItems.Contains(UniqueID))
{
AddCell(key, titleLink);
if (multiday)
{
// Multi-Day events appear as one list item; add remaining days
DateTime thisEndDate = (StartDate.AddDays(NumberOfDays) <
itemEndDate) ? StartDate.AddDays(NumberOfDays) : itemEndDate;
for (DateTime nextDay = itemStartDate.AddDays(1);
nextDay <= thisEndDate; nextDay = nextDay.AddDays(1))
{
if (ItemIsInDateRange(nextDay))
{
key = AllDayHour + "-" +
((int)nextDay.DayOfWeek).ToString();
AddCell(key, titleLink);
}
}
}
processedListItems.Add(UniqueID, null);
}
} // foreach ListItem
} // foreach day in weeks
} // using SPWeb web ...
}
Last bitsYou’ll notice that tooltips (or screentips) here are handled by assigning them to the Once the sorted list is built, we’re ready to build a One of the challenges of web part design is that there is no design surface, so you really can’t “see” what you’re doing. I found it very helpful to preview the CodaNote: WebPart deployment is not covered here; for an introduction, see: Write Custom WebParts for SharePoint 2007. Another note: You’ll probably need to refresh the project reference to the Sharepoint.dll, typically found here – C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI\Microsoft.SharePoint.dll.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||