How to use a loop function to count each occurrence of a unique value based on another column and determine earliest date for each unique value?

allicat44

New Member
Joined
Apr 11, 2022
Messages
4
Office Version
  1. 365
  2. 2010
Platform
  1. Windows
I'm new-ish to VBA and have been able to do some simple coding but I've been having a hard time with my new, more complex task. My overall goal is to identify the number/percentage of samples that are collected within 12 hours and 24 hours of the first sample collected for each unique manufacturing code. I have been able to identify and pull each unique manufacturing code (B-Code) to column L and I'm hoping to be able to loop the code so that it determines the percentage of samples collected within 12 and 24 hours for each unique manufacturing code. I'm imagining this being done in steps-

  1. Count and hold the number of samples for each manufacturing code (B-Code).
  2. Determine the first sample of each B-Code and hold the time.
  3. Count the number of samples that are collected 12 hours after the first sample identified in #2 for each B-Code and get the percentage.
  4. Count the number of samples that are collected 24 hours after the first sample identified in #2 for each B-Code and get the percentage.
  5. Loop
I'm running into a few issues with my current code so far- printing the value from #1 to my very last row instead of the corresponding row and returning a date for blank cells as the earliest sample for #2, even though I've used a worksheetfunction.minif function.



Attached is a picture of the code I have so far for counting. My image of the file I have is too large to attach, but column 1 has every time that the unique value in column 12 appears. I'm trying to count the number of times that the value in column 12 appears in column 1. Then establish the earliest time it appears, excluding blanks, in column 5. Then count the number of time of samples from that unique manufacturing code occur within 12 and 24 hours of the first time. Thank you!!
 

Attachments

  • VBA Count Code.png
    VBA Count Code.png
    139.6 KB · Views: 21

Excel Facts

Excel Wisdom
Using a mouse in Excel is the work equivalent of wearing a lanyard when you first get to college
it's easy with a pivottable or in your 365 with formulas.
 
Upvote 0
Cell Formulas
RangeFormula
A1A1=NOW()
A2:A17A2=+A1+TIME(0,1,0)


for a new-ish, perhaps too complex, because everything is done in arrays (much quicker)
VBA Code:
Sub MyCounters()
     Dim Result()
     With ActiveSheet
          arr = .Range("A1").CurrentRegion.Resize(, 12).Value2  'read a contigious block of data around A1 (number of rows unknown) and 12 columns width (because your B-code in in col 12)

          ReDim Result(1 To UBound(arr), 1 To 4)
     'in result we store
     'column 1 = B-code
     'column 2 = earliest time
     'column 3 = count 12 hours
     'column 4 = count 24 hours

          ptr = 0
          For i = 1 To UBound(arr)                              'loop through your data
               bcode = arr(i, 12)
               If bcode <> "" Then
                    r = Application.Match(bcode, Application.Index(Result, 0, 1), 0)     'check if code already exists in 1st column RESULT
                    If Not IsNumeric(r) Then                    'code doesn't exist,
                         ptr = ptr + 1                          ' so increment pointer
                         r = ptr                                ' r=pointer
                         Result(r, 1) = bcode
                         Result(r, 2) = arr(i, 1)               'earliest time
                    End If
                    If WorksheetFunction.Median(arr(i, 1), Result(r, 2), Result(r, 2) + 0.5) = arr(i, 1) Then Result(r, 3) = Result(r, 3) + 1     'within the 12 hours-period (between earliest time and earliest + 12 hours (=0.5)
                    If WorksheetFunction.Median(arr(i, 1), Result(r, 2), Result(r, 2) + 1) = arr(i, 1) Then Result(r, 4) = Result(r, 4) + 1     'within the 12 hours-period
               End If
          Next

          .Range("AA1").Resize(ptr, 4).Value2 = Result
     End With
End Sub
 
Upvote 0
Thank you for your quick response! I've been getting thrown a few errors while trying this and have been able to solve most of them except for Error 9: Subscript out of range. When I try to debug it highlights the If WorksheetFunction.Median(arr.. line. When I hover over the arr(i, 1) it correctly shows that it's the b-code, but when I hover over the Result (r, 2) part I get: "Result(r,5) = <Subscript out of range>.

I'm not sure what's impact this, maybe because the dates being referenced aren't in chronological order or because there's blank cells within the column, so I'm attaching my code. I do have the part of the code that I'm getting the error referencing the column that actually has the dates.


Material Tracking Data FY23.xlsm
ABCDEFKLMNOP
1B CodeProduct Code CodeSampleBO Date + TimeBK Date + TimeRelease Date + Time
2B11091222000015091B10014/2/22 2:21 PM4/2/22 2:38 PM4/4/22 10:0091B110912233.4333333343.36666667622000015.00
3B11091222000015091B10074/2/22 4:31 PM4/2/22 5:27 PM4/4/22 10:0091B120912217.4833333335.58333333622000015
4B11091222000015091B10144/2/22 10:15 PM4/3/22 12:34 AM4/4/22 10:0092B110922213.8833333345.08333333622000015
5B11091222000015091B10204/2/22 9:49 PM4/2/22 10:30 PM4/4/22 10:0092B120922237.6833333353.71666667622000015
6B12091222000015091B10214/2/22 9:24 PM4/2/22 10:25 PM4/4/22 10:0093B110932231.0166666740.33333333622000015
7B12091222000015091B10284/3/22 4:10 AM4/3/22 8:48 AM4/4/22 10:0093B120932238.9666666751.3622000017
8B12091222000015091B10354/3/22 3:31 AM4/3/22 8:55 AM4/4/22 10:0094B110942254.9166666778.25622000017
9B12091222000015091B10424/3/22 1:43 PM4/3/22 4:31 PM4/4/22 10:0094B120942231.4833333336.71666667622000017
10B12091222000015091B10484/3/22 1:04 PM4/3/22 1:50 PM4/4/22 10:0095B1209522116.4125.1166667622000015
11B12091222000015091B10554/3/22 12:29 PM4/3/22 1:05 PM4/4/22 10:0096B110962274.494.23333333622000015
12B12091222000015091B10624/3/22 11:57 AM4/4/22 10:0096B120962262.175.33333333622000015
13B11092222000015092B10014/3/22 11:53 AM4/3/22 12:55 PM4/5/22 10:0097B110972247.7666666761.13333333622000015
14B11092222000015092B10074/3/22 7:55 PM4/3/22 9:15 PM4/5/22 10:0097B120972236.3333333347.6622000015
15B11092222000015092B10144/3/22 7:10 PM4/3/22 7:20 PM4/5/22 10:0098B110982222.8166666737.63333333622000015
16B11092222000015092B10204/3/22 7:03 PM4/3/22 7:55 PM4/5/22 10:0098B120982232.1551.75622000015
17B11092222000015092B10274/4/22 5:30 AM4/4/22 7:47 AM4/5/22 10:0099B110992247.2666666765622000015
18B11092222000015092B10334/4/22 4:44 AM4/4/22 7:57 AM4/5/22 10:0099B1209922NO VALUENO VALUE622000015
19B11092222000015092B10394/4/22 12:47 AM4/4/22 2:20 AM4/5/22 10:00100B1110022NO VALUENO VALUE622000015
20B11092222000015092B10464/4/22 12:07 AM4/4/22 2:35 AM4/5/22 10:00100B1210022NO VALUENO VALUE622000015
21B11092222000015092B10524/4/22 4:05 AM4/4/22 8:07 PM4/5/22 10:00101B1110122NO VALUENO VALUE622000015
22B12092222000015092B10534/4/22 4:00 AM4/4/22 8:19 PM4/6/22 10:00101B1210122NO VALUENO VALUE622000015
23B12092222000015092B10604/4/22 3:11 AM4/4/22 4:17 AM4/6/22 10:000
24B12092222000015092B10664/4/22 10:55 AM4/4/22 12:39 PM4/6/22 10:00
25B12092222000015092B10734/4/22 10:20 AM4/4/22 12:47 PM4/6/22 10:00
26B12092222000015092B10804/4/22 3:50 PM4/4/22 4:29 PM4/6/22 10:00
27B12092222000015092B10864/4/22 3:16 PM4/4/22 4:59 PM4/6/22 10:00
28B12092222000015092B10934/4/22 2:14 PM4/4/22 2:37 PM4/6/22 10:00
29B12092222000015092B10994/4/22 6:02 PM4/4/22 6:57 PM4/6/22 10:00
30B12092222000015092B11064/4/22 5:32 PM4/4/22 6:13 PM4/6/22 10:00
31B11093222000015093B10014/4/22 5:22 PM4/4/22 5:40 PM4/6/22 10:00
32B11093222000015093B10084/4/22 7:59 PM4/4/22 8:41 PM4/6/22 10:00
33B11093222000015093B10154/5/22 2:31 AM4/5/22 2:59 AM4/6/22 10:00
34B11093222000015093B10224/5/22 12:45 AM4/5/22 1:25 AM4/6/22 10:00
35B12093222000017093B10234/7/22 10:00
36B12093222000017093B10294/5/22 6:01 AM4/5/22 6:42 AM4/7/22 10:00
BackerData


Cell Formulas
RangeFormula
A1A1=NOW()
A2:A17A2=+A1+TIME(0,1,0)


for a new-ish, perhaps too complex, because everything is done in arrays (much quicker)
VBA Code:
Sub MyCounters()
     Dim Result()
     With ActiveSheet
          arr = .Range("A1").CurrentRegion.Resize(, 12).Value2  'read a contigious block of data around A1 (number of rows unknown) and 12 columns width (because your B-code in in col 12)

          ReDim Result(1 To UBound(arr), 1 To 4)
     'in result we store
     'column 1 = B-code
     'column 2 = earliest time
     'column 3 = count 12 hours
     'column 4 = count 24 hours

          ptr = 0
          For i = 1 To UBound(arr)                              'loop through your data
               bcode = arr(i, 12)
               If bcode <> "" Then
                    r = Application.Match(bcode, Application.Index(Result, 0, 1), 0)     'check if code already exists in 1st column RESULT
                    If Not IsNumeric(r) Then                    'code doesn't exist,
                         ptr = ptr + 1                          ' so increment pointer
                         r = ptr                                ' r=pointer
                         Result(r, 1) = bcode
                         Result(r, 2) = arr(i, 1)               'earliest time
                    End If
                    If WorksheetFunction.Median(arr(i, 1), Result(r, 2), Result(r, 2) + 0.5) = arr(i, 1) Then Result(r, 3) = Result(r, 3) + 1     'within the 12 hours-period (between earliest time and earliest + 12 hours (=0.5)
                    If WorksheetFunction.Median(arr(i, 1), Result(r, 2), Result(r, 2) + 1) = arr(i, 1) Then Result(r, 4) = Result(r, 4) + 1     'within the 12 hours-period
               End If
          Next

          .Range("AA1").Resize(ptr, 4).Value2 = Result
     End With
End Sub
 
Upvote 0
VBA Code:
Sub BackerSampleCounter()

Worksheets("BackerData").Activate

Dim Result() As String

With ActiveSheet

arr = .Range("A1").CurrentRegion.Resize(, 8).Value2

ReDim Result(1 To UBound(arr), 1 To 4)

ptr = 0

For y = 1 To UBound(arr)

BackerBCode = arr(y, 1)

If BackerBCode <> "" Then

r = Application.Match(BackerBCode, Application.Index(Result, 0, 1), 0)

If Not IsNumeric(r) Then

ptr = ptr + 1

r = ptr

Result(r, 1) = BackerBCode

Result(r, 2) = arr(y, 1)

End If

If WorksheetFunction.Median(arr(y, 1), Result(r, 5), Result(r, 5) + 0.5) = arr(y, 1) Then Result(r, 3) = Result(r, 3) + 1

If WorksheetFunction.Median(arr(y, 1), Result(r, 5), Result(r, 5) + 1) = arr(I, 1) Then Result(r, 4) = Result(r, 4) + 1

End If

Next

.Range("Q2").Resize(ptr, 4).Value2 = Result

End With

End Sub
 
Upvote 0
Result is the array where the macro prepares the output and that one is x rows by 4 columns, because of the ReDim Result(1 To UBound(arr), 1 To 4), so assigning a value to the 5th column is an error.
Each of the 4 columns of "Result" stores a value,
1 was the B-code (here A-column, so that's okay with your "Backercode",
2 was the earliest time, but i don't know which column of your table you're choosing for that one, so Result(r, 2) = arr(y, 1), that 1 must be a 4, 5 or 6 (column D, E or F). So Result(r,5) that 5 has to remain 2

If there is no time given like in row 35, that causes no problem i think.
Does this help or still errors ?
 
Upvote 0
I am now getting a 'Run-Time Error '1004': Unable to get the median property of the WorksheetFunction class'.

I've been playing around with the code, and I'm not sure if this error is because the If WorksheetFunction.Median part is trying to find the average of time and string values, if I'm reading the code correctly.
 
Upvote 0
allicate44.xlsm
important problems/errors
* the array Result can't be declared as string, because it also contains numbers
declaring variables isn't an obligation, it's an option (see "Option Explicit")
* start reading at the 2nd line, because the first is the headerrow
* if the earliest timestamp doesn't exist and later it does, use that timestamp as earliest.
BUT : is it allowed to use this records to count in the 12 and 24 hours period ??? (now it does)
* the column for the earliest time is fixed by the variable "mycolumn" to the value 4 (the BO date)

VBA Code:
Sub BackerSampleCounter()

     Worksheets("BackerData").Activate

     Dim Result() As Variant                                    'NOT AS STRING, only the 1st column is string, the 2nd is a timestamp (=double) and 3-4 are integers !!!
     mycolumn = 4                                               'during the whole macro, column 4 of Arr is the column with your timestamp, BO Date + time  as "earliest moment"

     With ActiveSheet

          arr = .Range("A1").CurrentRegion.Resize(, 8).Value2   'read your data (with datevalues, so date2) to an array, x rows by 8 columns

          ReDim Result(1 To UBound(arr), 1 To 4)                'redimension your result-array, also x rows but only 4 columns

          ptr = 0                                               'this is the pointer to know the last written row in Result during this macro, so now it's 0

          For y = 2 To UBound(arr)                              'loop through the data of arr, MY ERROR !!!! START AT THE 2ND ROW, THE 1ST IS THE HEADERROW

               BackerBCode = arr(y, 1)                          '1st column, so your Backercode

               If BackerBCode <> "" Then                        'the backercode is not empty

                    r = Application.Match(BackerBCode, Application.Index(Result, 0, 1), 0)     'is that backercode already known in the 1st column of Result ?

                    If Not IsNumeric(r) Then                    'NO

                         ptr = ptr + 1                          'the linenumber in Result that now 'll be used (thus increment 1)

                         r = ptr                                'r was not numeric 2 lines ago, so r is that new line further in this macro

                         Result(r, 1) = BackerBCode             'add backercode as 1st element in that new line of Result

                         Result(r, 2) = arr(y, mycolumn)        'add BO Date + time (4th column of Arr) as "earliest moment"

                    End If

                    If IsEmpty(Result(r, 2)) And Not IsEmpty(arr(y, mycolumn)) Then Result(r, 2) = arr(y, mycolumn)     'if the bakercode in a previous line didn't have a BO date and this one has, well that's the earliest time

                    If WorksheetFunction.Median(arr(y, mycolumn), Result(r, 2), Result(r, 2) + 0.5) = arr(y, mycolumn) Then Result(r, 3) = Result(r, 3) + 1     'if the timestamp of this record is between the earliest and earliest + 1/2 day then counter +1

                    If WorksheetFunction.Median(arr(y, mycolumn), Result(r, 2), Result(r, 2) + 1) = arr(y, mycolumn) Then Result(r, 4) = Result(r, 4) + 1     'ame for a whole day

               End If

          Next

          With .Range("Q2")                                     'this is the topleftcorner to write
               .Resize(1000, 4).ClearContents                   'erase previous data (oversized 1000 rows * 4 columns)
               .Resize(1000, 1).Offset(, 1).NumberFormat = "dd/mm/yy hh:mm"     'specify the numberformat to this format
               .Resize(ptr, 4).Value2 = Result                  'write the collected data in Result to the sheet (only the first used rows = ptr)
               .Resize(, 4).EntireColumn.AutoFit                'adjust columnwidth so that everything fits
          End With

     End With

End Sub
 
Upvote 0

Forum statistics

Threads
1,214,525
Messages
6,120,052
Members
448,940
Latest member
mdusw

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top