How to pass operators through a UDF

MrKowz

Well-known Member
Joined
Jun 30, 2008
Messages
6,653
Office Version
  1. 365
  2. 2016
Platform
  1. Windows
I am looking to expand my knowledge of UDFs, and am wanting to know how to write basic conditional statements as an argument in the UDF. Something similar to how SUMIF/COUNTIF works, where I can select a range, and then say it is ">10", "<>Joe", "="&A1, etc.

Thanks in advance!
 
Zvi,

Yes, that does what I want (with a slight modification to trim the end based on the length of the delimiter). Would you be able to explain the code a bit? I'm trying to pick it apart so I can better understand it, but I can't follow it without really understanding the variables.
 
Upvote 0

Excel Facts

Square and cube roots
The =SQRT(25) is a square root. For a cube root, use =125^(1/3). For a fourth root, use =625^(1/4).
... Would you be able to explain the code a bit? I'm trying to pick it apart so I can better understand it, but I can't follow it without really understanding the variables.
Ok, below is the same code but with more detailed comments.
Let me know if something is still not clear.
Rich (BB code):

' ZVI:2011-03-09 http://www.mrexcel.com/forum/showthread.php?t=534231
' Function to return concatenated values of RngToConcat for which Condition happens
' Optional Delim argument (comma) is the delimiter of the resulting list
' Note1:   It's faster if performed as array formula via Ctrl-Shift-Enter
' Note2:   Decimal separator of numbers is the dot char for all localizations
' Example: =ConcatIf(A1:A10, (B1:B10>1)*(C1:C10<10), CHAR(10))
Function ConcatIf(RngToConcat As Range, Condition, Optional Delim$ = ",") As String
  
  ' Variables are reserved for:
  ' a - for array/value of RngToConcat, processing of array is faster than of range
  ' b - for array/value of Condition, used also for parsing of Condition part from the caller formula
  ' r - row counter, rs - rows count
  ' c - column counter, cs - columns count
  ' s - concatenated string, used also as temporary variable
  ' x - temporary vatiable
  ' vt - vartype of x-variable
  ' In Dim the suffix "&" is equal to "As Long", "$" =  "As String"
  Dim vt As VbVarType, a, b, i&, r&, rs&, c&, cs&, s$, x
  
  ' Copy range value to variable, processing of VBA array is much faster than processing of range
  a = RngToConcat.Value
  
  ' If only 1 cell is on the RngToConcat, then a-variable is not array, else it's array
  If Not IsArray(a) Then
    ' There is only single cell in RngToConcat - process it and exit
    If Condition Then ConcatIf = a: Exit Function
  End If
  
  ' Copy Condition to b-variable
  b = Condition
  
  ' If formula was entered as array formyla by CSE, then b-variable is array, else it's not array
  If Not IsArray(b) Then
    ' Ctrl-Shift-Enter was not performed - do evaluation of Condition formula(s)
    
    With Application.ThisCell
      ' Application.ThisCell.Formula gives the formula of the caller cell
      
      ' Temporarily split that formula with comma delimiter into zero based b() array
      b = Split(.Formula, ",")
      
      ' b() now is zero based array, b(1) consists Conditional equation
      ' It is assumed that comma is not used in Conditional equation, if does then more strong parsing is required
      s = b(1)
      
      ' If optional Delim was not passed into function then delete right round bracket
      If UBound(b) = 1 Then s = Left$(s, Len(s) - 1)
      
      ' Evaluate Condition in the sheet with caller cell
      ' Application.ThisCell.Parent is reference to that sheet
      b = .Parent.Evaluate(s)
      
      ' Clean s for further usage
      s = ""
      
    End With
  
  End If
  
  ' Calc rows count in b()
  rs = UBound(b, 1)
  
  ' Calc columns count in b()
  cs = UBound(b, 2)
  
  ' Loop through b() array,
  ' if not Error/False/Empty/Zero condition found
  ' then get value from a() at the same row & column for concatenation
  For r = 1 To rs
    For c = 1 To cs
      x = b(r, c)
      If VarType(x) <> vbError Then
        ' value of b(r, c) is not error - process it
        If x Then
          ' value of b(r, c) is not False/Zero/Empty - get value from a() at the same row & column
          x = a(r, c)
          vt = VarType(x)
          If vt <> vbError Then
            ' value of a(r, c) is not error - process it
            If Len(x) Then
              ' value of a(r, c) is not empty - provide dot char as the decimal separator for all localizations
              If IsNumeric(x) And vt <> vbString Then x = Trim$(Str(x))
              ' Concatenate the result in temporary s-variable
              s = s & x & Delim
            End If
          End If
        End If
      End If
    Next
  Next
  
  ' Set result
  i = Len(s)
  
  ' Delete the last comma in s
  If i Then ConcatIf = Left$(s, i - 1)
  
End Function
 
Last edited:
Upvote 0
ZVI, that definitely clears up a LOT with that code. Very, very, much appreciated. Also, shg, rorya, tusharm, and mancubus, thank you much for the input! I really like getting multiple ideas!

Now for me to understand exactly how the array from .Evaluate() is built/works, and I think I'll fully understand the entire thing! Off to google with me!
 
Last edited:
Upvote 0
Did some testing, and I think I understand it now. I'm starting to like Evaluate!
 
Upvote 0
Now for me to understand exactly how the array from .Evaluate() is built/works, and I think I'll fully understand the entire thing!
It's easy to understand :)
Sheets(NameOrIndex).Evaluate("Formula") is equal to the situation in which "Formula" is entered into the cell as array formula by Ctrl-Shift-Enter, its result is an array.
Select some cells, for example C1:C10, put array formula A1:A10>1 and confirm by Ctrl-Shift-Enter.
The values in C1:C10 will reflect the same values as in array returned via ActiveSheet.Evaluate("A1:A10>1")
 
Last edited:
Upvote 0
It's easy to understand :)
Sheets(NameOrIndex).Evaluate("Formula") is equal to the situation if "Formula" is entered into the cell as array formula by Ctrl-Shift-Enter, its result is an array

Awesome, that confirms exactly what I was thinking.

Cheers! (y)
 
Upvote 0

Forum statistics

Threads
1,216,028
Messages
6,128,399
Members
449,447
Latest member
M V Arun

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