Return and display picklist value (display value) in custom sql report reporting services report in Microsoft Dynamics CRM 4 entity attribute and StringMap picklist values table

Normally, you should be able to get the picklist display value and picklist item id in the filtered view of any entity. In some cases, you may need to work with StringMap table directly to get the picklist values for a specific field of a given entity. This could be the case if you are not using the filtered view for some reason or if you want to write a report based on the table or the non-filtered view, the following post is providng the query (queries) needed to do so.

To get the display value of any picklist, you need to use the StringMap table. If you are writing a custom ssrs (SQL Server Reporting Services) report for Dynamics CRM 4, you usually need to return the picklist display value not the picklist item id.

For example: in the opportunity entity, you have a picklist attribute “Rating” (attribute name opportunityratingcode). If you are writing a custom SQL report to add to CRM and you want to display the values of the attribute, you will find that the display value of the picklist is not stored in the filtered view of Opportunity (FilteredOpportunity). To get the display value of any picklist, you need to use the StringMap table.

There many ways to get the information from the StringMap table, I will mention two ways here:

1) using Inner Join (simple - one picklist only)
This way, you just simply join the two tables: your entity filteredview and the StringMap table
/* the query uses out of the box attributes, so should run successfully on all CRM organisations*/
SELECT opp.name, opp.estimatedvalue_base, opp.closeprobability, StringMap.Value
FROM Opportunity as Opp INNER JOIN
  StringMap ON Opp.opportunityratingcode = StringMap.AttributeValue
WHERE (StringMap.ObjectTypeCode = 3) AND (StringMap.AttributeName = N'opportunityratingcode')
AND (opp.accountid = 'input your accoung GUID here'

This query will return list of all Opportunities for the specified account display the picklist display value rather than the id.

2) using Temp table (my prefered way for multiple picklists)

This query is longer and uses/declares temp tables but it is the simplest way in case you have several picklists and you want to return the display value of multiple picklists. You just create several temp tables just like @TempSM, where each temp table returns the list of display values for each picklist and then join them together.

1 Picklist query:
/* the query uses out of the box attributes, so should run successfully on all CRM organisations*/
Declare @TempOpp table(OpportunityID uniqueidentifier, OpportunityName nVarchar(max),
Estimatedvalue float, Probability float, Rating nVarchar(max))
Insert into @TempOpp
select opp.opportunityid,opp.name ,
opp.estimatedvalue_base,
opp.closeprobability,
opp.OpportunityRatingCode
From Opportunity opp
where opp.accountid = '97F97A5A-2622-DF11-A1C3-005056BA6B8A'
Declare @TempSM table(AttributeValue nVarchar(max), Value nVarchar(max))
Insert into @TempSM
select AttributeValue, Value
from StringMap
WHERE (StringMap.ObjectTypeCode = 3) AND
(StringMap.AttributeName = N'opportunityratingcode' )
select t1.OpportunityName, t1.Estimatedvalue, t1.Probability, t2.Value as RatingDisplayValue
from @TempOpp as t1 left outer JOIN @TempSM as t2 ON
(t1.Rating = t2.AttributeValue)

This query will return list of all Opportunities for the specified account display the picklist display value rather than the id.

2 Picklists query:
------------------
/* the query uses out of the box attributes, so should run successfully on all CRM organisations*/
Declare @TempOpp1 table(OpportunityID uniqueidentifier, OpportunityName nVarchar(max),
Estimatedvalue float, Probability float, Rating nVarchar(max), Priority nVarchar(max))
Insert into @TempOpp1
select opp.opportunityid,opp.name ,
opp.estimatedvalue_base,
opp.closeprobability,
opp.OpportunityRatingCode,
opp.PriorityCode
From Opportunity opp
where opp.accountid = '97F97A5A-2622-DF11-A1C3-005056BA6B8A'
/* Now we have @TempOpp1 with list of all opportunities for the specified account but with ID for picklist value not display names*/
/*Then we declare a temp table for Rating picklist*/
Declare @TempSM table(AttributeValue nVarchar(max), Value nVarchar(max))
Insert into @TempSM
select AttributeValue, Value
from StringMap
WHERE (StringMap.ObjectTypeCode = 3) AND
(StringMap.AttributeName = N'opportunityratingcode' )
Declare @TempOpp2 table(OpportunityID uniqueidentifier, OpportunityName nVarchar(max),
Estimatedvalue float, Probability float, Rating nVarchar(max), Priority nVarchar(max))
Insert into @TempOpp2
select t1.OpportunityID, t1.OpportunityName, t1.Estimatedvalue, t1.Probability,
t2.Value as RatingDisplayValue,t1.Priority as Priority
from @TempOpp1 as t1 left outer JOIN @TempSM as t2 ON
(t1.Rating = t2.AttributeValue)
/*tempopp2 now has opportunities with the rating display value*/
/*Now creating a temp table for Priority picklist*/
Declare @TempSM1 table(AttributeValue nVarchar(max), Value nVarchar(max))
Insert into @TempSM1
select AttributeValue, Value
from StringMap
WHERE (StringMap.ObjectTypeCode = 3) AND
(StringMap.AttributeName = N'PriorityCode' )
select t1.OpportunityID, t1.OpportunityName, t1.Estimatedvalue, t1.Probability,
t1.Rating as RatingDisplayValue,t2.Value as Priority
from @TempOpp2 as t1 left outer JOIN @TempSM1 as t2 ON
(t1.Rating = t2.AttributeValue)

--------------------------------------------

and so on. You create temp table for each picklist, join it with opportunity temp table and then carry on.

Note: This is one way of doing this. There are obviously many other shorter ways of doing this. I personally prefer temp tables a lot because although longer, they are simpler and easier to use. They also bypass any issues with null values in the right table of the join.

Not related Note: Always use filtered views when writing custom SQL reports on SSRS for CRM as they comply with CRM security.

Hide, Display, Resize and Rename left navigation links, CRM fields and attributes using Javascript for Microsoft Dyanmics CRM 4.

Scripts for Resizing, Hiding and renaming left navigation links, fields and attributes in Microsoft Dynamics CRM 4 using Javascript. This post is just a collection of some Javascript code for various common scripts that is frequently used in CRM form events, CRM entity events, etc. These script blocks can be used in OnLoad, OnSave events for CRM forms and OnChange events for CRM fields.

//------- Resize CRM form in the onload event
window.resizeTo(screen.availWidth * 0.85, screen.availHeight * 0.85);
//-------Rename left menu link / Left Navigation. Example: Contacts
var navItem = document.getElementById(’navContacts’);
navItem.innerHTML = navItem.innerHTML.replace(’>Contacts’,'>Students’);
//------Hide left menu link / Navigation. Example: Workflow
var navLeftItem = document.getElementById(’navAsyncOperations’);
navLeftItem.style.display = ‘none’;
//-----Hide Left navigation menu item link of a CRM form based on
// a value in a picklist on the same form.
//Get contacts left navigation menu item element.
var navLeftItem = document.getElementById(’navContacts’);
//if picklist (customer type code) value is equal to 1 (1st item in picklist) then
//hide left menu item (contacts link is used as an example), otherwise, show it.
if(crmForm.all.customertypecode.DataValue == 1)
{
 navLeftItem.style.display = ‘none’;
}
else
{
 navLeftItem.style.display = ‘inline’;
}
 //-----Hide a CRM field on a form. example: the "name" field.
crmForm.all.name_c.style.display = 'inline';
crmForm.all.name_d.style.display = 'inline';
//-----Hide a CRM field on a form (example: the "name" field)
//based on the selected value in a picklist
if(crmForm.all.customertypecode.DataValue == 1)
{
         crmForm.all.name_c.style.display = 'inline';
         crmForm.all.name_d.style.display = 'inline';
}
else
{
         crmForm.all.name_c.style.display = 'none';
         crmForm.all.name_d.style.display = 'none';
}  ////Add this code to the OnLoad event of the form and
////to the on change event of the picklist attribute (field) as well
//---------Function to hide CRM field in a form. 
//Function accept fieldname as a parameter and
//boolean parameter to remove (hide) entire row on form
HideField('name'); //replace "name" with your field/attribute name
 
function HideField( fieldName, removeEntireRow )
{
 // Always hide the elements, even if we will be hiding the whole row.
 // This allows us to show another field in this row later without this
 // one showing up.
 var elem = crmForm.all[fieldName + "_c"];
 if( elem != null ) elem.style.display = "none";
 elem = crmForm.all[fieldName + "_d"];
 if( elem != null ) elem.style.display = "none";     
 
 if (removeEntireRow)
 {
  var elem = crmForm.all[fieldName + "_d"];
  if( elem != null ) elem.parentElement.style.display = "none";
 }
}

 This post was written quickly from memory and some code blocks here and there, so you might find some minor spelling mistakes. Please comment below if you find any issues with the script blocks or if you want me to extend this post to include additional script.

Script to Hide Add Existing Record button and Add New Record button using Javascript in Microsoft Dyanmics CRM

If you want to hide the two top left  buttons in the assicated view of any entity,  Add Existing Record and Add New Record Buttons, you can use the following javascript code i the onLoad Event of the Microsofty Dyanmics CRM 4 Form.  This post relies on and is an extension to the existing useful post by Dave Hawes.

 //This javascript should be added to the onLoad event for the form of the entity where you want to hide buttons for the associated views of other entities

//-------Hide Add Existing Record Button Only----Method 1----
HideAssociatedViewButton('new_account_new_project', 'Add existing Project to this record');
function HideAssociatedViewButton(loadAreaId, buttonTitle)
{
    var navElement = document.getElementById('nav_' + loadAreaId);
    if (navElement != null)
    {
        navElement.onclick = function LoadAreaOverride()
        {
            // Call the original method to launch the navigation link
            loadArea(loadAreaId);
            var associatedViewIFrame = document.getElementById(loadAreaId + 'Frame');
            if (associatedViewIFrame != null)
            {
                associatedViewIFrame.onreadystatechange = function HideTitledButton()
                {
                    if (associatedViewIFrame.readyState == 'complete')
                    {
                        var iFrame = frames[window.event.srcElement.id];
                        var liElements = iFrame.document.getElementsByTagName('li');
                        for (var i = 0; i < liElements.length; i++)
                        {
                            if (liElements[i].getAttribute('title') == buttonTitle)
                            {
                                liElements[i].style.display = 'none'; //this will hide and align properly
                                liElements[i].style.visibility = 'hidden'; // this is needed when re-sizing cause button to re-appear.
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
}

//—End of Hide Add existing button Only

//——————Hide Add New Record Button and Add Existing Button ———

//Hide Both Buttons-----------
HideAssociatedViewButtons('new_account_new_project', ['Add existing Project to this record', 'Add a new Project to this record']); //Where "Project" is a custom entity.
//OR Hide Add Existing Button Only-----Method 2-------
HideAssociatedViewButtons('new_account_new_project', ['Add existing Project to this record']);  //Where "Project" is a custom entity.

function HideAssociatedViewButtons(loadAreaId, buttonTitles){
    var navElement = document.getElementById('nav_' + loadAreaId);
   if (navElement != null)    {
        navElement.onclick = function LoadAreaOverride()        {
            // Call the original CRM method to launch the navigation link and create area iFrame
            loadArea(loadAreaId);
            HideViewButtons(document.getElementById(loadAreaId + 'Frame'), buttonTitles);
        }
    }
}

function HideViewButtons(Iframe, buttonTitles) {
    if (Iframe != null ) {
        Iframe.onreadystatechange = function HideTitledButtons() {
            if (Iframe.readyState == 'complete') {
                var iFrame = frames[window.event.srcElement.id];
                var liElements = iFrame.document.getElementsByTagName('li');

                for (var j = 0; j < buttonTitles.length; j++) {
                    for (var i = 0; i < liElements.length; i++) {
                        if (liElements[i].getAttribute('title') == buttonTitles[j]) {
                             liElements[i].style.display = 'none'; //this will hide and align properly
                             liElements[i].style.visibility = 'hidden'; // this is needed when re-sizing cause button to re-appear.
                            break;
                        }
                    }
                }
            }
        }
    }
} 

Credit goes to Dave Hawes Blog post mentioned above.