Rich Text Fields in Dynamics 365 and Model Driven Power Apps

 If you want to be able to use rich text (including adding inline tables and images) in your text area fields in Dynamics 365 or your Model Driven Power App, you can now do that using the out of the box Rich Text Editor component. In this post, I’ll take you through step-by-step instructions on how to set this up.

What does the Rich Text Editor allow you to do?

Here’s the end result – on the right of the screenshot below, I have added a text area field in Dynamics 365, with the Rich Text Editor component applied. You can see that you can add a variety of formats, including bold / italic / underline, change the color of the font, add highlighting, inline images, inline tables and more.

My example here shows this component in Dynamics 365 Sales, but you can do exactly the same thing in a Model Driven Power App (it’s all the same underneath, after all!)

How do I add this awesome component?

It’s not hard to do, but you do need to go into the Classic solution designer to find it, so it’s a little hidden away.

Navigate to https://make.powerapps.com

Select the entity you are working with from your Data menu, and click +Add field

Create a new field with data type: Text Area. Then open the Advanced options section.

Scroll down to find the Max length option. This sets your field character length (the default is 100, which isn’t enough to work with!). Set this to 4,000 (this is the maximum). Then click Done to create the field.

Save your entity.

Now open the Form where you want to add that field.

Inside the Form Editor, find the field you just created and add it to your Form. You might want to put it in a new section, or a new tab.

In the Formatting options, increase the Field Height (by default it’s only one line, and you’ll certainly want more than that!) You can come back and play around with the size and positioning later if you need to, depending on how much space you want for the field. If you want to use inline images, I suggest giving your field plenty of space on the form.

Click Save and then Publish, to save and publish your changes. Once that is done, click on the Switch to Classic option. You may get a pop up asking for feedback – you can just click Skip.

This will open the Classic solution designer in a new browser tab. This is the legacy app maker experience that we still need to switch back to occasionally for more advanced features. One day this will be gone! If you’re not familiar with this interface, it will be a little disorienting. You will find the field you just created on the form in the same place – it’s just more like looking at a skeleton view!

Double click on that field to open it for editing. (Click on the white field part, rather than the field name). This will pop up a Field Properties box. Select the Controls tab.

Select the Rich Text Editor and click Add.

Select all the radio buttons in the Rich Text Editor Control to make this the default display / control for this field across all device types. Then click OK

You will have more space for your Rich Text editor by putting the field name above the field, rather than to the left of it. To do this, click in the section where your field is.

Select the Formatting tab and scroll down to find the Field Label Position options. Set the field label position to Top, then click OK.

You’re all done! Now click the Save button, give it a few seconds to save, and then click the Publish button.

You’ll see this pop up message to confirm your changes are being published.

You can now close this tab. You’re all done. If you want to make any other changes to the size, height or positioning of the field, you can do that back in the Power Apps maker experience, where you started.

Now go back to your app, refresh your browser to pick up published changes, and you will see your rich text field ready to use!


Filter Option Set depending on another option set values by using java script in D365 CRM

I have filter option set by using another option set values with java script.


function OptionSetValuesAddRemove(executionContext)
{
     
    formContext = executionContext.getFormContext();
    
    var independentOptionSet = formContext.getAttribute("new_independentoptionset").getValue()
 
    var dependentOptionSet = formContext.ui.controls.get("new_dependentoptionset");
    var optionSetValues = dependentOptionSet.getAttribute().getOptions();
 
    dependentOptionSet.clearOptions();
 
    optionSetValues.forEach(function (element)
    {
 
       if (independentOptionSet == "100000000") {
            if (element.value == 100000013)
                dependentOptionSet.addOption(element);
        }
       
        if (independentOptionSet == "100000002") {
            if (element.value == 100000013)
                dependentOptionSet.addOption(element);
        }
        if (independentOptionSet == "100000006") {
            if (element.value == 100000013)
                dependentOptionSet.addOption(element);
        }
     
        if (independentOptionSet == "100000000") {
            if (element.value == 100000013)
                dependentOptionSet.addOption(element);
        }
        
        
    }
    );
}

To get Attachment details by using java script in d365

In Dynamics 365 CRM, To retrieve the attachments field name,type and Url by using javascript

Step 1: 
function GetName(executioncontext) 
{
var formcontext=executioncontext.getFormComtect();
var file= formcontext.getAttribute("new_attachment").getValue();

var view=file.fileUrl;
var attachment=file.fileName;
var attachments=file.mimtype;


var attach=attachments.split('/')[0];
if( attach== "image")
{
formcontext.getAttribute("new_attachmenttype").setValue("Image");
}
if( attach== "application")
{
formcontext.getAttribute("new_attachmenttype").setValue("Document");
}
if( attach== "video")
{
formcontext.getAttribute("new_attachmenttype").setValue("Video");
}
if( attach== "text")
{
formcontext.getAttribute("new_attachmenttype").setValue("Document");
}

}

Step 2: To get name and file type.

var attachments=file.mimtype;

We can get the file type.

Step 3: To get Url

var view=file.fileUrl;


Step 4: To split the file type.  I have used split.

var file= formcontext.getAttribute("new_attachment").getValue();

var attachments=file.mimtype;

var attach=attachments.split('/')[0];

 





Open entity modal popup in D365 CRM.

Now we can open Entity record as a popup. Here is the piece of code and it is supported only for opening records in the system. Try below.

Xrm.Navigation.navigateTo({
        pageType: "entityrecord",
        entityName: "contact",
        formType: 2, // Only Edit Mode is supported now. 
        formId: " ",
        entityId: " "
    }, {
        target: 2,
        position: 1,
        width: 700,
        height: 600
    });

Insert, update, delete, and order global option set options

How to Modify value of optionset by code C#?



DeleteOptionValueRequest deleteOptionValueRequest =
    new DeleteOptionValueRequest
{
    OptionSetName = _globalOptionSetName,
    Value = _insertedOptionValue
};

// Execute the request. svc.Execute(deleteOptionValueRequest);



Another method

UpdateOptionValueRequest updateOptionValueRequest =
    new UpdateOptionValueRequest
    {
        OptionSetName = _globalOptionSetName,
        // Update the second option value.
        Value = optionList[1].Value.Value,
        Label = new Label("Updated Option 1", _languageCode)
    };

_serviceProxy.Execute(updateOptionValueRequest);

Add html Tables while sending emails through custom workflow

I have created a custom workflow send email with table format dynamically in Dynamics CRM.

Email
My requirement is to create a html table and attach data dynamically.


Step1: First, I approached by query expression to get the data and total count.

           QueryExpression queryAccounts = new QueryExpression("entity");
            queryAccounts.ColumnSet = new ColumnSet(true);
            queryAccounts.ColumnSet = new ColumnSet(new String[] { "createdon", "subject", "statecode", "scheduledend", "createdby", "description" });
            queryAccounts.Criteria.AddCondition("subject", ConditionOperator.NotNull);
            queryAccounts.Criteria.AddCondition("statecode", ConditionOperator.Equal, 0);
            queryAccounts.Criteria.AddCondition(new ConditionExpression("createdby", ConditionOperator.In, values));

            EntityCollection collAccounts = service.RetrieveMultiple(queryAccounts);
            int count = collAccounts.Entities.Count();

Step2: Based on count, I started using stringbuilder format, To create html table in email body section.

                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.Append("<HTML><Head>");
                stringBuilder.Append("</head><body style='font-family:verdana'>");
                stringBuilder.Append("Dear Owner");
                stringBuilder.Append("<br/> Below are the list of this week.<br/><br/>");
                stringBuilder.Append("<Table border='1' cellspacing='0' cellpadding='3' style='width:100%; font-family:Segoe UI'>");
                stringBuilder.Append("<tr><th>Task Subject</th><th>Description</th><th>Due Date</th> </tr>");

                foreach (Entity entity in collAccounts.Entities)
                {
                //Based on your reqirements
                }

                stringBuilder.Append("</table>");
                stringBuilder.Append("</body>");
                stringBuilder.Append("</html>");

Step3: To send email without creating from and to emils dynamics by customworkflow. I have approached by using "activityparty" and "partyid" in my custom workflow and attached the strinbuilder in description


                Entity Fromparty = new Entity("activityparty");
                Fromparty.Attributes.Add("partyid", new EntityReference("systemuser", workflowContext.UserId));
                Entity Toparty = new Entity("activityparty");
                Toparty.Attributes.Add("partyid", new EntityReference("systemuser", erfUser.Id));

                Entity entity6 = new Entity("email");
                entity6["from"] = new Entity[] { Fromparty };
                entity6["to"] = new Entity[] { Toparty };
                entity6["subject"] = "Open task till today";
                entity6["description"] = Convert.ToString(stringBuilder); //stringBuilder.ToString();

                Guid guid = service.Create(entity6);

To send email by token,emailId. We used SendEmailRequest() and SendEmailResponse.
                SendEmailRequest req = new SendEmailRequest();
                req.EmailId = guid;
                req.TrackingToken = "";
                req.IssueSend = true;
                SendEmailResponse sendEmailResponse = (SendEmailResponse)service.Execute(req);

Change label format in Charts

In Dynamics CRM 365, We change the Label formats by using some logic.

Here, I have created a little cheat sheets, so i can find the change with different cheats.

I have used LabelFormat and Format . I have used for values displyed in charts.

Before:                                                             After:
 

We have downloaded the xml file and made changes in label format.

Attach SSRS report Pdf and Attach to Notes in CRM form

In Dynamics CRM 365 online, We have a requirement to attach create dynamics ssrs report through javascript and attach to notes.

I have a create custom ssrs report and attached to CRM.

Step1: Get the name and id of custom report and also fetchxml to create a custom reports. Like name.rdl, ID.

var reportName = "LeadReports.rdl";  //Name.rdl
var reportGuid = "664741B6-D356-E911-A822-000D3A315BF6"; //Id of your lead report

Step2: Based on your requirements, create a path with custom report and ID.


var number = Xrm.Page.getAttribute("subject").getValue();
if(number != null)
{
var params = getReportingSession(); 
var newPth = Xrm.Page.context.getClientUrl() + "/Reserved.ReportViewerWebControl.axd?ReportSession=" + params[0] + "&Culture=1033&CultureOverrides=True&UICulture=1033&UICultureOverrides=True&ReportStack=1&ControlID=" + params[1] + "&OpType=Export&FileName=" + number+ "&ContentDisposition=OnlyHtmlInline&Format=PDF";
window.open(newPth, "_self");
encodePdf(params);
}
else
{
alert("Lead ID is Missing");
}


Step3:  Change your fetchxml as per your requirement along with ID, logical name of entity. In below logic we get url of ssrs reports, reportguid, reportname and along with parameters of fetchxml will be retrieved. We convert  responseText into array.

        var recordId = Xrm.Page.data.entity.getId();
recordId = recordId.replace('{', '').replace('}', '');

var strParameterXML = "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'><entity name='lead'><all-attributes /><filter type='and'><condition attribute='leadid' operator='eq' value='" + recordId + "' /> </filter></entity></fetch>";

   
var pth = Xrm.Page.context.getClientUrl() + "/CRMReports/rsviewer/QuirksReportViewer.aspx";
var retrieveEntityReq = new XMLHttpRequest();
retrieveEntityReq.open("POST", pth, false);
retrieveEntityReq.setRequestHeader("Accept", "*/*");
retrieveEntityReq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
retrieveEntityReq.send("id=%7B" + reportGuid + "%7D&uniquename=" + Xrm.Page.context.getOrgUniqueName() + "&iscustomreport=true&reportnameonsrs=&reportName=" + reportName + "&isScheduledReport=false&p:CRM_lead=" + strParameterXML);

var x = retrieveEntityReq.responseText.lastIndexOf("ReportSession=");
var y = retrieveEntityReq.responseText.lastIndexOf("ControlID=");

var ret = new Array();
ret[0] = retrieveEntityReq.responseText.substr(x + 14, 24);
ret[1] = retrieveEntityReq.responseText.substr(x + 10, 32);
return ret;

Step4:
In below, we convert the ssrs report into PDF conversion by using bytes by passing the above parameters

var retrieveEntityReq = new XMLHttpRequest();
var pth = Xrm.Page.context.getClientUrl() + "/Reserved.ReportViewerWebControl.axd?ReportSession=" + responseSession[0] + "&Culture=1033&CultureOverrides=True&UICulture=1033&UICultureOverrides=True&ReportStack=1&ControlID=" + responseSession[1] + "&OpType=Export&FileName=Public&ContentDisposition=OnlyHtmlInline&Format=PDF";

retrieveEntityReq.open("GET", pth, true);
retrieveEntityReq.setRequestHeader("Accept","*/*");
retrieveEntityReq.responseType = "arraybuffer";
retrieveEntityReq.onreadystatechange = function ()
{

if (retrieveEntityReq.readyState == 4 && retrieveEntityReq.status == 200)
{
var binary = "";
var bytes = new Uint8Array(this.response);
for (var i = 0; i < bytes.byteLength; i++)
{
binary += String.fromCharCode(bytes[i]);
}
var bdy = btoa(binary);
createNote(bdy);
}
};
retrieveEntityReq.send();


Step5: Based on my requirement, I want to add pdf into notes in the CRM Form.
I have created pdf and and named it by "subject.pdf" and attached to "Annotation" "Notes" by using SDK.Create();

var note = {};
var recordId = Xrm.Page.data.entity.getId();
recordId = recordId.replace('{', '').replace('}', '');
var inumber= Xrm.Page.getAttribute("subject").getValue();


var refInvoice = new Object();
refInvoice.LogicalName = "lead";
refInvoice.Id = recordId;
note.ObjectId = refInvoice;
note.ObjectTypeCode = refInvoice.LogicalName;

note.Subject = "lead: " + inumber;
note.MimeType = "application/pdf";
note.DocumentBody = data;
note.FileName = invoicenumber + ".pdf";

SDK.REST.createRecord(note,"Annotation",function (result) {
alert("Note Created");
Xrm.Page.data.refresh(false);
},
function (error) {
alert(error.message);
},true);


Switch Business process flow through java script in Dynamics 365 CRM

In my dynamics 365 CRM, version 9+ and above.
The update of java script to switch business process flows.
We should use Executioncontext.
As per my requirement, I have done as onsave event.

Synatx:
function OnsaveForm(Executioncontext)
{
var formcontext = Executioncontext.getFormContext();
var processId1="";
var processId2="";
if(Xrm.Page.getAttribute("attributen").getValue() != null)
{
formContext.data.process.setActiveProcess(processId1, callbackFunction);
}
else
{
      formContext.data.process.setActiveProcess(processId2, callbackFunction);
}
}
function callbackFunction(response)
{
if (response == "success")
{
alert("BPF changed !!!");
}
else
{
alert("Error changing BPF!!!");
}
}

After binding the java script, we should enable the "Pass Execution Context as first parameters".



Counting Total number of records retrived by Fetch Xml using Custom workflow


We have done a custom workflow by using fetchxml to get the count of total opened tasks in CRM instance.

Script: 
protected override void Execute(CodeActivityContext context)
{
ITracingService tracingService = context.GetExtension<ITracingService>();
IWorkflowContext workflowContext = context.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory =       context.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(workflowContext.UserId);

String query = @"<fetch version='1.0' mapping='logical' distinct='false' >
<entity name='task'>
<attribute name='subject' />
<attribute name='createdby' alias='countAlias' />
<order attribute='subject' descending='false' />
<filter type='and'>
<condition attribute='statecode' operator='eq' value='0' />
</filter>
</entity>
</fetch>";

FetchExpression fetch = new FetchExpression(query);
EntityCollection results = service.RetrieveMultiple(fetch);
int count = results.Entities.Count; //show this in your message box;
this.count.Set(context, count);

var countname = ((AliasedValue)count.["createdby"]).Value;
systemuser.Set(context, countname);
}
       [Output("Count")]
public OutArgument<int> count { get; set; }

}

}





JavaScript in OData portals

We have done odata services in CRM Portals to achieve through java script.


Step 1: Enable the portal entity list(Contact,Account,etc)
Go to Portal > Entity List. Create a new Entity List for Case Entity.

Step2: Enable Odata feed with entity type and views also in entity list


Step3: Now, To retrieve the data, Hit the URL in browser.
URL : Portal_URL/_odata  
      URL : Portal_URL/_odata/Entity_Set_Name : To retrieve the data
Here we can see the <atom:title type=”text”>Cases</atom:title>

Step4: Upload your JavaScript in your respective “entity form”.
Below script :
if (window.jQuery) {
   (function ($) {
      $(document).ready(function () {
         if (typeof (Page_Validators) == 'undefined') return;
         // Create new validator
         var newValidator = document.createElement('span');
         newValidator.style.display = "none";
         newValidator.id = "titleValidator";
         newValidator.controltovalidate = "title";
         newValidator.errormessage = "<a href='#title_label'>This Case has been already generated.</a>";
         newValidator.validationGroup = ""; // Set this if you have set ValidationGroup on the form
         newValidator.initialvalue = "";
         newValidator.evaluationfunction = function () {
       var count =   GetCase();
               if (count > 0 )
              return false;   // Return false mean apply validation.
             else
              return true;   // Return true mean successful.        
         };
         // Add the new validator to the page validators array:
         Page_Validators.push(newValidator);
         // Wire-up the click event handler of the validation summary link
         $("a[href='#title_label']").on("click", function () { scrollToAndFocus('title_label','title'); });
      });
   }(window.jQuery));
}
function GetCase(){
  var count = 0;
  var title=$("#title").val();
$.ajax({
    type: "GET",
    contentType: "application/json; charset=utf-8",
    datatype: "json",
    url: "~/_odata/Cases?$filter=title eq '"+title+"'",
    beforeSend: function(XMLHttpRequest) {
        XMLHttpRequest.setRequestHeader("Accept", "application/json");
    },
    async: false,
    success: function(data, textStatus, xhr) {
     count = data.value.length;       
    },
    error: function(xhr, textStatus, errorThrown) {
        Xrm.Utility.alertDialog(textStatus + " " + errorThrown);
    }
});
return count;
}


Step5: If duplicate case is created then it will show you like “This Case has been already generated.” Please refer to below screenshot.


To get the Dialog Popup box through html on entity form in Dynamics 365 CRM

We have requirement in Dynamics CRM to get dialog popup box through html.
To get the html

<html><head>
<title> Account Type</title>
<script src="ClientGlobalContext.js.aspx"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script language="javascript" type="text/javascript">
//To get parent form data on popup write logic
function GetAllAccountsRecords()
{
//custom logic
}
function btnSubmit()
{
           //on submit button perform action
  var crmWindow = parent.Alert.getCrmWindow();
     
          //write here to perform action on submit button

parent.$("#alertJs-wrapper").hide();
}

</script>
</head><body onload="GetAllAccountsRecords()">
<br><p>Please, select data.</p><br>
 <br>
<input onclick="btnSubmit();" value="Submit" style="height: 24px;font-family: Segoe UI,Tahoma,Arial;border: 1px solid #C6C6C6;   background-image: none;margin-top: 10px; width: auto !important; min-width: 80px;white-space: nowrap; color: #444444; background-color: #FFFFFF" type="Button">
</body>
</html>

To get lookup details through Plugin in Dynamics Crm

We did a plugin to get lookup reference and set the data in current form. Plugin on post operation,
Update method.

        // Obtain the target entity from the input parameters.
Entity entity = (Entity)context.InputParameters["Target"];
try
{
// Refer to the lead entity .
if (entity.LogicalName == "lead")
{
if (entity.Attributes.Contains("parentcontactid"))

//to get data of lookup we used entityrefernce
var currency = ((EntityReference)(entity.Attributes["parentcontactid"]));
var actualCurrency = service.Retrieve(currency.LogicalName, currency.Id, new ColumnSet(true));
var currencyName = actualCurrency["firstname"].ToString();
var last = actualCurrency["lastname"].ToString();
//throw new InvalidPluginExecutionException("The contact123" + last);
entity.Attributes["firstname"] = currencyName;
//throw new InvalidPluginExecutionException("The contact" + entity["firstname"]);
entity.Attributes["lastname"] = last;
}
}
// Obtain the organization service reference.
service.Update(entity);
}
catch (FaultException<OrganizationServiceFault> ex)
    {
throw new InvalidPluginExecutionException("Howdy! error occurred" +ex.Message);
}
}

To get more than 50 records through ODATA Services

In Dynamics CRM, There is a page limit of 50 records through Odata services. To increase that we should use paging to get more than 50+ records.

//To get account records through Odata services

relatedAccounts = [];

function GetAllAccountsRecords() {
debugger;
    var serverUrl = Xrm.Page.context.getClientUrl();
    var oDataUri = serverUrl + "/xrmservices/2011/OrganizationData.svc/AccountSet?$select=AccountId,Name";
    GetRecords(oDataUri);
    var totalRecords = relatedAccounts.length;
   //alert("Total records :" +totalRecords);


}
 //Calling Odata
function GetRecords(url) {
    $.ajax({
        type: "GET",
        contentType: "application/json; charset=utf-8",
        datatype: "json",
        url: url,
        async: false,
        beforeSend: function (XMLHttpRequest) {
            XMLHttpRequest.setRequestHeader("Accept", "application/json");
        },
        success: function (data, textStatus, XmlHttpRequest) {
            if (data && data.d != null && data.d.results != null) {
                AddRecordsToArray(data.d.results);
                FetchRecordsCallBack(data.d);
}
        },
        error: function (XmlHttpRequest, textStatus, errorThrown) {
            alert("Error :  has occured during retrieval of the records ");
        }
    });
}
//To get more records through Odata services
function AddRecordsToArray(records) {
    for (var i = 0; i < records.length; i++) {
        relatedAccounts.push(records[i]);
  }
}
//To get next page records through Odata services
function FetchRecordsCallBack(records) {
    if (records._next != null) {
        var url = records._next;
        GetRecords(url);
    }
}
//end of Odata services

Display all fields read only in Dynamics CRM Forms


We used javascript to make all fields read only in the MS CRM Forms. We bind the script and on Form "onload event". After "save&Publish" the form.


 function disableAllFields()
 {
   debugger;
    Xrm.Page.ui.controls.forEach(function (control, i) {
    if (control && control.getDisabled && !control.getDisabled()) {
             control.setDisabled(true);
             alert("Hi");
}
        });
 }

we displayed all read only fields in the form

Remove New Registration Process completely from Microsoft CRM Portal


Microsoft CRM Portal allows organizatioon to set up their portal with minimal steps.


When we install the Portal Add-on, the registration process will be enabled by default. The Users can see the 'Registration' page when they click on 'Sign-In ' as shown in below screenshot.

Steps to remove the Registration Process in Microsoft CRM Portal:

Step1: To eliminate the registration process, we can use ‘Authentication/Registration/Enabled’ site setting.
   
  Goto Portals-> Site setting.

Step2: First, we have to create a Site Setting entity record with Name ‘Authentication/Registration/Enabled’ and set the value to false. This setting will completely remove the Registration process from the Portal.



Step3: As seen in the above screenshot, the Register and Redeem Invitation tab has disappeared. 
This setting will not allow users to browse the Register Page URL and the https://<PortalURL>/Account/Login/Register URL is not accessible.

https://<PortalURL>/Register is not accessible.