Using Calculated Fields in CAML to Display Conditional Images
Came across a nice gem in the newsgroups that I thought I would share here. Someone had a choice field with three values: failed; pass; re-run; and wanted to display a red image for items in the list matching the failed value, green for pass, and yellow for re-run (oh yeah, can you see where this is going).
I pointed them immediately to Ian Morrish’s article here on conditional formatting using a DataView Web Part which works nicely for this. However Colin Gardner came up with a nice solution that used the RenderPattern tag in CAML for a list to do the job. Here’s his solution:
1. Edit the FieldTypes.xml file (make backups for safety) and look for the row definition for the calculated field type (search for <Field Name="TypeName" DisplayName="TypeName">Calculated</Field>).
2. Modify the deafult render pattern in the
<FieldSwitch> statement so that it handles the values
returned by a calculated file in such a way that will return
you an image/icon/traffic light. You will see that the
<FieldSwitch> statement handles Boolean, Number,
Currency and DateTime field types but anything else falls
through and is processed by the code in the <Default>
tag which is: <Column HTMLEncode="TRUE"
AutoHyperLink="TRUE" AutoNewLine="TRUE"/>
You
need to replace this default rendering with you're own
custom logic. In my implementation I replaced it with
another complete switch statement like the one below:
<Switch>
<Expr>
<GetFileExtension><Column/></GetFileExtension>
</Expr>
<Case
Value="giF">
<HTML><![CDATA[<IMG
SRC="]]></HTML><Column
HTMLEncode="TRUE"/><HTML>"</HTML>
</Case>
<Default>
<Column
HTMLEncode="TRUE" AutoHyperLink="TRUE"
AutoNewLine="TRUE"/>
</Default>
</Switch>
In this example the the Switch <Expr> calles
the GetFileExtension function which processes the value in
the calculated field and tries to extract a file
extension. You can then use a Case statement to render the
value returned by the calculated field in a way that makes
sense. In the example above - if the GetFileExtension
returns the string "giF" then I process the value as an
image and render it as an HTML <IMG> tag.
Note
that I chose to take advantage of the fact that the
comparison is case sensitive but the source url for the
image is not. This means that if my calculated field
returns a string that ends with ".gif" rather than ".giF"
then it will slip through the case statement and be rendered
as before i.e. not as an image.
Of course you can
modify the above to handle jpeg or any other graphics format
that WSS can render.
3. Save the modified
FieldTypes.xml file.
4. Create a Caluclated
field in your list in the standard way with a formula that
checks the value of your Choice field and returns a URL
(relative will work) to the appropriate graphic file making
sure that it is a format that will be handled by the newly
modified render pattern. Something like:
=IF(Choice="A","/imagepath/red.giF", IF(Choice="B",
"/imagepath/yellow.giF", "/imagepath/green.giF"))
Now you can use the calculated field wherever you
like.
This is pretty elegant and nice to do since a) you don’t need to create a DVWP and therefore unghost a page b) it uses CAML which is always cool and c) you can set up a list with this in it so anyone creating a new list of this type will get the results. RenderPattern is a pretty powerful little thing because basically you can do anything in it, including conditional logic.
NUnit test results stored in a SharePoint list anyone? Yeah, who needs Team Server Foundation when you do stuff like this.