Friday, October 12, 2012

SharePoint and XSLT 1.0 - How to compare dates

==============================================================
UPDATE: Be aware that Microsofts's XSLT library date_templates.xsl contains a minor bug.
Using the "getDateFromDays" template will return NaN (not-a-number) when attempting to calculate the last day of the year (12/31).  All other days calculate correctly.
==============================================================
When it comes to performing date comparisons and calculations in SharePoint using XSLT 1.0 can be tricky, but here's a simple way

Navigate out to this document library
http://YourSite/Style%20Library/Forms/AllItems.aspx

And click on the "XSL Style Sheets" link
Microsoft has created an XSLT file with many handy templates for doing date calculations.
Download this Microsoft XSLT file date_templates.xsl and add it to the "XSL Style Sheets" folder.
Now locate the "ItemStyle.xsl" file and check it out for editing.  Add these styling blocks within the item you wish to transform

<!-- This is an example using the MS date_templates templates -->
<!-- Here it's calculating the date of tomorrow -->
<xsl:variable name="tomorrow">
  <xsl:call-template name="getDateFromDays">
  <!-- This template requires the date in the ISO format -->
  <xsl:with-param name="paramBaseDate" select="ddwrt:TodayIso()"/>
  <xsl:with-param name="paramDelta" select="1"/>
  </xsl:call-template>
</xsl:variable>

<!-- 1st step in date comparisons in XSLT 1.0 is to convert dates to numbers.  Stripping the dashes from an ISO date converts '2012-10-10' to the number '20121010' -->

<xsl:variable name="tomorrowAsNumber" select="(translate($tomorrow,'-',''))" />

<!-- The Content Query Web Part is returning a list of tasks that contain a field called "Due Date"
<xsl:variable name="listOfTasks" select="/dsQueryResponse/Rows/Row" />

<!-- Count the number of "Tasks Due Now" by converting the "Due Date" criteria to a number and comparing it to the "Tomorrow Number" using "less-than" -->
<xsl:variable name="countOfTasksDueNow" select="count($listOfTasks[translate(substring(@DueDate,1,10),'-','') &lt; $tomorrowAsNumber])" />

<!-- Count the number of "Tasks Due Tomorrow" by converting the "Due Date" criteria to a number and comparing it to the "Tomorrow Number" using "equals" -->
<xsl:variable name="countOfTasksDueTomorrow" select="count($listOfTasks[translate(substring(@DueDate,1,10),'-','') = $tomorrowAsNumber])" />

<!-- Count the number of "Future Tasks Due" by converting the "Due Date" criteria to a number and comparing it to the "Tomorrow Number" using "greater-than" -->

<xsl:variable name="countOfFutureTasks" select="count($listOfTasks[translate(substring(@DueDate,1,10),'-','') &gt; $tomorrowAsNumber])" />


SharePoint & Linq: More with less

Linq makes it easy to navigate thru a record set object of SharePoint List items.

// Using Statement

using System.Linq;

// Build the Query Object
SPQuery queryObject = new SPQuery();
queryObject.Query = 

@"<where>
   <contains>
      <fieldref name="FirstName">
         <value type="Text">Bob</value>
      </fieldref>
   </contains>
</where>
<orderby>
   <fieldref ascending="TRUE" name="Modified">
   </fieldref>
</orderby>";
Now, here's where the magic starts
Super Linq! -  Retrieving list items with a single line of code!

var results = list.GetItems(queryObject).Cast<splistitem>();


// Here's how to see if any records were returned
if (!results.Count().Equals(0))

// Want just the Last record?

var resultItem = list.GetItems(queryObject).Cast<SPListItem>().Last();

// Want just the First record?
var resultItem = list.GetItems(queryObject).Cast<SPListItem>().First();