我已经编写了一个函数来处理有效数字减少百分比的计算,并且我在保留尾随零时遇到问题。 功能:
Function RegexReduction(IValue As Double, EValue As Double) As String
Dim TempPercent As Double
Dim TempString As String
Dim NumFormat As String
Dim DecPlaces As Long
Dim regex As Object
Dim rxMatches As Object
TempPercent = (1 - EValue / IValue)
NumFormat = "0"
Set regex = CreateObject("VBScript.RegExp")
With regex
.Pattern = "([^1-8])*[0-8]{1}[0-9]?"
.Global = False
End With
Set rxMatches = regex.Execute(CStr(TempPercent))
If rxMatches.Count <> 0 Then
TempString = rxMatches.Item(0)
DecPlaces = Len(Split(TempString, ".")(1)) - 2
If DecPlaces > 0 Then NumFormat = NumFormat & "." & String(DecPlaces, "0")
End If
RegexReduction = Format(TempPercent, NumFormat & "%")
End Function
在任何前导零或九之后将百分比修剪为两位数:
99.999954165% -> 99.99954%
34.564968% -> 35%
0.000516% -> 0.00052%
我发现的一个问题与正则表达式无关,而是与Excel的四舍五入有关:
99.50% -> 99.5%
是否有解决方案可以保存可在此处实现的尾随零?
答案 0 :(得分:1)
这是一个UDF,它试图“读取”传入的原始(非百分比)值,以确定要包含的小数位数。
Function udf_Specific_Scope(rng As Range)
Dim i As Long, str As String
str = rng.Value2 'raw value is 0.999506 for 99.9506%
For i = 1 To Len(str) - 1
If Asc(Mid(str, i, 1)) <> 48 And _
Asc(Mid(str, i, 1)) <> 57 And _
Asc(Mid(str, i, 1)) <> 46 Then _
Exit For
Next i
If InStr(1, str, Chr(46)) < i - 1 Then
udf_Specific_Scope = Val(Format(rng.Value2 * 100, "0." & String(i - 3, Chr(48)))) & Chr(37)
Else
udf_Specific_Scope = Format(rng.Value2, "0%")
End If
End Function
这里的缺点是从单元格条目中删除数值但是镜像了原始的RegEx方法。理想情况下,像上面这样的东西可以写成基于Application.Selection属性的子。只需突出显示(也就是选择)一些单元格,运行sub,它会为选择中的每个单元格分配一个正确的小数位数字格式。
答案 1 :(得分:1)
我建议使用LTrim
与Replace
结合而不是(代价高昂的)正则表达式来计算DecPlaces
的值的函数版本。 DecPlaces
的计算已成为&#34;单行&#34;。
其他代码是相同的,除了额外调用CDec
以避免CStr
在值很小时返回科学记数法(如1.123642E-12
)。
Function Reduction(IValue As Double, EValue As Double) As String
Dim TempPercent As Double
Dim TempString As String
Dim NumFormat As String
Dim DecPlaces As Long
TempPercent = (1 - EValue / IValue)
' Apply CDec so tiny numbers do not get scientific notation
TempString = CStr(CDec(TempPercent))
' Count number of significant digits present by trimming away all other chars,
' and subtract from total length to get number of decimals to display
DecPlaces = Len(TempString) - 2 - _
Len(LTrim(Replace(Replace(Replace(TempString, "0"," "), "9"," "), "."," ")))
' Prepare format of decimals, if any
If DecPlaces > 0 Then NumFormat = "." & String(DecPlaces, "0")
' Apply format
Reduction = Format(TempPercent, "0" & NumFormat & "%")
End Function
假设TempPercent
的计算结果为0到1之间的值。
您写道:
我发现的一个问题与正则表达式无关,而是与Excel的四舍五入有关:
99.50% -> 99.5%
这实际上与Excel的舍入无关。在您的代码中以下
DecPlaces = Len(Split(TempString, ".")(1)) - 2
将评估为Len(Split("0.995", ".")(1)) - 2
,1
,因此您应用的格式为0.0%
,说明您获得的输出。
还要意识到虽然正则表达式中有一个捕获组,但实际上并没有使用它。 rxMatches.Item(0)
将为您提供完整匹配的字符串,而不仅仅是与捕获组的匹配。
对于正则表达式不产生匹配的情况,您应用0%
的数字格式。任何除0
和9
之外没有其他数字的数字将不匹配。例如,0.099
应显示格式0.000%
以提供9.900
,但使用的格式为0%
,因为您没有Else
块来处理此案例。< / p>
最后,CStr
可以将数字转换为科学记数法,这也会产生错误的结果。似乎CDec
可以避免这种情况。