正则表达式VBA:查找特定的数据集

时间:2017-06-25 14:55:23

标签: regex vba excel-vba excel

我的宏遇到了问题。 我试图在字符串中找到以FP 608或TM 608开头的元素。

我尝试提取的字符串始终以FP或TM开头。后面的元素是数字,3或4个数字(100或1000)。它们也可以有2位小数(100.10或1000.10)。

例如,它应该提取:

  • ABCDF FP 573,83 ABDFEG HIJ KLM 0124“:摘录:573,83
  • ABCFED ERD 536,98 [...] =无提取
  • TM 123,12 ABCDD EFGHIJ KLM:提取TM 123,12
  • FP 100:提取:FP 100

这似乎有效,但效率低下:

Function GetRealCost(MyRange As Variant)

Application.ScreenUpdating = False
Application.EnableEvents = False
Application.DisplayStatusBar = False

    Dim regEx As Object
    Set regEx = CreateObject("vbscript.regexp")
    Dim strPattern As String
    Dim strInput As String
    Dim strOutput As Object

    strPattern = "\b(TM )([0-9]{3,4})(,[0-9]{1,2}\b)"

    With regEx
        .Global = True
        .MultiLine = True
        .IgnoreCase = False
        .Pattern = strPattern
    End With

        strInput = MyRange

        If regEx.test(strInput) Then
            regEx.Pattern = "(\b[0-9]{3,4})(,[0-9]{1,2}\b)"
            Set strOutput = regEx.Execute(MyRange)
            GetRealCost = regEx.Execute(strInput)(0)
        Else
            strPattern = "\b(TM )([0-9]{3,4}\b)"
            regEx.Pattern = strPattern
                If regEx.test(strInput) Then
                    regEx.Pattern = "(\b[0-9]{3,4}\b)"
                    Set strOutput = regEx.Execute(MyRange)
                    GetRealCost = regEx.Execute(strInput)(0)
                        Else
                            strPattern = "\b(FP )([0-9]{3,4})(,[0-9]{1,2}\b)"
                            regEx.Pattern = strPattern
                                If regEx.test(strInput) Then
                                regEx.Pattern = "(\b[0-9]{3,4})(,[0-9]{1,2}\b)"
                                Set strOutput = regEx.Execute(MyRange)
                                GetRealCost = regEx.Execute(strInput)(0)
                                        Else
                                strPattern = "\b(FP )([0-9]{3,4}\b)"
                                regEx.Pattern = strPattern
                                    If regEx.test(strInput) Then
                                        regEx.Pattern = "(\b[0-9]{3,4}\b)"
                                        Set strOutput = regEx.Execute(MyRange)
                                        GetRealCost = regEx.Execute(strInput)(0)
                                            Else
                                        GetRealCost = ""
                                    End If
                    End If
                End If
        End If

Application.ScreenUpdating = True

End Function

谢谢!

1 个答案:

答案 0 :(得分:0)

效率低下主要是由于应用和测试了许多正则表达式,所有正则表达式都可以合并为一个。此外,通过仅创建和设置RegExp个对象一次可以提高代码速度,因为使用公式为每个单元格创建和设置它可能会变得非常无效。

最后,我不相信在 UDF 中禁用/启用屏幕更新和其他内容是一个好主意,因为这将对每个单独计算的单元格应用一次,这是违反直觉的,它实际上没有任何效果,因为除了计算结果之外,不允许UDF更改应用程序的状态。

您可以尝试使用此UDF:

Function GetRealCost(strInput As String) As String
  Static reg As Object
  If reg Is Nothing Then
    Set reg = CreateObject("vbscript.RegExp")
    reg.Global = True
    reg.MultiLine = True
    reg.IgnoreCase = False
    reg.Pattern = "\b((FP )|(TM ))\d{3,4}(,\d{1,2})?\b"
  End If

  Dim matches As Object: Set matches = reg.Execute(strInput)
  If matches.count <> 0 Then GetRealCost = Mid(matches(0), 4)
End Function