Recent updates from all custom lists using SPServices/GetListItems

Mar 29, 2012 at 7:17 AM
Edited Mar 29, 2012 at 7:19 AM

I am trying to get recent updates and limit to 3 from entire site collection based on BaseType=0 (all custom lists)

<script type="text/javascript" src="http://sp2010/Style%20Library/jquery-1.6.1.min.js"></script>
<script type="text/javascript" src="http://sp2010/Style%20Library/Scripts/jquery.SPServices-0.7.1a.min.js"></script>

<script type="text/javascript">
var lhtml = "";
$().SPServices({
  operation: "GetAllSubWebCollection",
  completefunc: function(xData, Status) {
    $(xData.responseXML).find("Webs > Web").each(function() {
      var $node = $(this);
      $().SPServices({
 operation: "GetListCollection",
 webURL: $(this).attr("WebFullUrl"),
 async:false,
 completefunc: function(xData, Status) {
  $(xData.responseXML).find("List").each(function(){
  //function to get all items inside every list called "Pages"
  if(($(this).attr("BaseType") == "0") ) {
   lhtml = "<div><span>List Name:" + $(this).attr("Title") + "</span></div>";
//&& ($(this).attr("Title") == "TIPS")
var myQueryOptions = "<QueryOptions><ViewAttributes Scope='RecursiveAll' IncludeRootFolder='True' /></QueryOptions>";
var myQuery = "<Query><OrderBy><FieldRef Name='ows_Modified' Ascending='FALSE' /></OrderBy></Query>";

   $().SPServices({
    operation: "GetListItems",
    webURL: $(this).attr("WebFullUrl"),
    async: false,
    listName: $(this).attr("Title"),
    CAMLQuery: myQuery,
    CAMLViewFields: "<ViewFields><FieldRef Name='EncodedAbsUrl' /><FieldRef Name='Title' /></ViewFields>",
    CAMLQueryOptions: myQueryOptions,
    CAMLRowLimit: 3,
    completefunc: function (xData, Status) {
       $(xData.responseXML).SPFilterNode("z:row").each(function() {
             //alert(xData.responseXML.xml);
             var url = $(this).attr("ows_EncodedAbsUrl") + "";
       var liHtml = lhtml + "<li><a href='" + url + "'>" + $(this).attr("ows_Title") + "</a><div>"+ $(this).attr("ows_Modified") + "</div></li>";
             $("#sitelist").append(liHtml);
      });
     }
    });
   }
  })
 }
});


    });
  }
});

</script>

<span id="sitelist">Recent Updates:</span>

But I am getting below results: I am getting more than 3 items and duplicates. I have test even for one list itself which has only 3 items but it comes back with multiple of 3 items with same version numbers.

Output data:

Recent Updates:

List Name:TIPS
Quick Outlook Item Creation
2012-03-28 16:31:27
List Name:TIPS
Outlook Quick Parts
2012-03-21 12:36:53
List Name:TIPS
Bulk Delete Items
2012-03-21 21:56:44
List Name:TIPS
Quick Outlook Item Creation
2012-03-28 16:31:27
List Name:TIPS
Outlook Quick Parts
2012-03-21 12:36:53
List Name:TIPS
Bulk Delete Items
2012-03-21 21:56:44
List Name:TIPS
Quick Outlook Item Creation
2012-03-28 16:31:27
List Name:TIPS
Outlook Quick Parts
2012-03-21 12:36:53
List Name:TIPS
Bulk Delete Items
2012-03-21 21:56:44
List Name:TIPS
Quick Outlook Item Creation
2012-03-28 16:31:27
List Name:TIPS
Outlook Quick Parts
2012-03-21 12:36:53
List Name:TIPS
Bulk Delete Items
2012-03-21 21:56:44
List Name:TIPS
Quick Outlook Item Creation
2012-03-28 16:31:27
List Name:TIPS
Outlook Quick Parts
2012-03-21 12:36:53
List Name:TIPS
Bulk Delete Items
2012-03-21 21:56:44
List Name:TIPS
Quick Outlook Item Creation
2012-03-28 16:31:27
List Name:TIPS
Outlook Quick Parts
2012-03-21 12:36:53
List Name:TIPS
Bulk Delete Items
2012-03-21 21:56:44
List Name:TIPS
Quick Outlook Item Creation
2012-03-28 16:31:27
List Name:TIPS
Outlook Quick Parts
2012-03-21 12:36:53
List Name:TIPS
Bulk Delete Items
2012-03-21 21:56:44
List Name:TIPS
Quick Outlook Item Creation
2012-03-28 16:31:27
List Name:TIPS
Outlook Quick Parts
2012-03-21 12:36:53
List Name:TIPS
Bulk Delete Items
2012-03-21 21:56:44
List Name:TIPS
Quick Outlook Item Creation
2012-03-28 16:31:27
List Name:TIPS
Outlook Quick Parts
2012-03-21 12:36:53
List Name:TIPS
Bulk Delete Items
2012-03-21 21:56:44
List Name:TIPS
Quick Outlook Item Creation
2012-03-28 16:31:27
List Name:TIPS
Outlook Quick Parts
2012-03-21 12:36:53
List Name:TIPS
Bulk Delete Items
2012-03-21 21:56:44

Coordinator
Mar 30, 2012 at 3:45 AM

This looks like it ought to work. I'd just try doing some debugging to see what requests are going out and whether you've got some extra call in there somewhere.

M.

Apr 1, 2012 at 3:01 PM

Marc,

As per your suggestion, I debugged above code, it is repeating for all subsites with the repeated information: but see my below requirements to see if SPServices designed to do such requests:

Please see below requirement is what I am trying to do:

1. I have few custom list in top level sitecollection and subsites

2. I need to get most recent updates sorted descending oder across all my custom lists (not rollup the similar LIST across sites) in this entire site collection

3. I do not have access to sandbox solutions or object model

4. Consume SPServices to accomplish this

5. Please help

If I find any solution, I will post it to you.

Thanks Again,

Venky

Coordinator
Apr 3, 2012 at 3:46 PM

Venky:

You can certainly use SPServices for this, but I would probably go with a DVWP because it would run server side and be more efficient.

M.

Apr 3, 2012 at 6:48 PM
Edited Apr 3, 2012 at 8:02 PM

Thanks Marc,

Big issue and concern about this in below line:

I got it working but with one issue, Visitors are not able to see the results but where as I am login as site owner, I could see results. Is it a issue querying Modified field for visitor in SPServices? it is not even alerting fir first foreach. (I am using HTML FORM WEBPART to inject)

Thanks,

<script type="text/javascript" language="javascript">
var i = 0;
var listName = "";
$().SPServices({
  operation: "GetAllSubWebCollection",
  completefunc: function(xData, Status) {
    $(xData.responseXML).find("Webs > Web").each(function() {
      var $node = $(this);
      // BEGIN IF FOR EACH WEB SITE
      if (
          ($node.attr("Title") == "HOME") ||
          ($node.attr("Title") == "SOLUTIONS") ||
          ($node.attr("Title") == "MY REPORTS") ||
          ($node.attr("Title") == "PRODUCTS")
         )
       {
         alert($node.attr("Title"));
         $().SPServices({
         operation: "GetListCollection",
         webURL: $(this).attr("Url"),
         async:false,
         completefunc: function(xData, Status) {

       $(xData.responseXML).find("Lists > List").each(function(){
        if (($(this).attr("BaseType") == "0") &&
             ($(this).attr("Hidden") == "False") &&
              (
               ($(this).attr('ServerTemplate') == '104') ||
               ($(this).attr('ServerTemplate') == '106') ||
               ($(this).attr('ServerTemplate') == '100')
               ) &&
               (
               ($(this).attr('Title') == 'SOLUTIONS') ||
               ($(this).attr('Title') == 'TIPS') ||
               ($(this).attr('Title') == 'FAQS') ||
               ($(this).attr('Title') == 'PRODUCTS') ||
               ($(this).attr('Title') == 'Calendar') ||
               ($(this).attr('Title') == 'REPORTS') ||
               ($(this).attr('Title') == 'PROJECTS')
               )
           )
        {
            listName = $(this).attr('Title');
            //alert(xData.responseXML.xml);
            var $listNode = $(this);
            var nbrDays = -3;
            //lhtml = lhtml + "<div>List Name:" + $listNode.attr("Title") + "</div>";
            var myQueryOptions = "<QueryOptions><ViewAttributes Scope='Recursive' IncludeRootFolder='False' /></QueryOptions>";
            var myQuery = "<Query>" + "<Where><Gt><FieldRef Name='Modified' /><Value Type='DateTime'><Today OffsetDays='" + nbrDays + "'/></Value></Gt></Where>";
            myQuery = myQuery + "<OrderBy><FieldRef Name='Modified' Ascending='False' /></OrderBy>";
            myQuery = myQuery + "</Query>";
            $().SPServices({
            operation: "GetListItems",
            webURL: $(this).attr("WebFullUrl"),
            async: false,
            listName: $(this).attr("Title"),
            CAMLQuery: myQuery,
            CAMLViewFields: "<ViewFields><FieldRef Name='EncodedAbsUrl' /><FieldRef Name='Title' /><FieldRef Name='Title2' /></ViewFields>",
    CAMLQueryOptions: myQueryOptions,
    CAMLRowLimit: 1,
    completefunc: function (xData, Status) {
            $(xData.responseXML).SPFilterNode("z:row").each(function() {
             if (($(this).attr("ows_Title") != "View") && (i <=2))
             {
               var url = $(this).attr("ows_EncodedAbsUrl") + "";
               url = url.substring(0 , url.lastIndexOf("/", url.length));
               url = url + "/DispForm.aspx?ID=" + $(this).attr("ows_ID");
               var lhtml = $(this).attr("ows_Title2").replace('string;#','') + "<div class='announceCategory'>" + listName + "</div>";
               var liHtml = "<p/>" + lhtml + "<div><a href=\"javascript:\" onclick=\"SP.UI.ModalDialog.ShowPopupDialog('" + url + "');\">" + $(this).attr("ows_Title") + "</a><hr/></div>";
               $("#sitelist").append(liHtml);
               i = i + 1;
             }
             }); //for each row data
         }
         });  // end of function 
        }

          }); // for each List

       }
       });  // end of function
       }
       //END IF EACH WEB SITE
    }); // foreach Web
  }
});

</script>
<span id="sitelist"/>

Venky

 

Coordinator
Apr 5, 2012 at 3:36 PM

I'm not positive what permissions one needs to call GetAllSubWebCollection, but obviously you have to be able to enumerate the subsites. If your users can't do that, then this won't work.

One of the benefits of using a DVWP with DataSourceMode="CrossList" is that you don't have to do that enumeration.

M.

Apr 12, 2012 at 4:35 PM

Hi,

If I'm not remember totally wrong the GetAllSubWebCollection and GetWebs needs the "<label for="idspnidBrowseDirectories">Browse Directories" permission level to work.</label>

Like Marc writes this is probably something easier accomplished with the DVWP or CQWP, but if you must use spservices for this I think the only way is to sort the table after printing it with a javascript or jquery plugin/own script or save all results in an array, sort the array and then print the table based on that array

Something I've looked for myself is a way to merge results into one XML and then print it, but I haven't been able to find a way to do that

/Fredrik

Coordinator
Apr 13, 2012 at 8:11 PM
Edited Apr 13, 2012 at 8:11 PM

Fredrik:

I think you're right on the permissioning. I couldn't remember the specifics, but it sounds right.

There's no "join" available anywhere in all of this. I usually just build loops within loops, just like I did in the good old days.

M.

Apr 23, 2012 at 1:02 PM

Was thinking a bit more about this, and one solution could be to use the $().SPServices.SPXmlToJson function since the json objects can be joined. When all results are returned, these can be sorted before printed, either by doing it yourself or using somthing like http://www.datatables.net/

/Fredrik

Apr 23, 2012 at 3:37 PM

You can also use jQuery to combine all <z:row>'s into one <soap> message... I have done this in the past with getting similar data from multiple lists, combine into one single XML message...Somethign like (disclaimer: untested code snippet):

var originalMessage = $(xData.responseXML);

// Build loop to Get data from subsquent sites ...

$().SPServices({
    operation: "GetListItems",
    async: false,
    listName: "listNameHere",
    CAMLQuery: '<Query>....</Query>',
    CAMLViewFields: "",
    completefunc: function(xData, Status) {
        originalMessage.find("[nodeName='rs:data']").append(
            $(xData.responseXML).find("[nodeName='z:row']").clone()
        );
    }
});

Paul

Apr 23, 2012 at 9:55 PM

The function I thought was missing, thanks a lot

/F

Coordinator
Apr 24, 2012 at 1:42 AM

I'll often just build up an array containing the values I need for the task at hand rather than gluing multiple XML sources together. Either way should work, of course.

M.