-1

I have a data in excel sheet that contains client id, date of a result and the result of some lab tests. The dates are sorted ascending for each client. I want a VBA code to go through the dates of every client and test if the difference between every date is not more than 2 months and to find the longest consecutive set of Dates and Highlight it with color, yellow for example. This set of date is not necessarily to be the oldest or the newest, but should be the longest duration of non interrupted date by more than 2 months.

Also, it would be great if the duration is calculated for that long set next to the result column, so we can sort the data accordingly.

Here is a link to my file. and below is a screenshot for the requirement. image for the excel sheet

Example data extracted from linked file

        +----+----------+------------------------+---------+
        | #  |    A     |         B              |    C    |
        +----+----------+------------------------+---------+
        | 1  | ClientId | Results Date & Time    | Results |
        +----+----------+------------------------+---------+
        |... |    ...   |         ...            |    ...  |
        +----+----------+------------------------+---------+
        |105 |    1     | 12/06/2018 12:42:00 PM | 1.9     |
        +----+----------+------------------------+---------+
        |106 |    1     | 6/25/2018  1:55:00 PM  | 1.8     |
        +----+----------+------------------------+---------+
        |107 |    2     | 3/29/2016  9:11:00 AM  | 1       |
        +----+----------+------------------------+---------+
        |108 |    2     | 6/8/2016  12:50:00 PM  | 2       |
        +----+----------+------------------------+---------+
        |...
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
user72343
  • 53
  • 1
  • 7
  • Hi Ahmed, please consider instead upload a picture of example data as many people (including myself) are unwilling to follow download links https://stackoverflow.com/help/mcve – Marcucciboy2 Aug 08 '18 at 16:21
  • 1
    SO is not a code-writing service. Maybe someone will be kind enough to help but without seeing any initial effort on your part, chances are slimmer... – BigBen Aug 08 '18 at 16:22
  • 2
    Hi! welcome to Stack Overflow. This is not a code writing service, but if you [edit](https://stackoverflow.com/posts/51751330/edit) your question, adding what you have tried so far, we can help you achieve your goal. You may also want to read [How to Ask](https://stackoverflow.com/help/how-to-ask) – cybernetic.nomad Aug 08 '18 at 16:23
  • 1
    Hello guys, I've attached a picture for the excel sheet. – user72343 Aug 08 '18 at 16:30
  • @user72343 - As **all** your displayed date differences are <= 60 days, you would have to highlight all cells if one follows your OP or do you start new date sets at the beginning of each year? Please edit how you define full months, too. – T.M. Aug 08 '18 at 19:03
  • Hello T.M,, the difference between result in 10th line 13/11/2014 and the next one is more than 60 days, then the first ten results are not longest series, so we will highlight starting from the 11th result. We will go through each client and test the same logic. It is not also necessary to have full month of result, that is 1 or 2 result per month is fine. Date range can continue from previous year to new year, but to keep not more than 60 days gap. – user72343 Aug 09 '18 at 03:06
  • Will post a solution using a datafield array after this weekend. BTW Your first image link (with all date differences below 61 days) shows *other* data than your second. - @user72343 – T.M. Aug 10 '18 at 18:50
  • @T.M. Thank you. Awaiting the solution :) – user72343 Aug 11 '18 at 02:47
  • Posted proposed solution together with hopefully helpful explanations regarding **Arrays** and the use of **conditional formatting**, where in *international* cases a *local formula* is needed instead of the default English formula code. – T.M. Aug 13 '18 at 19:14
  • @T.M. Hello T.M. and thank you for sharing this answer. I tried to copy the codes in the VBA editor and run the macro Sheet1.GetLongestDuration, but I get error "Subscript out of range"! Am I missing anything? – user72343 Aug 13 '18 at 22:02
  • 1. Did you Change the source worksheet to your actual sheet name. 2. Insert a new code module in the VBE (VBA Editor) and write the code there. - @user72343 – T.M. Aug 14 '18 at 07:22

1 Answers1

1

Solution via datafield array

"I want a VBA code to go through the dates of every client and test if the difference between every date is not more than 2 months and to find the longest consecutive set of dates and highlight it with color, yellow for example"

Loops through a range are always time consuming, so I demonstrate an approach via a datafield array instead simplifying the 2-months condition to day differences <= 64 days as I didn't want to overcomplicate this example.

As "the dates are sorted ascending for each client", it's easy to check the next Client id, calculate day differences, add them in a current duration variable and compare it with remembered variables in order to find the longest set of dates within the same id, then changing to the next id.

Finally results are written to an overview array to collect the item numbers to be highlighted. This can be done via conditional formatting

Furthermore I integrate an Enum declaration in the declaration head of your code module just to show the use of meaningful variables instead of pure numbers (replacing here array 'column' numbers).

0. Declaration head of your code module

It's strictly recommanded to use Option Explicit to make the type declaration of variables obligatory thus avoiding apparently unexplainable type mismatches or other issues.

The already mentioned Enum declaration has another feature if you are using the automatic enumeration starting from a defined first element, e.g. [_Zero]: you can easily restructure the internal order without changing every code line containing only pure numbers.

Hint: All Enum elements are displayed using IntelliSense with exception of elements in [] brackets and element names starting with an underline character _.

Minor change 08/28 <-- Edit #100 --> The current edit does without enumerating data.Results without influencing the wanted output, as all data members are renumbered automatically with an additional increment of +1 (calculated after [_Zero]=0).

Option Explicit                                         ' force declaration of variables

' assign meaningful number variables for your array columns
Enum data                                               ' automatically enumerates column numbers 1 to 5 (-> array v)
    [_Zero] = 0
      Id
      Date
      days
      Duration
End Enum
Enum Ov                                                ' automatically enumerates column numbers 1 to 6 (-> array overview)
    [_Zero] = 0
    Id
    StartDate
    EndDate
    duration
    StartItem
    enditem
End Enum

1. Main procedure GetLongestDuration()

Edit 1: I changed the Type of all calculated day variables from Long to Double (i.e. maxDAYS#, currDuration#, memDuration#) to prevent type mismatches, especially when calculating broken days.

Edit 2: See changes in section II to avoid empty date calculation (e.g. in last row as mentioned in comment) (<-- Edit 13# -->) and eventual error 13 writing back durations in section III b).

Edit 3: See additional check for non-numeric items in section II (<-- Edit 14# and 15# -->)

Edit 4: The original approach didn't assume that data rows exceeded the number of 65,536 being the absolute Limitation to use the ►Index function (trying to isolate an array column here).

This hopefully final edit avoids an Error 13 Type mismatch using an extra array d with all relevant duration data (cumulated day differences within the defined 2 month range) and corrects some other minor issues. Corrections are made in section II <-- Edit #101 --> and section III <-- Edit #102 to #122 -->

Sub GetLongestDuration()
' Purpose:    Highlight longest set of dates <= 64 days
' Condition:  Client IDs and Dates are sorted in ascending order.
' Edit 8/16:  Enumerated type changes of maxDAYS#, currDuration#, memDuration# changed to DOUBLE (#)
' Edit 8/17:  Edit in section II <-- Edit #13         -->
' Edit 8/22:  Edit in section II <-- Edit #14 and #15 -->
' Edit 8/28:  Edit in section II <-- Edit #101 -->, section III <-- Edit #102 to #122 -->
  Const maxDAYS# = 64#                                ' << <--#1 Double--> change maximal difference to next date
  Const DATASHEET$ = "LABs and Diagnostics"           ' << replace with your data sheet name
  Const OVSHEET$ = "Overview"                         ' << replace with your Overview sheet name
  Const OVTITLES$ = "ID,Start Date,End Date,Duration,Start Item, End Item"
' declare variables
  Dim ws As Worksheet, ws2 As Worksheet               ' declare object variables as worksheet
  Set ws = ThisWorkbook.Worksheets(DATASHEET)         ' set data sheet object to memory

  Dim v As Variant, overview As Variant               ' variant datafield array and results array
  Dim Id            As String                         ' current state
  Dim StartItem     As Long
  Dim StartDate     As Double, EndDate      As Double '
  Dim days          As Double, currDuration As Double '   <-- #2 Double -->

  Dim memStartDate#, memEndDate#                      ' remember highest findings
  Dim memDuration#                                    '   <-- #3 Double -->
  Dim memStartItem&, memLastItem&                     ' remember highest findings
  Dim i As Long, ii As Long, n As Long, iOv As Long   ' counters

' 0. get last row number n and assign values to a 2-dim array v
  ws.Columns("D:D") = ""                              ' clear column D (duration)

  n = ws.Range("A" & ws.Rows.Count).End(xlUp).Row + 2 ' find last row number n plus 2 more rows
  v = ws.Range("A2:E" & n).Value2                     ' create 2-dim datafield array omitting headers
  ReDim overview(1 To n, 1 To 6)                      ' create a helper array with results

' =======================
' loop through data array
' =======================
' remember first ID (for later comparation with changing array item id)
  Id = v(1, data.Id) & ""
  For i = LBound(v) To UBound(v)                      ' loop through items 1 to items count UBound(v) in data array v

    ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' I. check new ID in first 'column' of each array item
    ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      If v(i, data.Id) & "" & "" <> Id Then           ' check current id against remembered id
        ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        '... complete analytics of preceding id in overview
        ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         If i > 1 Then
            ii = ii + 1
            overview(ii, Ov.Id) = Id
            overview(ii, Ov.StartDate) = memStartDate
            overview(ii, Ov.EndDate) = memEndDate
            overview(ii, Ov.Duration) = memDuration
            overview(ii, Ov.StartItem) = memStartItem
            overview(ii, Ov.enditem) = memLastItem
         Else
            overview(ii, Ov.StartItem) = 1
         End If
        '... and switch to new current id
         Id = v(i, data.Id) & ""
         currDuration = 0#: memDuration = 0#             ' <-- #4 Double --> reset to zero
         memStartItem = 0&: memLastItem = 0&
      End If

    ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' II. calculate days and check coherent periods
    ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      If i < UBound(v) Then                              ' stop calculation one item before last item row
         If Len(Trim(v(i + 1, data.Date))) = 0 Then      ' avoid type mismatch if empty
            days = 0#
         ElseIf Not IsNumeric(v(i, data.Date)) Then      ' <-- #14 not numeric -->
            days = 0#
            MsgBox "Item no " & i & " " & v(i, data.Date) & " is not numeric!"
         Else
            If IsNumeric(v(i + 1, data.Date)) Then       ' <-- #15 not numeric -->
               days = v(i + 1, data.Date) - v(i, data.Date) ' get days difference to next date

               v(i, data.days) = days                    ' <-- #101 remind days difference -->

            End If
         End If
      Else                                               ' there's nothing more to add
         days = 0#                                       ' <-- #5 Double -->
      End If
    ' avoid negative day counts in last row
      If days < 0 Then days = 0#                         ' <-- #6 Double -->
    ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' a) days till next date within two months (i.e. <=64)
    ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      If days <= maxDAYS And days > 0 Then
         v(i, data.days) = days                          '    assign days to column 5
         currDuration = currDuration + days              '    add days in current set to cumulated duration
         If i > 1 Then
            If v(i - 1, data.days) = 0 Then
                StartItem = i                            '    StartItem number in current data set
                StartDate = v(i, data.Date)              '    StartDate current data set
            End If
         End If
    ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' b) days till next date exceed two months
    ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      Else
         v(i, data.days) = 0#                            ' <-- #7 Double -->   therefore no count

         ' if longer duration then remember this set within current id
         If currDuration > memDuration Then
            memDuration = currDuration
            memStartDate = StartDate
            memEndDate = v(i, data.Date)
            memStartItem = StartItem
            memLastItem = i
         End If

         ' start new set
         currDuration = 0#                                     ' <-- #8 Double --> reset to zero
      End If
  Next i
  v(UBound(v), data.days) = 0#                                 ' <-- #9 Double --> days in last row
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' III. calculate durations for longest coherent periods and write it to new column D
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' a) loop through all overview items

Dim d: ReDim d(1 To UBound(v), 1 To 1)                            ' <-- #102 create separate duration array -->

If overview(1, Ov.enditem) > 0 Then overview(1, Ov.StartItem) = 1 ' <-- #103 set startitem of 1st to 1 if relevant date range -->
For iOv = 1 To ii
      currDuration = 0#                                           ' <--  #10 Double --> reset to 0 (Double!)
      '''      If overview(iOv, Ov.StartItem) = 0 Then Exit For   ' <-- #104 DELETE last Edit #0/Aug 14th 18) -->
      memStartItem = overview(iOv, Ov.StartItem)                  ' <-- #105 remember start item              -->
      If memStartItem = 0 Then                                    ' <-- #106/107/108 clear not relevant dates -->
          overview(iOv, Ov.StartDate) = ""                        '
          overview(iOv, Ov.EndDate) = ""                          '
      Else                                                        ' <-- #109 relevant dates                   -->
        ''' v(overview(iOv, Ov.StartItem), data.Duration) = 0#    ' <-- #110 DELETE last Edit #11 Double      -->
          d(memStartItem, 1) = currDuration                       ' <-- #111 write current duration to array  -->

          For i = memStartItem To overview(iOv, Ov.enditem) - 1   ' <-- #112 first item no to last item no    -->
              currDuration = currDuration + CDbl(v(i, data.days)) ' <--  #12 CDbl --> add days to cumulated sum currDuration
              v(i + 1, data.Duration) = currDuration              ' <-- #113 (unchanged) --> assign duration to source array v in column 4
              d(i + 1, 1) = currDuration                          ' <-- #114
          Next i                                                  ' <-- #115 (unchanged)                      -->
      End If                                                      ' <-- #116 closing IF to #106               -->

  Next iOv                                                        ' <-- #117 (unchanged)                      -->

  ' b) write cumulated duration into column D

  '  **********************************************************
  '  avoid ERROR 13 type mismatch, ii 6379 **ISSUE 2018/08/22**
  '  **********************************************************
  '  Caveat: Index function (trying to isolate single array column) has limitation to 65,536 rows only!
   '''  ws.Range("D2").Resize(UBound(v), 1) = Application.Index(v, 0, data.Duration) <-- #118 uncomment/DELETE -->

   ws.Range("D2").Resize(UBound(d), 1) = d                        ' <-- #119 write relevant durations to column D -->

    ws.Range("D1") = "Duration"                                   ' <-- #120 add title                           -->
    ws.Range("D:D").NumberFormat = "# ??/24"                      ' <-- #121 fraction format shows days + hours  -->

' IV. set Conditional Format in order to highlight found items (condition: existing value in column D)
'    (calls helper function SetConditionalFormat with arguments range and condition)
  SetConditionalFormat ws.Range("A:D"), "=LEN(TRIM($D1 & """"))>0" ' <--#122 (unchanged)                         -->

' V.  optional display of results in sheet 'Overview', see below

End Sub

Optional Display of results

If you want to display the found item data in a separate sheet "Overview", you could add this to the code above:

' V. optional display of separate Overview sheet with results
' a) add Overview sheet if it doesn't exist yet
  If Not SheetExists(OVSHEET) Then
     With ThisWorkbook.Worksheets.Add
          .Name = OVSHEET                                       ' baptize it e.g. "Overview"
          .Columns("B:C").NumberFormat = "dd/mm/yyyy;@"         ' << change columns B:C do wanted local format
     End With
  End If
  Set ws2 = ThisWorkbook.Worksheets(OVSHEET)                     ' set overview sheet object to memory
' b) write titles and results to Overview sheet
  ws2.Range("A:F") = ""                                          ' clear columns
  ws2.Range("A1:F1") = Split(OVTITLES, ",")                      ' write titles to overview!A1:F1

  If ii < 1 Then
    ws2.Range("A2") = "No duration sets identified!"
  Else
    ws2.Range("A2").Resize(ii, UBound(overview, 2)) = overview     ' write array overview back to Overview sheet
  End If

2. Helper procedure SetConditionalFormat()

This procedure is called in section [IV.] of the main procedure and highlights the found date sets for all cells in column D containing data. One possible condition is to ask if the trimmed string length equals zero. International use: It has to be considered that conditional format (CF) requires ►local formulae - therefore a helper function getLocalFormula() is integrated.*

 Sub SetConditionalFormat( _
                   ByRef rng As Range, _
                   ByVal sFormula As String, _
                   Optional ByVal myColor As Long = 65535, _
                   Optional bDelFormerFormats As Boolean = True)
 ' Author:  T.M.
 ' Purpose: set conditional format to given range using sFormula
 ' Note:    former formats are deleted by default unless last argument isn't set to False
 ' Hint:    Formula1 always needs the LOCAL formula, so the string argument sFormula
 '          has to be translated via helper function getLocalFormula() using a work around
     With rng
        ' a) delete existing conditional formats in A:D
             If bDelFormerFormats Then .FormatConditions.Delete
        ' b) add new condition with needed LOCAL formula
             .FormatConditions.Add _
                    Type:=xlExpression, _
                    Formula1:=getLocalFormula(sFormula)  ' << get local formula via helper function
             .FormatConditions(.FormatConditions.Count).SetFirstPriority
        With .FormatConditions(1).Interior
             .PatternColorIndex = xlAutomatic
             .color = myColor                         ' yellow by default parameter
             .TintAndShade = 0
        End With
     .FormatConditions(1).StopIfTrue = False
     End With
 End Sub

3 a) Helper function getLocalFormula()

This function is called by the above helper procedure, as conditional formatting always needs the local formula thus considering internationalization:

 Function getLocalFormula(ByVal sFormula As String) As String
 ' Author:  T.M.
 ' Purpose: work around to translate English formula to local formula
 ' Caveat:  assumes there is no value in last cell (e.g. $XFD$1048576 in more recent versions)
     With ActiveSheet.Range("A1").Offset(ActiveSheet.Rows.Count - 1, ActiveSheet.Columns.Count - 1)
       ' assign formula to temporary cell in order to get local formula string
         .Formula = sFormula
       ' get local formula
         getLocalFormula = .FormulaLocal
         .Value = ""                              ' delete temporary formula
     End With
 End Function

3 b) Helper function SheetExists()

Called by optional section [V.] of the main procedure:

 Function SheetExists(SheetName As String, Optional wb As Workbook) As Boolean
 ' Author:  Tim Williams
 ' Purpose: check if worksheet exists (returns True or False)
 ' cf Site: https://stackoverflow.com/questions/6688131/test-or-check-if-sheet-exists
 Dim ws As Worksheet
 If wb Is Nothing Then Set wb = ThisWorkbook
 On Error Resume Next
 Set ws = wb.Worksheets(SheetName)
 On Error GoTo 0
 SheetExists = Not ws Is Nothing
 End Function
T.M.
  • 9,436
  • 3
  • 33
  • 57
  • Hello T.M. and thank you for sharing this answer. I tried to copy the codes in the VBA editor and run the macro Sheet1.GetLongestDuration, but I get error "Subscript out of range"! Am I missing anything? – user72343 Aug 13 '18 at 23:03
  • In Addition to my above comment: a) at which code line precisely does code stop? Move your mouse over any Loop variable - which value do you see? - Please tell me the **code line** causing the error no 9! (b) You could also debug your code by inserting a Stop` statement at any point and check a suspected variable directly in the immediate window (Crtl+G) of your VBA Editor (VBE) by typing ist name plus Enter key to get the last value, press F8 to continue or end the test by clicking at the blue square button on top of VBE or F5 (cf http://www.cpearson.com/excel/DebuggingVBA.aspx) - @user72343 – T.M. Aug 14 '18 at 09:06
  • A common cause of error 9 is a wrong sheet name - so you could check if you assigned an existing worksheet name to the DATASHEET constant. – T.M. Aug 14 '18 at 09:17
  • Hello T.M. I added the code to a module, and I get error 9 from line ==> v(overview(iOv, Ov.StartItem), data.Duration) = 0& so I added On error resume next and the code worked and generated a new sheet Overview, but no rows highlighted yellow in my data sheet. The other thing is, for example client 2, is counting from line 174 to line 188, while it should start from line 111 to line 198. I tried to attach screenshots but I cannot find a way to add in the comment. Here is the link to the new file saved as xlsb to decreas size https://1drv.ms/x/s!AvGP2RZ7Ro4lggMymPMsv2WtBA24 Thank you. – user72343 Aug 14 '18 at 13:56
  • in the shared file, the continuous range is the bold range where the difference between each 2 dates is less than 64 as suggested by you. – user72343 Aug 14 '18 at 13:59
  • It's not recommended to skip over ANY occurring error via `On error resume next`. Do the following instead: 1) try to insert a new code line `If overview(iOv, Ov.StartItem) = 0 Then Exit For` before the found line causing issues and I'd like to hear if you get results in overview. 2) I didn't assume that you have several entries the same day, so it will be necessary to change days and Duration declarations as well as related resets to zero from Long `0&` to Double `0#` - I will try to edit the code the next days, but tell me first what happened after the code insertion in (1) - @user72343 – T.M. Aug 14 '18 at 17:38
  • Error 13 (type mismatch) occurred at ' b) write cumulated duration into column D ws.Range("D2").Resize(UBound(v), 1) = Application.Index(v, 0, data.Duration) after insertion the code – user72343 Aug 14 '18 at 22:38
  • Please try the edited code with changed variable types (`Long` to `Double`) which I tested based on some date values without problems (don't want to download entire file); if there occur issues, check at which date item code stops (are all entries formatted as date - e.g. check in the immediate window via `? TypeName(...)`) and tell me an item example and some related counters (e.g. i, ii) - @user72343 – T.M. Aug 16 '18 at 11:24
  • Hi T.M. same error 13 still occur at ws.Range("D2").Resize(UBound(v), 1) = Application.Index(v, 0, data.Duration) . I think the code stops at item ii=6379 which is the last item where the underneath cell is empty and has no date. I might be wrong, I not very expert in coding. – user72343 Aug 16 '18 at 13:34
  • Hi @user72343, thank you for narrowing the error range, so I could try another attempt editing section [II.] in the main procedure. – T.M. Aug 17 '18 at 20:32
  • 1
    One-liner to check sheet existence: `SheetExists = Not IsError(Application.Evaluate(ws & "!A1"))`. ` – JohnyL Aug 17 '18 at 20:57
  • @T.M. hello dear. I copied the data in a new file and also copied the code. I'm still getting the error msg and I can not test the code to see the results. This a new link for the new file https://1drv.ms/x/s!AvGP2RZ7Ro4lggZQhduRoD560fiz Could you please check where the error is. Thank you – user72343 Aug 20 '18 at 17:27
  • @user72343 - new edit checks for non-numeric items in section II; checks the code in column B - but it's up to you to provide for corrected entries before executing code again. – T.M. Aug 22 '18 at 12:03
  • @user72343 - your row number exceeds 200 000, so I found the main cause in a known limitation to the `Index` function - I try to modify my answer the next days. – T.M. Aug 27 '18 at 18:14
  • @user72343 - please try the promised edit (main issue was the 65k limitation of `Index` function), would be glad to hear you succeeded so that you can mark this question as solved. – T.M. Aug 28 '18 at 17:20
  • @T.M.- I split the sheet into parts less than 65K row and it worked without error, but there was no rows highlighted yellow, any idea? – user72343 Aug 28 '18 at 18:18
  • @user72343 - I edited a completely new and hopefully working code including a work around and some minor changes *) - please copy the entire code in the answer from sections I. to V. into your code module and try again. If you get data written to column D, rows with values there should be highlighted now. – T.M. Aug 28 '18 at 18:25
  • 1
    @T.M. Hello, worked as a charm, this is awesome! We really appreciate your help. Thank you very much :) – user72343 Aug 28 '18 at 19:23
  • @user72343 - you are welcome, really appreciated your feed back to this apparently simple question actually exhibiting some challenges (VBA `Index` function limitations, number vs date types, hidden enumeration members, conditional formatting with local formats etc.) - enjoy it :-) – T.M. Aug 28 '18 at 19:49