This seems to be the most popular subject available on this blog. Seems no one has tried playing with the Microsoft CRM grids as much as me, which is rather interesting

A while back I touched on how to "colourise" the grid rows, a reader comment got me thinking about how I could satisfy an internal request here. In our old system, they used a dummy entry to trigger a filter which changed the formatting to highlight it. IE they created a record of type "notice" and it would make it bold and bright purple! Couldn't miss it!
So they've asked whether it would be possible to implement something similar with CRM. As these screenshots show, it is!
Before
After
As you can see, a huge improvement, they should have no problems working out that there are no more repairs to be booked for those days

This uses the same colourising code as the previous post, with a few additions

Click on a comment to hide it. Click
here to show all comments.
// if someone can work out why the computers here insist the week starts at Thursday what would be
good
var days = new Array ('Thursday', 'Friday', 'Saturday', 'Sunday', 'Monday', 'Tuesday',
'Wednesday');
var months = new Array('', 'January', 'February', 'March', 'April', 'May', 'June', 'July',
'August', 'September', 'October', 'November', 'December');
var suffixes = new Array('', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'st',
'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th',
'th', 'th', 'th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th', 'th');
// OLD STUFF
// ok so what we need to do, is go through each and er, change em?
var nextcolour;
var index;
for (var i = 0; i < grid.childNodes.length; i++)
{
// NEW STUFF -->
// for repairs
if (table == 'repairs')
{
// pull out the entire row if the name happens to be the bookings one.
if (grid.childNodes[i].childNodes[4].firstChild.firstChild.oid ==
'{9E05CB45-C407-DB11-ADB9-0003FF03C872}')
{
// get the date
var bdate = new Date();
var byear = grid.childNodes[i].childNodes[5].firstChild.innerText.substring(6,
10);
var bmonth = grid.childNodes[i].childNodes[5].firstChild.innerText.substring(3,
5);
var bday = grid.childNodes[i].childNodes[5].firstChild.innerText.substring(0, 2);
bdate.setFullYear(byear, bmonth, bday);
// take the entire row, and suck it out of existance - except for the one field
with our text!
grid.childNodes[i].removeChild(grid.childNodes[i].childNodes[10]);
grid.childNodes[i].removeChild(grid.childNodes[i].childNodes[9]);
grid.childNodes[i].removeChild(grid.childNodes[i].childNodes[8]);
grid.childNodes[i].removeChild(grid.childNodes[i].childNodes[7]);
grid.childNodes[i].removeChild(grid.childNodes[i].childNodes[6]);
grid.childNodes[i].removeChild(grid.childNodes[i].childNodes[5]);
grid.childNodes[i].removeChild(grid.childNodes[i].childNodes[3]);
grid.childNodes[i].removeChild(grid.childNodes[i].childNodes[2]);
grid.childNodes[i].removeChild(grid.childNodes[i].childNodes[1]);
grid.childNodes[i].removeChild(grid.childNodes[i].childNodes[0]);
// expand our row
grid.childNodes[i].childNodes[0].colSpan = 11;
// remove the existing text
grid.childNodes[i].firstChild.firstChild.removeChild(grid.childNodes[i].firstChild.firstChild.firstChild);
// build our new span
grid.childNodes[i].firstChild.firstChild.innerHTML = 'No more repairs to be booked
in for ' + days[bdate.getDay()] + ', ' + bdate.getDate() + suffixes[bdate.getDate()] + ' ' +
months[bdate.getMonth()] + ' ' + bdate.getFullYear();
grid.childNodes[i].firstChild.firstChild.style.textAlign = 'center';
grid.childNodes[i].firstChild.firstChild.style.fontWeight = 'bold';
grid.childNodes[i].colourised = true;
continue;
}
}
// <-- END NEW STUFF
// OLD STUFF
// for everything
index = grid.childNodes[i].childNodes[col].firstChild.innerText;
if (colourmatrix[index] != null)
{
nextcolour = colourmatrix[index];
grid.childNodes[i].style.backgroundColor = '#' + nextcolour;
grid.childNodes[i].colourised = true;
}
}
This will take the contents of a lookup field in the grid, check its GUID against the correct one, and if it is remove all TD's from the field except for the one containing the lookup, and then expand and modify it.
Now please remember, this is a VERY BASIC example. If you modify the view at all or the view contains different fields it won't work. This goes for all grid modifying via javascript. Its also very definitely NOT SUPPORTED by Microsoft. So don't ask them.
From Steve:
Hi, I'm thinking whether we can modify the grid view such as add .gif images in the column?
I need to do that because there's a user requirement which the customer wants me to show different gif images (like traffic lights) based on the status....
Do you have any idea?
Sure do Steve!
What you would do, is once you are in the loop checking each row, instead of replacing the background colour (or in addition to) you could add an image to a column, or replace the icon. To replace the icon you would be looking at something like:
grid.childNodes[i].childNodes[1].innerHTML = '<img src="http://server/your/img_here.gif" alt=""
/>';
This has been tested and seems to work

As always, I hope this helps someone!
-bok
Update!
I get several requests a week for the content of statuses.aspx, and given that I don't actively work with Microsoft CRM anymore I figure it might just be easier if I post the source here. Feel free to comment if you need help, keep in mind though that I'll probably be a bit rusty by now

<%@ Page Language="c#" Debug="true"%>
<%@ Import Namespace="crm" %>
<%@ Import Namespace="metadata" %>
<%
MetadataService service = new MetadataService();
service.Credentials =
System.Net.CredentialCache.DefaultCredentials;
// table
string table = "";
switch (Request.QueryString["table"])
{
case "cases":
table = EntityName.incident.ToString();
break;
default:
Response.Write("<error>Invalid Table specified</error>");
return;
}
// get the data!
StatusAttributeMetadata statuscode = (StatusAttributeMetadata)
service.RetrieveAttributeMetadata(table, "statuscode");
Response.ContentType = "text/xml";
Response.Write("<statuses>");
ArrayList list = new ArrayList();
foreach (StatusOption option in statuscode.Options)
{
Response.Write("<status><text>" + option.Description + "</
text><integer>" + option.OptionValue.ToString() + "</integer></
status>");
}
Response.Write("</statuses>");
%>