fx
XLnCAD

Excel · Python in Excel & VBA

Turn numbers into words, right inside a cell.

A number in, the spelled-out words out — for English amounts and Indian Rupees. Grab the code below and paste it into Excel. Try it first:

C3
fx
=InWords(B3)
B
3
C
3
One Thousand Two Hundred Thirty-Four Point Five Six

Live preview — the same logic as the code below.

For the Python code

Microsoft 365 Excel with Python in Excel. Enter it in a cell with =PY() and pull the number in using xl("B3").

For the VBA code

Any Excel with macros. Paste into a module (Alt+F11), save as .xlsm, then use =InWords(B3).

The code — copy what you need

Python
InWords()
English words — Thousand, Million, Billion. Handles decimals and negatives.
def InWords(n):
    s = str(n).strip()
    try:
        float(s)          # validate it's a number
    except:
        return ""
    ones = ["Zero","One","Two","Three","Four","Five","Six","Seven","Eight","Nine",
            "Ten","Eleven","Twelve","Thirteen","Fourteen","Fifteen","Sixteen",
            "Seventeen","Eighteen","Nineteen"]
    tens = ["","","Twenty","Thirty","Forty","Fifty","Sixty","Seventy","Eighty","Ninety"]
    def three(num):
        if num == 0:
            return ""
        if num < 20:
            return ones[num]
        if num < 100:
            return tens[num // 10] + ("-" + ones[num % 10] if num % 10 else "")
        return ones[num // 100] + " Hundred" + (" " + three(num % 100) if num % 100 else "")
    def whole(num):
        if num == 0:
            return "Zero"
        out = []
        for value, name in [(10**12,"Trillion"), (10**9,"Billion"), (10**6,"Million"), (1000,"Thousand")]:
            if num >= value:
                out.append(three(num // value) + " " + name)
                num %= value
        if num:
            out.append(three(num))
        return " ".join(out)
    negative = s.startswith("-")
    s = s.lstrip("-+")
    if "." in s:
        int_part, dec_part = s.split(".", 1)
    else:
        int_part, dec_part = s, ""
    int_part = int_part or "0"
    words = whole(int(int_part))
    if dec_part:
        words += " Point " + " ".join(ones[int(d)] for d in dec_part)
    return ("Minus " if negative else "") + words

InWords(xl("B3"))
Python
InRupees()
Indian Rupees — Lakh, Crore & Paise, in cheque wording (“Rupees … Only”).
def InRupees(n):
    s = str(n).strip()
    try:
        float(s)          # validate it's a number
    except:
        return ""
    ones = ["Zero","One","Two","Three","Four","Five","Six","Seven","Eight","Nine",
            "Ten","Eleven","Twelve","Thirteen","Fourteen","Fifteen","Sixteen",
            "Seventeen","Eighteen","Nineteen"]
    tens = ["","","Twenty","Thirty","Forty","Fifty","Sixty","Seventy","Eighty","Ninety"]
    def three(num):
        if num == 0:
            return ""
        if num < 20:
            return ones[num]
        if num < 100:
            return tens[num // 10] + ("-" + ones[num % 10] if num % 10 else "")
        return ones[num // 100] + " Hundred" + (" " + three(num % 100) if num % 100 else "")
    def indian(num):
        if num == 0:
            return "Zero"
        crore = num // 10**7
        num %= 10**7
        lakh = num // 10**5
        num %= 10**5
        thousand = num // 1000
        hundred = num % 1000
        parts = []
        if crore:
            parts.append(indian(crore) + " Crore")   # recursive: handles beyond 99 crore
        if lakh:
            parts.append(three(lakh) + " Lakh")
        if thousand:
            parts.append(three(thousand) + " Thousand")
        if hundred:
            parts.append(three(hundred))
        return " ".join(parts)
    negative = s.startswith("-")
    s = s.lstrip("-+")
    int_part, _, dec_part = s.partition(".")
    int_part = int_part or "0"
    # Paise = first two decimal places, rounded on the third digit
    dec_part = (dec_part + "000")[:3]
    paise = int(dec_part[:2])
    if int(dec_part[2]) >= 5:
        paise += 1
    rupees = int(int_part)
    if paise == 100:      # e.g. 99.999 rounds up
        rupees += 1
        paise = 0
    words = "Rupees " + indian(rupees)
    if paise:
        words += " and " + three(paise) + " Paise"
    words += " Only"
    return ("Minus " if negative else "") + words

InRupees(xl("B3"))
VBA
InWords() & InRupees()
For Excel without Python. One module gives both formulas. Paste and save as .xlsm.
' ================= International words:  =InWords(B3) =================
Function InWords(ByVal n As Variant) As String
    Dim s As String
    s = Trim(CStr(n))

    If Not IsNumeric(s) Then
        InWords = ""
        Exit Function
    End If

    Dim negative As Boolean
    negative = (Left(s, 1) = "-")

    Do While Len(s) > 0 And (Left(s, 1) = "-" Or Left(s, 1) = "+")
        s = Mid(s, 2)
    Loop

    Dim intPart As String, decPart As String
    Dim dotPos As Long
    dotPos = InStr(s, ".")
    If dotPos > 0 Then
        intPart = Left(s, dotPos - 1)
        decPart = Mid(s, dotPos + 1)
    Else
        intPart = s
        decPart = ""
    End If
    If Len(intPart) = 0 Then intPart = "0"

    Dim result As String
    result = WholeToWords(intPart)

    ' Read each digit after the decimal point individually
    If Len(decPart) > 0 Then
        Dim onesArr As Variant
        onesArr = Array("Zero", "One", "Two", "Three", "Four", "Five", _
                        "Six", "Seven", "Eight", "Nine")
        Dim i As Long, d As Integer
        result = result & " Point"
        For i = 1 To Len(decPart)
            d = CInt(Mid(decPart, i, 1))
            result = result & " " & onesArr(d)
        Next i
    End If

    If negative Then result = "Minus " & result
    InWords = result
End Function


' ================= Indian Rupees:  =InRupees(B3) =================
Function InRupees(ByVal n As Variant) As String
    Dim s As String
    s = Trim(CStr(n))

    If Not IsNumeric(s) Then
        InRupees = ""
        Exit Function
    End If

    Dim negative As Boolean
    negative = (Left(s, 1) = "-")

    Do While Len(s) > 0 And (Left(s, 1) = "-" Or Left(s, 1) = "+")
        s = Mid(s, 2)
    Loop

    Dim intPart As String, decPart As String
    Dim dotPos As Long
    dotPos = InStr(s, ".")
    If dotPos > 0 Then
        intPart = Left(s, dotPos - 1)
        decPart = Mid(s, dotPos + 1)
    Else
        intPart = s
        decPart = ""
    End If
    If Len(intPart) = 0 Then intPart = "0"

    ' Paise = first two decimals, rounded using the third digit
    decPart = Left(decPart & "000", 3)
    Dim paise As Integer
    paise = CInt(Left(decPart, 2))
    If CInt(Mid(decPart, 3, 1)) >= 5 Then paise = paise + 1

    If paise = 100 Then           ' e.g. 99.999 rounds up
        paise = 0
        intPart = CStr(CDec(intPart) + 1)
    End If

    Dim words As String
    words = "Rupees " & IndianToWords(intPart)
    If paise > 0 Then
        words = words & " and " & ThreeToWords(paise) & " Paise"
    End If
    words = words & " Only"

    If negative Then words = "Minus " & words
    InRupees = words
End Function


' ================= Helpers (shared by both functions) =================
Private Function WholeToWords(ByVal digits As String) As String
    Do While Len(digits) > 1 And Left(digits, 1) = "0"
        digits = Mid(digits, 2)
    Loop

    If digits = "0" Then
        WholeToWords = "Zero"
        Exit Function
    End If

    Do While (Len(digits) Mod 3) <> 0
        digits = "0" & digits
    Loop

    Dim scales As Variant
    scales = Array("", "Thousand", "Million", "Billion", "Trillion", _
                   "Quadrillion", "Quintillion")

    Dim groupCount As Long
    groupCount = Len(digits) \ 3

    Dim out As String, g As Long, grpVal As Integer
    Dim grpWords As String, scaleIndex As Long
    out = ""

    For g = 1 To groupCount
        grpVal = CInt(Mid(digits, (g - 1) * 3 + 1, 3))
        scaleIndex = groupCount - g
        If grpVal > 0 Then
            grpWords = ThreeToWords(grpVal)
            If scaleIndex > 0 And scaleIndex <= UBound(scales) Then
                grpWords = grpWords & " " & scales(scaleIndex)
            End If
            If Len(out) > 0 Then out = out & " "
            out = out & grpWords
        End If
    Next g

    WholeToWords = out
End Function


Private Function IndianToWords(ByVal digits As String) As String
    Do While Len(digits) > 1 And Left(digits, 1) = "0"
        digits = Mid(digits, 2)
    Loop
    If digits = "0" Then
        IndianToWords = "Zero"
        Exit Function
    End If

    Dim hundred As Integer, thousand As Integer, lakh As Integer
    Dim L As Long

    ' Last 3 digits -> hundreds group
    L = Len(digits)
    If L >= 3 Then
        hundred = CInt(Right(digits, 3))
        digits = Left(digits, L - 3)
    Else
        hundred = CInt(digits)
        digits = ""
    End If

    ' Next 2 digits -> thousands
    thousand = 0: lakh = 0
    If Len(digits) > 0 Then
        L = Len(digits)
        If L >= 2 Then
            thousand = CInt(Right(digits, 2))
            digits = Left(digits, L - 2)
        Else
            thousand = CInt(digits)
            digits = ""
        End If
    End If

    ' Next 2 digits -> lakhs
    If Len(digits) > 0 Then
        L = Len(digits)
        If L >= 2 Then
            lakh = CInt(Right(digits, 2))
            digits = Left(digits, L - 2)
        Else
            lakh = CInt(digits)
            digits = ""
        End If
    End If

    ' Anything left is the crore count -> spell it the same way
    Dim parts As String
    parts = ""
    If Len(digits) > 0 Then
        Dim cp As String
        cp = digits
        Do While Len(cp) > 1 And Left(cp, 1) = "0"
            cp = Mid(cp, 2)
        Loop
        If cp <> "0" And cp <> "" Then
            parts = IndianToWords(cp) & " Crore"
        End If
    End If
    If lakh > 0 Then parts = Trim(parts & " " & ThreeToWords(lakh) & " Lakh")
    If thousand > 0 Then parts = Trim(parts & " " & ThreeToWords(thousand) & " Thousand")
    If hundred > 0 Then parts = Trim(parts & " " & ThreeToWords(hundred))

    IndianToWords = Trim(parts)
End Function


Private Function ThreeToWords(ByVal num As Integer) As String
    Dim ones As Variant, tens As Variant
    ones = Array("Zero", "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")

    Dim r As String
    r = ""

    If num >= 100 Then
        r = ones(num \ 100) & " Hundred"
        num = num Mod 100
        If num > 0 Then r = r & " "
    End If

    If num > 0 Then
        If num < 20 Then
            r = r & ones(num)
        Else
            r = r & tens(num \ 10)
            If (num Mod 10) > 0 Then
                r = r & "-" & ones(num Mod 10)
            End If
        End If
    End If

    ThreeToWords = r
End Function
XLnCAD/Excel tutorials by Ajay Anand /Free to use — a credit or link back is appreciated.