For a data set like the following, I'd like to, if the value in Row 1 equals a specified value, return all ID column values in rows where the cell value in the specified column is less than 3. (No values repeat in the ID column or in Row 1 "headers".)
ID | X | Y | Z
123 | 1 | 2 | 5
456 | 2 | 6 | 4
789 | 6 | 1 | 2
e.g., if a column header = "X", return value of "123, 456". If Y, "123, 789". If Z, "789". I've found a variation of a "multicat formula" (in the edit to the linked answer) that comes close to addressing my needs, but I'm having trouble adapting it.
Public Function MultiCat2( _
ByRef rRng As Excel.Range, _
Optional ByVal sDelim As String = "") _
As String
Dim rCell As Range
For Each rCell In rRng
If rCell.Value < 3 Then
MultiCat2 = MultiCat2 & sDelim & rCell.Text
End If
Next rCell
MultiCat2 = Mid(MultiCat2, Len(sDelim) + 1)
End Function
If I run the function as is on X, for example, it returns a value of "1, 2." The result needs to always be from the ID column, regardless of the column being evaluated. That part should be simple, but I can't figure out how to do it without Offset, which doesn't help me, because the evaluated column will be variable.
I have the plain English logic I need: "If value of cell in a1:d1 = X, MultiCat a1:a4 where cell value in [selected column] is <3." I can find the column I'd like to perform the evaluation on using the Match function, and I have the code I think I need to concatenate results in a single cell.
I just can't figure out how to incorporate the result of the Match into the function, or how to get the function to concatenate the ID column.
You could a) hard-code the ID column into the function; b) add a parameter to pass the ID column into the function; c) pass the column header name into the function.
Option Explicit
Public Function MultiCat2A(ByRef rRng As Excel.Range, _
Optional ByVal sDelim As String = ",") _
As String
Dim c As Long, cRng As Range
'restrict rRng to the .UsedRange
Set rRng = Intersect(rRng, rRng.Parent.UsedRange)
'set cRng to another column but equal to rRng
Set cRng = Intersect(rRng.EntireRow, rRng.Parent.Columns("A"))
For c = 1 To rRng.Count
If rRng(c).Value < 3 Then
MultiCat2A = MultiCat2A & sDelim & cRng(c).Text
End If
Next c
MultiCat2A = Mid(MultiCat2A, Len(sDelim) + 1)
If CBool(Len(sDelim)) Then
Do While Right(MultiCat2A, Len(sDelim)) = sDelim
MultiCat2A = Left(MultiCat2A, Len(MultiCat2A) - Len(sDelim))
Loop
End If
End Function
Public Function MultiCat2B(ByRef cRng As Range, _
ByRef rRng As Excel.Range, _
Optional ByVal sDelim As String = ",") _
As String
Dim c As Long
'restrict rRng to the .UsedRange
Set rRng = Intersect(rRng, rRng.Parent.UsedRange)
'resize cRng to the same as rRng
Set cRng = cRng(1, 1).Resize(rRng.Rows.Count, rRng.Columns.Count)
For c = 1 To rRng.Count
If rRng(c).Value < 3 Then
MultiCat2B = MultiCat2B & sDelim & cRng(c).Text
End If
Next c
MultiCat2B = Mid(MultiCat2B, Len(sDelim) + 1)
If CBool(Len(sDelim)) Then
Do While Right(MultiCat2B, Len(sDelim)) = sDelim
MultiCat2B = Left(MultiCat2B, Len(MultiCat2B) - Len(sDelim))
Loop
End If
End Function
Public Function MultiCat2C(ByVal sHdr As String, _
ByRef rRng As Excel.Range, _
Optional ByVal sDelim As String = ",") _
As String
Dim c As Long, cRng As Range
'restrict rRng to the .UsedRange
Set rRng = Intersect(rRng, rRng.Parent.UsedRange)
'find the column by header label
c = Application.Match(sHdr, rRng.Parent.Rows(1), 0)
'offset cRng by its column vs rRng's column
Set cRng = rRng(1, 1).Offset(0, c - rRng.Column)
For c = 1 To rRng.Count
If rRng(c).Value < 3 Then
MultiCat2C = MultiCat2C & sDelim & cRng(c).Text
End If
Next c
MultiCat2C = Mid(MultiCat2C, Len(sDelim) + 1)
If CBool(Len(sDelim)) Then
Do While Right(MultiCat2C, Len(sDelim)) = sDelim
MultiCat2C = Left(MultiCat2C, Len(MultiCat2C) - Len(sDelim))
Loop
End If
End Function
In sample image's G2:G5 as,
=MultiCat2A(B2:B4)
=MultiCat2B($A2:$A4, B2:B4)
=MultiCat2C("ID", B2:B4)
=MultiCat2C($A1, B2:B99)
Fill right as necessary.