Friday, December 15, 2006

Sharepoint rollup web parts

I've recently been working with Sharepoint 2007 on a large scale project. A common requirement for many Sharepoint-enabled web portals is to create what is termed as a 'rollup' of data. In a nutshell, this entails the amalgamation of one or more Sharepoint 'Lists' - e.g. Tasks, Shared Documents, etc. But not simply an amalgamation of that data on one level - For if, as is commonly the case, you have set up sub-sites underneath your top level site, then you'll want to collect data from the lists within those sites too. The term associated with this bundling of site and sub-sites' data is known as a rollup.

One of the requirements for the portal I've been working on was to create a rollup webpart of all the Tasks lists across the entire site collection. Using VS.NET, I created the following WebPart-derived class and deployed it to the Sharepoint server.



    1 using System;


    2 using System.Runtime.InteropServices;


    3 using System.Web.UI;


    4 using System.Web.UI.WebControls.WebParts;


    5 using System.Xml.Serialization;


    6 


    7 using Microsoft.SharePoint;


    8 using Microsoft.SharePoint.WebControls;


    9 using Microsoft.SharePoint.WebPartPages;


   10 


   11 using System.Xml;


   12 using System.Xml.Xsl;


   13 using System.IO;


   14 using System.Text;


   15 


   16 using System.Data;


   17 


   18 namespace Custom.WebParts


   19 {


   20     [Guid("9e209402-e946-4070-b869-3faa90a92513")]


   21     public class TasksRollUp : System.Web.UI.WebControls.WebParts.WebPart


   22     {


   23         // Private vars.


   24         private string strCulture = "en-GB";


   25         private string strUserOrGroup = "Context"; // by default, base the results on the user in context.


   26 


   27         // Checkbox private vars.


   28         private bool bStatusNotStarted = true;


   29         private bool bStatusInProgress = true;


   30         private bool bStatusCompleted = true;


   31         private bool bStatusDeferred = true;


   32         private bool bStatusWaitingOnSomeoneElse = true;


   33 


   34 


   35         /// <summary>


   36         /// The main method to write to the UI.


   37         /// </summary>


   38         /// <param name="writer"></param>


   39         protected override void Render(HtmlTextWriter writer)


   40         {


   41             string results = LoadTasks();


   42             writer.Write(results);


   43         }


   44 


   45         /// <summary>


   46         /// Loads 'All My Tasks'.


   47         /// </summary>


   48         private string LoadTasks()


   49         {


   50             // Knock up a SPSiteDataQuery object and detail the CAML query.


   51             bool applyContextOrGroup = (this.UserOrGroup == "") ? false : true;


   52 


   53             string user = "";


   54             if (this.UserOrGroup.ToLower() == "context")


   55                 user = SPContext.Current.Web.CurrentUser.Name;


   56             else


   57                 user = this.UserOrGroup;


   58 


   59             SPSiteDataQuery q = new SPSiteDataQuery();


   60 


   61             if (!applyContextOrGroup)


   62             {


   63                 q.ViewFields = "<FieldRef Name=\"ID\" /><FieldRef Name=\"Title\" /><FieldRef Name=\"Created\" /><FieldRef Name=\"Body\" />";


   64                 q.Lists = "<Lists ServerTemplate=\"107\"/>";


   65                 q.Webs = "<Webs Scope=\"Recursive\"/>";


   66                 q.Query = "<Where><Eq><FieldRef Name=\"ID\"/><Value Type=\"String\">1</Value></Eq></Where>";


   67             }


   68             else if (applyContextOrGroup == true && user == "context")


   69             {


   70                 q.ViewFields = "<FieldRef Name=\"ID\" /><FieldRef Name=\"Title\" /><FieldRef Name=\"Created\" /><FieldRef Name=\"Body\" />";


   71                 q.Lists = "<Lists ServerTemplate=\"107\"/>";


   72                 q.Webs = "<Webs Scope=\"Recursive\"/>";


   73                 q.Query = "<Where><And><Eq><FieldRef Name=\"ID\" /><Value Type=\"Counter\">1</Value></Eq><Eq><FieldRef Name=\"AssignedTo\" /><Value Type=\"User\">" + user + "</Value></Eq></And></Where>";


   74             }


   75             else


   76             {//GROUPS.


   77                 q.ViewFields = "<FieldRef Name=\"ID\" /><FieldRef Name=\"Title\" /><FieldRef Name=\"Created\" /><FieldRef Name=\"Body\" />";


   78                 q.Lists = "<Lists ServerTemplate=\"107\"/>";


   79                 q.Webs = "<Webs Scope=\"Recursive\"/>";


   80                 q.Query = "<Where><Eq><FieldRef Name=\"AssignedTo\" /><Value Type=\"User\">" + user + "</Value></Eq></Where>";


   81             }


   82 


   83             DataTable dt = null;


   84             SPWeb w = SPContext.Current.Web;


   85             // Load ALL 'My' tasks from across ALL sites.


   86             dt = w.GetSiteData(q);


   87 


   88             w = null;


   89 


   90             if (dt.Rows.Count == 0)


   91                 return "No tasks to view on this level.";


   92 


   93             DataSet ds = new DataSet();


   94             ds.Tables.Add(dt);


   95 


   96             string xml = ds.GetXml();


   97 


   98             // Format the data.


   99             xml = System.Text.RegularExpressions.Regex.Replace(xml, "&lt;", "<");


  100             xml = System.Text.RegularExpressions.Regex.Replace(xml, "&gt;", ">");


  101 


  102             // XSL parameter list.


  103             XsltArgumentList oArgList = new XsltArgumentList();


  104 


  105             // Site ID is based on SPContext.


  106 


  107 #if DEBUG


  108             oArgList.AddParam("SiteId", "", "2352352"); // FOR TEST.           


  109 #else


  110             oArgList.AddParam("SiteId", "", SPContext.Current.Site.ID.ToString());


  111 #endif


  112             // Set the culture, based on the setting. (Default to site wide culture setting).


  113             oArgList.AddParam("Culture", "", this.Culture);


  114 


  115             string outHtml = XslTransform(xml, "/", "Shared Documents", "TaskList.xsl", oArgList);


  116             return outHtml;


  117         }


  118 


  119         public CustomDocument GetDocument(string fileName, string pathWeb, string listName)


  120         {


  121             SPSite gSite = null;


  122             SPWeb gWeb = null;


  123             SPList gList;


  124             CustomDocument bdoc = new CustomDocument();


  125             try


  126             {


  127                 // If the Path web is passed in then use it to find the list otherwise use current context               


  128 #if DEBUG


  129                 //FOR TEST.


  130                 SPSite s = new SPSite("http://localhost");


  131                 gSite = s;


  132 #else


  133                 // gSite = SPContext.Current.Site; // Doesn't work. Mais pourquoi?


  134                 SPSite s = new SPSite("http://localhost");


  135                 gSite = s;


  136 #endif


  137                 gWeb = gSite.AllWebs[pathWeb];


  138                 gList = gWeb.Lists[listName];


  139 


  140                 foreach (SPListItem item in gList.Items)


  141                 {


  142                     if (item.Title.ToLower() == fileName.ToLower())


  143                     {


  144                         byte[] xmlfile = item.File.OpenBinary();


  145                         System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();


  146 


  147                         bdoc.Body = enc.GetString(xmlfile);


  148                         bdoc.DocumentID = item.UniqueId.ToString();


  149                         bdoc.list = gList.ID.ToString();


  150                         //bdoc.CheckedOutTo = item.File.CheckedOutBy.ToString();


  151                     }


  152                 }


  153                 return bdoc;


  154             }


  155             catch (Exception ex)


  156             {


  157                 bdoc.Body = ex.Message.ToString();


  158                 return bdoc;


  159             }


  160             finally


  161             {


  162 


  163                 if (gSite != null)


  164                     gSite.Dispose();


  165 


  166                 if (gWeb != null)


  167                     gWeb.Dispose();


  168             }


  169         }


  170 


  171         /// <summary>


  172         /// Perform an XSL transform.


  173         /// </summary>


  174         /// <param name="xml">The raw XML to use</param>


  175         /// <param name="xsl">The XSL document name</param>


  176         /// <param name="sharepointPath">The Sharepoint path</param>


  177         /// <param name="sharepointList">The Sharepoint list name</param>


  178         /// <param name="parameters">A list of XSL parameters</param>


  179         /// <returns></returns>


  180         public string XslTransform(string xml, string sharepointPath, string sharepointList, string xsl, XsltArgumentList parameters)


  181         {


  182             // Get the TaskList.xsl file from Sharepoint.


  183             CustomDocument oDoc = GetDocument(xsl, sharepointPath, sharepointList);


  184 


  185             TextReader trXSL;


  186             trXSL = new StringReader(oDoc.Body);


  187 


  188             // Load up a reader object with the contents of the XSL.


  189             XmlReader xrXSL = XmlReader.Create(trXSL);


  190 


  191             StringBuilder sbHTML = new StringBuilder(); // Used for HTML to be returned.


  192 


  193             // Load up an XMLDocument object with the incoming XML...


  194             XmlDocument xDoc = new XmlDocument();


  195             xDoc.LoadXml(xml);


  196 


  197             // Create an XMLWriter object based on the string builder.


  198             XmlWriter xwHTML = XmlWriter.Create(sbHTML);


  199 


  200             // Perform the conversion.


  201             XslCompiledTransform xsltTransform = new XslCompiledTransform();


  202             xsltTransform.Load(xrXSL);


  203 


  204             try


  205             {


  206                 // Attempt the transform.


  207                 xsltTransform.Transform(xDoc, parameters, xwHTML);


  208             }


  209             catch (IOException ioEx)


  210             {


  211                 throw ioEx;


  212             }


  213             catch (Exception ex)


  214             {


  215                 throw ex;


  216             }


  217             finally


  218             {


  219                 // Write the results to file.


  220                 xwHTML.Flush();


  221                 xwHTML.Close();


  222 


  223                 // Clean up.


  224 


  225                 trXSL.Close();


  226                 trXSL.Dispose();


  227 


  228                 xrXSL.Close();


  229             }


  230 


  231             return sbHTML.ToString();


  232         }


  233 


  234 


  235         [WebPartStorage(Storage.Shared), System.Xml.Serialization.XmlElement(Namespace = "http://localhost")]


  236         [WebBrowsable(true), Personalizable(true)]


  237         [WebDescription("What is the culture? Choose for the time being from two options: the default 'en-GB' or 'en-US'")]


  238         [WebDisplayName("Active Culture")]


  239         [System.ComponentModel.Category("Custom Settings")]


  240         public string Culture


  241         {


  242             get


  243             {


  244                 return strCulture;


  245             }


  246             set


  247             {


  248                 strCulture = value;


  249             }


  250         }


  251 


  252         [WebPartStorage(Storage.Shared), System.Xml.Serialization.XmlElement(Namespace = "http://localhost")]


  253         [WebBrowsable(true), Personalizable(true)]


  254         [WebDescription("Base the task list that is generated on the user in context (type 'Context') - e.g. show only tasks assigned to the user in context, or specify a group name, e.g. 'Administrators'")]


  255         [WebDisplayName("Filter by User or Group")]


  256         [System.ComponentModel.Category("Custom Settings")]


  257         public string UserOrGroup


  258         {


  259             get


  260             {


  261                 return strUserOrGroup;


  262             }


  263             set


  264             {


  265                 strUserOrGroup = value;


  266             }


  267         }


  268 


  269         [WebPartStorage(Storage.Shared), System.Xml.Serialization.XmlElement(Namespace = "http://localhost")]


  270         [WebBrowsable(true), Personalizable(true)]


  271         [WebDescription("Tick to show/hide tasks that have not been started.")]


  272         [WebDisplayName("Not started")]


  273         [System.ComponentModel.Category("Task Status")]


  274         public bool NotStarted


  275         {


  276             get


  277             {


  278                 return bStatusNotStarted;


  279             }


  280             set


  281             {


  282                 bStatusNotStarted = value;


  283             }


  284         }


  285 


  286         [WebPartStorage(Storage.Shared), System.Xml.Serialization.XmlElement(Namespace = "http://localhost")]


  287         [WebBrowsable(true), Personalizable(true)]


  288         [WebDescription("Tick to show/hide tasks that are in progress.")]


  289         [WebDisplayName("In progress")]


  290         [System.ComponentModel.Category("Task Status")]


  291         public bool InProgress


  292         {


  293             get


  294             {


  295                 return bStatusInProgress;


  296             }


  297             set


  298             {


  299                 bStatusInProgress = value;


  300             }


  301         }


  302 


  303         [WebPartStorage(Storage.Shared), System.Xml.Serialization.XmlElement(Namespace = "http://localhost")]


  304         [WebBrowsable(true), Personalizable(true)]


  305         [WebDescription("Tick to show/hide tasks that have been completed.")]


  306         [WebDisplayName("Completed")]


  307         [System.ComponentModel.Category("Task Status")]


  308         public bool Completed


  309         {


  310             get


  311             {


  312                 return bStatusCompleted;


  313             }


  314             set


  315             {


  316                 bStatusCompleted = value;


  317             }


  318         }


  319 


  320         [WebPartStorage(Storage.Shared), System.Xml.Serialization.XmlElement(Namespace = "http://localhost")]


  321         [WebBrowsable(true), Personalizable(true)]


  322         [WebDescription("Tick to show/hide tasks that have been deferred.")]


  323         [WebDisplayName("Deferred")]


  324         [System.ComponentModel.Category("Task Status")]


  325         public bool Deferred


  326         {


  327             get


  328             {


  329                 return bStatusDeferred;


  330             }


  331             set


  332             {


  333                 bStatusDeferred = value;


  334             }


  335         }


  336 


  337         [WebPartStorage(Storage.Shared), System.Xml.Serialization.XmlElement(Namespace = "http://localhost")]


  338         [WebBrowsable(true), Personalizable(true)]


  339         [WebDescription("Tick to show/hide tasks that are waiting on someone else.")]


  340         [WebDisplayName("Waiting on someone else")]


  341         [System.ComponentModel.Category("Task Status")]


  342         public bool WaitingOnSomeoneElse


  343         {


  344             get


  345             {


  346                 return bStatusWaitingOnSomeoneElse;


  347             }


  348             set


  349             {


  350                 bStatusWaitingOnSomeoneElse = value;


  351             }


  352         }


  353     }


  354 


  355     public class CustomDocument


  356     {


  357         public string Body;


  358         public string DocumentID;


  359         public string CheckedOutTo;


  360         public string site;


  361         public string list;


  362     }


  363 }



No comments:

Fixes to common .NET problems, as well as information on .NET features and solutions to common problems that are not language-specific.

Fixes to common .NET problems, as well as information on .NET features and solutions to common problems that are not language-specific.

Z