Pages

Tuesday 30 April 2013

How to open new record with existing record data when click on the button

The following code will helps you to open the lead record with some existing record data when click on the button but not save the opened record until click on the save button.

 
 
 
function createMultiple() {
    var features = "location=no,menubar=no,status=no,toolbar=no,resize=yes,height=850,width=1000 top=20";
    var compname = Xrm.Page.getAttribute("companyname").getValue();
    var leadid = Xrm.Page.data.entity.getId();
    var leadname=Xrm.Page.getAttribute("subject").getValue();
    var fn=Xrm.Page.getAttribute("firstname").getValue();
    var ln=Xrm.Page.getAttribute("lastname").getValue();
    var fax=Xrm.Page.getAttribute("fax").getValue();
    var extraqs = "companyname=" + compname;
        extraqs+="&subject="+leadname;
        extraqs+="&firstname="+fn;
        extraqs+="&fax="+fax;
        extraqs+="&lastname="+ln;
    window.open(Xrm.Page.context.getServerUrl() + "/main.aspx?etn=lead&pagetype=entityrecord&extraqs=" + encodeURIComponent(extraqs), "_blank", features, false);
}

Monday 29 April 2013

How to Create Custom Workflow in CRM 2011

Scenario: Company A used to get many leads on weekend, but none of their existing sales executive wants to work on weekend, so they have recently recruited one part time sales person Suresh who will be working on weekends. So we have a requirement to assign all the leads created during weekends to Suresh and we also need to display Created Day in lead records.

We have to follow below steps to run custom workflow.
1.       Find out name of the day when lead is created and set it for Created Day.
2.       Assign all the leads created during weekend to Alan.
So let’s follow step by step to implement our requirement.
1.  Modify lead entity and add a new field let’s say “Created Day” of type Text and publish your changes.
2.  Once we have customized lead entity let’s create custom workflow assembly to find name of the day when lead is created.

Create project for Custom Workflow:

1.  Start Visual Studio and select New Project->Workflow->Activity Library
2.  Delete “Activity1.xaml” file.
3.  Right Click on project and select Add New->add a class and name it “LeadCreatedDay.cs”
4.  Right Click on project -> select properties and make sure Target Framework is “.Net Framework 4” under Application tab.
5.  Sign your assembly.
6.  Right Click on project and select Add Reference to add required assemblies to our project.
We need to add below Microsoft CRM 2011 SDK assemblies and .net assemblies
Microsoft.xrm.sdk
Microsoft.xrm.sdk.workflow
Microsoft.crm.sdk.proxy
System.Runtime.Serialization
C# Code:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Activities;
using Microsoft.Xrm.Sdk.Workflow;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Crm.Sdk.Messages;

namespace DayOfWeek
{
    public class LeadCreatedDay : CodeActivity
    {
        [Output("DayofWeek")]
        public OutArgument<String> DayofWeek { get; set; }

        protected override void Execute(CodeActivityContext Execution)
        {
            string Day = string.Empty;

            DateTime _Date = DateTime.MinValue;

            //get context

            IWorkflowContext context = Execution.GetExtension<IWorkflowContext>();

            //create iorganization service object

            IOrganizationServiceFactory serviceFactory = Execution.GetExtension<IOrganizationServiceFactory>();

            IOrganizationService service = serviceFactory.CreateOrganizationService(context.InitiatingUserId);

            //get created date of the lead

            Entity _lead = (Entity)service.Retrieve("lead", context.PrimaryEntityId, new ColumnSet(new string[] { "createdon" }));

            if (_lead.Contains("createdon"))
            {
                //get day of the week based on created on date
                Day = ((DateTime)_lead.Attributes["createdon"]).DayOfWeek.ToString();
            }
            //set value to output variable
            DayofWeek.Set(Execution, Day);
            if (Day == "Sunday")
            {
                Guid _UserID = GetUserID(service);

                Assignlead(service, context.PrimaryEntityId, _UserID);

            }
        }

        private Guid GetUserID(IOrganizationService service) //function to get userid
        {
            Guid _UserID = Guid.Empty;

            ConditionExpression condition1 = new ConditionExpression();

            condition1.AttributeName = "firstname";

            condition1.Operator = ConditionOperator.Equal;

            condition1.Values.Add("Suresh");

            ConditionExpression condition2 = new ConditionExpression();

            condition2.AttributeName = "lastname";

            condition2.Operator = ConditionOperator.Equal;

            condition2.Values.Add("Kumar");

            FilterExpression filter1 = new FilterExpression();

            filter1.Conditions.AddRange(condition1, condition2);

            QueryExpression query = new QueryExpression("systemuser");

            query.Criteria.AddFilter(filter1);

            EntityCollection EntityCol = service.RetrieveMultiple(query);

            if (EntityCol.Entities.Count > 0)
            {
                Entity _User = (Entity)EntityCol.Entities[0];

                _UserID = _User.Id;

            }

            return _UserID;

        }
        private void Assignlead(IOrganizationService service, Guid LeadID, Guid UserID)
        {

            AssignRequest _Assign = new AssignRequest()
            {

                Assignee = new EntityReference("systemuser", UserID),

                Target = new EntityReference("lead", LeadID)

            };

            service.Execute(_Assign);

        }
    }
}
Image for add steps for workflow when lead is created:

Follow the below image and add steps in your workflow when lead is created.

Don't remember to click on the Activate button.


Friday 26 April 2013

Add Custom View to lookup window when click on the "Add Existing Button"

Add the following script to the JS file (I borrowed the fetchXml and layoutXml combination from SDK document).
function addExistingFromSubGridCustom(params) {

    var relName = params.gridControl.getParameter("relName"),
        roleOrd = params.gridControl.getParameter("roleOrd"),
        viewId = "{00000000-0000-0000-0000-000000000001}"; // a dummy view ID
    
    var customView = {
        fetchXml: params.fetchXml,
        id: viewId, 
        layoutXml: params.layoutXml,
        name: "Filtered Lookup View",
        recordType: params.gridTypeCode,
        Type: 0
    };

    var lookupItems = LookupObjects(null, "multi", params.gridTypeCode, 0, null, "", null, null, null, null, null, null, viewId, [customView]);
    if (lookupItems && lookupItems.items.length > 0) {
        AssociateObjects(crmFormSubmit.crmFormSubmitObjectType.value, crmFormSubmit.crmFormSubmitId.value, params.gridTypeCode, lookupItems, IsNull(roleOrd) || roleOrd == 2, "", relName);
    }
}

function addExistingFromSubGridAccount(gridTypeCode, gridControl) {
    addExistingFromSubGridCustom({
        gridTypeCode: gridTypeCode,
        gridControl: gridControl,
        fetchXml: "<fetch version='1.0' " +
                       "output-format='xml-platform' " +
                       "mapping='logical'>" +
                   "<entity name='account'>" +
                   "<attribute name='name' />" +
                   "<attribute name='address1_city' />" +
                   "<order attribute='name' " +
                           "descending='false' />" +
                   "<filter type='and'>" +
                       "<condition attribute='ownerid' " +
                                   "operator='eq-userid' />" +
                       "<condition attribute='statecode' " +
                                   "operator='eq' " +
                                   "value='0' />" +
                   "</filter>" +
                   "<attribute name='primarycontactid' />" +
                   "<attribute name='telephone1' />" +
                   "<attribute name='accountid' />" +
                   "<link-entity alias='accountprimarycontactidcontactcontactid' " +
                                   "name='contact' " +
                                   "from='contactid' " +
                                   "to='primarycontactid' " +
                                   "link-type='outer' " +
                                   "visible='false'>" +
                       "<attribute name='emailaddress1' />" +
                   "</link-entity>" +
                   "</entity>" +
               "</fetch>",
        layoutXml: "<grid name='resultset' " +
                             "object='1' " +
                             "jump='name' " +
                             "select='1' " +
                             "icon='1' " +
                             "preview='1'>" +
                         "<row name='result' " +
                              "id='accountid'>" +
                           "<cell name='name' " +
                                 "width='300' />" +
                           "<cell name='telephone1' " +
                                 "width='100' />" +
                           "<cell name='address1_city' " +
                                 "width='100' />" +
                           "<cell name='primarycontactid' " +
                                 "width='150' />" +
                           "<cell name='accountprimarycontactidcontactcontactid.emailaddress1' " +
                                 "width='150' " +
                                 "disableSorting='1' />" +
                         "</row>" +
                       "</grid>"

    });
}
 
Customize CRM Ribbon to Hook up the JS Function
  1. In CRM, create a new solution, and add account entity (the entity in the sub-grid) to the solution.
  2. Export the solution to a .zip file, and extract the file somewhere in your local file system.
  3. Open the customizations.xml from the extracted file, and locate RibbonDiffXml section in the file, under the account entity.


          <RibbonDiffXml>
            <CustomActions />
            <Templates>
              <RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates>
            </Templates>
            <CommandDefinitions />
            <RuleDefinitions>
              <TabDisplayRules />
              <DisplayRules />
              <EnableRules />
            </RuleDefinitions>
            <LocLabels />
          </RibbonDiffXml>
  4. What we need to change is the CommandDefinitions part, which we can get the template code from applicationribbon.xml file (or <entityname>ribbon.xml if it's a system entity) in CRM SDK's resources\exportedribbonxml folder.
  5. In applicationribbon.xml file (or <entityname>ribbon.xml), locate <CommandDefinition Id="Mscrm.AddExistingRecordFromSubGridAssociated"> line (You can search by addExistingFromSubGridAssociated to get there).
  6. Copy the xml content under <CommandDefinition Id="Mscrm.AddExistingRecordFromSubGridAssociated"> (including itself and its closing tag as well) to the customizations.xml file, so it should look like this.
  7. Modify the JavaScriptFunction part to point to the custom JS function that we previously developed, so it should be something like this:


    The following is the final customization xml.
      <CommandDefinition Id="Mscrm.AddExistingRecordFromSubGridAssociated">
        <EnableRules>
          <EnableRule Id="Mscrm.AppendPrimary" />
          <EnableRule Id="Mscrm.AppendToPrimary" />
          <EnableRule Id="Mscrm.EntityFormIsEnabled" />
        </EnableRules>
        <DisplayRules>
          <DisplayRule Id="Mscrm.AddExisting" />
          <DisplayRule Id="Mscrm.ShowForManyToManyGrids" />
          <DisplayRule Id="Mscrm.AppendPrimary" />
          <DisplayRule Id="Mscrm.AppendToPrimary" />
          <DisplayRule Id="Mscrm.AppendSelected" />
          <DisplayRule Id="Mscrm.AppendToSelected" />
          <DisplayRule Id="Mscrm.CanWriteSelected" />
        </DisplayRules>
        <Actions>
          <JavaScriptFunction FunctionName="addExistingFromSubGridAccount" Library="$webresource:new_Project">
            <CrmParameter Value="SelectedEntityTypeCode" />
            <CrmParameter Value="SelectedControl" />
          </JavaScriptFunction>
        </Actions>
      </CommandDefinition>
    Note that your JS webresource name could be in different format. You can find out that by openning the web resource in CRM, which tells you the path to the web resource file.

  8. Save the file, and zip it back to the original solution export file.
  9. Import the solution file, and publish changes. If everything goes OK, you will see a filtered lookup like the following.