我注意到excel中的奇怪和恼人的行为可能是由于比利时的数字符号不同。 当我在即时窗口中输入此内容时,我会得到反直觉的结果:
?val("0,5")
0
?val("0.5")
0,5
所以我的解决方法就是像这样使用它(通常字符串“0,5”被 textbox.value 替换)
val(replace("0,5",",","."))
同样,当使用numberformat()函数时,这会让我陷入这种麻烦。
起初,我在文本框中有一个受限制的KeyPresses:
Select Case KeyAscii
Case vbKey0 To vbKey9, vbKeyBack, vbKeyClear, vbKeyDelete, vbKeyLeft, _
vbKeyRight, vbKeyUp, vbKeyDown, vbKeyTab, vbDecimal
Case Else
KeyAscii = 0
Beep
End Select
但是vbDecimal只允许我输入'。'作为小数点,然后在运行时它将被解释为1000的值。
对此有何看法?
答案 0 :(得分:2)
Val
功能仅识别“。”作为小数分隔符(您可以在相应的MSDN article中阅读);与其他VBA功能相同的事情发生。因此,如果您修改由VBA / Excel计算的小数分隔符,相当多的函数将无关紧要(并且将继续使用“。”)。我通常做的是设置一个自定义函数来分析所有输入数据(它可以只包含你在问题中引用的基本Replace
;但我也可以利用它来调整数字格式到一个我期待的,例如:最大小数位数),确保在计算过程中计算的所有小数分隔符都是“。”。完成所有计算后,我有另一个功能来使输出适应预期的格式(通过修改Excel单元格或数字变量本身)。如果你知道的话,这不是一个理想的情况,也不是一个难以解决的问题。
答案 1 :(得分:1)
修改强> 的 找到了覆盖“区域区域设置数字设置”
的良好示例here您可以通过查看当地的环境变量来尝试容纳欧洲或美国的分离者。
'Locale support
Private Declare Function GetLocaleInfo Lib "kernel32" Alias "GetLocaleInfoA" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String, ByVal cchData As Long) As Long
Const LOCALE_ICOUNTRY = &H5 ' country code
Const LOCALE_SENGCOUNTRY = &H1002 ' English name of country
Const LOCALE_USER_DEFAULT = &H400
然后在你的代码中做这样的事情:
If getLocale <= 1 Then 'US
'use commas
else 'UK
'use period
End If
我确信有一种更有效的方法但是如果你加载一个dll,你现在可以根据你的支持有两个不同的dll负载。
答案 2 :(得分:1)
在巴西,我们使用相同的数字符号(“,”作为小数分隔符,“。”作为千位分隔符)。我通常使用CDbl()
来转换数字,因为它会考虑区域语言环境设置。
正如您已经提出的那样,val()
对于我来说对任何现实世界的使用都太不一致了。它很容易与逗号和点混淆。
这是我对每个功能的看法。请记住,该值在区域设置中返回(在本例中,逗号为小数点分隔符),但在内部它独立于表示法。
? val("2.500,50")
2,5
? cdbl("2.500,50")
2500,5
这里,val()
停止读取逗号上的字符串 - 因此只读取“2.500”,并将点视为小数点分隔符。另一方面,CDbl()
完全识别出这个数字。
? val("2,500.50")
2
? cdbl("2,500.50")
2,5005
在这里,一切都变得一团糟,你可以看到......再次val()
停止阅读逗号(尽管数字是美国符号),CDbl()
与之混淆在小数点分隔符后“错放”了千位分隔符并忽略它。
答案 3 :(得分:0)
Public Function GetNumber(ByVal Subject As String, ByVal Default As Double) As Double
GetNumber = Default
On Error GoTo EndNow
Subject = Replace(Subject, ",", ".")
Subject = Trim(Subject)
Dim SplitArray() As String
SplitArray = Split(Subject, ".", 2)
Dim FirstNumber As Double
Dim SecondNumber As Double
SecondNumber = 1
Dim IndexOne As Long
Dim IndexTwo As Long
Dim PowerLength As Long
IndexOne = LBound(SplitArray)
IndexTwo = UBound(SplitArray)
FirstNumber = CDbl(SplitArray(IndexOne))
GetNumber = FirstNumber
If (IndexTwo > IndexOne) Then
SecondNumber = CDbl(SplitArray(IndexTwo))
PowerLength = Len("" & CDbl("1" & SplitArray(IndexTwo)))
PowerLength = PowerLength - 1
If (FirstNumber < 0) Then
SecondNumber = SecondNumber * -1
End If
GetNumber = GetNumber + (SecondNumber / Application.WorksheetFunction.Power(10, PowerLength))
End If
EndNow:
End Function