Thursday, December 22, 2011

Display Custom Advance Find view in Iframe in CRM 2011

Hi All, To bind FetchXml to Iframe Adi Katz,MVP has provided nice article to do in CRM4.0. Thanks Adi Katz for the great article. I just started converting it to work with CRM 2011. Here is the working copy of mine, to bind FetchXml to Iframe.


function loadIFrame() {

    window.fetchActivtities = new FetchViewer("IFRAME_TEST");
    fetchActivtities.FetchXml = getFetchXml();
    fetchActivtities.LayoutXml = getLayoutXml();
    fetchActivtities.Entity = "activitypointer";
    fetchActivtities.QueryId = "{00000000-0000-0000-00aa-000010001899}"; // view GUID
    fetchActivtities.RegisterOnTab(2); //IFRAME TAB INDEX


}



function getFetchXml() {

//  FetchXML Query
    return ' <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true">' +
                '<entity name="activitypointer">' +
                 ' <attribute name="subject" />' +
                 ' <attribute name="scheduledstart" />' +
                 ' <attribute name="regardingobjectid" />' +
                 ' <attribute name="prioritycode" />' +
                 ' <attribute name="scheduledend" />' +
                 ' <attribute name="activitytypecode" />' +
                 ' <attribute name="instancetypecode" />' +
                 ' <order attribute="scheduledend" descending="false" />' +
                '<filter type="and">'+
                  '<condition attribute="regardingobjectid" operator="in">'+
                    '<value  uitype="account">{7CC58DF6-3114-E111-8E22-1CC1DEEAE7D7}</value>'+                  
                 ' </condition>'+
                '</filter>'+
                '  <attribute name="activityid" />' +
               ' </entity>' +
             ' </fetch>';

}

function getLayoutXml() {

// grid layout, you can get easily from Customization.xml file
    return '<grid name="resultset" object="4200" jump="subject" select="1" icon="1" preview="1">' +
               ' <row name="result" id="activityid" multiobjectidfield="activitytypecode">' +
               '   <cell name="instancetypecode" width="100" ishidden="1" />' +
               ' </row>' +
             ' </grid>';

}

function FetchViewer(iframeId) {
    var Instance = this;
    var vDynamicForm;
    var m_iframeTab;
    var m_iframeDoc;

    Instance.Entity = "";
    Instance.Iframe = null;
    Instance.FetchXml = "";
    Instance.QueryId = "";
    Instance.LayoutXml = "";

    Instance.RegisterOnTab = function (tabIndex) {
        Instance.Iframe = document.getElementById(iframeId);

        if (!Instance.Iframe)
            return alert("Iframe " + iframeId + " is undefined");

        m_iframeDoc = getIframeDocument();
        var loadingGifHTML = "<table height='100%' width='100%' style='cursor:wait'>";
        loadingGifHTML += "<tr>";
        loadingGifHTML += "<td valign='middle' align='center'>";
        loadingGifHTML += "<img alt='' src='/_imgs/AdvFind/progress.gif'/>";
        loadingGifHTML += "<div/><b>Loading View...</b>";
        loadingGifHTML += "</td></tr></table>";
        m_iframeDoc.body.innerHTML = loadingGifHTML;

        Instance.Refresh();

    }

    function RefreshOnReadyStateChange() {

        if (Instance.Iframe.readyState != 'complete')
            return;

        Instance.Refresh();
    }

    Instance.Refresh = function () {
   
        if (!Instance.Iframe)
            return alert("Iframe " + iframeId + " is undefined");

        m_iframeDoc = getIframeDocument();

        Instance.Iframe.detachEvent("onreadystatechange", RefreshOnReadyStateChange);

        var create = m_iframeDoc.createElement;
        var append1 = m_iframeDoc.appendChild;
        vDynamicForm = create("<FORM name='vDynamicForm' method='post'>");

        var append2 = vDynamicForm.appendChild;
        append2(create("<INPUT type='hidden' name='FetchXml'>"));
        append2(create("<INPUT type='hidden' name='LayoutXml'>"));
        append2(create("<INPUT type='hidden' name='EntityName'>"));
        append2(create("<INPUT type='hidden' name='DefaultAdvFindViewId'>"));
        append2(create("<INPUT type='hidden' name='ViewType'>"));
        append1(vDynamicForm);

        vDynamicForm.action = prependOrgName("/AdvancedFind/fetchData.aspx");
        vDynamicForm.FetchXml.value = Instance.FetchXml;
        vDynamicForm.LayoutXml.value = Instance.LayoutXml;
        vDynamicForm.EntityName.value = Instance.Entity;
        vDynamicForm.DefaultAdvFindViewId.value = Instance.QueryId;
        vDynamicForm.ViewType.value = 1039;
        vDynamicForm.submit();


        Instance.Iframe.attachEvent("onreadystatechange", OnViewReady);
    }

    function OnViewReady() {
        if (Instance.Iframe.readyState != 'complete') return;

        Instance.Iframe.style.border = 0;
        Instance.Iframe.detachEvent("onreadystatechange", OnViewReady);
        m_iframeDoc = getIframeDocument();
        m_iframeDoc.body.scroll = "no";
        m_iframeDoc.body.style.padding = "0px";
    }

    function getIframeDocument() {
        return Instance.Iframe.contentWindow.document;
    }

}


Note: This script is completely unsupported. it may break in the future with roll-up updates. 

Monday, December 19, 2011

Adding New Group to Subgrid in CRM 2011

Hi All, Now i am going to add new custom group to subgrid. Here I am going to add a custom group to contact entity subgrid.





1. Export the solution and open the customization.xml file using visual studio to edit.
2. Now edit the customization file, change the <RibbonDiffXml> of contact entity like this

  <RibbonDiffXml>
        <CustomActions>
          <CustomAction Id="sample.SubGrid.contact.MainTab.CustomGroup.CustomAction" Location="Mscrm.SubGrid.contact.MainTab.Groups._children" Sequence="110">
            <CommandUIDefinition>
              <Group Id="sample.SubGrid.contact.MainTab.CustomGroup.SampleGroup" Command="sample.SubGrid.contact.MainTab.CustomGroup.Command" Title="$LocLabels:CustomGroup.Title" Sequence="32" Template="Mscrm.Templates.Flexible2" Image32by32Popup="$webresource:new_samplebutton32x32.png">
                <Controls Id="sample.SubGrid.contact.MainTab.CustomGroup.Controls">
                  <Button Id="sample.SubGrid.contact.MainTab.CustomGroup.CustomButton.A" Command="sample.SubGrid.contact.MainTab.CustomGroup.CustomButton.A.Command" Sequence="21" LabelText="$LocLabels:CustomButton.A.LableText" ToolTipTitle="$LocLabels:CustomButton.A.LableText" ToolTipDescription="$LocLabels:CustomButton.A.ToolTipDescription" Image16by16="$webresource:new_samplebutton16x16.png" Image32by32="$webresource:new_samplebutton32x32.png" TemplateAlias="o1" />
                </Controls>
              </Group>
            </CommandUIDefinition>
          </CustomAction>
          <CustomAction Id="sample.SubGrid.contact.MainTab.CustomGroup.Maxsize.CustomAction" Location="Mscrm.SubGrid.contact.MainTab.Scaling._children" Sequence="120">
            <CommandUIDefinition>
              <MaxSize Id="sample.SubGrid.contact.MainTab.CustomGroup.Maxsize" GroupId="sample.SubGrid.contact.MainTab.CustomGroup.SampleGroup" Sequence="21" Size="LargeMedium" />
            </CommandUIDefinition>
          </CustomAction>
        </CustomActions>
        <Templates>
          <RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates>
        </Templates>
        <CommandDefinitions>
          <CommandDefinition Id="sample.SubGrid.contact.MainTab.CustomGroup.Command">
            <EnableRules>
              <EnableRule Id="sample.SubGrid.contact.CustomGroup.EnableRule" />
            </EnableRules>
            <DisplayRules>
            </DisplayRules>
            <Actions />
          </CommandDefinition>
          <CommandDefinition Id="sample.SubGrid.contact.MainTab.CustomGroup.CustomButton.A.Command">
            <EnableRules>
              <EnableRule Id="sample.SubGrid.contact.SingleRecordSelection.EnableRule" />
            </EnableRules>
            <DisplayRules />
            <Actions>
              <!-- This new_sample.js webresource must be added before customizing -->
              <JavaScriptFunction FunctionName="TestFunction" Library="$webresource:new_sample.js">
                <CrmParameter Value="SelectedControlSelectedItemIds" />
              </JavaScriptFunction>
            </Actions>
          </CommandDefinition>
        </CommandDefinitions>
        <RuleDefinitions>
          <TabDisplayRules />
          <DisplayRules />
          <EnableRules>
            <EnableRule Id="sample.SubGrid.contact.CustomGroup.EnableRule">
              <EntityRule AppliesTo="PrimaryEntity" EntityName="account" />
            </EnableRule>
            <EnableRule Id="sample.SubGrid.contact.SingleRecordSelection.EnableRule">
              <SelectionCountRule AppliesTo="SelectedEntity" Minimum="1" Maximum="1" />
            </EnableRule>
          </EnableRules>
        </RuleDefinitions>
        <LocLabels>
          <LocLabel Id="CustomButton.A.LableText">
            <Titles>
              <Title languagecode="1033" description="Sample Button" />
            </Titles>
          </LocLabel>
          <LocLabel Id="CustomButton.A.ToolTipDescription">
            <Titles>
              <Title languagecode="1033" description="Sample Button Description" />
            </Titles>
          </LocLabel>
          <LocLabel Id="CustomGroup.Title">
            <Titles>
              <Title languagecode="1033" description="Custom Group" />
            </Titles>
          </LocLabel>
        </LocLabels>
      </RibbonDiffXml>


3. java script function on custom button click


function TestFunction(selectedRecordID) {  
   alert(selectedRecordID[0]);  
   // your logic 
}


4. Save the customization.xml file and export back to CRM.

        Now you will find the custom group and button on the contact subgrid. Here custom button will be enable when you are accessing contact entity subgrid from only Account entity. For rest of all the entities this custom button will be in disable mode. Only single record selection from subgrid will be allowed.

keep coding!!!!!

Tuesday, December 13, 2011

Retrieve OptionSet Text in CRM 2011 using C#

Hi All, In CRM 2011 we have two types of Option Sets. one will be normal Option set Filed and the other one will be Global Option Set. Lets see how to retrieve Option Set Text for both types.

Retrieve Normal(Local) Option Set Text


// Get Normal option set Text
string optionsetText = entity.FormattedValues["new_optionset"];

or

string optionsetText = entity.GetFormattedAttributeValue("new_optionset");

Retrieve Global Option Set Text

int OptionsetValue = ((Microsoft.Xrm.Sdk.OptionSetValue)entity["new_localoptionset"]).Value;
string GlobaloptionsetText= GetOptionsetText(entity, service, "new_globaloptionset", OptionsetValue );



  // Retrieves Global Option set Selected Text
        // Parameters: 1. Entity Name   2. Service  3. Global Option Set Name   4. optionset selected value
        public string GetOptionsetText(Entity entity, IOrganizationService service,string  optionsetName,int optionsetValue)
        {
            string optionsetSelectedText = string.Empty;
            try
            {


                RetrieveOptionSetRequest retrieveOptionSetRequest =
                    new RetrieveOptionSetRequest
                    {
                        Name = optionsetName
                    };

                // Execute the request.
                RetrieveOptionSetResponse retrieveOptionSetResponse =
                    (RetrieveOptionSetResponse)service.Execute(retrieveOptionSetRequest);

                // Access the retrieved OptionSetMetadata.
                OptionSetMetadata retrievedOptionSetMetadata = (OptionSetMetadata)retrieveOptionSetResponse.OptionSetMetadata;

                // Get the current options list for the retrieved attribute.
                OptionMetadata[] optionList = retrievedOptionSetMetadata.Options.ToArray();
                foreach (OptionMetadata optionMetadata in optionList)
                {
                    if (optionMetadata.Value == optionsetValue)
                    {
                        optionsetSelectedText = optionMetadata.Label.UserLocalizedLabel.Label.ToString();
break;
                    }
                }
            }
            catch (Exception)
            {


                throw;
            }
            return optionsetSelectedText;
        }

===========================================


// Gets Local/Normal optionset Lable using Metadata Service
         public static string GetoptionsetText(string entityName, string attributeName, int optionSetValue, IOrganizationService service)
         {
             string AttributeName = attributeName;
             string EntityLogicalName = entityName;
             RetrieveEntityRequest retrieveDetails = new RetrieveEntityRequest
             {
                 EntityFilters = EntityFilters.All,
                 LogicalName = EntityLogicalName
             };
             RetrieveEntityResponse retrieveEntityResponseObj = (RetrieveEntityResponse)service.Execute(retrieveDetails);
             Microsoft.Xrm.Sdk.Metadata.EntityMetadata metadata = retrieveEntityResponseObj.EntityMetadata;
             Microsoft.Xrm.Sdk.Metadata.PicklistAttributeMetadata picklistMetadata = metadata.Attributes.FirstOrDefault(attribute => String.Equals

(attribute.LogicalName, attributeName, StringComparison.OrdinalIgnoreCase)) as Microsoft.Xrm.Sdk.Metadata.PicklistAttributeMetadata;
             Microsoft.Xrm.Sdk.Metadata.OptionSetMetadata options = picklistMetadata.OptionSet;
             IList<OptionMetadata> OptionsList = (from o in options.Options
                                                     where o.Value.Value == optionSetValue
                                                     select o).ToList();
             string optionsetLabel = (OptionsList.First()).Label.UserLocalizedLabel.Label;
             return optionsetLabel;
         }




happy coding :)