Posted to microsoft.public.excel.worksheet.functions
|
|
Convert numbers to words: Revisited
On Jul 22, 5:28*pm, "Rick Rothstein"
wrote:
I just tried the check template that can be found at the
following url.
http://groups.google.com/group/micro...orksheet.funct...
http://tinyurl.com/NumberAsText
It did exactly what I needed it to do. Well, almost exactly. And
of course that's the problem.
The Function converts the following:
A1: *123.45
In B1:
=NumberAsText(A1) *== *One Hundred Twenty Three Point Four Five
=NumberAsText(A1,"And") *== *One Hundred and Twenty Three Point Four
Five
=NumberAsText(A1,"Check") *== *One Hundred Twenty Three and 45/100
=NumberAsText(A1,"Dollar") *== *One Hundred Twenty Three Dollars and
Forty Five Cents
The problem is that the format I write checks in is a combination of
the last two.
ie.
=NumberAsText(A1,"MyCheckFormat") *== *One Hundred Twenty Three
Dollars and 45/100
Well, since that is my function, I guess I should be the one to modify it
for you.<g In the code below, use "CheckDollar" as the optional second
argument (all other options should still work as they did originally.
Although I only changed one procedure, I decided to post the complete code
(with instructions) so that anyone viewing this in the future in the
archives will have everything they need from their one search.
--
Rick (MVP - Excel)
Go into the VB Editor (Alt+F11) and add a Module to the Workbook
(Insert/Module from the VBA menu) and then paste in all of the code
appearing after my signature into the Module's code window. You can call the
function from your work sheet like this =NumberAsText(A1) where A1 is
assumed to hold the number you want to convert. There is an Optional
argument you can use to format the results to your liking. Here are some
examples to show the options available...
A1: *123.45
In B1:
=NumberAsText(A1) *== *One Hundred Twenty Three Point Four Five
=NumberAsText(A1,"And") *== *One Hundred and Twenty Three Point Four Five
=NumberAsText(A1,"Check") *== *One Hundred Twenty Three and 45/100
=NumberAsText(A1,"Dollar") *== *One Hundred Twenty Three Dollars and Forty
Five Cents
=NumberAsText(A1,"CheckDollar") *== One Hundred Twenty Three Dollars and
45/100
To summarize, using "And" adds the word "and" in front of the tens/units
text; using "Check" formats any decimal values as would be written on a
check; and using "Dollar" adds the words "Dollars" and "Cents" in their
appropriate positions. The code is laid out in a reasonably straight forward
manner, so if Dollars/Cents is not you native currency designation, you
should be able to modify the program accordingly. In addition to the above,
for all modes, the Plus and Minus sign can be used and will be reported back
as a word; commas may be used to separate the numbers to the left of the
decimal point but they will not be reported back by the routine and are
permitted for the users convenience (however, if commas are used, they must
be placed in their correct positions). And, finally,if I remember correctly,
this function will work with a whole number part up to one less than a
quintillion (you can have as many decimal points as desired), but remember
to format large numbers as Text values... VB will convert large non-Text
values to Doubles (which will destroy the conversion).
Private sNumberText() As String
Public Function NumberAsText(NumberIn As Variant, Optional _
* * * * * * * * AND_or_CHECK_or_DOLLAR_or_CHECKDOLLAR As String) As String
* *Dim cnt As Long
* *Dim DecimalPoint As Long
* *Dim CardinalNumber As Long
* *Dim CommaAdjuster As Long
* *Dim TestValue As Long
* *Dim CurrValue As Currency
* *Dim CentsString As String
* *Dim NumberSign As String
* *Dim WholePart As String
* *Dim BigWholePart As String
* *Dim DecimalPart As String
* *Dim tmp As String
* *Dim sStyle As String
* *Dim bUseAnd As Boolean
* *Dim bUseCheck As Boolean
* *Dim bUseDollars As Boolean
* *Dim bUseCheckDollar As Boolean
* '----------------------------------------
* ' *Begin setting conditions for formatting
* '----------------------------------------
* ' *Determine whether to apply special formatting.
* ' *If nothing passed, return routine result
* ' *converted only into its numeric equivalents,
* ' *with no additional format text.
* *sStyle = LCase(AND_or_CHECK_or_DOLLAR_or_CHECKDOLLAR)
* ' *User passed "AND": "and" will be added
* ' *between hundredths and tens of dollars,
* ' *ie "Three Hundred and Forty Two"
* *bUseAnd = sStyle = "and"
* ' *User passed "DOLLAR": "dollar(s)" and "cents"
* ' *appended to string,
* ' *ie "Three Hundred and Forty Two Dollars"
* *bUseDollars = sStyle = "dollar"
* ' *User passed "CHECK" *or* "DOLLAR"
* ' *If "check", cent amount returned as a fraction /100
* ' *i.e. "Three Hundred Forty Two and 00/100"
* ' *If "dollar" was passed, "dollar(s)" and "cents"
* ' *Appended instead.
* *bUseCheck = (sStyle = "check") Or (sStyle = "dollar")
* *bUseCheckDollar = sStyle = "checkdollar"
* '----------------------------------------
* ' *Check/create array. If this is the first
* ' *time using this routine, create the text
* ' *strings that will be used.
* '----------------------------------------
* *If Not IsBounded(sNumberText) Then
* * * Call BuildArray(sNumberText)
* *End If
* '----------------------------------------
* ' *Begin validating the number, and breaking
* ' *into constituent parts
* '----------------------------------------
* ' *Prepare to check for valid value in
* *NumberIn = Trim$(NumberIn)
* *If Not IsNumeric(NumberIn) Then
* * *' *Invalid entry - abort
* * * NumberAsText = "Error - Number improperly formed"
* * * Exit Function
* *Else
* * *' *Decimal check
* * * DecimalPoint = InStr(NumberIn, ".")
* * * If DecimalPoint 0 Then
* * * * ' *Split the fractional and primary numbers
* * * * *DecimalPart = Mid$(NumberIn, DecimalPoint + 1)
* * * * *WholePart = Left$(NumberIn, DecimalPoint - 1)
* * * Else
* * * * ' *Assume the decimal is the last char
* * * * *DecimalPoint = Len(NumberIn) + 1
* * * * *WholePart = NumberIn
* * * End If
* * * If InStr(NumberIn, ",,") Or _
* * * * *InStr(NumberIn, ",.") Or _
* * * * *InStr(NumberIn, ".,") Or _
* * * * *InStr(DecimalPart, ",") Then
* * * * *NumberAsText = "Error - Improper use of commas"
* * * * *Exit Function
* * * ElseIf InStr(NumberIn, ",") Then
* * * * *CommaAdjuster = 0
* * * * *WholePart = ""
* * * * *For cnt = DecimalPoint - 1 To 1 Step -1
* * * * * * If Not Mid$(NumberIn, cnt, 1) Like "[,]" Then
* * * * * * * *WholePart = Mid$(NumberIn, cnt, 1) & WholePart
* * * * * * Else
* * * * * * * *CommaAdjuster = CommaAdjuster + 1
* * * * * * * *If (DecimalPoint - cnt - CommaAdjuster) Mod 3 Then
* * * * * * * * * NumberAsText = "Error - Improper use of commas"
* * * * * * * * * Exit Function
* * * * * * * *End If
* * * * * * End If
* * * * *Next
* * * End If
* *End If
* *If Left$(WholePart, 1) Like "[+-]" Then
* * * NumberSign = IIf(Left$(WholePart, 1) = "-", "Minus ", "Plus ")
* * * WholePart = Mid$(WholePart, 2)
* *End If
* '----------------------------------------
* ' *Begin code to assure decimal portion of
* ' *check value is not inadvertently rounded
* '----------------------------------------
* *If bUseCheck = True Then
* * * CurrValue = CCur(Val("." & DecimalPart))
* * * DecimalPart = Mid$(Format$(CurrValue, "0.00"), 3, 2)
* * * If CurrValue = 0.995 Then
* * * * *If WholePart = String$(Len(WholePart), "9") Then
* * * * * * WholePart = "1" & String$(Len(WholePart), "0")
* * * * *Else
* * * * * * For cnt = Len(WholePart) To 1 Step -1
* * * * * * * If Mid$(WholePart, cnt, 1) = "9" Then
* * * * * * * * *Mid$(WholePart, cnt, 1) = "0"
* * * * * * * Else
* * * * * * * * *Mid$(WholePart, cnt, 1) = _
* * * * * * * * * * * * * * CStr(Val(Mid$(WholePart, cnt, 1)) + 1)
* * * * * * * * *Exit For
* * * * * * * End If
* * * * * * Next
* * * * *End If
* * * End If
* *End If
* '----------------------------------------
* ' *Final prep step - this assures number
* ' *within range of formatting code below
* '----------------------------------------
* *If Len(WholePart) 9 Then
* * * BigWholePart = Left$(WholePart, Len(WholePart) - 9)
* * * WholePart = Right$(WholePart, 9)
* *End If
* *If Len(BigWholePart) 9 Then
* * * NumberAsText = "Error - Number too large"
* * * Exit Function
* *ElseIf Not WholePart Like String$(Len(WholePart), "#") Or _
* * * * *(Not BigWholePart Like String$(Len(BigWholePart), "#") _
* * * * * And Len(BigWholePart) 0) Then
* * * NumberAsText = "Error - Number improperly formed"
* * * Exit Function
* *End If
* '----------------------------------------
* ' *Begin creating the output string
* '----------------------------------------
* ' *Very Large values
* *TestValue = Val(BigWholePart)
* *If TestValue 999999 Then
* * * CardinalNumber = TestValue \ 1000000
* * * tmp = HundredsTensUnits(CardinalNumber) & "Quadrillion "
* * * TestValue = TestValue - (CardinalNumber * 1000000)
* *End If
* *If TestValue 999 Then
* * *CardinalNumber = TestValue \ 1000
* * *tmp = tmp & HundredsTensUnits(CardinalNumber) & "Trillion "
* * *TestValue = TestValue - (CardinalNumber * 1000)
* *End If
* *If TestValue 0 Then
* * * tmp = tmp & HundredsTensUnits(TestValue) & "Billion "
* *End If
* ' *Lesser values
* *TestValue = Val(WholePart)
* *If TestValue = 0 And BigWholePart = "" Then tmp = "Zero "
* *If TestValue 999999 Then
* * * CardinalNumber = TestValue \ 1000000
* * * tmp = tmp & HundredsTensUnits(CardinalNumber) & "Million "
* * * TestValue = TestValue - (CardinalNumber * 1000000)
* *End If
* *If TestValue 999 Then
* * * CardinalNumber = TestValue \ 1000
* * * tmp = tmp & HundredsTensUnits(CardinalNumber) & "Thousand "
* * * TestValue = TestValue - (CardinalNumber * 1000)
* *End If
* *If TestValue 0 Then
* * * If Val(WholePart) < 99 And BigWholePart = "" Then bUseAnd = False
* * * tmp = tmp & HundredsTensUnits(TestValue, bUseAnd)
* *End If
* ' *If in dollar mode, assure the text is the correct plurality
* *If bUseDollars = True Then
* * * CentsString =
...
read more »
If you really want to customize this I have seen people write on their
checks NO/100 instead of 00/100.
But what you have done already totally meets my needs. Thank you very
very much.
|