水如烟

秋里生活,恬淡宁静。那如洗碧空,那伏黄草地,风凉夜寂,心儿涌动,情绪萦绕。可以凭窗,可以临江,可以坐,可以仰卧,可以独处,可以相依。倚明月,抚清辉,人生多少情怀,尽在秋里?

原创 HOW TO:货币金额拼写转换收藏

新一篇: How TO:应用特定字体文件字体  | 旧一篇: HOW TO:程序内嵌自定义数据集(一)(.NET2.0) (错)

Author:水如烟

''' <summary>
'
'' 货币拼写转换
'
'' </summary>
'
'' <remarks>LzmTW 20060127</remarks>
Public Class CurrencySpell
    
'定义为静态类
    Private Sub New()
    
End Sub


    
''' <summary>
    ''' 货币金额拼写转换
    ''' </summary>
    ''' <param name="Money">金额</param>
    ''' <param name="mType">格式类型</param>
    ''' <returns>拼写字符串</returns>
    Public Shared Function Convert(ByVal Money As DecimalByVal mType As CurrencyType) As String
        
Dim mMinus As String = "" '“负”符号
        Dim mResult As String = ""

        
'如果是负金额,定义“负”符号,将输入金额转为正金额
        '!不懂财会,不知以下的定义是否正确
        If Money < 0 Then
            
Select Case mType
                
Case CurrencyType.Dollar
                    mMinus 
= "Minus "
                
Case CurrencyType.RMB
                    mMinus 
= ""
                
Case CurrencyType.RMB36
                    mMinus 
= ""
                
Case CurrencyType.RMBCaps
                    mMinus 
= ""
            
End Select
            Money 
= -Money
        
End If

        
Select Case mType
            
Case CurrencyType.Dollar
                mResult 
= Dollar.Spellout(Money)
            
Case CurrencyType.RMB36
                mResult 
= RMB.SpelloutAll(Money)
            
Case CurrencyType.RMB
                mResult 
= RMB.Spellout(Money)
            
Case CurrencyType.RMBCaps
                mResult 
= RMB.SpellCaps(Money)
        
End Select

        mResult 
= mMinus & mResult
        
Return mResult
    
End Function


    
''' <summary>
    ''' 货币金额拼写转换
    ''' </summary>
    ''' <param name="Money">金额</param>
    ''' <param name="mType">格式类型</param>
    ''' <returns>拼写字符串</returns>
    Public Shared Function Convert(ByVal Money As StringByVal mType As CurrencyType) As String
        
Dim mResult As String = ""
        
Dim mMoney As Decimal '处理字符串Money后供函数调用的实际参考值

        
'对输入字符串进行处理、验证有效性,最后转为Decimal类型
        '除去前后空格
        Money = Money.Trim

        
If Money = "" OrElse Money = "." OrElse Money = "-" OrElse Money = "-." Then
            mMoney 
= 0 '若为空,“.”或“-”或“-.”,当0处理
        Else
            
'输入字串转为Decimal类型
            '这里偷懒了,如用正则判别,不符的话也要Throw New Exception
            mMoney = Decimal.Parse(Money)
        
End If

        
'调用函数输出结果
        mResult = Convert(mMoney, mType)
        
Return mResult
    
End Function


    
''' <summary>
    ''' 格式类型
    ''' </summary>
    Public Enum CurrencyType
        
''' <summary>
        ''' 美元
        ''' </summary>
        Dollar
        
''' <summary>
        ''' 人民币
        ''' </summary>
        RMB
        
''' <summary>
        ''' 人民币36位格式
        ''' </summary>
        RMB36
        
''' <summary>
        ''' 数字大写
        ''' </summary>
        RMBCaps
    
End Enum


    
Private Class RMB
        
'定义为静态类
        Private Sub New()
        
End Sub

        
''' <summary>
        ''' 拼写单个数字
        ''' </summary>
        ''' <param name="Digit">数字字符</param>
        ''' <returns>字符串数字</returns>
        Private Shared Function spSingle(ByVal Digit As StringAs String
            
Dim mResult As String = ""
            
Select Case Digit
                
Case "0"
                    mResult 
= ""
                
Case "1"
                    mResult 
= ""
                
Case "2"
                    mResult 
= ""
                
Case "3"
                    mResult 
= ""
                
Case "4"
                    mResult 
= ""
                
Case "5"
                    mResult 
= ""
                
Case "6"
                    mResult 
= ""
                
Case "7"
                    mResult 
= ""
                
Case "8"
                    mResult 
= ""
                
Case "9"
                    mResult 
= ""
                
Case "."
                    mResult 
= "."
            
End Select
            
Return mResult
        
End Function


        
''' <summary>
        ''' 数字大写
        ''' </summary>
        ''' <param name="mMoney"></param>
        Friend Shared Function SpellCaps(ByVal mMoney As DecimalAs String
            
Dim mResult(mMoney.ToString.Length - 1As String
            
Dim tmp As String = mMoney.ToString
            
For i As Integer = 0 To tmp.Length - 1
                mResult(i) 
= spSingle(tmp.Substring(i, 1))
            
Next
            
Return String.Concat(mResult)
        
End Function


        
'本函数采用格式化来处理.
        '定义金额最大格式,然后将金额转为相应字符数组装填

        
''' <summary>
        ''' 36位格式,形如“零仟零佰零拾零兆零仟零佰零拾零亿零仟零佰壹拾贰万叁仟肆佰伍拾陆元柒角捌分”共36位
        ''' </summary>
        ''' <param name="mMoney">金额</param>
        Friend Shared Function SpelloutAll(ByVal mMoney As DecimalAs String
            
Dim mSpellFormat As String = _
            
"{0}仟{1}佰{2}拾{3}兆{4}仟{5}佰{6}拾{7}亿{8}仟{9}佰{10}拾{11}万{12}仟{13}佰{14}拾{15}元{16}角{17}分" '共18位数字
            Dim mResult As String = ""

            
'这里加上0.00000001是为了保证有小数位
            mMoney += 0.00000001D

            
'小数角分部分依逢五进一取.对于Net1.0版本的Decimal.Round,若舍去位是5,前头一位是奇数则进位,偶数则不进.而Net2.0可用以下方法实现
            mMoney = Decimal.Round(mMoney, 2, MidpointRounding.AwayFromZero)

            
'临时转为字符串存到mResult中
            mResult = mMoney.ToString

            mResult 
= mResult.Replace(".""")   '金额字符串,小数二位,略去小数点
            '为保证18位数字字符,前面置0
            mResult = mResult.PadLeft(18"0"c)

            
'将数字字符串转为数组,使用spSingle函数得到相应的拼写,存到tmp临时数组中.再格式化存入mResult去.
            Dim tmp(17As String
            
For i As Integer = 0 To 17
                tmp(i) 
= spSingle(mResult.Substring(i, 1))
            
Next
            mResult 
= String.Format(mSpellFormat, tmp)
            
'到了这里,金额为123456.775转换成以下字符串.这个字符串对票据固有格式的填位较为方便,使用时按实际要求进行截取和格式化
            '零仟零佰零拾零兆零仟零佰零拾零亿零仟零佰壹拾贰万叁仟肆佰伍拾陆元柒角捌分

            
Return mResult
        
End Function



        
''' <summary>
        ''' 拼写输出
        ''' </summary>
        ''' <param name="mMoney">金额</param>
        ''' <returns>金额拼写字符串</returns>
        Friend Shared Function Spellout(ByVal mMoney As DecimalAs String
            
Dim mResult As String = ""
            
'取36位格式
            mResult = SpelloutAll(mMoney)
            
'转规范处理
            mResult = Normalization(mResult)

            
Return mResult
        
End Function



        
''' <summary>
        ''' 格式字符串的规范处理
        ''' </summary>
        ''' <param name="spellFormatString">36位格式</param>
        Private Shared Function Normalization(ByVal spellFormatString As StringAs String
            
Dim mResult As String = ""
            
'取36位格式
            mResult = spellFormatString

            
'处理元后面部分.
            '除去零角或零分.
            mResult = System.Text.RegularExpressions.Regex.Replace(mResult, "零[角分]""")
            
'若结尾是元,用元整来代替.
            mResult = System.Text.RegularExpressions.Regex.Replace(mResult, "元$""元整")

            
'零仟零佰零拾零[兆亿万元],都要除去.只是元为基本单位需要保留,所以这里加上一个元,判别完后置回
            mResult = System.Text.RegularExpressions.Regex.Replace(mResult, """元元")
            mResult 
= System.Text.RegularExpressions.Regex.Replace(mResult, "零仟零佰零拾零[兆亿万元]""")
            mResult 
= System.Text.RegularExpressions.Regex.Replace(mResult, "元元""")

            
'现在的焦点是看 X仟X佰X拾X[兆亿万元],其中四个X中至少有一个不为零.
            '凡零[仟佰拾]的,都用一个零表示
            mResult = System.Text.RegularExpressions.Regex.Replace(mResult, "零[仟佰拾]""")
            
'出现两个零及以上的,用一个零表示
            mResult = System.Text.RegularExpressions.Regex.Replace(mResult, "零{2,}""")
            
'零[兆亿万元]的,去掉零
            mResult = System.Text.RegularExpressions.Regex.Replace(mResult, "零([兆亿万元])""${1}")

            
'最后结果整理
            '零开头的,去掉零
            mResult = System.Text.RegularExpressions.Regex.Replace(mResult, "^零""")
            
'元开头的,前加零
            mResult = System.Text.RegularExpressions.Regex.Replace(mResult, "^元""零元")

            
Return mResult
        
End Function

    
End Class


    
'本类参照《SQL Server 7编程技术内幕》8.2.3章节关于拼写金额存储过程而做,该书作者John Papa,Matthew Shepker等。
    '英文书名 Microsoft SQL Server 7.0 Programming Unleashed
    '机械工业出版社 ISBN 7-111-07649-4
    Private Class Dollar
        
'定义为静态类
        Private Sub New()
        
End Sub


        
''' <summary>
        ''' 拼写单个数字
        ''' </summary>
        ''' <param name="Digit">数字字符</param>
        ''' <returns>字符串数字</returns>
        Private Shared Function spSingle(ByVal Digit As StringAs String
            
Dim mResult As String = ""
            
Select Case Digit
                
Case "0"
                
Case "1"
                    mResult 
= "One"
                
Case "2"
                    mResult 
= "Two"
                
Case "3"
                    mResult 
= "Three"
                
Case "4"
                    mResult 
= "Four"
                
Case "5"
                    mResult 
= "Five"
                
Case "6"
                    mResult 
= "Six"
                
Case "7"
                    mResult 
= "Seven"
                
Case "8"
                    mResult 
= "Eight"
                
Case "9"
                    mResult 
= "Nine"
            
End Select
            
Return mResult
        
End Function


        
''' <summary>
        ''' 拼写十位列
        ''' </summary>
        ''' <param name="Digit">两位数字字符串</param>
        ''' <returns>十位字符串</returns>
        Private Shared Function spTwonum(ByVal Digit As StringAs String
            
Dim mResult As String = ""
            
Select Case Digit.Substring(01)
                
Case "0"
                
Case "1"
                    
Select Case Digit
                        
Case "10"
                            mResult 
= "Ten"
                        
Case "11"
                            mResult 
= "Eleven"
                        
Case "12"
                      &nb