Skip to main content

Mastering Default Dimensions in D365 F&O

Mastering Default Dimensions in D365 F&O: X++ Helper Methods to Create, Read, and Update

One of the most common yet complex tasks in X++ development for Dynamics 365 Finance and Operations is manipulating Financial Dimensions. Whether you are importing data, integrating with external systems, or simply updating a record based on business logic, interacting with the DimensionAttributeValueSet framework is inevitable.

To save you time, I have put together a set of static helper methods that handle the "heavy lifting" of the DimensionAttributeValueSetStorage class.

Below are three essential methods to Create, Read, and Update Default Dimensions.


1. Creating a New Default Dimension

If you have a list of dimension names and their corresponding values (for example, coming from a CSV import or an integration), you need to generate a new RecId for the DefaultDimension field.

This method accepts two containers: one for dimension names (e.g., Department, CostCenter) and one for values.


public static DimensionDefault createDefaultDimension(container _attributes, container _values)
{
    DimensionAttributeValueSetStorage valueSetStorage = new DimensionAttributeValueSetStorage();
    DimensionDefault            ret;
    int                         itemsCounter;
    DimensionAttribute          dimensionAttribute;
    DimensionAttributeValue     dimensionAttributeValue;
    str                         dimValue;

    for (itemsCounter = 1; itemsCounter <= conLen(_attributes); itemsCounter++)
    {
        // 1. Find the Dimension Attribute by Name (e.g., "Department")
        dimensionAttribute = dimensionAttribute::findByName(conPeek(_attributes, itemsCounter));

        if (dimensionAttribute.RecId == 0)
        {
            continue;
        }

        // 2. Get the value from the container
        dimValue = conPeek(_values, itemsCounter);

        if (dimValue != "")
        {
            // 3. Find the Value record. 
            // The last two parms (false, true) ensure we don't create new names, but we create values if missing.
            dimensionAttributeValue = dimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute, dimValue, false, true);
            
            // 4. Add to storage
            valueSetStorage.addItem(dimensionAttributeValue);
        }
    }

    // 5. Save and return the RecId
    ret = valueSetStorage.save();

    return ret;
}

2. Reading a Specific Dimension Value

Sometimes you don't need to change anything; you just need to know: "What is the Cost Center on this Sales Order?"

This method takes the DefaultDimension RecId and the name of the dimension you want to inspect, returning the display string.


public static str getDimensionDisplayValue(RecId _defaultDimension, Name _dimName)
{
    DimensionAttributeValueSetStorage dimStorage;
    
    // 1. Load the existing dimension set
    dimStorage = DimensionAttributeValueSetStorage::find(_defaultDimension);
    
    // 2. Return the value specific to the Dimension Name provided
    return dimStorage.getDisplayValueByDimensionAttribute(DimensionAttribute::findByName(_dimName).RecId);
}

3. Updating an Existing Dimension

A common requirement is to take an existing record (like a Customer or Vendor) and update just one specific dimension while keeping the others distinct.

This method loads the existing set, adds (or overwrites) the specific dimension value, and returns the new DefaultDimension RecId.


public static DimensionDefault updateDimensionValue(DefaultDimension _currentDim, Name _dimName, DimensionValue _dimValue)
{
    DimensionAttributeValueSetStorage   dimStorage = new DimensionAttributeValueSetStorage();
    DimensionAttribute                  dimAttribute;
    DimensionAttributeValue             dimAttributeValue;
    DimensionDefault                    defaultDimension;

    ttsBegin;
    // 1. Load the existing dimension set
    dimStorage = DimensionAttributeValueSetStorage::find(_currentDim);

    // 2. Find the attribute to update
    dimAttribute = DimensionAttribute::findByName(_dimName);

    if (dimAttribute)
    {
        // 3. Find or Create the new value
        dimAttributeValue = DimensionAttributeValue::findByDimensionAttributeAndValue(dimAttribute, _dimValue, true, true);
    }

    if (dimAttributeValue)
    {
        // 4. Add item (this overwrites the existing value for this attribute if it exists)
        dimStorage.addItem(dimAttributeValue);
        
        // 5. Save to get the new RecId
        defaultDimension = dimStorage.save();
    }
    ttsCommit;

    return defaultDimension;
}

Summary

  • createDefaultDimension: Great for data migration or creating new master data records.
  • getDimensionDisplayValue: Useful for reporting or conditional logic based on dimensions.
  • updateDimensionValue: Essential for patching specific values on existing transactions or records.

Feel free to wrap these in a utility class (e.g., GlobalDimensionHelper) to make them accessible across your project!

Comments

Popular posts from this blog

Developing SSRS Reports Using Report Data Provider in D365F&O

Developing SSRS Reports Using Report Data Provider in D365F&O In this article, we will cover the Report Data Provider (RDP) class and the Report Contract class. We will also learn how to implement these classes for reporting needs in Dynamics 365 Finance & Operations and create a report using the RDP class via a step-by-step walkthrough. Report Data Provider (RDP) Framework A Report Data Provider (RDP) class is an X++ class used to access and process data for a report. An RDP class is an appropriate data source type when the following conditions are met: You cannot query directly for the data you want to render on a report. The data to be processed and displayed is complex and requires specific business logic. Report Data Provider Class This is an X++ class used to access and process data for an SSRS report. The RDP class processes business logic based on specified parameters and/or queries and return...

Fix SSRS Parameter Panel Layout Error

Fix SSRS Parameter Panel Layout Error [Fix] SSRS Error: "The parameter panel layout for this report contains more parameters than total cells available" Tags: #SSRS #Dynamics365 #SQLServer #ReportingServices #Troubleshooting If you have been working with SSRS (SQL Server Reporting Services) lately—especially within the Dynamics 365 environment—you might have encountered a frustrating error when trying to deploy a report after adding a new parameter. It usually happens when you add a Hidden Parameter or modify the existing list, and suddenly the deployment fails with this severity code: Error: The parameter panel layout for this report contains more parameters than total cells available. Source: Microsoft.ReportingServices.Library.ReportingService2005Impl.CreateReport The Scenario You have an existing report. You need to add a new par...

Developing SSRS Reports Using a Query in D365F&O

Developing SSRS Reports Using a Query in D365F&O In this tutorial, we will learn how to develop a report based on a predefined Query in the Application Object Tree (AOT) within Visual Studio. This method is often faster than using a Report Data Provider (RDP) class when complex business logic is not required. Scenario: We will create a report that prints a simple list of customer transactions directly from the CustTrans table without writing X++ business logic. Step 1: Create the Project and Query Unlike previous versions of Dynamics, all development for D365F&O occurs inside Visual Studio. Open Visual Studio as an administrator. Create a new Finance and Operations project. In the Solution Explorer , right-click the project node. Select Add > New Item . Select Query from the list and name it CustomerTransactionQuery . Click Add . Configuring the Data Source...