【问题标题】:Check string has a date in it and extract part of the string检查字符串中有一个日期并提取部分字符串
【发布时间】:2019-09-30 16:55:10
【问题描述】:

我有数千行需要处理的文本以及我感兴趣的行,如下所示:

01/04/2019 09:35:41 - Test user (Additional Comments)

我目前正在使用此代码过滤掉所有其他行:

If InStr(FullCell(i), " - ") <> 0 And InStr(FullCell(i), ":") <> 0 And InStr(FullCell(i), "(") <> 0 Then

FullCell 是我正在处理的数组。

我知道这不是最好的方法。有没有办法检查字符串开头是否有日期,格式为 dd/mm/yyyy,然后在“-”和“(”符号之间提取用户名。

我玩了正则表达式,看看是否有帮助,但我的技能有限,无法在同一代码中同时实现 VBA 和正则表达式。

最好的方法是什么。

【问题讨论】:

  • 尝试像^\d?\d\/\d?\d\/\d\d\d\d[^-]*-([^(]*)\(.* 这样的正则表达式,其中名称在第 1 组中
  • Msgbox CDate(Left("01/04/2019 09:35:41 - Test user (Additional Comments)", 19))

标签: regex excel vba date regex-lookarounds


【解决方案1】:

假设Fullcell(i)包含字符串,

If Left(Fullcell(i), 10) Like "##/##/####"

如果您有日期,将返回 True(请注意,它不会区分 dd/mm/yyyymm/dd/yyyy

还有

Mid(Fullcell(i), InStr(Fullcell(i), " - ") + 2, InStr(Fullcell(i), " (") - InStr(Fullcell(i), " - ") - 2)

将返回用户名

【讨论】:

    【解决方案2】:

    我确信有一种更有效的方法可以做到这一点,但我已经多次使用以下解决方案:

    这将选择日期:

    x = 1
    Do While Mid(FullCell,1,x) <> " "
        x = x + 1
    Loop
    strDate = Left(FullCell,x)
    

    这将找到连字符的字符数,用户名后2个字符开始。

    x = 1
    Do While Mid(FullCell,x,1) <> "-"
        x = x + 1
    Loop
    

    然后我们会找到用户名的结尾

    y = x + 2
    Do While Mid(FullCell,y,1) <> " "
        y = y + 1
    Loop
    

    用户名现在应该是字符(x+2 到 y-1)

    strUsername = Mid(FullCell, x + 2, y - (x + 2) - 1)
    

    【讨论】:

    • 您是否有理由使用循环而不是 Instr 来确定搜索字符串的第一次出现?
    【解决方案3】:

    我会这样做

    调暗变量

    Dim ring as Range
    Dim dat as variant
    Dim FullCell() as string
    Dim User as string
    Dim I as long
    

    设置你的范围

    Set rng = ` any way you choose
    Dat = rng.value2
    

    循环数据

    For i = 1 to UBound(dat, 1)
    

    拆分数据

        FullCell = Trim(Split(FullCell, "-"))
    

    测试是否分裂

        If UBound(FullCell) > 0 Then
    

    测试是否匹配

        If IsDate(FullCell(0)) Then
            i  = Instr(FullCell(1), "(")-1)
            If i  then
                User = left$(FullCell(1), i)
                '  Found a user 
    
            End If
        End If
    
        End If
    
    Next
    

    【讨论】:

      【解决方案4】:

      抽象是你的朋友,只要有可能,将它们分解成它们自己的私有函数总是有帮助的。您可以将您的代码放在一个函数中,然后将其命名为ExtractUsername

      下面我做了一个例子,我决定使用 RegExp 方法(后期绑定),但你也可以使用上面例子中的字符串函数。

      如果找到上面提到的模式,此函数返回用户名,否则返回空字符串。

      Private Function ExtractUsername(ByVal SourceString As String) As String
      
          Dim RegEx As Object
          Set RegEx = CreateObject("vbscript.regexp")
      
          '(FIRST GROUP FINDS THE DATE FORMATTED AS DD/MM/YYY, AS WELL AS THE FORWARD SLASH)
          '(SECOND GROUP FINDS THE USERNAME) THIS WILL BE SUBMATCH 1
          With RegEx
              .Pattern = "(^\d{2}\/\d{2}\/\d{4}.*-)(.+)(\()"
              .Global = True
          End With
      
          Dim Match As Object
          Set Match = RegEx.Execute(SourceString)
      
          'ONLY RETURN IF A MATCH WAS FOUND
          If Match.Count > 0 Then
              ExtractUsername = Trim(Match(0).SubMatches(1))
          End If
      
          Set RegEx = Nothing
      
      End Function
      

      正则表达式模式分为三部分:日期(和斜线)、用户名和左括号。您感兴趣的是用户名,在 SubMatch 中将是数字 1。

      Regexr 是一个对练习正则表达式很有帮助的网站,可以向您展示我所使用的模式的更多作用。

      请注意,使用正则表达式可能会给您带来性能问题,您应该针对常规字符串函数对其进行测试,看看哪种方法最适合您的情况。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-15
        • 2013-09-06
        • 2020-12-18
        • 1970-01-01
        相关资源
        最近更新 更多