💬 Amount in Words in Microsoft Dynamics 365 Business Central
When dealing with financial documents like invoices, payment vouchers, and purchase orders, it's often necessary to express numeric amounts in words. This isn't just for formality—many organizations and legal systems require it to avoid ambiguity or fraud.
That’s where the "Amount in Words" feature in Microsoft Dynamics 365 Business Central becomes handy.
📌 What is "Amount in Words"?
The Amount in Words refers to the textual representation of a numeric currency value. For example:
• Numeric: ₹1,234.56
• In Words: "One Thousand Two Hundred Thirty-Four Rupees and Fifty-Six Paise"
This is often printed at the bottom of cheques, invoices, and legal documents to clearly convey the total payable amount in text form.
🎯 Why is it Useful?
- ✅ Prevents tampering or fraud (changing “1,000” to “9,000” is easy in numbers, harder in words)
- ✅ Complies with legal and accounting standards in many countries
- ✅ Improves clarity for customers and stakeholders
- ✅ Adds professionalism to printed reports or PDFs
🏗️ How to Use "Amount in Words" in Business Central
✅ Standard (Out-of-the-box) Method
Business Central includes a standard function to convert numbers to words, located in Report 18935 "Check Report".
Here’s how to use it in AL code:
var
CheckReport: Report "Check Report";
AmountInWords: Text;
begin
AmountInWords := GenJnlPostLine.FormatNoText(1234.56, 'INR');
Message(AmountInWords);
end;
This returns:
🗣️ One Thousand Two Hundred Thirty-Four Rupees and Fifty-Six Paise
Parameters:
- The first parameter is the amount (Decimal)
- The second is the currency code (e.g., 'USD', 'INR', 'EUR')
This function is localization-aware and works seamlessly in standard reports, including:
- Sales Invoice
- Purchase Order
- Payment Journal
You can bind this result to a label in RDLC or Word layout if you’re building or customizing a report.
🧑💻 Custom "Amount in Words" Function (If You Need More Control)
While the standard method works great, sometimes you may want to customize the output—for example:
- Show amount without "Paise" or "Cents"
- Use uppercase text only
- Add prefix or suffix like "Rupees Only"
- Support for custom currency formats (e.g., Lakhs/Crores in Indian format)
Here’s a simplified custom function:
codeunit 50101 "Amount in Words"
{
procedure FormatNoText(var NoText: array[2] of Text[80]; No: Decimal; CurrencyCode: Code[10])
var
GLSetup: Record "General Ledger Setup";
PrintExponent: Boolean;
DecimalPart: Decimal;
DecimalInt: Integer;
Exponent: Integer;
Hundreds: Integer;
NoTextIndex: Integer;
Ones: Integer;
OnesDec: Integer;
Tens: Integer;
TensDec: Integer;
begin
Clear(NoText);
NoTextIndex := 1;
InitTextVariable();
InitExponentText(CurrencyCode);
GLSetup.Get();
if No < 1 then
AddToNoText(NoText, NoTextIndex, PrintExponent, Text026Lbl)
else
for Exponent := 4 downto 1 do begin
PrintExponent := false;
Ones := No div Power(1000, Exponent - 1);
No := No mod Power(1000, Exponent - 1);
Hundreds := Ones div 100;
Tens := (Ones mod 100) div 10;
Ones := Ones mod 10;
if Hundreds > 0 then begin
if Hundreds in [1 .. 9] then
AddToNoText(NoText, NoTextIndex, PrintExponent, OnesText[Hundreds]);
AddToNoText(NoText, NoTextIndex, PrintExponent, Text027Lbl); // "Hundred"
end;
if Tens >= 2 then begin
AddToNoText(NoText, NoTextIndex, PrintExponent, TensText[Tens]);
if Ones > 0 then
AddToNoText(NoText, NoTextIndex, PrintExponent, OnesText[Ones]);
end else
if (Tens * 10 + Ones) > 0 then
AddToNoText(NoText, NoTextIndex, PrintExponent, OnesText[Tens * 10 + Ones]);
if PrintExponent and (Exponent > 1) then
AddToNoText(NoText, NoTextIndex, PrintExponent, ExponentText[Exponent]);
end;
if No <> 0 then
AddToNoText(NoText, NoTextIndex, PrintExponent, Text028Lbl); // "AND"
DecimalPart := ABS(No - ROUND(No, 1, '<'));
DecimalInt := ROUND(DecimalPart * 100, 1, '=');
TensDec := DecimalInt DIV 10;
OnesDec := DecimalInt MOD 10;
if TensDec >= 2 then begin
AddToNoText(NoText, NoTextIndex, PrintExponent, TensText[TensDec]);
if OnesDec > 0 then
AddToNoText(NoText, NoTextIndex, PrintExponent, OnesText[OnesDec]);
end else
if (TensDec * 10 + OnesDec) > 0 then
AddToNoText(NoText, NoTextIndex, PrintExponent, OnesText[TensDec * 10 + OnesDec]);
if DecimalInt > 0 then
if CurrencyCode = 'INR' then
AddToNoText(NoText, NoTextIndex, PrintExponent, 'PAISE')
else
AddToNoText(NoText, NoTextIndex, PrintExponent, 'CENTS');
if CurrencyCode <> '' then
AddToNoText(NoText, NoTextIndex, PrintExponent, 'ONLY');
end;
local procedure AddToNoText(var NoText: array[2] of Text; var NoTextIndex: Integer; var PrintExponent: Boolean; AddText: Text[30])
begin
PrintExponent := true;
while StrLen(NoText[NoTextIndex] + ' ' + AddText) > MaxStrLen(NoText[1]) do begin
NoTextIndex := NoTextIndex + 1;
if NoTextIndex > ArrayLen(NoText) then
Error(Text029Lbl, AddText);
end;
NoText[NoTextIndex] := DelChr(NoText[NoTextIndex] + ' ' + AddText, '<');
end;
procedure InitTextVariable()
begin
OnesText[1] := Text032Lbl;
OnesText[2] := Text033Lbl;
OnesText[3] := Text034Lbl;
OnesText[4] := Text035Lbl;
OnesText[5] := Text036Lbl;
OnesText[6] := Text037Lbl;
OnesText[7] := Text038Lbl;
OnesText[8] := Text039Lbl;
OnesText[9] := Text040Lbl;
OnesText[10] := Text041Lbl;
OnesText[11] := Text042Lbl;
OnesText[12] := Text043Lbl;
OnesText[13] := Text044Lbl;
OnesText[14] := Text045Lbl;
OnesText[15] := Text046Lbl;
OnesText[16] := Text047Lbl;
OnesText[17] := Text048Lbl;
OnesText[18] := Text049Lbl;
OnesText[19] := Text050Lbl;
TensText[1] := '';
TensText[2] := Text051Lbl;
TensText[3] := Text052Lbl;
TensText[4] := Text053Lbl;
TensText[5] := Text054Lbl;
TensText[6] := Text055Lbl;
TensText[7] := Text056Lbl;
TensText[8] := Text057Lbl;
TensText[9] := Text058Lbl;
end;
local procedure InitExponentText(CurrencyCode: Code[10])
begin
Clear(ExponentText);
if CurrencyCode = 'INR' then begin
ExponentText[1] := ''; // Ones
ExponentText[2] := 'THOUSAND';
ExponentText[3] := 'LAKH';
ExponentText[4] := 'CRORE';
end else begin
ExponentText[1] := ''; // Ones
ExponentText[2] := Text059Lbl; // THOUSAND
ExponentText[3] := Text060Lbl; // MILLION
ExponentText[4] := Text061Lbl; // BILLION
end;
end;
var
TensText: array[10] of Text[30];
OnesText: array[20] of Text[30];
ExponentText: array[5] of Text[30];
Text032Lbl: Label 'ONE';
Text033Lbl: Label 'TWO';
Text034Lbl: Label 'THREE';
Text035Lbl: Label 'FOUR';
Text036Lbl: Label 'FIVE';
Text037Lbl: Label 'SIX';
Text038Lbl: Label 'SEVEN';
Text039Lbl: Label 'EIGHT';
Text040Lbl: Label 'NINE';
Text041Lbl: Label 'TEN';
Text042Lbl: Label 'ELEVEN';
Text043Lbl: Label 'TWELVE';
Text044Lbl: Label 'THIRTEEN';
Text045Lbl: Label 'FOURTEEN';
Text046Lbl: Label 'FIFTEEN';
Text047Lbl: Label 'SIXTEEN';
Text048Lbl: Label 'SEVENTEEN';
Text049Lbl: Label 'EIGHTEEN';
Text050Lbl: Label 'NINETEEN';
Text051Lbl: Label 'TWENTY';
Text052Lbl: Label 'THIRTY';
Text053Lbl: Label 'FORTY';
Text054Lbl: Label 'FIFTY';
Text055Lbl: Label 'SIXTY';
Text056Lbl: Label 'SEVENTY';
Text057Lbl: Label 'EIGHTY';
Text058Lbl: Label 'NINETY';
Text059Lbl: Label 'THOUSAND';
Text060Lbl: Label 'MILLION';
Text061Lbl: Label 'BILLION';
Text026Lbl: Label 'ZERO';
Text027Lbl: Label 'HUNDRED';
Text028Lbl: Label 'AND';
Text029Lbl: Label '%1 results in a written number that is too long.';
}
Note: You can write your own converter or use external libraries/API if you need support for special formatting (like Indian number system: Lakhs/Crores).
✅ Example Results:
Input: 12345678.25 with INR
Output: ONE CRORE TWENTY THREE LAKH FORTY FIVE THOUSAND SIX HUNDRED SEVENTY EIGHT AND TWENTY FIVE PAISE ONLY
Input: 12345678.25 with USD
Output: TWELVE MILLION THREE HUNDRED FORTY FIVE THOUSAND SIX HUNDRED SEVENTY EIGHT AND TWENTY FIVE CENTS ONLY
📄 Where Can You Use "Amount in Words"?
- Sales Invoices
- Credit Memos
- Purchase Invoices
- Payment Vouchers
- Cheques
- Custom Reports
- Excel/Word exports
🧠 Final Thoughts
The "Amount in Words" feature, though often overlooked, is a crucial detail in any business application that handles monetary values. Business Central 365 provides a clean, standard way to achieve this, but also allows customization for more specific or region-based needs.
Whether you're building compliance-focused reports or simply want to add polish to your documents, implementing amount in words is a small detail with big impact.