包含不带空格的文本的单元格中的数字总和

Sum numbers in cell containing text without spaces

我对 SO 和 google 进行了广泛的研究,但没有提出解决方案。 虽然之前可能有人问过这个问题,但我的情况略有不同

如果文本和数字之间有 space,则该函数可以正常工作。但是,如果没有任何 spaces.

,则不起作用
Function SumNumbers(rngS As Range, Optional strDelim As String = " ") As Double
Dim xNums As Variant, lngNum As Long
xNums = Split(rngS, strDelim)
For lngNum = LBound(xNums) To UBound(xNums) Step 1
    SumNumbers = SumNumbers + Val(xNums(lngNum))
Next lngNum
End Function

我的手机数据是这样的:su9m11w11.5th8

我尝试添加一个字母表数组,但没有成功。欢迎帮助。

strDelim = Array("F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "U")

嗯,根据你的数据,你可以试试:

Sub Test()

Dim StrIn As String: StrIn = "su9m11w11.5th8"
Debug.Print SumDigits(StrIn)

End Sub    

Function SumDigits(str As String) As Double

With CreateObject("vbscript.regexp")
    .Global = True
    .Pattern = "[a-z]+"
    SumDigits = Application.Evaluate(.Replace(str, "+") & ".0")
End With

End Function

这里我使用正则表达式将 a-z 范围内的所有小写字符替换为“+”。然后可以将生成的字符串计算为 return 总和。


编辑:

另一种方法可能是使用正则表达式 return 所有可能的(负)数,然后求和:

Function SumDigits(str As String) As Double

With CreateObject("vbscript.regexp")
    .Global = True
    .Pattern = "-?\d+(?:\.\d+)?"
    If .Test(str) Then
        For Each Match In .Execute(str)
            SumDigits = SumDigits + Match
        Next
    End If
End With

编辑 2:

要return一个平均值,我们应该捕获匹配子串的数量并将总和除以该计数:

Function SumDigits(str As String, Optional avg As Boolean) As Double

With CreateObject("vbscript.regexp")
    .Global = True
    .Pattern = "-?\d+(?:\.\d+)?"
    If .Test(str) Then
        Set Matches = .Execute(str)
        For Each Match In Matches
            SumDigits = SumDigits + Match
        Next
        If avg Then SumDigits = SumDigits / Matches.Count
    End If
End With

End Function

改为使用 Debug.Print SumDigits(StrIn, True) 调用。

这里有一个 VBA 函数,可以生成嵌入数字的总和或平均值...它也可以处理负数。这是纯粹的 Excel VBA,没有引用外部库:

Function SumEmbeddedNumbers#(s$, Optional bAverage As Boolean)
    Dim i&, p&, max&, t&, pluses&
    Dim b() As Byte, res() As Byte
    Static keep() As Boolean

    Const VALS$ = "0123456789.-"
    
    If (Not Not keep) = 0 Then
        ReDim keep(0 To 255)
        For i = 1 To Len(VALS)
            keep(Asc(Mid$(VALS, i, 1))) = 1
        Next
    End If
    
    max = LenB(s)
    ReDim res(0 To max)
    b = StrConv(s, vbFromUnicode)
    For i = 0 To Len(s) - 1
        t = b(i)
        If keep(t) Then
            res(p) = t
            p = p + 1
        Else
            If p Then
                If res(p - 1) <> 43 Then
                    res(p) = 43
                    pluses = pluses + 1
                    p = p + 1
                End If
            End If
        End If
    Next
    SumEmbeddedNumbers = Evaluate(Left$(StrConv(res, vbUnicode), p))
    If bAverage Then SumEmbeddedNumbers = SumEmbeddedNumbers / (pluses + 1)
End Function

MsgBox SumEmbeddedNumbers("su9m11w11.5th8")          '<---displays: 39.5
MsgBox SumEmbeddedNumbers("su9m11w11.5th8", True)    '<---displays: 9.875