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.
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.
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 Decimal) As 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.