1

Excel builtin functions and operators can accept both scalars (single values) and arrays (such as a range of cells) as arguments, and will return scalar or array accordingly as results, spilling when approriate.

To mimic this feature in user-defined functions (UDF) is not straightforward, however. I have to test the arguments and handle them accordingly. Is there a simple way to do this without doing this complex logic for each and every UDF?

I have done one such function as shown below, and hope someone can point me to a simpler way to doing this. The function is not actually finished and has holes in it, but I hope you get the idea.

Note that the problem becomes even more complicated if both 'chars' and 'inText' are arrays. But, Excel handles such situations just fine, and you just have to watch out for mixing columns and rows.

Function FindChar(chars As String, inText As Variant, Optional start_Num As Variant = 1) As Variant
' find any char in 'Chars' within 'inText' and return the index of found char or 0 if not found.
    If IsRange(inText) Then
        ' inText is range
        Dim ii As Long, res() As Variant
        ReDim res(1 To inText.Count)
        For ii = 1 To inText.Count
            If IsRealArray(start_Num) _
            Then res(ii) = FindChar(chars, inText(ii).Value, start_Num(ii)) _
            Else res(ii) = FindChar(chars, inText(ii).Value, start_Num)
        Next ii
        FindChar = res
        Exit Function
    End If
    If IsRealArray(inText) Then
        'inText is array
        Dim errMSG As String
        errMSG = "FindChar: cannot handle array yet"
        Debug.Print errMSG
        MsgBox errMSG
        Stop
        Exit Function
    End If
    ' inText is scalar
    If start_Num <= 0 Then
        FindChar = CVErr(xlErrValue)
        Exit Function
        End If
    If Not inText Like "*[" & chars & "]*" Then
        FindChar = 0
        Exit Function
    End If
    Dim jj As Integer, pos As Long, cc as string
    FindChar = 0
    For jj = 1 To Len(chars)
        cc = Mid(chars, jj, 1)
        pos = InStr(start_Num, inText, cc, vbTextCompare)
        If pos <> 0 Then 
            FindChar=pos
            Exit Function
    Next jj
    FindChar = 0
End Function

Function IsRange(arg As Variant) As Boolean
    IsRange = "Range" = TypeName(arg)
End Function

Function IsRealArray(arg As Variant) As Boolean
' the built in function IsArray will return TRUE for range
' but this function will not
' because it looks for the '(' in TypeName
    IsRealArray = InStr(TypeName(arg), "(") > 0
End Function
Yuan Liu
  • 11
  • 2
  • 1
    sorry, wrong one. This one I created when TEXTJOIN was not widely available: https://stackoverflow.com/questions/45843881/textjoin-udf-for-excel-2013/45845229#45845229 – Scott Craner Sep 06 '22 at 13:51
  • 1
    Also see the discussion here: https://codereview.stackexchange.com/questions/180332/test-for-array-vs-range-in-my-textjoin-udf where I asked if there is a better way to do it on CodeReview. – Scott Craner Sep 06 '22 at 14:04

0 Answers0