在正则expression式匹配公式中保留尾随零

我有一个函数,我已经写了处理有效位数的百分比减less计算,我有保持尾随零的问题。 function:

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% 

我发现的一个问题与正则expression式无关,而是与Excel四舍五入:

 99.50% -> 99.5% 

有没有一个解决scheme可以节省可以在这里实现的尾随零?

我build议你使用LTrimReplace组合,而不是(昂贵的)正则expression式来计算DecPlaces的值。 DecPlaces的计算已经成为“ DecPlaces ”。

除了额外的CDec调用以避免CStr在数值很1.123642E-12返回科学记数法(如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之间。

对你的代码的评论

你写了:

我发现的一个问题与正则expression式无关,而是与Excel四舍五入:

 99.50% -> 99.5% 

这实际上与Excel的舍入无关。 在你的代码如下

 DecPlaces = Len(Split(TempString, ".")(1)) - 2 

将评估为Len(Split("0.995", ".")(1)) - 2 ,这是1 ,所以你应用的格式是0.0% ,解释你得到的输出。

也意识到,尽pipe在正则expression式中有一个捕获组,但实际上并没有使用它。 rxMatches.Item(0)会为您提供完整的匹配string,不仅与捕获组匹配。

对于正则expression式不会产生匹配的情况,您应用0%的数字格式。 任何没有其他数字比09数字将不匹配。 例如0.099应该以0.000%格式显示给9.900 ,但是使用的格式是0%因为你没有Else块来处理这种情况。

最后, CStr可以把数字变成科学记数法,这也会给出错误的结果。 CDec似乎可以避免。

这是一个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 

specific_scope

这里的缺点是从单元格中删除数字值,但是这反映了您原来的RegEx方法。 理想情况下,类似上面的东西可以写成基于Application.Selection属性的子。 只需突出显示(又名select)一些单元格,运行该子程序,并为select中的每个单元格指定一个具有正确小数位数的单元格数字格式。