''' <summary>
''' A FormatProvider specific to the Money structure, which will format the
''' Money value the word representation.
''' </summary>
''' <remarks></remarks>
Public Class MoneyWordFormatter
Implements ICustomFormatter, IFormatProvider
Private _result As Text.StringBuilder
Public Function Format(ByVal formatString As String, ByVal arg As Object, ByVal formatProvider As System.IFormatProvider) As String Implements System.ICustomFormatter.Format
If TypeOf arg Is Money Then
Dim mny As Money = CType(arg, Money)
Return ValueToWords(mny)
ElseIf TypeOf arg Is Decimal Then
Return ValueToWords(New Money(arg))
End If
Return ""
End Function
Public Function GetFormat(ByVal formatType As System.Type) As Object Implements System.IFormatProvider.GetFormat
If formatType Is GetType(ICustomFormatter) Then
Return Me
Else
Return Nothing
End If
End Function
Private Function ValueToWords(ByVal value As Money) As String
Dim nfi As New NumberFormatInfo
nfi.NumberGroupSeparator = ""
Dim temp As String = Math.Abs(value.Value).ToString("N2", nfi)
Dim m As Decimal = Decimal.Parse(temp)
_result = New Text.StringBuilder
If Math.Abs(m) < 1 Then
_result.Append("No")
Else
temp = temp.PadLeft(15, "0"c)
SubProcess(0, temp, "Billion")
SubProcess(3, temp, "Million")
SubProcess(6, temp, "Thousand")
Dim number As Integer = Integer.Parse(temp.Substring(9, 3))
If number > 0 And number < 100 Then
If _result.ToString.Length > 0 Then
_result.Append("And ")
End If
End If
SubProcess(9, temp)
End If
If Not _result.ToString.EndsWith(" ") Then
_result.Append(" ")
End If
_result.Append("Dollar")
If Decimal.Truncate(m) <> 1 Then
_result.Append("s ")
Else
_result.Append(" ")
End If
Dim cents As Integer = 0
Dim input As String = "000"
input = temp.Substring(temp.IndexOf(".") + 1).PadRight(2, "0"c)
If input.Length > 6 Then
input = input.Substring(0, 6)
End If
cents = Integer.Parse(input)
If cents = 0 Then
_result.Append("And No")
Else
_result.Append("And ")
SubProcess(0, input)
End If
If cents = 1 Then
_result.Append(" Cent")
Else
_result.Append(" Cents")
End If
Return _result.ToString
End Function
Private Sub SubProcess(ByVal start As Integer, ByVal value As String, Optional ByVal wordToAdd As String = "")
Dim input As String = value.PadLeft(3, "0").Substring(start, 3)
Dim number As Integer = Integer.Parse(input)
If number <> 0 Then
ConvertInput(input)
If wordToAdd.Length > 0 Then
If Not _result.ToString.EndsWith(" "c) Then _result.Append(" ")
_result.Append(wordToAdd)
_result.Append(" ")
End If
End If
End Sub
Private Sub ConvertInput(ByVal input As String)
Dim hundred As Integer = Integer.Parse(input.PadLeft(3, "0"c).Substring(0, 1))
If hundred > 0 Then
AppendLiteral(hundred)
_result.Append(" Hundred")
End If
Dim tens As Integer = Integer.Parse(input.PadLeft(3, "0"c).Substring(1, 2))
If hundred > 0 AndAlso tens > 0 Then
_result.Append(" And ")
End If
AppendLiteral(tens)
End Sub
Private Sub AppendLiteral(ByVal index As Integer)
If index < 20 Then
_result.Append(GetString(index))
Else
Dim tens As Integer = Convert.ToInt32(index \ 10) * 10
_result.Append(GetString(tens))
If index > tens Then
index -= tens
_result.Append(" ")
_result.Append(GetString(index))
End If
End If
End Sub
Private Function GetString(ByVal value As Integer) As String
Select Case value
Case 0
Return ""
Case Is < 10
Return Choose(value, "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine")
Case 11 To 19
Return Choose(value - 10, "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen")
Case Else
Return Choose(value \ 10, "Ten", "Twenty", "Thirty", "Fourty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety")
End Select
End Function
End Class