In most accounting applications there is a need to convert currency values to words. Here's a simple Delphi project you can use to convert a number to English words. For example, the number "6.2 $" will be "translated" to "six dollars and twenty cents".
Before I get off on a big ramble about what the code does you need to know that it is not at all universal. It uses the American "Short Scale" format for "Names of Large Numbers". Although it is very simple to edit the code to accommodate your locale and system, you'll have to do a bit of research to accommodate that.
The Number2Words routineI have declared four const Arrays in the interface section of the unit to hold the string values that will be required and some local variables in the var section of the routine that are required to get the job done.
const Ones: array[0..9] of string = ('zero ', 'one ', 'two ', 'three ', 'four ', 'five ', 'six ', 'seven ', 'eight ', 'nine ') ; Teens: array[10..19] of string = ('ten ', 'eleven ', 'twelve ', 'thirteen ', 'fourteen ', 'fifteen ', 'sixteen ', 'seventeen ', 'eighteen ', 'nineteen ') ; Tens: array[2..9] of string = ('twenty ', 'thirty ', 'forty ', 'fifty ', 'sixty ', 'seventy ', 'eighty ', 'ninety ') ; Suffix: array[0..5] of string = ('hundred ', 'thousand, ', 'million, ', 'billion, ', 'trillion, ', 'quadrillion, ') ;
Initially we use the actual number that is passed in to find out if it is negative or not.
Then we try and extract both the integer and fractional parts of the number as the logic I used required that both parts be processed separately. In addition to that, I needed the integer part to be formatted with commas. One of the issues I ran into doing this was that the FormatFloat function would choke if the number is a quintillion (which, using the American "Short Scale" format, is a number written as one followed by 18 zeros) or more so I've wrapped it in a try-except for the time being. I hope that you will not need to use numbers in the quintillion range or above. Of interest (I think it's a bug) I've found that it doesn't actually choke until you get to 20 digits but at 19 what it returns causes the program to choke so it required a little extra coding to catch the anomaly. If you plug in one of these huge numbers, the return will be 'ERROR'. Once we have the sign, integer and fraction parts we are ready to begin processing.
The primary reason for using FormatFloat was to give me a comma separated string value that I can easily load into a TStringList using the CommaText property. On the other hand, if in your locale the thousand separator is ".", you can use DelimitedText with Delimiter properties along with the TFormatSettings type. This quite simply provides me with an array of values which represents the number broken down into 100s.
The DoHundreds routine quite simply ensures that it has a three-character string to process and then processes each character in the string translating its equivalent English word. Once I have a string that represents the hundreds section processed all you do is add the appropriate suffix. After processing all the sections, we have the descriptive value of the integer section of the original number.
Processing the decimal value is straightforward. If a currency result was asked for and there is a decimal value available then clip off the first two digits (if only one digit is there make sure you have a two digit value by adding a 0 to the string) and pass it to the DoHundreds method for processing and stuff in the appropriate string values where required. If currency was asked for but there is not a decimal value just add "dollars" to the result. If a currency value is not required then just loop through the decimal value and get the representative string for each number.
Thats all there is to it. Id like to ensure that you are aware that you need to be certain that you fully understand this routine before you use it. Im not a professional programmer, but a hobbyist and I wrote this routine as a training exercise.