这一楼放VBA代码,有兴趣的可以翻译为VFP代码。

程序代码:
Option Explicit
Const BiaoChi As String = "十百千万 亿" '本字串中的顺序和中间的空格有讲究
Public Function UsrChnDstr2Digtal(ByVal zf0 As Range, Optional iType As Integer = 0) As Variant
'把中文数字字串转换为阿拉伯字串,精确到小数点后四位(后来不限制了),最大不超过千亿.
'特点:能自动排除用户输入的其它字符,支持中文大小写阿拉伯数字混输。
'支持字符中以“元”或“点”界定小数点位置
'参数1:一个中文字串(或一个Range对象)
'参数2:决定返回字串(默认值)还是返回双精度数值?
'代码:王德榜 2019-12-25
Dim zf As String, zfAlone As String, zfXs As String '净化后的字串,取出的单个字串,净化后的小数部分字串
Dim zfZs As String, zf2Xs As String, zf2Out As String '尝试返回的结果:整数部分字串(填充零后),小数部分字串,整数部分字串(输出)
Dim iXsd As Integer, ii As Integer, iWw As Integer, iYy As Integer '是否含有小数点/临时变量/万位以上/亿以上
Dim zf3Out As Double '数字结果,整数+小数部分
Dim zfZF As String '正负标志
Dim iLocalW As Integer, iLocalY As Integer '万位/亿位.在标尺中的位置
iLocalW = InStr(1, BiaoChi, "万", vbTextCompare)
iLocalY = InStr(1, BiaoChi, "亿", vbTextCompare)
'检查用户输入的值是否超过本函数的允许值(小不超过小数后4位,大不超过千亿)
If InStr(1, zf0, "兆", vbTextCompare) > 0 Then
UsrChnDstr2Digtal = IIf(iType = 0, "数据超范围。", 999999999999#)
Exit Function
End If
zf = zf0
If Left(zf, 1) = "负" Or Left(zf, 1) = "-" Or Left(zf, 1) = "-" Then
zfZF = "-" '先判断正负.
zf = Mid(zf, 2)
End If
zf = ProcStr(zf) '先净化字串
'排除用户可能的错误输入:例如一万零零五元,应为一万零五元
While InStr(1, zf, "〇〇", vbTextCompare) > 0
zf = Replace(zf, "〇〇", "〇", 1, -1, vbTextCompare)
Wend
'检查用户输入的值是否超过本函数的允许值(小不超过小数后4位,大不超过千亿)
'原来是小不超过小数点后四位,后来放开这个限制,就不再截断字串了.
iXsd = InStr(1, zf, "点", vbTextCompare) '再判断是否含有小数点,若iXsd>0表示含有小数点
If iXsd > 0 Then '如果有小数点,先处理小数部分.
zfXs = Mid(zf, iXsd)
For ii = 1 To Len(zfXs)
zfAlone = Mid(zfXs, ii, 1)
zf2Xs = zf2Xs & GetAlone(zfAlone)
' If ii > 1 Then '这是原来想直接获取小数部分数值型值的想法,后来觉得太麻烦不用了.
' zf3Xs = zf3Xs + Val(GetAlone(zfAlone)) * GetWs(LTrim(Str((ii - 1) * -1)))
' End If
Next ii
zf = Left(zf, iXsd - 1) '处理完小数部分后,小数后部分就不用了.
End If
'接下来处理整数部分,整数部分必须考虑"〇"占位的问题,
'例如"一万〇二"转换为"一〇〇〇二","一千〇二"转换为"一〇〇二","一千"转换为"一〇〇〇"
'也就是说,把标志位"千"替换为相应多的"〇"
For ii = Len(zf) To 1 Step -1 '考虑到上述问题,整数部分倒循环比较好.
zfAlone = Mid(zf, ii, 1)
iXsd = InStr(1, BiaoChi, zfAlone, vbTextCompare) '再判断取出的单个字符是否恰是"亿万千百十"中的一个标志位
'由于BiaoChi字串作了精心的安排,此时取出的数位长度与iXsd恰好相关.
If iXsd > 0 Then '是标志位字符,则检查填充的〇够不够?够了的话,再去掉标志字符.
If iWw = 0 And iYy = 0 Then '万和亿都尚未出现.此时补足到整个字串长度的"〇"
If Len(zfZs) < iXsd Then zfZs = String(iXsd - Len(zfZs), "〇") & zfZs
ElseIf iWw > 0 And iYy = 0 Then '万已出现,而亿尚未出现.此时补足到"万"的"〇"
iWw = InStr(1, zfZs, "万", vbTextCompare)
If zfAlone <> "亿" Then
If iWw - 1 < iXsd Then zfZs = String(iXsd - iWw + 1, "〇") & zfZs
Else '此时看“亿”与“万”之间的“〇”+其它数字够不够?不够补足三个.
If iWw - 1 < iLocalY - iLocalW Then zfZs = String(iLocalY - iLocalW - iWw + 1, "〇") & zfZs
End If
ElseIf iYy > 0 And iWw > 0 Then '万和亿都已出现.此时补足到"亿"的"〇"
iYy = InStr(1, zfZs, "亿", vbTextCompare)
If iYy - 1 < iXsd Then zfZs = String(iXsd - iYy + 1, "〇") & zfZs
ElseIf iYy > 0 And iWw = 0 Then '万未出现,但亿单独出现了(比如"三亿"/"三亿零五百".此时补足到"亿"的"〇"
iYy = InStr(1, zfZs, "亿", vbTextCompare)
If iYy - 1 < iXsd Then zfZs = String(iXsd - iYy + 1, "〇") & zfZs
End If
If (zfAlone = "万" And Left(zfZs, 1) <> "万") Then
zfZs = zfAlone & zfZs '"万" Or "亿"标志位先保留,方便找出十万/百万/千万/十亿/百亿/千亿
iWw = Len(zfZs) ' InStr(1, zf, "万", vbTextCompare) '找到“万”位置,万是一个重要节点。
End If
If (zfAlone = "亿" And Left(zfZs, 1) <> "亿") Then
zfZs = zfAlone & zfZs '"万" Or "亿"标志位先保留,方便找出十万/百万/千万/十亿/百亿/千亿
iYy = Len(zfZs) ' InStr(1, zf, "亿", vbTextCompare) '找到“亿”位置,亿是一个重要节点。
End If
Else '不是标志位字符,且字符是数字的(不是胡乱输入的),则字符直接相加,此步可以进一步过滤用户的乱输入.
'比如用户输入 "二亿一千万欠三百元",中间有"欠"字,既非标志字符,又不是数字字符,则应该在此步过滤掉.
If InStr(1, "一,二,三,四,五,六,七,八,九,〇,1,2,3,4,5,6,7,8,9,0", zfAlone, vbTextCompare) Then zfZs = zfAlone & zfZs
End If
Next ii
'整数部分填充零完毕,接下来可直接"翻译"输出了:
zfZs = Replace(zfZs, "万", "", 1, -1, vbTextCompare) '但是,在正式"翻译"前,
zfZs = Replace(zfZs, "亿", "", 1, -1, vbTextCompare) '须先把"万","亿"还原.
For ii = 1 To Len(zfZs)
zfAlone = Mid(zfZs, ii, 1)
zf2Out = zf2Out & GetAlone(zfAlone)
Next ii
zf3Out = Val(zfZF & zf2Out & zf2Xs)
'返回整数 + 小数部分:
If iType = 0 Then
' Debug.Print zf0 & "-->" & zf & zfXs & "==>"; zf2Out & zf2Xs
UsrChnDstr2Digtal = zfZF & zf2Out & zf2Xs
Else
' Debug.Print zf3Out
UsrChnDstr2Digtal = zf3Out
End If
End Function
Function GetWs(ByVal str1) As Double
'返回万千百拾等字符对应的位数 --后来觉得直接获取字符型值要简单些,这个Func不用了.
'例如参数为“万”则返回数字10000
'如果原始字串含有“点”则证明有小数点后数字,参数为“-1”,则返回数字0.1;参数为“-2”,则返回数字0.01
Select Case str1
Case "-1"
GetWs = 0.1
Case "-2"
GetWs = 0.01
Case "-3"
GetWs = 0.001
Case "-4"
GetWs = 0.0001
Case "十"
GetWs = 10
Case "百"
GetWs = 100
Case "千"
GetWs = 1000
Case "万"
GetWs = 10000
Case "十万"
GetWs = 100000
Case "百万"
GetWs = 1000000
Case "千万"
GetWs = 10000000
Case "亿"
GetWs = 100000000
Case "十亿"
GetWs = 1000000000
Case "百亿"
GetWs = 10000000000#
Case "千亿"
GetWs = 100000000000#
End Select
End Function
Function GetAlone(ByVal str1) As String
'本模块的任务:返回单个数字,
'把“一二三”等字符转换为“123”等对应的数字字符
Dim dx1 As String, dx2 As String, strTmp
Dim arrDx1() As String, arrDx2() As String
Dim ii As Integer
strTmp = str1
dx2 = "1,2,3,4,5,6,7,8,9,0,."
dx1 = "一,二,三,四,五,六,七,八,九,〇,点"
arrDx1 = Split(dx1, ",")
arrDx2 = Split(dx2, ",")
'Debug.Print UBound(arrDx1)
For ii = 0 To UBound(arrDx1)
If InStr(1, strTmp, arrDx1(ii), vbTextCompare) > 0 Then
strTmp = Replace(strTmp, arrDx1(ii), arrDx2(ii), 1, -1, vbTextCompare)
End If
Next ii
GetAlone = strTmp
End Function
Function ProcStr(ByVal str1) As String
'净化原始字串,本模块的任务有:
'统一“节点标志”,比如,把“仟”换为“千”;佰->百;拾->十;元->点;角、分->无
'再把大写的“壹贰叁”等转换为“一二三”
'若字符串的首字符为“拾”或“十”,则首字符换为“一”
'若字符串的首字符为除“拾”之外的“百/千/万/亿”等“标志位”,则去掉首字符。
'若字符串的末字符为“点”,则去掉末字符。
Dim dx1 As String, dx2 As String, strTmp
Dim arrDx1() As String, arrDx2() As String
Dim ii As Integer
strTmp = str1
dx1 = "壹,贰,叁,肆,伍,陆,柒,捌,玖,零,仟,拾,佰,元,角,分,正,整"
dx2 = "一,二,三,四,五,六,七,八,九,〇,千,十,百,点,,,,"
arrDx1 = Split(dx1, ",")
arrDx2 = Split(dx2, ",")
'Debug.Print UBound(arrDx1)
For ii = 0 To UBound(arrDx1)
If InStr(1, strTmp, arrDx1(ii), vbTextCompare) > 0 Then
strTmp = Replace(strTmp, arrDx1(ii), arrDx2(ii), 1, -1, vbTextCompare)
End If
Next ii
If Left(strTmp, 1) = "十" Then strTmp = "一" & strTmp '若字符串的首字符为“拾”或“十”,则首字符换为“一”
'若字符串的首字符为除“拾”之外的“百/千/万/亿”等“标志位”,则去掉首字符。
If InStr(1, "百/千/万/亿", Left(strTmp, 1), vbTextCompare) > 0 Then strTmp = Mid(strTmp, 2)
If Right(strTmp, 1) = "点" Then strTmp = Left(strTmp, Len(strTmp) - 1) '若字符串的末字符为“点”,则去掉末字符。
ProcStr = strTmp
End Function