Friday, August 24, 2012

Set the CRM Form as Read Only in MS CRM 2011


function setFormAsReadOnly() {
    // define the logic here
    disableFormFields(true);
}

function doesControlHaveAttribute(control) {
    var controlType = control.getControlType();
    return controlType != "iframe" && controlType != "webresource" && controlType != "subgrid";
}

function disableFormFields(onOff) {

    Xrm.Page.ui.controls.forEach(function(control, index) {
        if (doesControlHaveAttribute(control)) {
            control.setDisabled(onOff);
        }
    });
}

Custom Button on CRM Form in MS CRM 2011


Create a text box. (or use any unsed field)
Place the field on the CRM Form.
Through the script convert them to a Button on the CRM Form.
Attach the OnCLick event to the Button.
Define your own custom logic on Button Click.


function CreateButton() {
    ConvertToButton('new_testbutton', 'New Button', '100px', OpenSearchPage, 'Button Label');
}


function ConvertToButton(fieldname, buttontext, buttonwidth, clickevent, title) {
    //check if object exists; else return
    if (document.getElementById(fieldname) == null) {
        return;
    }
    functiontocall = clickevent;
    crmForm.all[fieldname].DataValue = buttontext;
    crmForm.all[fieldname].readOnly = true;
    crmForm.all[fieldname].style.borderRight = "#3366cc 1px solid";
    crmForm.all[fieldname].style.paddingRight = "5px";
    crmForm.all[fieldname].style.borderTop = "#3366cc 1px solid";
    crmForm.all[fieldname].style.paddingLeft = "5px";
    crmForm.all[fieldname].style.fontSize = "11px";
    crmForm.all[fieldname].style.backgroundImage = "url(/_imgs/btn_rest.gif)";
    crmForm.all[fieldname].style.borderLeft = "#3366cc 1px solid";
    crmForm.all[fieldname].style.width = buttonwidth;
    crmForm.all[fieldname].style.cursor = "hand";
    crmForm.all[fieldname].style.lineHeight = "18px";
    crmForm.all[fieldname].style.borderBottom = "#3366cc 1px solid";
    crmForm.all[fieldname].style.backgroundRepeat = "repeat-x";
    crmForm.all[fieldname].style.fontFamily = "Tahoma";
    crmForm.all[fieldname].style.height = "20px";
    crmForm.all[fieldname].style.backgroundColor = "#cee7ff";
    crmForm.all[fieldname].style.textAlign = "center";
    crmForm.all[fieldname].style.overflow = "hidden";
    crmForm.all[fieldname].attachEvent("onmousedown", push_button);
    crmForm.all[fieldname].attachEvent("onmouseup", release_button);
    crmForm.all[fieldname].attachEvent("onclick", functiontocall);
    crmForm.all[fieldname].style.lineHeight = "14px";
    crmForm.all[fieldname + '_c'].style.visibility = 'hidden';
    crmForm.all[fieldname].title = title;
    window.focus();

    function push_button() {
        window.event.srcElement.style.borderWidth = "2px";
        window.event.srcElement.style.borderStyle = "groove ridge ridge groove";
        window.event.srcElement.style.borderColor = "#3366cc #4080f0 #4080f0 #3366cc";
    }

    function release_button() {
        window.event.srcElement.style.border = "1px solid #3366cc";
    }
}

function OpenSearchPage() {
    var features = "location=no,menubar=no,status=no,toolbar=no";
    // Open the window
    window.open("http://SearchPage.aspx"_blank", features, false);
}


Monday, August 20, 2012

CRM 2011 Online Fetch XML Reporting


Very informative post on CRM 2011 Online Fetch XML Reporting.

Getting Started with CRM 2011 Online Fetch XML Reporting

More details on Fetch-Xml based Reports

Tuesday, August 14, 2012

Secure / Unsecure Configuration of Plugin Registration tool in MS CRM 2011

Difference between Secure / Unsecure Configuration of Plugin Registration tool in CRM 2011

http://crmdm.blogspot.in/2011/06/difference-between-secure-unsecure.html
Very nice post. I had problem while using Secure Configuration for few users, so i used to change the user context in plugin registration as CRM admin. Was not aware of the route cause.



Thursday, August 2, 2012

Hide/Show CRM form navigation Items in MS CRM 2011


function setNavigationVisibility(navItem, value) {
    var navitem = Xrm.Page.ui.navigation.items.get(navItem);
    if (navitem == null) {
        return;
    }
    navitem.setVisible(value);
}

Hide Date part from CRM DateTime Field on CRM form in MS CRM 2011


function removeDateField(attribute) {
    document.getElementById(attribute).childNodes[0].childNodes[0].style.display = "none";
    document.getElementById(attribute).childNodes[0].childNodes[1].style.display = "none";
}

JS to Hide/Show CRM Tabs/Sections in MS CRM 2011



function HideShowSection(tabnumber, section, visible) {
    tabs = Xrm.Page.ui.tabs.get();
    sections = tabs[tabnumber].sections.get();
    sections[section].setVisible(visible);

}

function HideShowTab(tabnumber, visible) {
    Xrm.Page.ui.tabs.get(tabnumber).setVisible(visible);
}

CRM 2011 JS


// change CRM fields color to red
crmForm.all.name_c.style.color = "#FF0000";
// Get picklist value
Xrm.Page.getAttribute("<field Schema name>").getValue();

// Get picklist selected text
Xrm.Page.getAttribute("<field Schema name>").getSelectedOption().text;

// Set picklist value
Xrm.Page.getAttribute("<field Schema name>").setValue("<set Int value>");
// Set picklist value to blank
Xrm.Page.getAttribute("<field Schema name>").setValue(null);
// Disable CRM field
Xrm.Page.getControl('<field Schema name>').setDisabled(true);
// set CRM field as required
Xrm.Page.getAttribute("<field Schema name>").setRequiredLevel("required");
// remove required level of the CRM form filed
Xrm.Page.getAttribute("<field Schema name>").setRequiredLevel("none");
// Hide CRM form Field
crmForm.all.<field Schema name>_c.style.display = 'none';
crmForm.all.<field Schema name>_d.style.display = 'none';

// force submit a field on save of the form
Xrm.Page.getAttribute("<Field Schema Name>").setSubmitMode("always");

// Set lookup value to a field
function SetLookupValue(fieldName, id, name, entityType) {
    if (fieldName != null) {
        var lookupValue = new Array();
        lookupValue[0] = new Object();
        lookupValue[0].id = id;
        lookupValue[0].name = name;
        lookupValue[0].entityType = entityType;

        Xrm.Page.getAttribute(fieldName).setValue(lookupValue);
    }
}

Get Entity details in Merge Plugin in MS CRM 2011



public void Execute(IServiceProvider serviceProvider)
{
    // Obtain the execution context from the service provider.
    IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
    IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

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

    Guid winnerEntityid = Guid.Empty;
    Guid looserEntityId = Guid.Empty;

    // The InputParameters collection contains all the data passed in the message request.
    if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is EntityReference)
    {
             
                EntityReference winnerEntityLookup = (EntityReference)context.InputParameters["Target"];
                winnerEntityid = winnerEntityLookup.Id;

                if (context.InputParameters.Contains("SubordinateId"))
                    looserEntityId = new Guid(context.InputParameters["SubordinateId"].ToString());
                       
                // write you logic here
     }
}

Share/Un-share bulk records in CRM


CRM has a feature where we can share bulk records with users at one time. But if we have achieved the same in some automation process, CRM service will not respond (or it will take more time, CRM may stop working for some time).  

I had a similar requirement like when sale rep moves from one city to another provide him/her the access of all records belongs to the new city and unshared all records were shared with him/her before. To achieve the same I wrote an SQL query to do the same. 


Declare @SystemUser nvarchar(100)
Declare @ObjectId nvarchar(100)
DECLARE @Count INT

set @SystemUser = (select systemuserid from systemuser where Name ='CRM sales Rep')

declare Cur_SHAREWITHUSER  cursor for 
Select accountId from account where Account.Address1_City = 'Bangalore'

open Cur_SHAREWITHUSER 
fetch Cur_SHAREWITHUSER  into @ObjectId
while(@@fetch_status=0)
BEGIN
SET @Count = 0
SET @Count = (SELECT COUNT(1) FROM PrincipalObjectAccess WHERE  ObjectId = @ObjectId AND PrincipalId = @SystemUser)
IF(@Count >0)
BEGIN
UPDATE PrincipalObjectAccess 
SET AccessRightsMask= 23, -- define access level 
InheritedAccessRightsMask=134217751,
ChangedOn = GETUTCDATE()
WHERE ObjectId = @ObjectId AND PrincipalId = @SystemUser
END
ELSE 
BEGIN
INSERT INTO PrincipalObjectAccess  
(Principalid,ObjectId,ObjectTypeCode,[PrincipalTypeCode],[AccessRightsMask],ChangedOn,
[InheritedAccessRightsMask] ,PrincipalObjectAccessId )
values (@SystemUser , @ObjectId ,1,8,23,GETDATE(),134217751,NEWID())
END 
fetch Cur_SHAREWITHUSER  into @ObjectId
END 


close Cur_SHAREWITHUSER 
deallocate Cur_SHAREWITHUSER 

Create offline filters for Custom Entity for each user in MS CRM 2011


In almost every CRM implementation we create custom entities. When user goes offline we need to create the offline filters for all the custom entities user wants to take in offline. To achieve this either we train users to create the offline filters or we create some package to do the same.

I achieve the same by creating offline filters in database by inserting new entry in UserQuery for each user for each custom entity.  Below find the Query. 

Declare @UserId nvarchar(100)
declare @OwningBusinessUnit nvarchar(100)
DECLARE @FetchXml nvarchar(max)
Declare @Description nvarchar(100)
Declare @Name nvarchar(100)
Declare @ObjectTypeCode int 

set @FetchXml ='<fetch version="1.0"
mapping="logical" output-format="xml-platform"><entity
name="new_salesgroup"><attribute name="new_salesgroupid" /><filter type="and"><condition attribute="statecode" operator="eq" value="0"
/></filter></entity></fetch>'

set @Description = 'Sales Groups owned by me'
set @Name = 'My Sales Groups'
select @ObjectTypeCode = ObjectTypeCode from EntityView where name='new_salesgroup'

declare cur_accounts cursor for
select SystemUserId from SystemUser where FullName not in ('SYSTEM','INTEGRATION')

open cur_accounts
fetch cur_accounts into @UserId
while (@@FETCH_STATUS =0)
begin
if not exists (select * from UserQueryBase where QueryType = 16 and FetchXml = @FetchXml and StateCode = 0 and Name=@Name and OwnerId = @UserId)
begin
select @OwningBusinessUnit=BusinessUnitId from SystemUser where SystemUserId = @UserId
Insert into UserQueryBase (QueryType,ModifiedOn,ModifiedBy,FetchXml,Description,StateCode,UserQueryId,Name,CreatedBy,ReturnedTypeCode,
OwningBusinessUnit,CreatedOn,OwnerId,OwnerIdType)
values (16, GETUTCDATE(),@UserId,@FetchXml,@Description,0, NEWID(),@Name,@UserId,@ObjectTypeCode,@OwningBusinessUnit,GETUTCDATE(),@UserId,8)
end
fetch cur_accounts into @UserId
end

close cur_accounts
deallocate cur_accounts

Force user to use CRM form for task, email appointment and contact for outlook in MS CRM 2011


Just execute below Query in CRM database, it will update the user settings for all user to use CRM form for task, email appointment and contact in outlook client for CRM.

UPDATE UserSettings 
SET UseCrmFormForTask=1, UseCrmFormForAppointment=1, UseCrmFormForContact=1, UseCrmFormForEmail=1 

Stop Outlook Contact Synchronization with MS CRM 2011

Just execute below Query in CRM database, it will stop outlook contact to sync with CRM.


update userquery set StateCode = 1
where QueryType = 256
and ReturnedTypeCode=2;

Get all user/team an object (account/contact/lead) is shared with in MS CRM 2011

Get all user/team an object (account/contact/lead) is shared with using OrganizationService service.

public void ProcessSharedUser()
        {
            PrincipalAccess[] sharedUsersOfAccount = getSharedUsersforAccount("account", accountId, service);
            if (sharedUsersOfAccount.Length > 0)
            {
                for (int i = 0; i < sharedUsersOfAccount.Length; i++)
                {
                    Guid user = sharedUsersOfAccount[i].Principal.Id;
                    // define your logic here
                }
            }
        }
        public PrincipalAccess[] getSharedUsersforAccount(string entityName, Guid accountId, IOrganizationService service)
        {
            RetrieveSharedPrincipalsAndAccessRequest retrieveSharedRequest = new RetrieveSharedPrincipalsAndAccessRequest()
            {
                Target = new EntityReference(entityName, accountId)
            };
            RetrieveSharedPrincipalsAndAccessResponse retrieveSharedResponse = (RetrieveSharedPrincipalsAndAccessResponse)service.Execute(retrieveSharedRequest);

            return retrieveSharedResponse.PrincipalAccesses;
        }