Retrieve events number from SharePoint calendar using JS

末鹿安然 提交于 2019-12-06 07:24:26
Thriggle

The Problem with Querying Calendars in JavaScript: Recurrence

Ordinarily retrieving data from SharePoint with JavaScript is really straightforward (at least for versions beyond SharePoint 2007) using either REST or the JavaScript Object Model. However, calendars have functionality for creating recurring events which can complicate things.

For example, a recurring event may have a start date of two years ago and an end date many years in the future, but maybe the event itself only actually occurs on the third Tuesday of every month. If you just query the list and try to compare today's date against the start date and end date to see if they overlap, that recurring event will show up in your results (even though today is not the third Tuesday of the month).

In server-side code you can get around this by setting the ExpandRecurrence property to true on the SPQuery object used to query the list. However, as of SP2010 and SP2013, that property is not exposed on the equivalent JavaScript Object Model.


Workaround: Using the Lists.GetListItems web service**

An alternative is to use one of the old web services that are still floating around... specifically the Lists web service accessible at /_vti_bin/Lists.asmx. This web service has a GetListItems method that accepts a SOAP message in which you can specify a query option to expand recurrence as you would on the server side.

Here's an example demonstrating how you can query the Lists web service using plain JavaScript:

// Set webUrl and listGuid to values specific to your site and list
var webUrl = "http://server/sitewhereyourlistexists";
var listGuid = "{000000000-0000-0000-0000-000000000000}"

// An XMLHttpRequest object is used to access the web service
var xhr = new XMLHttpRequest();
var url = webUrl + "/_vti_bin/Lists.asmx";
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type","text/xml; charset=utf-8");
xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/GetListItems");

// The message body consists of an XML document 
// with SOAP elements corresponding to the GetListItems method parameters
// i.e. listName, query, and queryOptions
var data = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"+
    "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" + 
        "<soap:Body>" +
        "<GetListItems xmlns=\"http://schemas.microsoft.com/sharepoint/soap/\">" + 
                "<listName>"+listGuid+"</listName>" + 
                "<query>" + 
                    "<Query><Where>" +
                        "<DateRangesOverlap>" + 
                            "<FieldRef Name=\"EventDate\"/>"+
                            "<FieldRef Name=\"EndDate\"/>"+
                            "<FieldRef Name=\"RecurrenceID\"/>"+
                            "<Value Type=\"DateTime\"><Today/></Value>"+
                        "</DateRangesOverlap>"+
                    "</Where></Query>"+
                "</query>" +
                "<queryOptions>"+
                    "<QueryOptions>"+
                        "<ExpandRecurrence>TRUE</ExpandRecurrence>"+
                    "</QueryOptions>"+
                "</queryOptions>" +
        "</GetListItems>" +
        "</soap:Body>" +
    "</soap:Envelope>";

// Here we define what code we want to run upon successfully getting the results
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        if(xhr.status == 200){
            var doc = xhr.responseXML;
            // grab all the "row" elements from the XML results
            var rows = doc.getElementsByTagName("z:row");
            var results = "Today's Schedule ("+rows.length+"):\n\n";
            var events = {};
            for(var i = 0, len = rows.length; i < len; i++){
                var id = rows[i].getAttribute("ows_FSObjType"); // prevent duplicates from appearing in results
                    if(!events[id]){ 
                        events[id] = true;
                        var allDay = rows[i].getAttribute("ows_fAllDayEvent"),
                            title = rows[i].getAttribute("ows_Title"),
                            start = rows[i].getAttribute("ows_EventDate"); 
                        var index = start.indexOf(" "); 
                        var date = start.substring(5,index)+"-"+start.substring(2,4); // get the date in MM-dd-yyyy format
                        start = start.substring(index, index+6); // get the start time in hh:mm format
                        var end = rows[i].getAttribute("ows_EndDate"); 
                        index = end.indexOf(" "); end = end.substring(index,index+6); // get the end time in hh:mm format
                        results += date + " " + (allDay == "1" ? "All Day\t" : start + " to " + end ) + " \t " + title + "\n";
                    }
                }
                alert(results);
            }else{
                alert("Error "+xhr.status);
            }   
    }
};

// Finally, we actually kick off the query
xhr.send(data);

Checking ranges other than today's date

In the <Value> child node of the <DateRangesOverlap> node, you can specify <Now />, <Today />, <Week />, <Month />, or <Year />.

Week, Month, and Year will check for events within the same week, month, or year of the current date.

To check a date range relative to some date other than today's, you can add a <CalendarDate> node to the <QueryOptions> node of the CAML query, as seen below.

"<query>" + 
    "<Query><Where>" + 
        "<DateRangesOverlap>" + 
            "<FieldRef Name=\"EventDate\"/>"+ 
            "<FieldRef Name=\"EndDate\"/>"+ 
            "<FieldRef Name=\"RecurrenceID\"/>"+ 
                "<Value Type=\"DateTime\"><Week /></Value>"+ 
        "</DateRangesOverlap>"+ 
    "</Where></Query>"+ 
"</query>" + 
"<queryOptions>"+ 
    "<QueryOptions>"+ 
        "<ExpandRecurrence>TRUE</ExpandRecurrence>"+ 
        "<CalendarDate>2017-03-10</CalendarDate>" +
    "</QueryOptions>"+ 
"</queryOptions>" + 

Note that values of <Now /> and <Year /> do not seem to respect the CalendarDate value.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!