【问题标题】:VBA: max Date from stringVBA:字符串中的最大日期
【发布时间】:2017-07-17 12:07:48
【问题描述】:

如何从具有多个日期值和不同字符的字符串中获取 MAX 日期?

字符串示例:

11AUG2016更改gggqqq2i8yj 29SEP2016移除tyijdg298 30SEP2016添加,mkdjenb200 03OCT2016 zzxxddd4423 04OCT2016 jioi == ++ - 234jju 24OCT2016更新tuiomahdkj 10JAN2017更新ZZZZ T4123III 13JAN2017更新jukalzzz123 20JAN2017 iiiwwwaazz678uuh P>

【问题讨论】:

  • 查看this question 的答案,然后在Excel 中应用MAX 函数?
  • 参考Regular expressions并使用正则表达式提取所有日期值。
  • 对日期使用正则表达式,然后循环匹配将它们转换为Date 并缓存最高匹配。
  • 为什么不使用文本编辑器将字符串拆分为多行,例如 Notepad2、Notepad++ 甚至 Ms Word(例如将 Update 替换为 ^p;重复 Added) ?然后,您可以将结果粘贴到 Excel - 每个值都将进入其自己的行。然后,您可以使用 RIGHTDATEVALUE 函数轻松提取日期。
  • 我发布了一个来自您之前帖子的答案。现在请您花时间对您的所有问题(包括这个问题和以前的问题)给予适当的反馈。谢谢

标签: string vba excel date max


【解决方案1】:

只是为了转折,我更喜欢使用这个正则表达式:

((0[1-9]|1[0-9]|2[0-9]|3[0-1])(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)([0-9][0-9][0-9][1-9]))

这将过滤掉00FOO99DEX 之类的字符串以及日期和月份之类的东西。如果年份是0000,也会拒绝。

有3个捕获组,所以可以用SubMatches(i)拉出日、月、年。

最大日期是通过在填充有匹配项本身的数组上使用 WorksheetFunction.Max 函数找到的 - 因此无需对工作表数据进行任何操作即可获得答案:

Option Explicit

Sub Test()

    MsgBox ExtractMaxDate(Sheet1.Range("A1"))

End Sub

Function ExtractMaxDate(str As String) As Date

    Dim objRegex As Object 'RegExp
    Dim objMatches As Object 'MatchCollection
    Dim varDates() As Long
    Dim i As Long
    Dim strMaxDate As String

    Set objRegex = CreateObject("VBScript.RegExp")
    With objRegex
        .Global = True
        .IgnoreCase = True
        ' will not match days > 31 or strings that are not months or year 0000
        .Pattern = "((0[1-9]|1[0-9]|2[0-9]|3[0-1])(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)([0-9][0-9][0-9][1-9]))"
    End With

    ' run regex
    Set objMatches = objRegex.Execute(str)

    ' any matches ?
    If objMatches.Count > 0 Then
        ' re-dim the array to number of matches
        ReDim varDates(0 To objMatches.Count - 1)
        For i = 0 To objMatches.Count - 1
            ' get date as yyyy-mm-dd and use CDate and store in array of Long
            varDates(i) = CDate(objMatches(i).SubMatches(3) & _
                "-" & objMatches(i).SubMatches(2) & _
                "-" & objMatches(i).SubMatches(1))
        Next i
        ' get the max date out of the matches
        strMaxDate = CDate(WorksheetFunction.Max(varDates))
    Else
        ' no matches
        strMaxDate = 0
    End If

    ExtractMaxDate = strMaxDate

End Function

【讨论】:

  • 想了Pattern里面的月份,但还是读完了,然后用If Not IsError(DateValue(...过滤掉“坏苹果”
  • @Robin Mackenzie:谢谢你的榜样!!这向我介绍了正则表达式,我意识到这种东西的存在!肯定会更多地研究正则表达式!
【解决方案2】:

按照我在您之前的帖子Link 上的回答,找到下面的代码:

Option Explicit

Sub ExtractDates()

Dim Reg1 As Object
Dim RegMatches As Variant
Dim Match As Variant
Dim i As Long

Dim dDay As Long
Dim dYear As Long
Dim dMon As String
Dim MaxDate As Date

Set Reg1 = CreateObject("VBScript.RegExp")
With Reg1
    .Global = True
    .IgnoreCase = True
    .Pattern = "(\d{2}[a-zA-Z]{3}\d{4})" ' Match any set of 2 digits 3 alpha and 4 digits
End With

Set RegMatches = Reg1.Execute(Range("A1").Value)

i = 1
If RegMatches.Count >= 1 Then ' make sure there is at least 1 match
    For Each Match In RegMatches
        dDay = Left(Match, 2)
        dYear = Mid(Match, 6, 4)
        dMon = Mid(Match, 3, 3)

        On Error Resume Next
        If Not IsError(DateValue(dDay & "-" & dMon & "-" & dYear)) Then '<-- check if string has a valid date value
            If Err.Number <> 0 Then
            Else
                Range("B" & i).Value = DateValue(dDay & "-" & dMon & "-" & dYear) ' <-- have the date (as date format) in column B
                i = i + 1
            End If
        End If
        On Error GoTo 0
    Next Match
End If
MaxDate = WorksheetFunction.Max(Range("B1:B" & i - 1))

MsgBox "Maximum valid date value in string is " & MaxDate

End Sub

您的字符串、提取日期和显示最大日期的 MsgBox 的屏幕截图:

【讨论】:

    【解决方案3】:

    对我之前的代码的解决方案稍作修改:

    Sub main()
        Dim arr As Variant
    
        With Range("A1")
            arr = Split(.Value, " ")
            With .Resize(UBound(arr) + 1)
                .Value = Application.Transpose(arr)
                .SpecialCells(xlCellTypeConstants, xlTextValues).Delete xlUp
                .cells(1, 1) = WorksheetFunction.Max(.cells)
                .Offset(1).Resize(.Rows.Count - 1).ClearContents
            End With
        End With
    End Sub
    

    【讨论】:

    • 这非常聪明 - 需要我的头脑!
    • @RobinMackenzie,谢谢。但我认识你,你只需不到 1 分钟就能掌握它,即阅读其他人代码的最短时间。
    • @user3598756 恭喜,您已达到半程马拉松赛点 :)
    • @ShaiRado,嗯?那是什么?
    • @user3598756 我猜你不适合跑步,21.1k(比如 21.1 公里,在马拉松的 42.2 公里之外)
    【解决方案4】:

    @user3598756 的回答让我想到了可以将字符串评估为数组(未测试):

    MsgBox Evaluate("TEXT(MAX(IFERROR(--""" & Replace([A1], " ", """,),IFERROR(--""") & """,)),""ddmmmyyyy"")")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-31
      • 1970-01-01
      • 1970-01-01
      • 2022-01-26
      • 2014-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多