0

How can I get MAX date from string with multiple date values and different characters?

Example of a string:

11AUG2016 Changed gggqqq2i8yj 29SEP2016 Removed tyijdg298 30SEP2016 Added ,mkdjenb200 03OCT2016 zzxxddd4423 04OCT2016 jioi==++-234jju 24OCT2016 Updated tuiomahdkj 10JAN2017 Updated zzzz T4123III 13JAN2017 Updated jukalzzz123 20JAN2017 iiiwwwaazz678uuh

Scott Craner
  • 148,073
  • 10
  • 49
  • 81
  • See the answers to [this question](http://stackoverflow.com/q/42470071/6535336) and then apply the `MAX` function in Excel? – YowE3K Feb 27 '17 at 01:11
  • 3
    Refer to [Regular expressions](http://stackoverflow.com/a/22542835/1110897) and use regex to extract all date values. – Serge Feb 27 '17 at 01:11
  • 1
    Use a regex for the date, then loop through the matches converting them to `Date` and caching the highest match. – Comintern Feb 27 '17 at 01:12
  • Why don't you split the string into multiple lines using a text editor, such as Notepad2, Notepad++ or even Ms Word (eg Replace `Update` with `^p`; repeat for `Added`)? You can then paste result into Excel - each value will go into its own row. You can then easily extract the date using `RIGHT` and `DATEVALUE` functions. – Serge Feb 27 '17 at 01:15
  • @YowE3K good one :) that's his previous post (~ 12 hours ago) – Shai Rado Feb 27 '17 at 06:28
  • 2
    I posted an answer deriving it from your previous post. Now you kindly take your time to give proper feedback to ALL of your questions (both this and the previous ones). Thank you – user3598756 Feb 27 '17 at 07:22
  • @ShaiRado - The previous question, with its multiple good (but apparently unacceptable!) answers was still in my mind when I read this question. I was sorely tempted to flag this as a duplicate of the previous question but, strictly speaking, the other question only answers 99.99% of what this question asks. (The other 0.01% of this question relating to how to type `MAX`.) – YowE3K Feb 27 '17 at 18:55
  • @user7078484 HELLO !!! any feddback to any of the answers you got here (and previous post) ? – Shai Rado Mar 02 '17 at 05:42
  • Thanks for the reminder, @Shai Rado! Thank you all for your comments, this discussion introduced me to a new area of Regular Expressions which I was not aware of! – user7078484 Mar 03 '17 at 13:01

4 Answers4

2

Just for a twist, I'd prefer to use this regex:

((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]))

Which will filter out strings like 00FOO or 99DEX and that sort of thing for the day and month. Also will reject if the year is 0000.

There are 3 capturing groups so the day, month and year can be pulled out with SubMatches(i).

The max date is found by using the WorksheetFunction.Max function on an array populated with the matches themselves - so no manipulation of worksheet data is done to get the answer:

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
Robin Mackenzie
  • 18,801
  • 7
  • 38
  • 56
  • thought about the month inside the `Pattern`, but went with reading all in, and afterwards filter out the "bad apples" with `If Not IsError(DateValue(...` – Shai Rado Feb 27 '17 at 07:45
  • @Robin Mackenzie: Thank you for your example!! This introduced me to Regular Expressions and I was bot aware that such thing existed! Will be definitely looking more into regex! – user7078484 Mar 03 '17 at 13:05
1

Following my answer on your previous post here Link , find the code below:

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

Screen-shot of your string, extracted date, and MsgBox displaying the maximum date:

enter image description here

Community
  • 1
  • 1
Shai Rado
  • 33,032
  • 6
  • 29
  • 51
1

with little modifications of my solution for your previous code:

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
user3598756
  • 28,893
  • 4
  • 18
  • 28
0

@user3598756's answer gave me an idea that the string can be evaluated as an array (not tested):

MsgBox Evaluate("TEXT(MAX(IFERROR(--""" & Replace([A1], " ", """,),IFERROR(--""") & """,)),""ddmmmyyyy"")")
Slai
  • 22,144
  • 5
  • 45
  • 53