如果我在PC的Excel VBA编辑器中运行CLng("22.14")
,则会得到预期的结果22
。如果我在某些国际同事的PC上执行此操作,它将产生2214
。
CDbl
在做类似的事情。我得到22.14
,他们得到2214
。
我的想法:我假设某个设置定义了小数字符(我的正确是“。”,而其他则是“。”)。我的搜索没有其他想法或解决方案。
答案 0 :(得分:4)
VBA中的所有数字转换函数都支持区域设置,因此它们将忽略数千个分隔符和货币符号。 IsNumeric
函数的行为方式相同:
Public Sub Example()
'en-US locale
Debug.Print IsNumeric("$1,1,1,1,1,") 'True
Debug.Print CLng("$1,1,1,1,1,") '11111
End Sub
我知道用于处理此问题的唯一主机不可知的解决方法(除了不将数字存储为String
之外)是完全绕过内置的VBA强制转换,并调用基础的{{3 }}直接使用硬编码的区域设置ID。例如,要从美国本地化字符串中获取Double
:
Public Declare PtrSafe Function VarR8FromStr Lib "oleaut32" _
(ByVal strIn As LongPtr, ByVal lcid As Long, ByVal dwFlags As Long, ByRef pdblOut As Double) As Long
Public Const EN_US As Long = 1033
Public Function DoubleFromEnUsString(converting As String) As Double
Dim converted As Double, result As Long
result = VarR8FromStr(StrPtr(converting), EN_US, 0, converted)
If (result = 0) Then
DoubleFromEnUsString = converted
Else
Err.Raise 5
End If
End Function
...或Long
:
Public Declare PtrSafe Function VarI4FromStr Lib "oleaut32" _
(ByVal strIn As LongPtr, ByVal lcid As Long, ByVal dwFlags As Long, ByRef plOut As Long) As Long
Public Const EN_US As Long = 1033
Public Function LongFromEnUsString(converting As String) As Long
Dim converted As Long, result As Long
result = VarI4FromStr(StrPtr(converting), EN_US, 0, converted)
If (result = 0) Then
LongFromEnUsString = converted
Else
Err.Raise 5
End If
End Function
用法示例:
Public Sub Sample()
Debug.Print LongFromEnUsString("12.34") '12
Debug.Print DoubleFromEnUsString("12.34") '12.34
End Sub
答案 1 :(得分:3)
两个最常见的十进制分隔符是"."
(美国,英国...)和","
(意大利,法国...)。
您可以使用Application.DecimalSeparator
(返回操作系统的分隔符)从VBA轻松访问此属性。
正确解决方案不是将"22.14"
视为String
,而是将其视为实数,这样,这种国际化问题就可以解决了。系统。
如果确实的这个数字不能与String
相同(例如,您是从英语/美国API获取这些值,则向您发送反序列化的数字),然后您可以使用类似的功能:
Function InternationalCLng(ByVal st As String)
Dim EnglishSep As Boolean: EnglishSep = ("." = Application.DecimalSeparator)
If Not EnglishSep Then
st = Replace(st, ".", Application.DecimalSeparator)
End If
InternationalCLng = CLng(st)
End Function
...将.
替换为正确的DecimalSeparator
,而使用InternationalCLng("22.14")
。
但老实说,这是一个hack。