Calci.inCalculate Today for a Better Tomorrow

How to convert number to words in Excel, in rupees, lakh and crore

Excel has no formula that writes 12,50,000 as Twelve Lakh Fifty Thousand Rupees Only. A short macro does, and here it is, tested on 20,037 amounts.

Calci Editorial · · 5 min read

A calci.in graphic showing Excel cells converted to Indian rupee words, such as 12,50,000 written as Twelve Lakh Fifty Thousand Rupees Only.

Every invoice, salary slip and cheque register in India ends up needing the same line: the amount in words. Type 12,50,000 into a cell and Excel will happily show it with commas. Ask it for "Twelve Lakh Fifty Thousand Rupees Only" and it has nothing to offer.

There is no built-in function for it. Not in Excel 2016, not in Microsoft 365. The help pages and most tutorials point you to a sample macro called SpellNumber, and that is where the second problem starts: it writes dollars and cents, and it counts in millions. 12,50,000 comes out as something like "One Million Two Hundred Fifty Thousand Dollars and No Cents". No accountant in India wants to see that on a bill.

So here is a macro that writes rupees the Indian way, in lakh and crore, with paise. It takes about two minutes to set up.

What it produces

In the cell=RupeesInWords(A2) gives
48000Forty-eight Thousand Rupees Only
1250000Twelve Lakh Fifty Thousand Rupees Only
155760.50One Lakh Fifty-five Thousand Seven Hundred and Sixty Rupees and Fifty Paise Only
10000000One Crore Rupees Only
123456789Twelve Crore Thirty-four Lakh Fifty-six Thousand Seven Hundred and Eighty-nine Rupees Only

Before publishing it, we ported the macro line by line and ran it against the converter behind our number to words tool on 20,037 amounts: 37 awkward ones that tend to break these things, from zero and ₹1 to round lakhs, round crores and about ₹98,765 crore, plus 20,000 random amounts up to thirteen digits, with and without paise. Not one result differed.

Step 1: open the VBA editor

Open your workbook and press Alt + F11. A separate window opens: the Visual Basic editor. On a Mac, use Fn + Option + F11, or Tools, Macro, Visual Basic Editor.

In that window, click Insert, then Module. A blank white code area appears.

Step 2: paste the code

Copy all of this into the blank module:

Function RupeesInWords(ByVal Amount As Variant) As String
    ' Amount in words, Indian system: "Twelve Lakh Fifty Thousand Rupees Only"
    Dim Value As Double, Rupees As Double, Paise As Double, Result As String
    If IsEmpty(Amount) Or Not IsNumeric(Amount) Then Exit Function
    Value = Application.WorksheetFunction.Round(Abs(CDbl(Amount)), 2)
    Rupees = Int(Value)
    Paise = Application.WorksheetFunction.Round((Value - Rupees) * 100, 0)
    Result = IndianWords(Rupees) & " rupees"
    If Paise > 0 Then Result = Result & " and " & IndianWords(Paise) & " paise"
    Result = Result & " only"
    If CDbl(Amount) < 0 Then Result = "minus " & Result
    RupeesInWords = TitleWords(Result)
End Function

Private Function IndianWords(ByVal n As Double) As String
    Dim Count As Double, Result As String
    If n = 0 Then IndianWords = "zero": Exit Function
    If n >= 10000000# Then
        Count = Int(n / 10000000#)
        If Count > 99 Then
            Result = IndianWords(Count) & " crore"
        Else
            Result = UnderThousand(Count) & " crore"
        End If
        n = n - Count * 10000000#
    End If
    If n >= 100000# Then
        Count = Int(n / 100000#)
        Result = Result & " " & UnderThousand(Count) & " lakh"
        n = n - Count * 100000#
    End If
    If n >= 1000# Then
        Count = Int(n / 1000#)
        Result = Result & " " & UnderThousand(Count) & " thousand"
        n = n - Count * 1000#
    End If
    If n > 0 Then Result = Result & " " & UnderThousand(n)
    IndianWords = Trim(Result)
End Function

Private Function UnderThousand(ByVal n As Double) As String
    Dim Ones As Variant, Tens As Variant, Result As String
    Ones = Array("", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", _
        "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen")
    Tens = Array("", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety")
    If n >= 100 Then
        Result = Ones(Int(n / 100)) & " hundred"
        n = n - Int(n / 100) * 100
        If n > 0 Then Result = Result & " and "
    End If
    If n >= 20 Then
        Result = Result & Tens(Int(n / 10))
        If n - Int(n / 10) * 10 > 0 Then Result = Result & "-" & Ones(n - Int(n / 10) * 10)
    ElseIf n > 0 Then
        Result = Result & Ones(n)
    End If
    UnderThousand = Result
End Function

Private Function TitleWords(ByVal Text As String) As String
    Dim Words As Variant, i As Long
    Words = Split(Text, " ")
    For i = 0 To UBound(Words)
        If Not (i > 0 And (Words(i) = "and" Or Words(i) = "of")) Then
            Words(i) = UCase(Left(Words(i), 1)) & Mid(Words(i), 2)
        End If
    Next i
    TitleWords = Join(Words, " ")
End Function

Close the editor. Nothing needs to be run; the function is now part of the workbook.

Step 3: use it like any formula

If the amount is in cell A2, type this in the cell where you want the words:

=RupeesInWords(A2)

Drag it down the column like any other formula. Change the number and the words change with it. It works on a typed number, on a cell, and on the result of another formula, so =RupeesInWords(SUM(B2:B10)) gives the bill total in words directly.

Step 4: save as a macro-enabled file

This is the step people miss. A normal .xlsx file cannot hold code. When you save, choose Save as type: Excel Macro-Enabled Workbook (*.xlsm). If you save as .xlsx, Excel warns you and then quietly drops the macro, and every cell shows #NAME? the next time you open it.

When you reopen the file, Excel may show a yellow bar saying macros are disabled. Click Enable Content. If the file came from email or a download, Windows marks it as coming from the internet, and Microsoft 365 blocks its macros altogether: right-click the file, choose Properties, tick Unblock, and open it again.

Rupees first, or rupees last?

Different offices have different habits. A cheque usually reads "Rupees Twelve Lakh Fifty Thousand Only"; a GST invoice often puts rupees at the end. The macro above writes it at the end. To put it first, change one line in the code:

Result = IndianWords(Rupees) & " rupees"

to

Result = "rupees " & IndianWords(Rupees)

12,50,000.50 then becomes "Rupees Twelve Lakh Fifty Thousand and Fifty Paise Only".

Want all capitals for a cheque? Wrap it: =UPPER(RupeesInWords(A2)). Want "Rs." instead of the word? =SUBSTITUTE(RupeesInWords(A2),"Rupees","Rs.") does it.

Using it in every workbook

The code lives inside the one file you pasted it into. If you write invoices in a fresh workbook every month, that gets tiresome. Two ways round it:

  • Keep a template. Make an invoice or salary-slip file with the macro in it and save it as an Excel Macro-Enabled Template (.xltm). Every new file made from it has the function.
  • Make an add-in. Paste the code into a blank workbook, save it as an Excel Add-in (.xlam), then turn it on under File, Options, Add-ins, Manage Excel Add-ins, Go, Browse. The function is then available in every workbook on that computer.

The same thing in Google Sheets

Google Sheets does not run VBA, but it runs JavaScript through Apps Script, and the same logic ports straight across. Open the sheet, click Extensions, Apps Script, delete what is there, paste this and press Save:

function RUPEESINWORDS(amount) {
  if (amount === "" || isNaN(amount)) return "";
  const ONES = ["", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
    "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"];
  const TENS = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"];
  const round = (x, d) => Math.round(x * 10 ** d + 1e-9) / 10 ** d;
  const under = (n) => {
    let r = "";
    if (n >= 100) { r = ONES[Math.floor(n / 100)] + " hundred"; n %= 100; if (n) r += " and "; }
    if (n >= 20) { r += TENS[Math.floor(n / 10)] + (n % 10 ? "-" + ONES[n % 10] : ""); }
    else if (n) r += ONES[n];
    return r;
  };
  const words = (n) => {
    if (n === 0) return "zero";
    let r = "", c;
    if (n >= 1e7) { c = Math.floor(n / 1e7); r = (c > 99 ? words(c) : under(c)) + " crore"; n -= c * 1e7; }
    if (n >= 1e5) { c = Math.floor(n / 1e5); r += " " + under(c) + " lakh"; n -= c * 1e5; }
    if (n >= 1e3) { c = Math.floor(n / 1e3); r += " " + under(c) + " thousand"; n -= c * 1e3; }
    if (n > 0) r += " " + under(n);
    return r.trim();
  };
  const value = round(Math.abs(Number(amount)), 2);
  const rupees = Math.floor(value);
  const paise = round((value - rupees) * 100, 0);
  let r = words(rupees) + " rupees" + (paise ? " and " + words(paise) + " paise" : "") + " only";
  if (amount < 0) r = "minus " + r;
  return r.split(" ").map((w, i) => (i && (w === "and" || w === "of") ? w : w[0].toUpperCase() + w.slice(1))).join(" ");
}

Back in the sheet, type =RUPEESINWORDS(A2). It works like any other formula and recalculates when the number changes. The script uses no Google services and needs no permissions; it only reads the number you give it.

Things that trip people up

#NAME? in the cell. The macro is not in this file, macros are disabled, or the file was saved as .xlsx. Check those three, in that order.

A blank result. The cell holds text, not a number. A value pasted from a PDF or a bank statement often carries a hidden space or an odd comma. =RupeesInWords(VALUE(TRIM(A2))) usually fixes it, or select the column and use Data, Text to Columns, Finish.

Paise rounded oddly. The macro rounds to two decimal places first, the way Excel's own ROUND does, so 99.995 becomes One Hundred Rupees Only. That is deliberate; a cheque cannot carry half a paisa.

Very large numbers. Excel stores only 15 significant digits, so an amount with paise beyond about a lakh crore loses its last digits before the macro even sees it. That is an Excel limit, not a macro one, and no invoice is that big.

When you do not need a macro

If you write one cheque a week, a macro is overkill. Type the amount into our number to words converter and copy the line; it also does Hindi, the international system and title, upper or sentence case. The macro earns its keep when the amount sits in a sheet that changes: an invoice register, a salary slip for twenty employees, or a payment voucher that is printed every day.

And if your amounts come from a GST calculation, work the tax out first with the GST calculator, then let the macro write the total in words.