Tag Archives: ribbon

Hiding a Group of Ribbon Buttons in CRM 2011

 

Scenario:  Removing the Actions group of buttons from the Opportunity screens (removing the Close as Won, Close as Lost, and Recalculate Opportunity buttons).

i.e.:  Before:

image

and After:

image

 

There are 2 parts to customising the Ribbon:

1. Determine the ID of the ribbon component you want to change

2. Add a custom action to the relevant entity’s exported customisation file to ‘request’ a change to that ribbon component

 

To figure out the ID browse to the following SDK folder…

\\sdk\SampleCode\CS\Client\Ribbon\ExportRibbonXml\ExportedRibbonXml\

.. and have a look at the ribbon definition for the entity involved.  In our case this is the file  opportunityribbon.xml.

[UPDATE: 14 Dec 2011 – The latest SDK did not include the ribbon definition XML files forcing you to build and run an app from source code provided in order to generate them for your self. I provide instructions on this process here]

There are separate ribbon definitions for: the main grid view of an entity, the related grid view, and the form.  In our case these buttons appear on the main grid view and on the form but not on the related grid ribbon, so there are 2 changes we need to make.

Ribbons are defined as a collection of tabs.  Each tab has Groups.  Each Group has buttons.

In your case we can either try and remove each of the 3 buttons or remove the entire “Actions” group they sit in.  I’m going to go with removing the entire Group because that’s bound to be easier and also I suspect there’s a 4th “Reopen Opportunity” button that will conditionally appear in that group and I want that hidden as well. 

clip_image002

The Tabs we are after and the Groups on those Tabs are as per below:

clip_image003

 

Now here’s the trap for young players, we don’t make changes to the opportunityribbon.xml.  It’s included in the SDK only as a reference.  Instead, we need to make our changes to the Opportunity entity itself by exporting and editing its customisation XML. 

 

Here’s the steps:

1. Create a new Solution called OppEntityOnly

2. Add the Opportunity entity to the Solution

3. Export the Solution and unzip it

4. Open the exported customization.xml file in Visual Studio (or NotePad if you don’t have VS)

5. Do a FIND on <RibbonDiffXml>

6. Replace  <CustomActions /> with the below:

<CustomActions > 
  <HideCustomAction Location="Mscrm.HomepageGrid.opportunity.MainTab.Actions" 
                    HideActionId="Mscrm.HomepageGrid.opportunity.MainTab.Actions.HideAction" /> 
  <HideCustomAction Location="Mscrm.Form.opportunity.MainTab.Actions" 
                    HideActionId="Mscrm.Form.opportunity.MainTab.Actions.HideAction" /> 
</CustomActions>

Note: the Location attributes refer to the Group ID’s I identified in the opportunityribbon.xml file

7. Save.

8. Re-zip

9. Import

10. Publish

11. Refresh your browser

 

Hope this helps Smile

Advertisements

Launching a Dialog from a Ribbon Button in CRM 2011

Here’s some sample code that demonstrates how to execute a Dialog from a Ribbon button in CRM 2011.  The solution sample is provided in managed and unmanaged formats:

Managed Solution (updated: 25 Feb 2011)

Unmanaged Solution (updated: 25 Feb 2011)

note: this has only been tested successfully in CRM Online 

I have built out a Dialog based solution for a call centre, further extending the solution I documented in one of my earlier blogs.  The scenario is as follows:

A call centre agent takes both sales and service inbound calls.  They are tasked with:

  • searching for the caller in CRM and adding them as a new Contact if not found
  • determining whether the call is sales or service related
  • logging the phone call in CRM
  • recording a new opportunity or case
  • informing the caller they will be called back within 24 hours

I wanted a Dialog based solution that would guide the call centre agent through the process with the minimal number of clicks.  I didn’t want the user to have to create the initial CRM record required for the Dialog, I wanted the user to simply click a button.   My solution design makes use of the REST End Point to retrieve the GUID of the Dialog that should be launched and also to create the initial Phone Call record.   Dialog’s are URL addressable so launching the dialog is not difficult once you have the context record and the Dialog GUID.  In the Dialog itself I make use of Dialog Variables and Database Queries to query CRM to see if the Caller exists and to present a list of possible matches back to the user.   Pretty powerful stuff.

 

The end result looks like this…

The user has an incoming call, they click the Incoming Call button. 

 

image

The Button executes a jscript function that does a window.open, launching an HTML page I’ve loaded into CRM as a web resource.

 

An HTML page pops indicating a Phone Call is being created and the Call Script is being loaded:

image

This HTML page is used to reference some jscript libraries I need to extract the CRM context and for the execution of the REST call.  The HTML page provides the progress indicators to the user and then executes a jscript function that does the heavy lifting.

The jscript function:

  • queries the REST end point for Processes to retrieve the GUID of the “Inbound Call Script” Dialog Process.
  • uses the REST end point for Phone Calls to create a Phone Call record.
  • formulates a URL using the CRM context, Dialog GUID and the Phone Call GUID
  • does a window.open to launch that URL

 

And then the Dialog appears:

image

 

The Call Centre Agent greets the caller, notes there reason for calling and collects their name (as prompted by the Dialog script):

image

 

The script then prompts the agent to find out whether the caller has an existing account:

image

 

If the caller indicates they are an existing customer a Contact search page is presented:

image

 

A search is executed against CRM using the search strings entered (doing a “like” search).  And the search results are returned to the agent for review:

image

 

The user can go back and modify their search, or they can select one of the search results, or they can indicate the caller was not found in the database:

image

 

Finally, the agent selects the nature of the enquiry so that an Opportunity or Case record can be created in CRM:

image

 

The final page of the Dialog provides the call wrap up script:

image

 

Behind the scenes a Phone Call record has been created and linked to either an existing Contact or to a new Contact.  A Case or an Opportunity has been created and linked to the Contact.  And the Phone Call has been marked as completed.

 

I was pretty impressed by the extensibility offered by the CRM platform here.  The REST end point performed a little slowly for me but I haven’t tried to performance tune anything here.  The Dialog functionality largely bent the way I needed it to.  The area it was weakest was the display of the Query Results, where a pick list is not really suitable.  

 

To see this in action:

– Download the solution, install, publish and refresh your browser

(Known Issue: Check the Dialog is Active.  The Dialog definition contains references to the Australian currency which prevent it from publishing in instances missing that currency.  Edit those mappings as required)

– Navigate to Workplace –> Contacts

– The “Incoming Call” button should appear on the Ribbon (it appears on the “Main” tab for the core data entities, i.e. on the Account and Contact ribbons)

– Click the button

– Navigate the dialog

– At conclusion you should see:

   – A new completed Phone Call record

   – Attached to either a new Case or a new Opportunity

   – And both records related to either an existing Contact or a new Contact

Under the hood – the CRM 2011 Ribbon

Here’s my high level (and very likely incorrect) understanding of how CRM determines how to render the application ribbon at runtime.  These notes are just my guesses based on my observations.  There’s plenty I’m not taking into account but I think these are useful notes and I’ll be coming back to these when I need to figure out to get a button added in the right place, looking the right way…

  • Each ribbon is essentially a collection of tabs
  • Tabs follow a strict naming convention which is used to determine which Tabs should be displayed.
  • The ribbon is constructed at run time based on:
    • the entity that has focus
    • whether the focus is on the entity’s form, grid, or contextual grid
  • i.e. If the Account Form is launched CRM looks for Tabs with names that conform to one of the 2 following masks:
    • Mscrm.Form.account.*
    • Mscrm.Form.{!EntityLogicalName}.*
  • The ribbon is constructed based on a combination of the global ribbon definition, the entity specific ribbon definition and any customisations you have made to either of those.   In each of these places each Tab may have properties defined.
  • CRM effectively reads these definitions from applicationribbon.xml, accountribbon.xml plus any RibbonDiff customisations you have made to either the Application Ribbon or to the Account entity.
  • I suspect the layering order starts with the base defined in applicationribbon.xml, overlays that with the changes defined in accountribbon.xml and then overlays that with the changes defined in your customisation to the application ribbon and then finally the Account entity customisations are applied. i.e.:
    • Out-of-the-box global definition
    • Out-of-the-box entity specific definition
    • Customisations to the global definition
    • Customisations to the entity specific definition
  • When rendering a specific group on a tab CRM obeys:
    • The scaling rules defined under the Tab (specified for each Group)
    • The Template defined for the Group
    • The Template Alias defined for each Button
    • The Sequence defined for each Button
  • e.g. When a Group uses Template Id “Mscrm.Templates.Flexible3” and the Group uses the “LargeMediumLarge” layout when at Max Size then the buttons in that group will be rendered in the following order:
    • Those with a Template Alias of o1 are rendered in sequence order, each displayed as large icons
    • Those with a Template Alias of o2 are rendered in sequence order, each displayed as medium icons in a 3 row (stacked) configuration
    • Those with a Template Alias of o3 are rendered in sequence order, each displayed as large icons
  • I get this from the GroupTemplate definition for Mscrm.Templates.Flexible3 which I find in applicationribbon.xml:

image_thumb[110]

Adding a Button to the Main CRM Ribbon in 2011

I find one of the most frequently requested enhancements to CRM is the addition of a button to the main menu that will launch an external URL.   Common examples of what customers want a button to provide access to include: the organisation’s intranet, a corporate reporting tool, a timesheet application,  quoting tool, an inventory inquiry screen.

So here’s a quick run through on how to add a button to CRM that will appear right next to the Advanced Find button in both the web client and the Outlook client which when clicked will launch a predefined URL…

Desired end result:

image

 

Step 1 – Create a new Solution called Ribbon

image

 

Step 2 – Click Add Existing and select the Application Ribbon component

Note: in my previous blog on customising the ribbon we added to our solution the CRM entity whose ribbon we wanted to change.  Here we want to change the global ribbon so we place the Application Ribbon in our Solution instead

image

 

Step 3 – Click Export Solution and save the ZIP file to your desktop

image

 

Step 4 – Navigate to the exported Solution file, unzip it into a folder of the same name, and then navigate to the unzipped files

image

 

Step 5 – Open the customisation.xml file in Visual Studio

image

 

Step 6 – In Visual Studio, add the following 4 schemas (from ..sdk\schemas) – to add intellisense:

image

 

Now before we can start coding our changes we need to determine the location Id of where we want our button added…

 

Step 7 – Navigate to the sdk folder location below and open the file applicationribbon.xml in Visual Studio:

..sdk\samplecode\cs\client\ribbon\exportribbonxml\exportedribbonxml

[UPDATE: 14 Dec 2011 – The latest SDK did not include the ribbon definition XML files forcing you to build and run an app from source code provided in order to generate them for your self.  I provide instructions on this process here]

Step 8 – Do a Find for…

<Group Id="Mscrm.HomepageGrid.{!EntityLogicalName}.MainTab.

… and then scan down under that Group until you find the Advanced Find button.  Now scan back up and take note of the Controls Id value which the Advanced Find button sits under:

image

Ok, so how did I know to do a Find for:   "<Group Id="Mscrm.HomepageGrid.{!EntityLogicalName}.MainTab."

Easy:

  • I want my button to appear on the grid ribbon, this is referred to as “HomepageGrid”
  • I’m wanting to make a global change, that’s why I opened the applicationribbon.xml rather than a specific entity’s ribbon xml, so I need to look for a global ribbon definition, these are defined using the {!EntityLogicalName} parameter.
  • And I’m wanting my button added to the main tab, the one that takes on the entity name
  • Therefore I am looking for a Tab with a name that starts with “Mscrm.HomepageGrid.{!EntityLogicalName}
  • If you scan through the Tabs that follow this naming convention you’ll see it’s pretty obvious the one we want is called MainTab. 
  • Stringing those bits altogether gives you:  Mscrm.HomepageGrid.{!EntityLogicalName}.MainTab and sure enough under there I see all the various groups and buttons that match what I see on the UI.

Step 9 – Close applicationribbon.xml and return your focus to your exported customization.xml file open in Visual Studio. 

 

Step 10 – Replace “<CustomActions />”  with the XML below.

<CustomActions> 
  <CustomAction Id="Sample.{!EntityLogicalName}.MainTab.LaunchURL.CustomAction" 
                Location="Mscrm.HomepageGrid.{!EntityLogicalName}.MainTab.ExportData.Controls._children" 
                Sequence="71"> 
    <CommandUIDefinition> 
      <Button Id="Sample.{!EntityLogicalName}.MainTab.LaunchURL.Button" 
              Command="Sample.all.MainTab.LaunchURL.Command" 
              LabelText="Launch URL" 
              ToolTipTitle="Launch URL" 
              ToolTipDescription="Click to launch external URL" 
              TemplateAlias="o3" 
              Image16by16="$webresource:new_star16x16" 
              Image32by32="$webresource:new_star32x32" /> 
    </CommandUIDefinition> 
  </CustomAction> 
</CustomActions>

Note:

  • The Location specified is the Controls Id we determined earlier
  • The TemplateAlias matches that specified for the Advanced Find button (this ensures the button will be sized and positioned how I want it)
  • The Sequence is 1 higher than that specified for the Advanced Find button (this places my button just after the Advanced Find button)
  • The button label will be “Launch URL”
  • The button icons will be sourced from webresources called “new_star16x16” and “new_star32x32” (you’ll need to upload these webresources, I won’t cover that here, change the XML to match your webresources names or remove the mention of the Icons – the specification of button icons is optional)
  • When clicked the button will perform the action defined by

    "Sample.all.MainTab.LaunchURL.Command"  (we will add this content in our next step)

     

Step 11 – Replace “<CommandDefinitions />” with the XML below:

<CommandDefinitions> 
  <CommandDefinition Id="Sample.all.MainTab.LaunchURL.Command"> 
    <EnableRules /> 
    <DisplayRules /> 
    <Actions> 
      <Url Address ="https://gtcrm.wordpress.com/" />                
    </Actions> 
  </CommandDefinition> 
</CommandDefinitions>

Note:

 

Step 12 – Save you changes, exit Visual Studio, select the 3 unzipped solution files and zip them up

  • I like to follow the naming convention and version numbering that CRM used at export, and I achieve this via WinZip’s context menu, I just modify the filename afterwards to increment the version number
  • Make sure the structure of your zip file matches the format CRM exports solutions in – i.e. no additional folder layers

 

Step 13 – Import the Solution, Publish, refresh your browser

image

 

Done.  Smile 

You should now see a new button beside your Advanced Find labelled “Launch URL” with a Star icon, and when clicked a browser window should pop and my blog should display.

image

 

One caveat; this button will appear only sometimes on the Ribbon.  Because the ribbon is contextual there are actually several ribbons you need to customise if you want your button always visible.  i.e. the button will appear when your focus is on a main CRM data entity like Account or Contact but not when you are on something like Dashboards or Solutions.  You may find it appears enough of the time that this single customisation, or this plus customising the Dashboard ribbon is sufficient.

Adding a Button to a CRM 2011 Form Ribbon

Here’s a shortcut guide to customising the Form ribbon in CRM 2011.  Rather than explaining all of the intricacies of the ribbon here’s a set of instructions that will get a button added to a form with the least amount of steps/complexity.  In this scenario we will add a button to the Account form that will launch an external web page (if you prefer the button executes a jscript function keep reading as I cover that as well)… 

Here’s the steps:

1. Create a new Solution called Ribbon.

2. Add to your Solution the Account entity and then export the Solution.

3. Determine the location ID for where you want your button to sit (note: this take a bit of research, keep reading…)

3a. Download and install the CRM SDK.  Then go to the following SDK folder:

sdk\samplecode\cs\client\ribbon\exportribbonxml\exportedribbonxml\

Here you will see Ribbon definitions for each entity (e.g. accountribbon.xml)

[UPDATE: 14 Dec 2011 – The latest SDK did not include the ribbon definition XML files forcing you to build and run an app from source code provided in order to generate them for your self. I provide instructions on this process here]

3b. Open accountribbon.xml in Visual Studio.

Now we need to find the relevant bit of XML that defines the ribbon component we want to customise.  Each entity has ribbon definitions for it’s form ribbon (“Form”), for the ribbon that appears when the entity’s grid view is selected from the main CRM menu (“HomePageGrid”) and for the ribbon that appears when the entity is displayed as an in-line grid on either a dashboard on another entity’s form (“SubGrid”).  You will see Tab definitions for each of this:

image

We are interested in the Form ribbon so minimise the other XML elements and have a look at the Tab definitions for the Account Form.  You will see 3 tabs are defined:

image

These are the definitions behind the “Account”, “Add” and “Customize” tabs you see when looking at the Account form in CRM:

(Note: As the “File” tab is generic it is defined in the application.ribbon.xml rather than inside each entity’s ribbon xml file)

image

The Tab that we want is the one that appears as “Account”.  The Tab definition for this is:

Tab Id="Mscrm.Form.account.MainTab"

(Note: look at the Buttons defined under each Tab  to help figure out the correct Tab)

To add a button to the CRM ribbon we need to specify a location.  The value we need is the “Controls Id”.   Find the button you want your button added next to and grab the “Controls ID” that button sits under.  We will add our button to the “Process” Group next to the “Run Workflow” button so the Controls ID value we want is:

Controls Id="Mscrm.Form.account.MainTab.Workflow.Controls"

image

3c. Copy the Controls Id value to NotePad

3d.  Close accountribbon.xml

 

That’s our research done, let’s get back to defining our button…


 

4. Open the customisation.xml file that was included in your exported Solution zip file (open in Visual Studio).

5. From the XML menu, click Schemas and then add from .. sdk\schemas\ the 3 xsd files that have “ribbon” in their name and also customizationssolution.xsd (this gives us intellisense)

7. Back in the main window of VS do a Find on “RibbonDiff” and then swap out: “<CustomActions />”  with:

<CustomActions> 
  <CustomAction Id="GT.account.Form.Star.CustomAction" 
                Location="Mscrm.Form.account.MainTab.Workflow.Controls._children" 
                Sequence="1"> 
    <CommandUIDefinition> 
      <Button Id="GT.account.Form.Star.Button" 
              Command="GT.account.Form.Star.Command" 
              LabelText="Star" 
              ToolTipTitle="Tip" 
              ToolTipDescription="This is a Star" 
              TemplateAlias="o1" 
              Image16by16="$webresource:new_star16x16" 
              Image32by32="$webresource:new_star32x32" 
      /> 
    </CommandUIDefinition> 
  </CustomAction> 
</CustomActions>

If you want to deviate from my scenario of customising the Account form the relevant bit in the above is the Location reference.  This is where the Controls ID value that we we obtained from our research goes.  Note: The Controls ID value needs to be appended with “._children” e.g.:

Location="Mscrm.Form.account.MainTab.Workflow.Controls._children"

 

8.  If you have 16×16 and 32×32 icons for your button go and add those into CRM as web resources and then change the references in the above code snippet.  Otherwise, remove the Image16by16 and Image32by32 lines (they’re optional, the button will still show).

9. Scroll down a bit and replace: “<CommandDefinitions />”  with:

<CommandDefinitions> 
  <CommandDefinition Id="GT.account.Form.Star.Command"> 
    <EnableRules> 
    </EnableRules> 
    <DisplayRules> 
    </DisplayRules> 
    <Actions> 
      <Url Address="http://www.google.com" /> 
    </Actions> 
  </CommandDefinition> 
</CommandDefinitions>

10.Adjust the Url reference to whatever you want.  You can use use a relative reference if you want to launch a CRM URL or an HTML page you have loaded into CRM.

or:

If you want to execute a jscript function instead swap out the <Actions> node with a jscript web resource and function name reference like the below:

<Actions> 
  <JavaScriptFunction Library="$webresource:new_getcontact" 
                      FunctionName="NewCaseOnClick" 
                      /> 
</Actions>

11. Save your customisation.xml changes.

12. Re-zip your unzipped solution back into a solution zip file, import, publish all and then refresh your browser.

Done.  Smile

 

End result:

image

 

This solution is available for download in both managed and unmanaged formats.