[ISSUE] Dynamics 365 - Advanced Find: One column doesn't show value, but shows in exported excel report

Issue:

   Dynamics 365 - Advanced Find:  One column doesn't show value, but shows in exported excel report.

   For example, below is an Invoice list, the red circled column below "Acutual Revenue(Base) (Opportunity)"  is supposed to show values instead of vacant.

   In exported excel report, this column shows values normally.



   


Reason:

    Unfortunately, I have no idea.

Solution:

    After adding one more column "Acutual Revenue (Opportunity)", the column "Acutual Revenue(Base) (Opportunity)" shows normally.


Free!!! Microsoft Dynamics 365 Fundamentals (CRM) certification

 Microsoft


Microsoft Dynamics 365 Virtual Training Day:
Fundamentals (CRM)

Microsoft Dynamics 365 Virtual Training Day: Fundamentals (CRM)

 

 

 

Learn about the customer relationship management (CRM) capabilities of Dynamics 365 at Microsoft Dynamics 365 Virtual Training Day: Fundamentals (CRM). Join us for this free virtual training event to learn more about the essentials of CRM sales, service, and marketing. You’ll explore how these facets work together to connect customer data, streamline business processes, and help you better manage your client relationships.

After completing this training, you’ll be eligible to take the Microsoft Dynamics 365 Fundamentals (CRM) certification exam at no cost.

You will have the opportunity to:

Join us at an upcoming virtual event:



Delivery Language: English
Closed Captioning Language(s): English

 

 

 

 

 

 

 

 

Didn’t see a date that works for you? Explore more upcoming events.

 

 

Unsubscribe / Se désabonner | Privacy Statement / Déclaration de confidentialité

 

Microsoft Canada
Suite 4400
81 Bay Street
Toronto, ON M5J 0E7 Canada

 

Microsoft




Dynamics 365 CRM Show/Retrieve Data of Grandparent Record

Requirement:

    We have a construct like entity1 - 1:n - entity2 - 1:n - entity3, and want to display data from entity1 in entity3 (form or list). 

Example:

     Opportunity 1:n Account

     Account 1:n Contact (Primarry Contact)

     Opportunity  no relationship with Contact (Primary Contact)

     So using Dynamics 365 CRM Advanced Find cannot retrieve fields of Contact to Opportunity list.

Solution:

      XrmtoolBox + FetchXML

  1. XML:     Download

      <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">

  <entity name="opportunity">

    <attribute name="name" />

    <attribute name="parentaccountid" />

    <filter type="or">

      <condition attribute="statecode" operator="eq" value="1" />

      <condition attribute="statecode" operator="eq" value="2" />

    </filter>

    <filter type="and">

      <filter>

        <condition attribute="actualclosedate" operator="last-x-months" value="8" />

      </filter>

    </filter>

    <order attribute="name" descending="false" />

    <link-entity name="account" from="accountid" to="customerid">

      <attribute name="primarycontactid" />

      <link-entity name="contact" from="contactid" to="primarycontactid">

        <attribute name="emailaddress1" />

      </link-entity>

    </link-entity>

  </entity>

</fetch>



     Result:



2. XrmToolBox:

  • FetchXML Builder:   Create XML

   

  • Export To Excel:   Export retrieve report to excel spreadsheet, work with FetchXML Builder




Switch Form Type Conditionally Using JavaScript(JS) in Dynamics 365

 In Dynamics 365, sometimes it could be a little overwhelming for some users to switch to the correct form when there are many types of forms for a specific entity(table).

For example, if the form type could be switched automatically when CUSTOMER filed value is changed, below JS could be your reference.

Applied Version:

  • Microsoft Dynamics 365 (on-premises) v9.0 or later
  • Microsoft Dynamics 365 Online

Trigger scenerio:

1. Form - Load

2. Filed: CUSTOMER - Changed

Sample Code:

function SwitchFormByCustomerLevel(executionContext)
{
    var form = executionContext.getFormContext();
    var formOpType = form.ui.getFormType();
   
    // variable to store the name of the form
    var FormShowType;

    debugger;
   
    // get the customer level picklist field
    var customerLevel = form.getAttribute("field_Customer_Level").getText();
    if(customerLevel == null )
    {
            return;
    }


    // switch statement to assign the form to the picklist value
    //change the switch statement based on the customer level picklist values
    switch (customerLevel)
    {        
        case "Gold":
            FormShowType = "Form - Gold";
            break;

        case "Silver":
            FormShowType = "Form - Silver";
            break;
           
        case "VIP":
            FormShowType = "Form - VIP";
            break;
                   
        default:
            //Assume Form Name is same with Product Type Name
            FormShowType = customerLevel;
    }

    // Current form's label
    var CurrentFormLabel = form.ui.formSelector.getCurrentItem().getLabel();

    //check if the current form is the form supposed to be displayed
    if (CurrentFormLabel != FormShowType)
    {
        var items = form.ui.formSelector.items.get();

        if (items == null)
        {
            console.log("Could Not Find Form List");
            return;
        }

        for (var i in items)
        {
            var item = items[i];
            var itemId = item.getId();
            var itemLabel = item.getLabel()

            if (itemLabel == FormShowType)
            {                    
                //navigate to the form
                item.navigate();
                break;
            } //endif
        } //end for    
    } //endif      
} //end function

Date/Time Columns(Fields) Error when Import Data File into Dynamics 365 from EXCEL(CSV)

When I tried to import an Invoice data into Dynamics 365,  I got a failure " The date/time format is not valid, or the value is outside the supported range."


So I compared the date/time column of the import spreadsheet with the date/time type field on Dynamics 365 and found they are in different format.

One is "DD/MM/YY" in Canadian format, and the other is "MM/DD/YY" in US format.





So I changed the date format of the import spreadsheet from US format to Canada format to be consistent with Dynamics 365 system. 

Try to import again, succeeded finally.



Duplicate Lookup Reference Failure When Import Data File in Dynamics 365

 Sometimes, when we tried to import excel data into Dynamics 365, we may get errors like "A duplicate lookup reference was found.".

For example, I tried to import the invoice list into Dynamics 365 CRM but got two duplicate errors for the Order and Opportunity fields(columns). 



    So, I search the order name on Dynamics 365 CRM,  yes, there are several order records that have the same name as the imported data. 
    Since these orders with the same name have been in Completed status, I can not easily change their name anymore. 


   But thank god, we have a column for Order ID in the spreadsheet. This order ID is unique.
So I determined to import "Order ID" and ignore "Order", and "Opportunity".

Then, map Order ID with Order field (lookup type) on Invoice form of CRM by using Order ID to search Order record.



Finally, I created a workflow to populate the Opportunity field based on Order field when new Invoice record created or Order field changed since there is 1:N relationship between Opportunity and Order Entities.





Customize Lookup Field Search Columns in Dynamics 365

For lookup fields in Dynamics 365 forms, sometimes we hope to search the record by some other columns other than its name column, so we may need to customize Quick Find View.

Customize Lookup Field View in Dynamics 365

 1. Change the Lookup fied view.

     Below is the view of lookup field - Order.  

     We can see there are two columns showing: Order name and customer.



      If we wanna change the columns it shows, we can customize Order entity's lookup View.

      This kind of view always named by " Entity Name + Lookup View".

       

Then, Add columns we are required to show.



Customize the queries for subgrids of Dynamics 365 form

 Subgrids are great but the limitation of needing a direct relationship between the sub entity and the main entity makes it very restrictive. There are many different use cases, if instead of using a pre-configured view that only allows linking to the active Record via a predefined relationship, we could instead bind a custom FetchXML do a subgrid and this custom FetchXML would allow for one token called #RecordID# to reference the currently open record on the form by returning the GUID. 

In Classic UI people used the subgrid.control.SetParameter("fetchxml") function but this is now broken in Unified Interface. In Unified Interface it appears a Retrieve Multiple Plugin is the only way to achieve this which is extremely complicated for something as simple as binding a query to a subgrid. 

 Here is the only way to currently do this: 

https://sank8sinha.wordpress.com/2020/01/07/adding-filtered-views-in-uci-in-dynamics-365-crm-finally...


 Reference:

  1. https://powerusers.microsoft.com/t5/Power-Apps-Ideas/Binding-FetchXML-to-Subgrid-with-reference-to-RecordID-to-filter/idi-p/675538
  2. https://cloudblogs.microsoft.com/dynamics365/no-audience/2012/04/16/deep-queries-for-subgrids/?source=crm


How to Retrieve the value of an optionset field within a plugin

 

In Dynamics 365 C# Plugin, if retrieve optionset type fields value, you may need to convert the object to optionsetvalue type before quote its value. See below bold red code.

namespace UpdateTasksByOpportunity.Plugin

{

    public class ChangeAllKidEntityRecordsStatusByParentEnty : IPlugin

    {

        public void Execute(IServiceProvider serviceProvider)

        {

            // Obtain the tracing service

            ITracingService tracingService =

            (ITracingService)serviceProvider.GetService(typeof(ITracingService));


            // Obtain the execution context from the service provider.  

            IPluginExecutionContext context = (IPluginExecutionContext)

                serviceProvider.GetService(typeof(IPluginExecutionContext));


            // The InputParameters collection contains all the data passed in the message request.  

            if (context.InputParameters.Contains("Target") &&

                (context.InputParameters["Target"] is Entity ||

                context.InputParameters["Target"] is EntityReference))

            {


                Guid regardingobjectid = Guid.NewGuid();


                if (context.InputParameters["Target"] is Entity)

                {

                    // Obtain the Parent entity from the input parameters.  

                    Entity entity = (Entity)context.InputParameters["Target"];


                    // Refer to the opportunity in the task activity.

                    // Get the current opportunity ID / Parent Entity GUID            

                    regardingobjectid = new Guid(entity.Id.ToString());

                }


                else if (context.InputParameters["Target"] is EntityReference)

                {

                    // Obtain the Parent entity reference from the input parameters.  

                    EntityReference entityReference = (EntityReference)context.InputParameters["Target"];


                    // Refer to the opportunity in the task activity.

                    // Get the current opportunity ID / Parent Entity GUID            

                    regardingobjectid = new Guid(entityReference.Id.ToString());

                }


               


                // Obtain the organization service reference which you will need for  

                // web service calls.  

                IOrganizationServiceFactory serviceFactory =

                    (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

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


                //Check if Opportunity status is changed to "OPEN". If not, return.

                //0 - "OPEN";  1 - "WON";  2 - "LOST"

                Entity entityOpportunity = service.Retrieve("opportunity", regardingobjectid, new ColumnSet("statecode"));

                if(((OptionSetValue)entityOpportunity["statecode"]).Value != 0)

                {

                    tracingService.Trace("Opportunity new status: {0} is not OPEN", ((OptionSetValue)entityOpportunity["statecode"]).Value);

                    return;

                }



                //0 Open;  1 Completed;  2 Canceled

                int stateCode = 2;

                string kidEntity = "task";


                try

                {

                    // Retrieve all tasks with regarding opportunity is current opportunity

                    var queryExpression = new QueryExpression(kidEntity);

                    var qeFilter = new FilterExpression(LogicalOperator.And);

                    qeFilter.AddCondition(new ConditionExpression("statecode", ConditionOperator.Equal, "Open"));

                    qeFilter.AddCondition(new ConditionExpression("subject", ConditionOperator.Like, "%F/U%"));

                    qeFilter.AddCondition(new ConditionExpression("description", ConditionOperator.Like, "%Automated Task%"));

                    qeFilter.AddCondition(new ConditionExpression("regardingobjectid", ConditionOperator.Like, regardingobjectid));

                    queryExpression.Criteria = qeFilter;

                    queryExpression.ColumnSet = new ColumnSet("regardingobjectid");


                    //Get results:

                    var result = service.RetrieveMultiple(queryExpression);

                    foreach (var relatedTask in result.Entities)

                    {

                        

                        // Create the Request Object

                        var state = new SetStateRequest();

                        state.State = new OptionSetValue(stateCode);


                        // Point the Request to the case whose state is being changed

                        state.EntityMoniker = new EntityReference(kidEntity, relatedTask.Id);


                        // Execute the Request

                        var stateSet = (SetStateResponse)service.Execute(state);                                             

                    }

                }


                catch (FaultException<OrganizationServiceFault> ex)

                {

                    throw new InvalidPluginExecutionException("An error occurred in FollowUpPlugin.", ex);

                }


                catch (Exception ex)

                {

                    tracingService.Trace("FollowUpPlugin: {0}", ex.ToString());

                    throw;

                }

            }

        }

    }


    [Serializable]

    internal class FaultException<T> : Exception

    {

        public FaultException()

        {

        }


        public FaultException(string message) : base(message)

        {

        }


        public FaultException(string message, Exception innerException) : base(message, innerException)

        {

        }


        protected FaultException(SerializationInfo info, StreamingContext context) : base(info, context)

        {

        }

    }

}

Query Expression Add Criteria for look up field (Dynamics 365

Microsoft Dynamics 365 Plugin C# code.

If you wanna retrieve multiple records, you may use RetrieveMultiple function.

You can set filters and select the columns(fields) in the retrieve response.

When I set a filter for a lookup field (GUID), I tried two ways.





Both options work normally, the second way is better, greatly reduced the Amount of retrieved records, better for system performance. But the first way is still a good try for reading and comparing GUID value from retrieve response.

Option 1:  Add filter in retrieve result procession. (Bad performance.)

// Retrieve all tasks with regarding opportunity is current opportunity

var queryExpression = new QueryExpression(kidEntity);

var qeFilter = new FilterExpression(LogicalOperator.And);

qeFilter.AddCondition(new ConditionExpression("statecode", ConditionOperator.Equal, "Open"));

qeFilter.AddCondition(new ConditionExpression("subject", ConditionOperator.Like, "%F/U%"));

qeFilter.AddCondition(new ConditionExpression("description", ConditionOperator.Like, "%Automated Task%"));

queryExpression.Criteria = qeFilter;

queryExpression.ColumnSet = new ColumnSet("regardingobjectid");

//Get results:

var result = service.RetrieveMultiple(queryExpression);

foreach (var relatedTask in result.Entities)

{

    if(((EntityReference)relatedTask.Attributes["regardingobjectid"]).Id.ToString() == (regardingobjectid).ToString())

    {

        // Create the Request Object

        var state = new SetStateRequest();

        state.State = new OptionSetValue(stateCode);

        // Point the Request to the case whose state is being changed

        state.EntityMoniker = new EntityReference(kidEntity, relatedTask.Id);

        // Execute the Request

        var stateSet = (SetStateResponse)service.Execute(state);

    }                        

}


Option 2:  Add the filter into the query expression criteria. (Good performance.)

// Retrieve all tasks with regarding opportunity is current opportunity

var queryExpression = new QueryExpression(kidEntity);

var qeFilter = new FilterExpression(LogicalOperator.And);

qeFilter.AddCondition(new ConditionExpression("statecode", ConditionOperator.Equal, "Open"));

qeFilter.AddCondition(new ConditionExpression("subject", ConditionOperator.Like, "%F/U%"));

qeFilter.AddCondition(new ConditionExpression("description", ConditionOperator.Like, "%Automated Task%"));

qeFilter.AddCondition(new ConditionExpression("regardingobjectid", ConditionOperator.Like, regardingobjectid));

queryExpression.Criteria = qeFilter;

queryExpression.ColumnSet = new ColumnSet("regardingobjectid");


//Get results:

var result = service.RetrieveMultiple(queryExpression);

foreach (var relatedTask in result.Entities)

{    

        // Create the Request Object

        var state = new SetStateRequest();

        state.State = new OptionSetValue(stateCode);

        // Point the Request to the case whose state is being changed

        state.EntityMoniker = new EntityReference(kidEntity, relatedTask.Id);

        // Execute the Request

        var stateSet = (SetStateResponse)service.Execute(state);                 

}