VBA: Custom Count and Search Function Help Needed

Ottsel

Board Regular
Joined
Jun 4, 2022
Messages
174
Office Version
  1. 365
Platform
  1. Windows
I have this custom function I'm working on. the setup is as follows:
Excel Formula:
=CountAwards(B2, 2023)

The sheet its referencing is "TRACKER". I want to be able to reference B2 or any cell really as the main search. In this example on the TRACKER sheet B2, B6, B7, and B8 are whats in being looked for. If whats in Column O equals AWARDED, then count if the other requires are met: J must equal the year that's selected, which in this example is 2023 and whats in column C must be unique. If whats in column C occurs again and the value changes in column O it needs to update the count. So, in this example below row 2's status is AWARDED, so +1 to the overall count, but later its changed in row 7 from AWARDED to LOST, so the count would change. So, with this example the answer should equal: 1, since only 1 was truly AWARDED. Since row 1 was in 2022 it won't be picked up in the count. Any help or direction regarding this would be highly appreciated! Also, if any form of the word "LOST" is located it would be great to have that included. For some reason people tend to put "ASSUMED LOST" even though its been noted to avoid that.
Book1
BCD
2abc#NAME?
Sheet2
Cell Formulas
RangeFormula
D2D2=CountAwarded(B2,2023)


Book1
ABCDEFGHIJKLMNO
1abcplace 012/20/2022AWARDED
2abcPLACE 19/5/2023AWARDED
3defVILLAGE 19/8/2023ASSUMED LOST
4defVILLAGE 29/13/2023AWARDED
5defVILLAGE 29/15/2023LOST
6abcplace 29/18/2023LOST
7abcplace 19/20/2023LOST
8abcplace 410/1/2023AWARDED
TRACKER


VBA Code:
Function CountAwards(lookupValue As Range, year As Integer) As String
    Dim ws As Worksheet
    Dim count As Integer
    Dim cell As Range
    Dim lastRow As Long
    
    Set ws = Worksheets("TRACKER")
    
    lastRow = ws.Cells(ws.Rows.count, "B").End(xlUp).Row
    
    count = 0
    
    For Each cell In ws.Range("B2:B" & lastRow)
        If cell.Value = lookupValue.Value Then
            If cell.Offset(0, 12).Value = "AWARDED" And year(cell.Offset(0, 9).Value) = year Then
                If Application.WorksheetFunction.CountIf(ws.Range("C2:C" & lastRow), cell.Offset(0, 1).Value) = 1 Then
                    count = count + 1
                ElseIf Application.WorksheetFunction.CountIfs(ws.Range("C2:C" & lastRow), cell.Offset(0, 1).Value, ws.Range("O2:O" & lastRow), "LOST") > 0 Then
                    count = count - 1
                End If
            End If
        End If
    Next cell
    
    CountAwards = count
End Function
 

Excel Facts

Best way to learn Power Query?
Read M is for (Data) Monkey book by Ken Puls and Miguel Escobar. It is the complete guide to Power Query.
The error that appears: "#NAME?" is because in the formula you have this:

=CountAwarded(B2,2023)


And the function has another name:
Function CountAwards(


You could put more possible scenarios, that is, what is the result in a case like the following, if it can occur:
varios 31oct2023.xlsm
ABCJO
1abcPLACE 101/sep/2023AWARDED
2abcPLACE 102/sep/2023AWARDED
3abcPLACE 103/sep/2023LOST
4abcPLACE 104/sep/2023LOST
5abcPLACE 105/sep/2023LOST
6abcPLACE 106/sep/2023LOST
7abcPLACE 107/sep/2023LOST
TRACKER

The result is -3?

Or in this case. What would be the result?
varios 31oct2023.xlsm
ABCJO
1abcPLACE 101/sep/2023AWARDED
2abcPLACE 102/sep/2023AWARDED
3abcPLACE 103/sep/2023LOST
4abcPLACE 104/sep/2023AWARDED
5abcPLACE 105/sep/2023AWARDED
6abcPLACE 106/sep/2023AWARDED
7abcPLACE 107/sep/2023AWARDED
TRACKER


----- --
I hope to hear from you soon.
Respectfully
Dante Amor
----- --
 
Upvote 0
The error that appears: "#NAME?" is because in the formula you have this:

=CountAwarded(B2,2023)


And the function has another name:
Function CountAwards(


You could put more possible scenarios, that is, what is the result in a case like the following, if it can occur:
varios 31oct2023.xlsm
ABCJO
1abcPLACE 101/sep/2023AWARDED
2abcPLACE 102/sep/2023AWARDED
3abcPLACE 103/sep/2023LOST
4abcPLACE 104/sep/2023LOST
5abcPLACE 105/sep/2023LOST
6abcPLACE 106/sep/2023LOST
7abcPLACE 107/sep/2023LOST
TRACKER

The result is -3?

Or in this case. What would be the result?
varios 31oct2023.xlsm
ABCJO
1abcPLACE 101/sep/2023AWARDED
2abcPLACE 102/sep/2023AWARDED
3abcPLACE 103/sep/2023LOST
4abcPLACE 104/sep/2023AWARDED
5abcPLACE 105/sep/2023AWARDED
6abcPLACE 106/sep/2023AWARDED
7abcPLACE 107/sep/2023AWARDED
TRACKER


----- --
I hope to hear from you soon.
Respectfully
Dante Amor
----- --

The error that appears: "#NAME?" is because in the formula you have this:

=CountAwarded(B2,2023)


And the function has another name:
Function CountAwards(


You could put more possible scenarios, that is, what is the result in a case like the following, if it can occur:
varios 31oct2023.xlsm
ABCJO
1abcPLACE 101/sep/2023AWARDED
2abcPLACE 102/sep/2023AWARDED
3abcPLACE 103/sep/2023LOST
4abcPLACE 104/sep/2023LOST
5abcPLACE 105/sep/2023LOST
6abcPLACE 106/sep/2023LOST
7abcPLACE 107/sep/2023LOST
TRACKER

The result is -3?

Or in this case. What would be the result?
varios 31oct2023.xlsm
ABCJO
1abcPLACE 101/sep/2023AWARDED
2abcPLACE 102/sep/2023AWARDED
3abcPLACE 103/sep/2023LOST
4abcPLACE 104/sep/2023AWARDED
5abcPLACE 105/sep/2023AWARDED
6abcPLACE 106/sep/2023AWARDED
7abcPLACE 107/sep/2023AWARDED
TRACKER


----- --
I hope to hear from you soon.
Respectfully
Dante Amor
----- --
Hey Dante!

My booklet crashed so I typed it on another workbook for the visual. Yes, it's suppose to be CountAwards. I was trying to get it to only count where AWARDED occurred and ignore counting LOSS, but if a duplicate occurs, then subtract or add accordingly. In your last example it would be 1, since the last time (September 1st, 2023) Place 1 occurred its status was AWARDED. Now, if it occurred again and it was LOST, then it would be 0. Hope that makes sense. Thanks for taking a look at this for me!
 
Upvote 0
Try this code:

VBA Code:
Option Explicit
Function CountAwards(lookupValue As Range, yr As Integer) As Long
Dim i&, rng, dic As Object, c&, item
Application.Volatile
Set dic = CreateObject("Scripting.Dictionary")
With Sheets("TRACKER")
    rng = .Range("B1", .Cells(Rows.Count, "O").End(xlUp)).Value
End With
For i = 1 To UBound(rng)
    If rng(i, 1) = lookupValue And year(rng(i, 9)) = yr Then
        
        'if ARWARDED then +1 if contains *LOST* then -1
        If UCase(rng(i, 14)) = "AWARDED" Then
            c = 1
        ElseIf InStr(1, UCase(rng(i, 14)), "LOST") Then
            c = -1
        End If
        
        'generate dictionary with key= unique "place" and item=addup the "c"
        If Not dic.exists(UCase(rng(i, 2))) Then
            dic.Add UCase(rng(i, 2)), c
        Else
            dic(UCase(rng(i, 2))) = dic(UCase(rng(i, 2))) + c
        End If
    End If
Next

'iterate key, then addup the item if item>0 (award-lost>0)
For Each item In dic.items
    If item > 0 Then CountAwards = CountAwards + item
Next
End Function
 
Upvote 0
Solution
Try this code:

VBA Code:
Option Explicit
Function CountAwards(lookupValue As Range, yr As Integer) As Long
Dim i&, rng, dic As Object, c&, item
Application.Volatile
Set dic = CreateObject("Scripting.Dictionary")
With Sheets("TRACKER")
    rng = .Range("B1", .Cells(Rows.Count, "O").End(xlUp)).Value
End With
For i = 1 To UBound(rng)
    If rng(i, 1) = lookupValue And year(rng(i, 9)) = yr Then
       
        'if ARWARDED then +1 if contains *LOST* then -1
        If UCase(rng(i, 14)) = "AWARDED" Then
            c = 1
        ElseIf InStr(1, UCase(rng(i, 14)), "LOST") Then
            c = -1
        End If
       
        'generate dictionary with key= unique "place" and item=addup the "c"
        If Not dic.exists(UCase(rng(i, 2))) Then
            dic.Add UCase(rng(i, 2)), c
        Else
            dic(UCase(rng(i, 2))) = dic(UCase(rng(i, 2))) + c
        End If
    End If
Next

'iterate key, then addup the item if item>0 (award-lost>0)
For Each item In dic.items
    If item > 0 Then CountAwards = CountAwards + item
Next
End Function
This worked perfectly! I'm now just trying to figure out the next step, but at least I have this go to off of. Someone failed to mention that when you type the year it has to always start from April 1st <year> and search through March 31st <year +1>.

Thanks for all the help you two!
 
Upvote 0
Try this code:

VBA Code:
Option Explicit
Function CountAwards(lookupValue As Range, yr As Integer) As Long
Dim i&, rng, dic As Object, c&, item
Application.Volatile
Set dic = CreateObject("Scripting.Dictionary")
With Sheets("TRACKER")
    rng = .Range("B1", .Cells(Rows.Count, "O").End(xlUp)).Value
End With
For i = 1 To UBound(rng)
    If rng(i, 1) = lookupValue And year(rng(i, 9)) = yr Then
       
        'if ARWARDED then +1 if contains *LOST* then -1
        If UCase(rng(i, 14)) = "AWARDED" Then
            c = 1
        ElseIf InStr(1, UCase(rng(i, 14)), "LOST") Then
            c = -1
        End If
       
        'generate dictionary with key= unique "place" and item=addup the "c"
        If Not dic.exists(UCase(rng(i, 2))) Then
            dic.Add UCase(rng(i, 2)), c
        Else
            dic(UCase(rng(i, 2))) = dic(UCase(rng(i, 2))) + c
        End If
    End If
Next

'iterate key, then addup the item if item>0 (award-lost>0)
For Each item In dic.items
    If item > 0 Then CountAwards = CountAwards + item
Next
End Function
Think I got it...
Changed
VBA Code:
[QUOTE]
If rng(i, 1) = lookupValue And year(rng(i, 9)) = yr Then
[/QUOTE]
to
VBA Code:
If rng(i, 1) = lookupValue And rng(i, 9) >= DateSerial(yr, 4, 1) And rng(i, 9) <= DateSerial(yr + 1, 3, 31) Then
 
Upvote 0

Forum statistics

Threads
1,223,888
Messages
6,175,217
Members
452,619
Latest member
Shiv1198

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