CDec:带小数的参数字符串的国际语法

时间:2019-07-05 10:49:08

标签: vba regional-settings

对于所有内容(公式,界面,指南),我的Excel均设置为英语。 我的Windows使用小数点符号“,”和“。”设置。我在意大利居住时在区域设置中使用数字分组符号。

如果我编写这段代码:

    Dim v As Variant
    v = CDec("12345678901234567000,123456789")
    v = v + 50

结果在“本地”窗口中显示为“ 12345678901234567050,123456789”(变量/十进制)。如果我用msgbox也是一样。

如果我使用“。”而不是“,”,结果是12345678901234567000123456839。

在VBA中,当写数字(以数字形式,而不是字符串形式)时,我必须使用英文语法,即“。”。十进制符号。

我相信我的示例代码将在具有英语区域设置的Windows上错误地运行。

如何(进行修改)使其在任何区域设置下都能正常运行?

1 个答案:

答案 0 :(得分:1)

C*转换功能(CIntCLngCStr等)均设计为在计算机的当前语言环境下工作。它们将使用当前的小数点分隔符,因此假设CDec将无法在具有不同小数点的系统上正确处理硬编码的,,是正确的。

相反,StrVal始终与英文分隔符一起使用,但它们不支持Decimal


因此想到的一种选择是获取小数点at runtime

Dim v As Variant
v = CDec("12345678901234567000" & Application.International(xlDecimalSeparator) & "123456789")

但是请注意,如果Application.UseSystemSeparatorsFalse并且Application.DecimalSeparator被更改,那么Application.International(xlDecimalSeparator)return that changed separator,而不是来自计算机语言环境。因此,如果不能保证UseSystemSeparatorsTrue,请不要使用此方法。


另一种选择是用除以10的幂的形式表示小数位,这对于精确的定点Decimal数据类型是很好的:

Dim v As Variant
v = CDec("12345678901234567000123456789") / CDec("1000000000")

另一种选择是拥有一个自定义的“ CDec”,该自定义“ CDec”在特定语言环境中显式工作,并始终在该语言环境中对字符串进行硬编码:

Option Explicit

#If VBA7 Then
Private Declare PtrSafe Function VarDecFromStr Lib "OleAut32.dll" (ByVal strIn As LongPtr, ByVal lcid As Long, ByVal dwFlags As Long, ByRef pdecOut As Variant) As Long
#Else
Private Declare Function VarDecFromStr Lib "OleAut32.dll" (ByVal strIn As Long, ByVal lcid As Long, ByVal dwFlags As Long, ByRef pdecOut As Variant) As Long
#End If

Private Const LOCALE_INVARIANT As Long = &H7F&
Private Const S_OK As Long = &H0

Public Function ParseDecimalFromEnUsString(ByVal s As String) As Variant
  Dim hr As Long

  hr = VarDecFromStr(StrPtr(s), LOCALE_INVARIANT, 0, ParseDecimalFromEnUsString)

  If hr <> S_OK Then
    Err.Raise 5, , "Cannot parse the string. Error " & Hex$(hr)
  End If
End Function
? ParseDecimalFromEnUsString("12345678901234567000.123456789")
12345678901234567000,123456789

? TypeName(ParseDecimalFromEnUsString("12345678901234567000.123456789"))
Decimal

(有关此代码的版本对what the string is allowed to contain有更多控制权,请参见此答案的revision 3。接收NUMPRS_STD的参数是要更改的参数。)< / em>