Visual Basic: Formatting Currency Values as Words

Introduction

A frequent question on programming forums such as Codeguru is how to convert numeric values into written words. It is not as complicated as you may think, but, it is a tad more difficult, or rather, involved. Today, I will show you how to convert numbers into words.

In a previous article, I demonstrated how to convert ordinary numbers into Roman Numerals. The reason I bring this up here is because I will approach this topic in the same manner I did with the Roman Numerals article. I sat long and hard, trying to figure out an easy way to attack this. Not attack per se, but a way to make it easier. Let’s hope I have achieved that goal today.

First, the boring stuff…

Magnitudes

I hope you’re listening, or reading, today, my Mr. Mathematics teacher…

Magnitude in mathematics is the size of a mathematical object. A mathematical object can be compared as smaller or larger (by its size) than other other objects of the same kind. Orders of magnitude are usually written in powers of 10. For example, the order of magnitude of 2700 is, for example, 3. Examples of numbers of different magnitudes can be found on Wikipedia.

Armed with this knowledge, we have a basic setup of how to incorporate these magnitudes into our program. We basically have three objects: ones, tens, and magnitudes.

Our Project

By now, you should know what you will be creating today, so let’s start!

Open Visual Studio and create a new Visual Basic Windows Forms project. There aren’t any controls that you need to add. You can, however, add a new class to your project. I have named my class clsCashtoWords, but you are welcome to name yours differently.

Add the following Namespace because we will be dealing with some text manipulation:

Imports System.Text

Add the following member variables:

   Private strMagnitudes() As String = New String() {"", " THOUSAND", " MILLION", _
      " BILLION", " TRILLION", " QUADRILLION", " QUINTILLION", " SEXTILLION", _
      " SEPTILLION", " OCTILLION", "NONILLION", "DECILLION", "UNDECILLION", _
      "DUODECILLION", "TREDECILLION", "QUATTUORDECILLION", "QUINDECILLION", _
      "SEXDECILLION", "SEPTENDECILLION", "OCTODECILLION", "NOVEMDECILLION", _
      "VIGINTILLION", "CENTILLION"}
   Private strTens() As String = New String() {"", "", "TWENTY", "THIRTY", _
      "FORTY", "FIFTY", "SIXTY", "SEVENTY", "EIGHTY", "NINETY"}
   Private strUnits() As String = New String() {"", "ONE", "TWO", "THREE", _
      "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE", "TEN", "ELEVEN", "TWELVE", _
      "THIRTEEN", "FOURTEEN", "FIFTEEN", "SIXTEEN", "SEVENTEEN", "EIGHTTEEN", _
      "NINETEEN"}

Oay, I know I may have gone a bit overboard with the magnitudes… We now have three main objects to work with: Units, Tens, and Magnitudes. Now, add the ShowNumber function:

   Public Function ShowNumber(ByVal decInput As Decimal) As String

      If decInput < 0 Then Throw New ArgumentException("Number must be zero or greater")

      Dim strNumbers As String = String.Format("{0:f2}", decInput)
      Dim sbOutput As StringBuilder = New StringBuilder
      Dim intDecimalDot As Integer = strNumbers.IndexOf("."c)

      strNumbers = New String("0"c, (3 - (intDecimalDot Mod 3)) Mod 3) & strNumbers
      intDecimalDot = strNumbers.IndexOf("."c)

      Dim intHigh As Integer = (intDecimalDot  3) - 1
      Dim strDigitGroup() As String = New String(intHigh) {}

      For i As Integer = 0 To intHigh

         strDigitGroup(i) = strNumbers.Substring(i * 3, 3)

      Next i

      For i As Integer = 0 To intHigh

         Dim g As String = GroupNumbers(strDigitGroup(i))

         If g.Length > 0 Then sbOutput.Append(g & strMagnitudes(intHigh - i) & " ")

      Next i

      If sbOutput.ToString.Trim.Length = 0 Then sbOutput = New StringBuilder("ZERO ")

         Dim cents As String = CalcTens(strNumbers.Substring(strNumbers.Length - 2, 2))

      If cents.Length = 0 Then cents = "ZERO"

         sbOutput.Append("RANDS, " & cents & " CENTS")

      Return sbOutput.ToString

   End Function

In the ShowNumber function, I ensured that the input is always positive by throwing an exception when a negative number has been entered. I then identify whether or not there are any decimals present by making use of the string’s IndexOf method.

With the magic of the Mod operator, I identify the highest numbers and start grouping them into magnitudes or tens or units respectively. Here is some more information regarding Visual Basic’s Mod operator.

Now, add the GroupNumbers function:

   Private Function GroupNumbers(ByVal strGroup As String, _
      Optional ByVal blnAND As Boolean = True) As String

      strGroup = strGroup.PadLeft(3, "0"c)

      Dim A As String = ""

      If Char.IsDigit(strGroup.Chars(0)) Then

         A = strUnits(Integer.Parse(strGroup.Chars(0)))

      End If

      If A.Length > 0 Then A &= " HUNDRED"

         Dim BC As String = CalcTens(strGroup.Substring(1, 2))

      If A.Length > 0 AndAlso BC.Length > 0 AndAlso blnAND _
         Then A &= " AND "

      Return (A & BC).Trim

   End Function

The GroupNumbers function does what its name implies: It groups the numbers into all their associated groups. This obviously happens after the ShowNumbers function has sorted the numbers into place. It determines whether or not the next character in the list is indeed a number and sorts them into Hundreds. Add the CalcTens function:

   Private Function CalcTens(ByVal sTens As String) As String

      Dim strTemp As String = ""

      Dim intTen As Integer = Integer.Parse(sTens.PadLeft(2, "0"c))

      If intTen < 20 Then

         strTemp = strUnits(intTen)

      Else

         strTemp = strTens(Integer.Parse(sTens.Chars(0))) & " " _
            & strUnits(Integer.Parse(sTens.Chars(1))).Trim

      End If

      Return strTemp

   End Function

This function follows the same principle as the previous function; however, it determines where the specific number fits and sorts it into the proper group.

Finally, add the following code for your form:

   Private CashWord As clsCashtoWords = New clsCashtoWords()

   Private Sub Form1_Load(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) Handles MyBase.Load

      MessageBox.Show(CashWord.ShowNumber(Decimal.Parse("2036.17")))

   End Sub

The preceding code creates and instantiates a new clsCashtowords object and calls its ShowNumber method to convert the number 2036.17 into words.

Conclusion

A simple topic such as this can become quite complex. But, by having a good understanding of how numbers work, it becomes a bit easier.

Hannes DuPreez
Hannes DuPreez
Ockert J. du Preez is a passionate coder and always willing to learn. He has written hundreds of developer articles over the years detailing his programming quests and adventures. He has written the following books: Visual Studio 2019 In-Depth (BpB Publications) JavaScript for Gurus (BpB Publications) He was the Technical Editor for Professional C++, 5th Edition (Wiley) He was a Microsoft Most Valuable Professional for .NET (2008–2017).

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read