Tuesday, January 20, 2009

Microsoft SharePoint 2007 - Calculated fields VS Computed fields

Audience
This article is intended for SharePoint Developers. Non-Developers, can understand what SharePoint can do thru this article. As I couldn't find much about this topic on the net, I thought I'd write about it :)

Introduction

SharePoint, being apart of Office, inherits a feature that is familiar amongst Microsoft Excel users - aka the "Calculated Field", which allows the user to specify a formula to determine the value of a field based on the value of other fields.

Recently I've had a go at trying to combine multiple reference fields into one field in SharePoint. Whilst there are many ways to do it (with an event handler, workflow, or calculated fields), I'd like to present to you a very clean solution based on a "Computed Field" type.

Computed fields are used by standard SharePoint components. For example, in a Blog Site there is a list named "Posts". This list contains a field called "PostedByWithDate" - which is a combination of a "Published" date-time field and a "Created By" person field. The output not only contains a combination of "Publised" and the "Created By" values but also includes custom text:



To show you what I mean, this is the "Posts" list, and their values:


Time to Play with Computed Fields
So what can we do with this? We can set the value of a computed field conditionally thru some field reference definitions!

Lets start by looking at the definition for the computed field (I'll assume you read the SDK to understand this):
<Field Name="OnBehalfOf" ID="{e9d780a5-ac18-4a04-ad63-39c6a7417212}" DisplayName="OnBehalfOf" Type="User" Required="FALSE" SourceID="http://schemas.microsoft.com/sharepoint/v3" List="UserInfo"
Description="Use this field when you are posting on behalf of the blog owner" ShowField="ImnName" UserSelectionMode="PeopleOnly" UserSelectionScope="0" StaticName="OnBehalfOf" ColName="int3" RowOrdinal="0" />


Original
The original field definition for the PostedByWithDate field (Which I extracted from the SharePoint Blog Site Definition contains):

<Field Name="PostedByWithDate" ID="{a1944d80-14e6-a71c-b235-3a28329f14b1}" Type="Computed" ReadOnly="TRUE" DisplayName="$Resources:posts_schema_blgfld_postedbywithdate;" Sortable="FALSE" SourceID="http://schemas.microsoft.com/sharepoint/v3"
StaticName="PostedByWithDate">
<FieldRefs>
<FieldRef Name="Author" />
<FieldRef Name="PublishedDate" />
</FieldRefs>
<DisplayPattern>
<HTML><![CDATA[Posted at ]]></HTML>
<Column Name="PublishedDate" Format="TimeOnly" HTMLEncode="TRUE" />
<HTML><![CDATA[ by ]]></HTML>
<Field Name="Author" />
</DisplayPattern>
</Field>



SharePoint Magic
Now what I did was create a copy of this column (in a new Site Template - remember it is not supported only if you modify existing SharePoint Site Templates), and modified it like the following:

<Field Name="PostedByWithDate" ID="{a1944d80-14e6-a71c-b235-3a28329f14b1}" Type="Computed" ReadOnly="TRUE" DisplayName="$Resources:posts_schema_blgfld_postedbywithdate;" Sortable="FALSE" SourceID="http://schemas.microsoft.com/sharepoint/v3"
StaticName="PostedByWithDate">
<FieldRefs>
<FieldRef Name="Author" />
<FieldRef Name="OnBehalfOf" />
<FieldRef Name="PublishedDate" />
</FieldRefs>
<DisplayPattern>
<HTML><![CDATA[Posted at ]]></HTML>
<Column Name="PublishedDate" Format="TimeOnly" HTMLEncode="TRUE" />
<HTML><![CDATA[ by ]]></HTML>
<IfEqual>
<Expr1>
<Column Name="OnBehalfOf" HTMLEncode="FALSE" />
</Expr1>
<Expr2></Expr2>
<Then><Field Name="Author" /></Then>
<Else><Field Name="OnBehalfOf" /></Else>
</IfEqual>
</DisplayPattern>
</Field>

The node is used for fields to allow for custom presentation of information. nodes can be added to introduce logical conditions for how data is presented. gives the field if-else logic; in this case, it checks if the value of the "OnBehalfOf" field is equal to nothing, and if it is, return the value from the "Author" field, else return the value from the "OnBehalfOf" field.

Very straight forward indeed :) The result can be seen in the screen shots above - when the OnBehalfOf field is blank, the value in the "Created by" field is shown with the date.


Some References:
Field Element: http://msdn.microsoft.com/en-us/library/ms437580.aspx
DisplayPattern Element: http://msdn.microsoft.com/en-us/library/ms977561.aspx
IfEqual Element: http://msdn.microsoft.com/en-us/library/ms948315.aspx