Randomly Displayed Content in SharePoint
Posted by Allyis Blogger on Wed, Oct 28, 2009 @ 03:44 PM
By Justin Botchek
On the most recent SharePoint site that I've worked on, I was tasked with finding a way to randomly select pieces of content to display on the site homepage after each page refresh. I've seen more complicated methods to implement this using javascript, but found the functionality can be easily accomplished using only two lines of xsl code within an existing SharePoint data view webpart. These lines are:
<xsl:variable name="highlight" select="ddwrt:Random(1,count($Rows))" />
<xsl:for-each select="$Rows[position()=$highlight]">
For this example I will be manipulating code that has been automatically generated by SharePoint Designer to display a simple multiple item data view. In a multiple item view, each item from the data source is collected via the Rows parameter. By default the data view will loop through all rows until every item has been displayed, but in this case we only want it to randomly select one of those items for display. Thankfully there is a bulit-in XSL function we can use to choose that random number for us. SharePoint also tracks each row item with a value called ‘position()'; so in order to randomly pick a row we simply need to generate a random number between one and the total number of rows and then filter the results by that position value.
Normally, a generic multiple item data view generated by SharePoint Designer will look something like this:

To randomly select one item to display, we search through the data view code for where it cycles through each row. It will be in a template block that looks like this:
<xsl:template name="dvt_1.body"> <xsl:param name="Rows"/> <xsl:for-each select="$Rows"> <xsl:call-template name="dvt_1.rowview"/></xsl:for-each></xsl:template>
Directly above the line shown in bold, we will want to add in the line to select the random position value:
<xsl:variable name="highlight" select="ddwrt:Random(1,count($Rows))" />
This creates a variable ‘highlight' and assigns a random value to it using ‘ddwrt:Random' between 1 and the total number of rows ‘count($Rows))'. Finally, we will want to modify the line in bold so that it looks like this:
<xsl:for-each select="$Rows[position()=$highlight]">
This applies a filter ‘[position()=$highlight]' to the xsl for-each statement so that it will only display rows with a position equal to the randomly selected value from the previous line. After this change, save the page changes and reload the page with your data view. The data view shown above would look something like this:

You will notice that the data view now only displays one entry, and after a couple page refreshes it will cycle randomly through the other items. Real world applications of this could be to display a different random ‘fun fact' on a site home page whenever someone visits, or even to draw random user names out of a SharePoint ‘hat'.
Update 3/31/2010:
I've been asked how to display a set of randomly selected items, instead of just one, so I thought I'd update my post with an example of how this could be done. This may not be the most elegant or efficient way to approach the problem, but it worked for me when pulling a relatively small set of entries.
First I moved the code to generate the random number into a template so I could easily call it multiple times. I placed this just before the dvt_1.body template definition:
<xsl:template name="randomNumber">
<xsl:param name="Rows"/>
<xsl:value-of select="ddwrt:Random(1,count($Rows))" />
</xsl:template>
Next, I created variables within the body template to store position values for the number of rows I wanted displayed. For each variable I called the randomNumber template showed above to get a value.
<xsl:variable name="value1">
<xsl:call-template name="randomNumber"> <xsl:with-param name="Rows" select="$Rows"/>
</xsl:call-template>
</xsl:variable>
If I wanted five rows displayed, for example, I would have five sets of this code with the variables labeled value1 through value5.
I then created another variable after the others to store my new set of rows, just to make it easier to reference.
<xsl:variable name="selectedRows" select="$Rows[position()=$value1 or position()=$value2]"/>
Here I'm pulling out two rows, but additional 'or' statements should be added for each value variable created previously. This by itself would work great, except there is nothing to ensure that the values returned are all unique. To work around the issue, I added an xsl choose statement and checked the count of the selectedRows variable. If it was less then 2, in the above example, then not all the values were unique. In this case I would call the body template again until all unique values were returned. I replaced the dvt_1.rowview template call with a choose statement that looked like this:
<xsl:choose>
<xsl:when test="count($selectedRows) < 2"> <xsl:call-template name="dvt_1.body">
<xsl:with-param name="Rows" select="$Rows"/>
</xsl:call-template>
</xsl:when> <xsl:otherwise>
<xsl:for-each select="$selectedRows"> <xsl:call-template name="dvt_1.rowview"/>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
This could be cumbersome to write or resource intensive when trying to pull large sets of unique values, but for a small set like 5 it worked great. Note that you will get a stack overflow error if an infinite loop is created by checking for a selectedRows count greater than the number of values available or missing any of the or statements for each value in the row filter.