CLng() 和 CDbl() 正在删除小数

Cor*_*rey 4 excel vba type-conversion internationalization

如果我CLng("22.14")在我的 PC 的 Excel VBA 编辑器中运行,我会得到预期的结果,22. 如果我在一些国际同事的 PC上执行此操作,则会产生2214.

CDbl正在做类似的事情。我得到22.14,他们得到2214

我的想法:我假设一些设置定义了十进制字符(我的正确是“.”,而他们的则是别的)。我的搜索没有产生任何其他想法或解决方案。

Com*_*ern 5

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
Run Code Online (Sandbox Code Playgroud)

我所知道的唯一与主机无关的解决方法(除了不将数字存储为String数据)是完全绕过内置的 VBA 转换,并直接使用硬调用oleaut32.dll 中的底层转换函数编码的区域设置 ID。例如,Double要从 en-US 本地化字符串中获取 a :

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
Run Code Online (Sandbox Code Playgroud)

...或一个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
Run Code Online (Sandbox Code Playgroud)

用法示例:

Public Sub Sample()
    Debug.Print LongFromEnUsString("12.34")     '12
    Debug.Print DoubleFromEnUsString("12.34")   '12.34
End Sub
Run Code Online (Sandbox Code Playgroud)