【问题标题】:How to find numbers from a string?如何从字符串中查找数字?
【发布时间】:2011-11-06 13:09:41
【问题描述】:

我需要从string 中查找号码。如何在 VBA Excel 中从string 中找到数字?

【问题讨论】:

    标签: string vba excel


    【解决方案1】:

    假设你的意思是你想去掉非数字,你应该能够使用类似的东西:

    Function onlyDigits(s As String) As String
        ' Variables needed (remember to use "option explicit").   '
        Dim retval As String    ' This is the return string.      '
        Dim i As Integer        ' Counter for character position. '
    
        ' Initialise return string to empty                       '
        retval = ""
    
        ' For every character in input string, copy digits to     '
        '   return string.                                        '
        For i = 1 To Len(s)
            If Mid(s, i, 1) >= "0" And Mid(s, i, 1) <= "9" Then
                retval = retval + Mid(s, i, 1)
            End If
        Next
    
        ' Then return the return string.                          '
        onlyDigits = retval
    End Function
    

    调用它:

    Dim myStr as String
    myStr = onlyDigits ("3d1fgd4g1dg5d9gdg")
    MsgBox (myStr)
    

    会给你一个对话框,其中包含:

    314159
    

    前两行显示了如何将它存储到任意字符串变量中,随心所欲。

    【讨论】:

    • 谢谢它的工作。抱歉,我问的是非常基本的问题,我想使用这个“onlydigits”值输入到另一种方法。
    • 没问题,@user905527,我已经更新了最后的示例代码,以展示您如何将其放入变量并将其传递给另一个函数。
    • 您可以使用 IsNumeric 函数减少比较次数。 if IsNumeric(Mid(s,i,1)) 那么
    • I 位数的 Pi 并存?
    • @ArulxZ,巧合,没有。我倾向于使用piexyzzyplugh42 和其他“神奇”项目 :-)
    【解决方案2】:

    正则表达式是用来解析的。虽然语法可能需要一段时间才能掌握,但这种方法非常有效,并且对于处理更复杂的字符串提取/替换非常灵活

    Sub Tester()
         MsgBox CleanString("3d1fgd4g1dg5d9gdg")
    End Sub
    
    Function CleanString(strIn As String) As String
        Dim objRegex
        Set objRegex = CreateObject("vbscript.regexp")
        With objRegex
         .Global = True
         .Pattern = "[^\d]+"
        CleanString = .Replace(strIn, vbNullString)
        End With
    End Function
    

    【讨论】:

    • +1 使用 regex,我很高兴我们可以在 VBA 中使用它,它为 VBA 的 coolness >dimdim照明文化 =)
    • 虽然正则表达式是最优雅的,但正则表达式是否会导致大规模的性能下降?
    • @DarylBennett 好问题。实例化对象可能会导致与循环等效或更差的命中。但是如果对象被实例化一次(比如在一个数组循环中)并重复运行它是非常有效的。
    • 也许将this link 添加到您的答案中?诚然,这个问题是用 Excel 托管的 VBA 来表述的,但大多数信息同样适用于任何 VBA 主机。
    【解决方案3】:

    扩展 brettdj 的答案,以便将不相交的嵌入数字解析为单独的数字:

    Sub TestNumList()
        Dim NumList As Variant  'Array
    
        NumList = GetNums("34d1fgd43g1 dg5d999gdg2076")
    
        Dim i As Integer
        For i = LBound(NumList) To UBound(NumList)
            MsgBox i + 1 & ": " & NumList(i)
        Next i
    End Sub
    
    Function GetNums(ByVal strIn As String) As Variant  'Array of numeric strings
        Dim RegExpObj As Object
        Dim NumStr As String
    
        Set RegExpObj = CreateObject("vbscript.regexp")
        With RegExpObj
            .Global = True
            .Pattern = "[^\d]+"
            NumStr = .Replace(strIn, " ")
        End With
    
        GetNums = Split(Trim(NumStr), " ")
    End Function
    

    【讨论】:

    【解决方案4】:

    如果数字在字符串的前端,则使用内置的 VBA 函数 Val:

    Dim str as String
    Dim lng as Long
    
    str = "1 149 xyz"
    lng = Val(str)
    

    lng = 1149

    Val Function, on MSDN

    【讨论】:

    • Val 做了一些非常奇怪的事情:Val("3d1fgd4g1dg5d9gdg") 返回30,而Va("3d11gd4g1dg5d9gdg") 返回300000000000
    • @zev-spitz 注意:非常奇怪的行为。我看到您上面示例中的异常结果分别被触发,但是前三个或四个字符;因此 Val("3d1")Val("3d11") 分别返回 30 和 300000000000。
    • 解释为浮点值(我不知道为什么):3d1=3*10^1; 3d11=3*10^11。不要使用 Val()!
    【解决方案5】:

    这是 brettdj 和 pstraton 帖子的变体。

    这将返回一个真值并且不会给您#NUM! 错误。 \D 是除数字以外的任何东西的简写。其余部分与其他部分非常相似,只是进行了这个小修复。

    Function StripChar(Txt As String) As Variant
    With CreateObject("VBScript.RegExp")
        .Global = True
        .Pattern = "\D"
        StripChar = Val(.Replace(Txt, " "))
    End With
    End Function
    

    【讨论】:

      【解决方案6】:

      这是基于another answer,但只是重新格式化:

      假设你的意思是你想去掉非数字,你应该能够使用类似的东西:

      '
      ' Skips all characters in the input string except digits
      '
      Function GetDigits(ByVal s As String) As String
          Dim char As String
          Dim i As Integer
          GetDigits = ""
          For i = 1 To Len(s)
              char = Mid(s, i, 1)
              If char >= "0" And char <= "9" Then
                  GetDigits = GetDigits + char
              End If
          Next i
      End Function
      

      调用它:

      Dim myStr as String
      myStr = GetDigits("3d1fgd4g1dg5d9gdg")
      Call MsgBox(myStr)
      

      会给你一个对话框,其中包含:

      314159
      

      前两行显示了如何将它存储到任意字符串变量中,随心所欲。

      【讨论】:

        【解决方案7】:

        我一直在寻找相同问题的答案,但有一段时间我找到了自己的解决方案,我想将其分享给将来需要这些代码的其他人。这是另一个没有功能的解决方案。

        Dim control As Boolean
        Dim controlval As String
        Dim resultval As String
        Dim i as Integer
        
        controlval = "A1B2C3D4"
        
        For i = 1 To Len(controlval)
        control = IsNumeric(Mid(controlval, i, 1))
        If control = True Then resultval = resultval & Mid(controlval, i, 1)
        Next i
        

        结果 = 1234

        【讨论】:

          【解决方案8】:

          通过Byte数组替代

          如果您将字符串分配给Byte 数组,您通常会获得数组元素对中每个字符的等效数字。通过Like 运算符使用循环进行数字检查,并将连接的数组作为字符串返回:

          Function Nums(s$)
            Dim by() As Byte, i&, ii&
            by = s: ReDim tmp(UBound(by))                    ' assign string to byte array; prepare temp array
            For i = 0 To UBound(by) - 1 Step 2               ' check num value in byte array (0, 2, 4 ... n-1)
                If Chr(by(i)) Like "#" Then tmp(ii) = Chr(by(i)): ii = ii + 1
            Next i
            Nums = Trim(Join(tmp, vbNullString))             ' return string with numbers only
            End Function
          

          调用示例

          Sub testByteApproach()
            Dim s$: s = "a12bx99y /\:3,14159"                 ' [1] define original string
            Debug.Print s & " => " & Nums(s)                  ' [2] display original string and result
          End Sub
          

          将在即时窗口中显示原始字符串和结果字符串:

            a12bx99y /\:3,14159 => 1299314159
          

          【讨论】:

            【解决方案9】:

            基于@brettdj 的回答,使用带有两个修改的 VBScript 正则表达式 ojbect:

            • 该函数处理变体并返回一个变体。也就是说,要处理一个空案例;和
            • 使用显式对象创建,并引用“Microsoft VBScript 正则表达式 5.5”库
            Function GetDigitsInVariant(inputVariant As Variant) As Variant
              ' Returns:
              '     Only the digits found in a varaint.
              ' Examples:
              '     GetDigitsInVariant(Null) => Null
              '     GetDigitsInVariant("") => ""
              '     GetDigitsInVariant(2021-/05-May/-18, Tue) => 20210518
              '     GetDigitsInVariant(2021-05-18) => 20210518
              ' Notes:
              '     If the inputVariant is null, null will be returned.
              '     If the inputVariant is "", "" will be returned.
              ' Usage:
              '     VBA IDE Menu > Tools > References ...
              '       > "Microsoft VBScript Regular Expressions 5.5" > [OK]
            
              ' With an explicit object reference to RegExp we can get intellisense
              ' and review the object heirarchy with the object browser
              ' (VBA IDE Menu > View > Object Browser).
              Dim regex As VBScript_RegExp_55.RegExp
              Set regex = New VBScript_RegExp_55.RegExp
              
              Dim result As Variant
              result = Null
              
              If IsNull(inputVariant) Then
                result = Null
                
              Else
                With regex
                  .Global = True
                  .Pattern = "[^\d]+"
                  result = .Replace(inputVariant, vbNullString)
                End With
              End If
              
              GetDigitsInVariant = result
            End Function
            

            测试:

            Private Sub TestGetDigitsInVariant()
              Dim dateVariants As Variant
              dateVariants = Array(Null, "", "2021-/05-May/-18, Tue", _
                      "2021-05-18", "18/05/2021", "3434 ..,sdf,sfd 444")
              
              Dim dateVariant As Variant
              For Each dateVariant In dateVariants
                Debug.Print dateVariant & ": ", , GetDigitsInVariant(dateVariant)
              Next dateVariant
              Debug.Print
            End Sub
            

            【讨论】:

              【解决方案10】:
              Public Function ExtractChars(strRef$) As String
              'Extract characters from a string according to a range of charactors e.g'+.-1234567890'
                Dim strA$, e%, strExt$, strCnd$: strExt = "": strCnd = "+.-1234567890"
                For e = 1 To Len(strRef): strA = Mid(strRef, e, 1)
                  If InStr(1, strCnd, strA) > 0 Then strExt = strExt & strA
                Next e: ExtractChars = strExt
              End Function
              

              在即时调试对话框中:

              ? ExtractChars("a-5d31.78K")

              -531.78

              【讨论】:

              • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
              • 函数返回字符串中的任意字符,例如'+.-1234567890'
              猜你喜欢
              • 2017-03-22
              • 2021-03-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-01-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多