Tuesday, November 25, 2025

How to Convert Amounts Between Currencies in D365F&O with X++

This code converts the specified amount from one currency to another using the exchange rates configured in the system, as shown in the images below.

 public Amount getExchangeRateCurrency(Amount _amount)

{

     CurrencyExchangeHelper  currencyExchangeHelper;

     CurrencyCode            toCurrency= SystemParameters::find().SystemCurrencyCode;

  

     TaxAmount               taxAmount;

    currencyExchangeHelper = currencyExchangeHelper::construct();

    currencyExchangeHelper.parmLedgerRecId(Ledger::current()); //gets the current company

    currencyExchangeHelper.parmExchangeRateTypeRecId(Ledger::budgetExchangeRateType()); // gets the budget rate type

 

    return currencyExchangeHelper.calculateCurrencyToCurrency(fromCurrencyCode,toCurrency,_amount, true);  

-------------------------------




Sunday, November 23, 2025

Get individual dimensions value from Ledger Dimension in X++

Static DimensionDisplayValue getAttributeValueFromCombination(

    DimensionAttributeValueCombination _combination, 

    Name _attributeName = 'BusinessUnit')

{

    DimensionAttributeLevelValueView valueView;

    DimensionAttribute attribute = DimensionAttribute::findByName(_attributeName); //Retrive attribute record by Name

    

    select valueView 

        where valueView.ValueCombinationRecId == _combination.recId 

        && valueView.DimensionAttribute == attribute.RecId; //Retrieve individual Dimension attribute record

 

    return valueView.DisplayValue; //Retrive dimension attribute value

}

Reference :

https://d365ffo.com/2021/11/17/ax-d365fo-get-individual-dimensions-value-from-ledger-dimension-in-x/

Friday, November 14, 2025

Code to Read Manually Uploaded CSV Files in D365FO Using X++

public static void main(Args _args)

{

   AsciiStreamIo                       file;

   Array                               fileLines;

   FileUploadTemporaryStorageResult    fileUpload;

   fileUpload = File::GetFileFromUser() as FileUploadTemporaryStorageResult;

   file = AsciiStreamIo::constructForRead(fileUpload.openResult());

   if (file)

   {

       if (file.status())

       {

           throw error("@SYS52680");

       }

       file.inFieldDelimiter('|');

       file.inRecordDelimiter('\r\n');

   }

   container record;

   while (!file.status())

   {

       record = file.read();

       if (conLen(record))

       {

           info(strFmt("%1 - %2",conPeek(record,1),conPeek(record,2)));

       }

   }

}

......................................

Output :













Code to read CSV file from local folder in D365F&O X++

public static void main(Args _args)

{

   AsciiStreamIo                       file;

   Array                               fileLines;

   FileUploadTemporaryStorageResult    fileUpload;

   #File

   System.IO.FileStream    fileStream;

   System.IO.Stream        fileContentStream;

   System.IO.Stream        stream;

   System.String           filePath = @"C:\Temp\Vendor.csv"; //specify the file path

   fileStream = new System.IO.FileStream(filePath, System.IO.FileMode::Open, System.IO.FileAccess::Read);

   stream = fileStream;

 

   file = AsciiStreamIo::constructForRead(stream);

   if (file)

   {

       if (file.status())

       {

           throw error("@SYS52680");

       }

       file.inFieldDelimiter('|');

       file.inRecordDelimiter('\r\n');

   }

   container record;

   while (!file.status())

   {

       record = file.read();

       if (conLen(record))

       {

           info(strFmt("%1 - %2",conPeek(record,1),conPeek(record,2)));

       }

   }

}

Output :










Wednesday, November 12, 2025

Activate Financial Dimensions without Maintenance Mode - D365 F&O

Export the entity 'Dimension attribute activation'.

Article content

  • Export the entity

Article content

  • Once the export is completed (Status: Succeeded), download the file.


  • The file should look something like this

Article content

  • Now create an import project and import this file using the same entity.

  • Once the file is uploaded, click on Import to run the import job. Do not make any changes to the file. Import it as is.

Article content

  • Once the import is successful, the Financial dimension will be active. Note that this will activate all the Financial dimensions that were inactive.

Article content

Tuesday, November 11, 2025

Visible specific dimensions to specific form in D365F&O X++

My requirement was to add a new custom dimension named “EmployeeDepartment” that retrieves the existing department values.

However, this new dimension should be visible only on a specific form. Typically, financial dimensions are derived from the accounting structure. If we configure this new dimension within the accounting structure, it becomes visible across all forms — which is not what we want.

To achieve this requirement, I developed the following custom code.

----------------------------------

    [FormEventHandler(formStr(LedgerJournalTransDimension), FormEventType::Initialized)]

   public static void LedgerJournalTransDimension_OnInitialized(xFormRun sender, FormEventArgs e)

   {

       if(sender.args().menuItemName() == menuItemDisplayStr(LedgerJourTransDimLedgerJourTrnVendPaym))

       {

           DimensionEntryControl           dimControl = sender.design().controlName(identifierStr(DimensionEntryControl));

           DimensionEnumeration            dimensionSetId = DimensionCache::getDimensionAttributeSetForLedger();

           DimensionAttributeSetStorage    dimensionAttributeSetStorage;

           DimensionAttribute              dimensionAttribute,dimensionAttributeloc;

           DimensionAttributeSetItem       dimAttrSetItem;

 

           dimensionAttributeSetStorage = new DimensionAttributeSetStorage();

 

           while select  dimensionAttribute

               where  dimensionAttribute.Name != "MainAccount"  // In my case i don't need Main Account in my form

               join dimAttrSetItem

            where dimAttrSetItem.DimensionAttribute == dimensionAttribute.RecId

                && dimAttrSetItem.DimensionAttributeSet == dimensionSetId

           {

               dimensionAttributeSetStorage.addItem(

                   dimensionAttribute.RecId,

                    dimensionAttribute.HashKey,

                    NoYes::Yes);

 

           }

 

           select  dimensionAttributeloc

               where  dimensionAttributeloc.Name == "EmployeeDepartment" ;

 

           if(dimensionAttributeloc)

           {

               dimensionAttributeSetStorage.addItem(

                   dimensionAttributeloc.RecId,

                    dimensionAttributeloc.HashKey,

                    NoYes::Yes);

           }

 

           dimControl.parmEditableDimensionSet(dimensionAttributeSetStorage.save());

           dimControl.parmDisplayedDimensionSet(dimensionAttributeSetStorage.save());

       }

   }

-------------------

Reference blog : https://d365dev.com/2018/04/20/disable-editing-of-specific-financial-dimensions-on-form/

Created a new custom dimension.


Output :







Tuesday, September 23, 2025

Update custom fields in voucher transactions in D365F&O X++

The code below will work for voucher transactions that were created automatically.

[ExtensionOf(classStr(LedgerVoucherTransObject))]

internal final class Dax_LedgerVoucherObject_Extension

{

   public void initFromLedgerPostingTransaction(

       LedgerPostingTransactionTmp _ledgerPostingTransaction,

       LedgerPostingTransactionProjectTmp _projectPostingTransaction)

   {

       next initFromLedgerPostingTransaction(_ledgerPostingTransaction,_projectPostingTransaction);

 

       generalJournalAccountEntry.Dax_CosnsolidateAccount = "testloc"; //Custom field

   }

}

The code below will work for voucher transactions that are transferred manually or through a batch.

[ExtensionOf(classStr(SubledgerJournalTransferCommand))]

internal final class Dax_SubledgerJournalTransferCommand_Extension

{

   public void executeTransfer(SubledgerJournalTransferRequest subledgerJournalTransferRequest)

   {

       GeneralJournalAccountEntry          accountEntry;

       GeneralJournalEntry                 generalJournalEntryloc;

       SubledgerJournalEntry subledgerJournalEntry;

       next executeTransfer(subledgerJournalTransferRequest);

       while select generalJournalEntryloc

join subledgerJournalEntry

               where subledgerJournalEntry.TransferId ==generalJournalEntryloc.TransferId

                && subledgerJournalEntry.TransferId == transferidVal

                && subledgerJournalEntry.Status == SubledgerJournalEntryStatus::Transferred

       {

           while select forupdate accountEntry

              where accountEntry.GeneralJournalEntry == generalJournalEntryloc.RecId

           {

               ttsbegin;

               accountEntry.Dax_CosnsolidateAccount = "test"; //Custom field

               accountEntry.update();

               ttscommit;

           }

       }

   }

}

...............

Output :

The above code works for voucher transactions that were created in the following ways :

1.Scenario - Product receipt voucher transactions. Manually transfer


2.Vendor invoice journal


3.Vendor payment journal.
4.Sales Packing slip vouchers.
5.Sales order invoice vouchers.
6.Free text invoices.
7.General journals.
8.Movement journals.
9.Hour journals.
10.Expense journals
11.Fixed asset journals. etc..