Displaying Multi-Currency Data in Salesforce: A Custom Approach

Managing multi-currency data in Salesforce can be challenging, especially when displaying currency fields in a specific format or currency that differs from a user’s personal currency settings. 

While Salesforce handles currency conversions automatically, there is no out-of-the-box way to override this behavior. This blog post explores a custom solution that uses a custom Lightning Web Component to control how currency data is displayed.

The Challenge

By default, Salesforce displays currency fields in the user’s personal currency, as defined in their user settings. This behavior persists in standard layouts and components, which can be limiting in scenarios like:

  • Displaying the record’s original currency instead of the user’s currency.
  • Showing amounts in a specific target currency with manual conversions.

For instance, on an Experience Cloud site, external users will see currency fields in their user’s currency unless explicitly overridden.

The Solution: A Custom LWC

To address these challenges, you can build a custom Lightning Web Component (LWC) to:

  1. Retrieve the record’s original currency and amount.
  2. Optionally perform currency conversions using the CurrencyType object.
  3. Display the amount using <lightning-formatted-number> with the desired currency code.

Implementation Steps

Retrieve Currency Data

Use Apex to fetch the record’s currency fields. For example, the CurrencyIsoCode and Amount fields on an Opportunity.

Decide Which Currency to Display:
  • If you want to show the record’s original currency: simply use the record’s CurrencyIsoCode.
  • If you need a different currency (not the user’s default and not the record’s default), you must:
    • Query the CurrencyType object to find the target currency’s conversion rate.
    • Perform the arithmetic conversion in Apex before returning the value to the LWC.

Apex Controller Example:

public with sharing class OpportunityDataController {
    @AuraEnabled(cacheable=true)
    public static OpportunityDTO getOpportunityData(Id oppId) {
        Opportunity opp = [
            SELECT Id, Amount, CurrencyIsoCode
            FROM Opportunity
            WHERE Id = :oppId
            LIMIT 1
        ];
       
        OpportunityDTO dto = new OpportunityDTO();
        dto.recordId = opp.Id;
        dto.amount = opp.Amount;
        dto.currencyCode = opp.CurrencyIsoCode;
       
        // If you wanted to convert to a different currency (e.g. USD),
        // you would query CurrencyType and do the math here.
       
        return dto;
    }
   
    public class OpportunityDTO {
        @AuraEnabled public Id recordId;
        @AuraEnabled public Decimal amount;
        @AuraEnabled public String currencyCode;
    }
}

Display Data in the LWC

Use the data fetched by Apex to render the currency amount in the desired format.

JavaScript (LWC) example

import { LightningElement, api, wire } from 'lwc';
import getOpportunityData from '@salesforce/apex/OpportunityDataController.getOpportunityData';

export default class OpportunityDisplay extends LightningElement {
    @api recordId;
    opportunity;
    error;
   
    @wire(getOpportunityData, { oppId: '$recordId' })
    wiredOpportunity({ error, data }) {
        if (data) {
            this.opportunity = data;
            this.error = undefined;
        } else if (error) {
            this.opportunity = undefined;
            this.error = error;
        }
    }

    get hasData() {
        return this.opportunity !== undefined;
    }

    // If you want to show a different currency than the record's original currency:
    // You could hardcode or dynamically set your desired currency here.
    // For simplicity, let's show the original currency from the record.
    get displayCurrencyCode() {
        return this.opportunity ? this.opportunity.currencyCode : 'USD'; // Fallback to USD
    }

    get displayAmount() {
        return this.opportunity ? this.opportunity.amount : 0;
    }
}

HTML (LWC) example

<template>
    <template if:true={hasData}>
        <!-- Display amount in the record's currency -->
        <p>
            <lightning-formatted-number
                value={displayAmount}
                style="currency"
                currency-code={displayCurrencyCode}>
            </lightning-formatted-number>
        </p>
    </template>
    <template if:true={error}>
        <p>Error: {error}</p>
    </template>
</template>

Metadata for Deployment

Expose the component to relevant pages by updating its metadata file.

LWC Metadata (opportunityDisplay.js-meta.xml) example

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>59.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightningCommunity__Page</target>
        <target>lightningCommunity__RecordPage</target>
    </targets>
</LightningComponentBundle>


Key Points to Remember

  • Direct Formatting
    • Use <lightning-formatted-number> with a currency-code to control the displayed format.
  • Manual Conversions
    • For amounts in currencies other than the record’s or user’s default, query the CurrencyType object and calculate conversions in Apex.
  • No Native Override
    • Salesforce does not provide a setting to bypass the user’s personal currency preferences, so custom solutions are necessary.

Conclusion

Customizing currency display in Salesforce requires extra effort but allows for precise control over how data is presented to users. By leveraging Apex and LWCs, you can overcome the limitations of Salesforce’s default multi-currency behavior, ensuring clarity and accuracy in your applications.

Have you faced similar challenges with multi-currency setups? 

Share your thoughts and solutions in the comments!

Comments

Popular posts from this blog

From JDK to ICU Locale Formats: Adapting Salesforce Applications for the Next Generation of Formatting

Building Stronger Relationships with Stakeholder Management in Nonprofit Cloud

Should I Migrate from NPSP to Nonprofit Cloud? A Strategic Decision for Your Mission