对于所有内容(公式,界面,指南),我的Excel均设置为英语。 我的Windows使用小数点符号“,”和“。”设置。我在意大利居住时在区域设置中使用数字分组符号。
如果我编写这段代码:
Dim v As Variant
v = CDec("12345678901234567000,123456789")
v = v + 50
结果在“本地”窗口中显示为“ 12345678901234567050,123456789”(变量/十进制)。如果我用msgbox也是一样。
如果我使用“。”而不是“,”,结果是12345678901234567000123456839。
在VBA中,当写数字(以数字形式,而不是字符串形式)时,我必须使用英文语法,即“。”。十进制符号。
我相信我的示例代码将在具有英语区域设置的Windows上错误地运行。
如何(进行修改)使其在任何区域设置下都能正常运行?
答案 0 :(得分:1)
C*
转换功能(CInt
,CLng
,CStr
等)均设计为在计算机的当前语言环境下工作。它们将使用当前的小数点分隔符,因此假设CDec
将无法在具有不同小数点的系统上正确处理硬编码的,
,是正确的。
相反,Str
和Val
始终与英文分隔符一起使用,但它们不支持Decimal
。
因此想到的一种选择是获取小数点at runtime:
Dim v As Variant
v = CDec("12345678901234567000" & Application.International(xlDecimalSeparator) & "123456789")
但是请注意,如果Application.UseSystemSeparators
为False
并且Application.DecimalSeparator
被更改,那么Application.International(xlDecimalSeparator)
将return that changed separator,而不是来自计算机语言环境。因此,如果不能保证UseSystemSeparators
是True
,请不要使用此方法。
另一种选择是用除以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>