Converting Numeric Dollar Values to Text in VB.NET

The article describes an easy approach to converting a numeric dollar value into its text equivalent; the primary purpose for such a mechanism would be to express the amount displayed on a check as a string within the ‘Amount’ section typical to most checks.

Introduction

The article describes an easy approach to converting a numeric dollar value into its text equivalent; the primary purpose for such a mechanism would be to express the amount displayed on a check as a string within the 'Amount' section typical to most checks.  It may have some other use as well but that was the goal I had in mind when I wrote a simple code module to perform the conversion.  The code provided in the example will convert numbers between 1 cent and $9,999,999.99 but it could be continued beyond this point with little additional effort.

To serve the purpose of a test harness, the sample application converts the numeric values into text and displays both in the form of a personal check.  This application is not a full blown check writing application, it is just a demo project without any sort of back end record keeping system whatsoever.

  AmountToText1.gif
 

Figure 1:  Demo Application Displaying converted numeric values as text

Getting Started:

Unzip the attached file; in it you will find solution containing a single windows forms project.  The project was written in Visual Basic 2005 and it contains only two significant files, a code module entitled, "DecimalToText" and a form class entitled, "frmCheck".  The module is used to perform the string conversion functions while the form class is used as a test harness that serves only to evaluate the code module.

AmountToText2.gif
 

Figure 2.  Check Writer Solution in the Solution Explorer

There are certainly many other options available for constructing code to perform such a translation, however, in a effort to keep things simple, I opted to convert the numeric value into a character array and to use a series of select case statements to determine the length of the array and to set portions of the text according to the length and content of the amount entered as a numeric value.  In this instance, I found that the select case statement approach used did offer more complete control over writing out the text given the current numeric value's content in terms of applying the correct text at the correct time to render out the correct amount string at the end of the processing task.  Still and all, the approach shown is not a terribly efficient way of handling the translation but it does appear to work well enough across the involved range of potential numeric values.

The Code:  DecimalToText Module

As was mentioned, this class was declared as a module to make its functions accessible throughout the application without the requiring the creation of an instance of the class.  This class contains only one public function, "ConvertDecimalToText"; the method accepts a decimal value as its only argument.  All other functions or subroutines in the class are declared private and are only called by this public function.

The class itself does not include any import statements nor does it inherit from any other class or implement any interfaces.  The ConvertDecimalToText function accepts the decimal value to translate into text and in order to determine the size number of places in the decimal value, the value is converted to a string and then into a character array.  The character array is stripped of the fractional portion of the number and its decimal place, the length of the remaining array is evaluated within a select statement in order to determine the type of number to process (ones, tens, hundreds, thousands, etc.).  Once the size of the number has been determined, the value is processed into text by values acquired from the character array passed into a collection of other functions used to retrieve the appropriate text for that value.  In some instances, to properly write out the text, either one or two values from the character array are joined together and processed (so that the function can return, for example, ninety-nine instead of ninety and nine).

The code used in this function is as follows:

Public Function ConvertDecimalToText(ByVal decAmount As DecimalAs String

 

        Dim strAmount As String = ""

        Dim decValue As Decimal = decAmount

        Dim amount() As Char

        amount = decValue.ToString.ToCharArray()

 

        Dim places As Integer

        places = amount.Length - 3

        If amount(0) = "0" Then

            places = places - 1

        End If

 

        Select Case places

            Case 0

                'change only

                strAmount = "Zero " & GetChange(amount)

            Case 1

                'dollar

                strAmount = GetDollars(amount(0)) & GetChange(amount)

            Case 2

                'tens of dollars

                Dim strTemp As String = amount(0) & amount(1)

                strAmount = GetTensOfDollars(strTemp) & GetChange(amount)

            Case 3

                'hundreds of dollars

                Dim strTemp As String = amount(1) & amount(2)

                strAmount = GetHundredsOfDollars(amount(0)) &

                GetTensOfDollars(strTemp) & GetChange(amount)

            Case 4

                'thousands of dollars

                Dim strTemp10s As String = amount(2) & amount(3)

                strAmount = GetThousandsOfDollars(amount(0)) &

                GetHundredsOfDollars(amount(1)) & GetTensOfDollars(strTemp10s) &

                GetChange(amount)

            Case 5

                'tens of thousands of dollars

                Dim strTemp1000s As String = amount(0) & amount(1)

                Dim strTemp10s As String = amount(3) & amount(4)

                strAmount = GetTenThousandsOfDollars(strTemp1000s) &

   GetHundredsOfDollars(amount(2)) & GetTensOfDollars(strTemp10s) & 

   GetChange(amount)

            Case 6

                'hundreds of thousands of dollars

                Dim strTemp1000s As String = amount(1) & amount(2)

                Dim strTemp10s As String = amount(4) & amount(5)

                If amount(1) = "0" And amount(2) = "0" Then

                    strAmount = Get100ThousandsOfDollars(amount(0), True) &

GetTenThousandsOfDollars(strTemp1000s) & GetHundredsOfDollars(amount(3)) & GetTensOfDollars(strTemp10s) & GetChange(amount)

                Else

                    strAmount = Get100ThousandsOfDollars(amount(0), false) &

GetTenThousandsOfDollars(strTemp1000s) &

GetHundredsOfDollars(amount(3)) & GetTensOfDollars(strTemp10s) &

GetChange(amount)

                End If

            Case 7

                'one million dollars

                Dim strTempMillions As String = amount(0)

                Dim strTemp1000s As String = amount(2) & amount(3)

                Dim strTemp10s As String = amount(5) & amount(6)

                If amount(2) = "0" And amount(3) = "0" Then

                    strAmount = GetMillionsOfDollars(strTempMillions) &

             Get100ThousandsOfDollars(amount(1), True)

& GetTenThousandsOfDollars(strTemp1000s) &

GetHundredsOfDollars(amount(4)) & GetTensOfDollars(strTemp10s) &

GetChange(amount)

                Else

                    strAmount = GetMillionsOfDollars(strTempMillions) &

Get100ThousandsOfDollars(amount(1), False) & GetTenThousandsOfDollars(strTemp1000s) & GetHundredsOfDollars(amount(4)) & GetTensOfDollars(strTemp10s) & GetChange(amount)

                End If

            Case 8

                strAmount = "Passed maximum amount"

     Case Else

                strAmount = "Unknown number submitted"

        End Select

 

        Return strAmount

 

End Function

As you can see from looking at the code, the select case statement is just used to process  the text describing each separate section of the translated number.  The more places the character array has, the more parts there are to process.  I stopped processing the numbers at nine million; if you need to write checks larger than $9,999,999.99 then just continue the processing with case 8, case 9, and so forth.

Each of the remaining functions in this module are used to process parts of the decimal value to be converted; since each portion of the number will return different text representations, there are separate functions for each portion of the number, e.g., dollars, tens of dollars, hundreds of dollars, thousands of dollars, tens of thousands of dollars, etc.

I won't place all of the subordinate functions into this document but, as an example, I will print up the function that calculates the portion that returns the single dollar value for the sting.  It is as follows:

Private Function GetDollars(ByVal cd As Char)

 

    Dim strDollars As String = ""

 

    Select Case cd

        Case "1"

            strDollars = "One "

        Case "2"

            strDollars = "Two "

        Case "3"

            strDollars = "Three "

        Case "4"

            strDollars = "Four "

        Case "5"

            strDollars = "Five "

        Case "6"

            strDollars = "Six "

        Case "7"

            strDollars = "Seven "

        Case "8"

            strDollars = "Eight "

        Case "9"

            strDollars = "Nine "

        Case "0"

            strDollars = "Zero "

    End Select

 

    Return strDollars

 

End Function

In examining this piece of code you will note that the function accepts a character value as an argument; this character value is stripped from the decimal value once it has been converted to a character array and then the value (a number between 0 and 9) is processed in this select statement.  In use, if the user keys in, for example, 1.05, the conversion function will pass "1" to this function which will in turn return "One"; this value will then be added to the value returned from function used to obtain the fraction values and then that assembled string is passed back to the form and displayed as "One and 05/100's Dollars" to the user.

The rest of the functions in this module operate in a very similar manner; review the code contained in this module to see how each portion of the amount string is built.

The Code:  Check Form (frmCheck.vb) Class

This portion of the project is used as a test harness to evaluate different decimal values.  I tested processing numbers between 0 and 9,999,999.99 using this same method.  The code is simple enough, the user may key a value up to the maximum amount (9,999,999.99) into a text box and click on an update button at the bottom of the form.  When the update button is clicked, the user entered text is processed and passed to the conversion function.  The string returned from the conversion function is then displayed in the 'Amount' area of the fake check.

The code in the form class is as follows:

Public Class frmCheck

 

    Private Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As

    System.EventArgs) Handles btnUpdate.Click

 

        If txtAmount.Text <> "" Then

            Try

                Dim decAmount As Decimal

 

                'convert the text into a decimal

                decAmount = Convert.ToDecimal(txtAmount.Text)

 

                'set the number of decimal places to 2

                decAmount = Decimal.Round(decAmount, 2)

 

                'update the textbox to show the decimal value

                'formatted to show only two decimal places

                txtAmount.Text = decAmount.ToString("0.00")

 

                'update the decimal amount variable to hold

                'the value with only two decimal places

                decAmount = Convert.ToDecimal(txtAmount.Text)

 

                'define a string to hold the converted value

                Dim strAmount As String

 

                'convert the decimal value to a string and pass

                'it to the conversion function, catch the returned

                'string

                strAmount = DecimalToText.ConvertDecimalToText(decAmount)

 

                'write the returned string out onto the check

                Me.lblAmount.Text = strAmount

 

            Catch ex As Exception

                MessageBox.Show(ex.Message, "Error")

            End Try

        End If

    End Sub

There is a little more code in this class; it is merely used to limit the user to entering numeric values into the text box and to display a date on the fake check.  I won't reprint that bit here but you can examine it in the sample project.

Summary.

There are many different ways in which the decimal values could be converted to text; this is only one possibility and it is something of a brute force approach to tackling the problem.  However, this approach is easy to extend or to modify if you were to wish to modify the output.  For example, I have noted that some machine drawn checks are formatted in this manner:

One thousand Eleven Hundred Nineteen Dollars and Fifty Eight Cents

Where as this example would print this same value in this format:

One Thousand Eleven Hundred Nineteen and 58/100's Dollars

I consider the later to be the more typical approach used and for that reason I wrote the conversion utility function to output in a manner consistent with this format.  Again, this is not a terribly efficient process and you may wish to generate string arrays containing each of the text values and devise a method for looping through the decimal value contents and assigning bits of text to each of its constituent parts, however, at the end of the day you still will end up writing out the text in some form or format somewhere.