+ Reply to Thread
Results 1 to 28 of 28

NthMatch UDF as An Alternative to Array function...

Hybrid View

  1. #1
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Thumbs up NthMatch UDF as An Alternative to Array function...

    Hi Folks,
    Yesterday I posted following thread in this section ..
    http://www.excelforum.com/tips-and-t...ift-enter.html
    The thread was about using "Sumproduct as an alternative to array formulas.."
    I was very happy that I made something like this..

    but our Sir Mr. XOR opened my eyes and explain me why my formula was not that much fast as array function.. and was more intensive resource wise as well...

    Then I started think about another alternative..
    Actually I had, before posting the above thread, made an UDF ie NthMatch.. to return the Row No. of the Nth Match of a value in the array..
    It is an improvement over Match function.. as Match function only returns row No. of the first Match...

    when I got the solution.. what I saw that The NthMatch alternative was short(lenght wise) of the Sumproduct and Array alternatives..
    So that is what I wanted to share with you all..
    Have a visit at the link below.. and let me know whether there are any chances of improvement..
    http://excel-buzz.blogspot.in/2014/0...-to-array.html

    Here is the code for NthMatch(Lookup_value, Lookup_Range, Match No.)

    Function NthMatch(ByVal Lvalue As Variant, ByVal Lrange As Variant, Mnum As Variant) As Integer
    '*************Developed by Vikas Gautam ****************
    '*************www.Excel-buzz.blogspot.com***************
    Dim Arr()
    ReDim Arr(0)
    r = 0
    If IsArray(Lrange) Then
        For Each cell In Lrange
            c = c + 1 'c counts row no. to be checked
            If cell = Lvalue Then
                ReDim Preserve Arr(r)
                Arr(r) = c 'assigning row no. of the match row to the Arr
                r = r + 1
            End If
        Next
    Else
        If Lvalue = Lrange Then Arr(0) = 1 'if the Lrange is a single value ....
    End If
    NthMatch = Arr(Mnum - 1)
    End Function
    View post #9 for better solution given by KVS

    Regards,
    Vikas Gautam
    Attached Files Attached Files
    Last edited by Vikas_Gautam; 08-15-2014 at 12:41 PM.

  2. #2
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Re: NthMatch UDF as An Alternative to Array function...

    I request all excel experts and gurus..
    if there is any chances of improvement and innovation in the code..

    then please have a comment..


    Regards,
    Vikas Gautam

  3. #3
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Thumbs up Re: NthMatch UDF as An Alternative to Array function...

    Improved A bit..

    Now It jump over the result when Match No. matches the row no....
    means It stops looping when Nth Match is found.. and throws the result...

    Here is the code..

    Function NthMatch(ByVal Lvalue As Variant, ByVal Lrange As Variant, Mnum As Variant) As Integer
    '*************Developed by Vikas Gautam ****************
    '*************www.Excel-buzz.blogspot.com***************
    Dim Arr()
    ReDim Arr(0)
    r = 0
    If IsArray(Lrange) Then
        For Each cell In Lrange
            c = c + 1 'c counts row no. to be checked
            If cell = Lvalue Then
                ReDim Preserve Arr(r)
                Arr(r) = c 'assigning row no. of the match row to the Arr
                If r = Mnum - 1 Then NthMatch = Arr(Mnum - 1): Exit Function 'Stops looping when Nth Match is found..
                r = r + 1
            End If
        Next
    Else
        If Lvalue = Lrange Then Arr(0) = 1 'if the Lrange is a single value ....
    End If
    NthMatch = Arr(Mnum - 1)
    End Function
    If there are chances of improvement then don't hesitate.. Have a comment..
    Attached Files Attached Files
    Last edited by Vikas_Gautam; 08-09-2014 at 10:38 AM.

  4. #4
    Forum Guru
    Join Date
    04-13-2005
    Location
    North America
    MS-Off Ver
    2002/XP, 2007, 2024
    Posts
    16,369

    Re: NthMatch UDF as An Alternative to Array function...

    My main criticism is that your use of the For each ... next loop will cause the code to search each and every entry for a match. It can be an effective "brute force" algorithm, and may be necessary for some situations. I would consider including, similar to Excel's built in lookup functions, a "range_lookup" argument. If the user will provide a sorted list -- then you can use a much more efficient binary search algorithm (http://en.wikipedia.org/wiki/Binary_search_algorithm ). You also only need to find the first and last match -- recognizing that, if the list is properly sorted, all matches will be in between the first and last match. I could see potential for significant performance improvement if you allow for (or even encourage) the search on a sorted list.
    Quote Originally Posted by shg
    Mathematics is the native language of the natural world. Just trying to become literate.

  5. #5
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Re: NthMatch UDF as An Alternative to Array function...

    Thanks for replying Mr. Shorty..
    if you can tell me how will I implement that that would be greatly appreciated..


    Regards,
    Vikas Gautam

  6. #6
    Forum Expert
    Join Date
    07-20-2011
    Location
    Mysore, India.
    MS-Off Ver
    Excel 2019
    Posts
    8,710

    Re: NthMatch UDF as An Alternative to Array function...

    Pl see attached file with FindNthMatch UDF .It is faster, I feel.
    Attached Files Attached Files

  7. #7
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Re: NthMatch UDF as An Alternative to Array function...

    You are great..
    KVS..
    Simply Superb..

    If you don't mind..
    I want to post your piece of excellence... in my blog.. under your name..

    Actually I tried the find and match method of worksheet function.. but I skipped the After:= Part..

    Thanks again...

    Regards,
    Vikas Gautam

  8. #8
    Forum Expert
    Join Date
    07-20-2011
    Location
    Mysore, India.
    MS-Off Ver
    Excel 2019
    Posts
    8,710

    Re: NthMatch UDF as An Alternative to Array function...

    Thanks for the compliments.I don't have any objection to post.
    With regards
    KVS

  9. #9
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Re: NthMatch UDF as An Alternative to Array function...

    Hi Folks,

    I just forgot to share... what KVS has made...
    Just simply superb.. Fastest till now for the same job...


    Function NthMatchNEW(ByVal Lvalue As Variant, Lrange As Variant, Mnum As Variant)
    'For ARRAY and RANGE input
    Dim M As Variant
    Dim X As Integer, MatchNo As Integer
    
    On Error Resume Next
    
    M = Join(Application.Transpose(Lrange), "&,")
    M = Join(Lrange, "&,")
    M = "&," & M & "&,"
    X = 1
    
    For t = 1 To Mnum
        X = InStr(X, M, "&," & Lvalue & "&,")
        If X < y Then GoTo Line1
        X = X + 1
        y = X
    Next t
    
    NthMatchNEW = Int((Len(Left(M, y)) - Len(Replace(Left(M, y), "&,", ""))) / 2)
    
    Line1:
    If NthMatchNEW = 0 Then NthMatchNEW = "#ERROR"
    
    End Function
    Thanks again KVS..
    Using Strings was a great idea..

    Vikas Gautam

  10. #10
    Forum Expert
    Join Date
    07-20-2011
    Location
    Mysore, India.
    MS-Off Ver
    Excel 2019
    Posts
    8,710

    Re: NthMatch UDF as An Alternative to Array function...

    Hi Vikas,
    Just curious if you can share your blog link.
    Regards,
    KVS

  11. #11
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Re: NthMatch UDF as An Alternative to Array function...

    yeah... of course...

    its..

    http://excel-buzz.blogspot.in/


    Vikas Gautam

  12. #12
    Forum Contributor Gregor y's Avatar
    Join Date
    10-24-2011
    Location
    Colorado, USA
    MS-Off Ver
    Excel 2010 32-Bit
    Posts
    280

    Re: NthMatch UDF as An Alternative to Array function...

    Thank you so much for posting this UDF it got me going on the right track.

    To answer your statement "and let me know whether there are any chances of improvement..", I believe the following would be a performance improvement, as it doesn't loop through every single cell, and also uses the built in range.find method to do the heavy lifting.

    Refer to seprate Excel Function: nXLookup thread for the nXLookup's VBA code.

    Cell Formula:
    =ROW(nXLookup(Lookup_value,Lookup_Range,0,0,Match No.))

    PS: I'm not trying to piggy back my thread on top of yours, please let me know if you feel this way and I'll delete this comment.

  13. #13
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Re: NthMatch UDF as An Alternative to Array function...

    Gregor Y,
    I really appreciate the work you have done..
    But I think you have not seen one given by KVS.. ies
    Function NthMatchNEW(ByVal Lvalue As Variant, Lrange As Variant, Mnum As Variant)
    'For ARRAY and RANGE input
    Dim M As Variant
    Dim X As Integer, MatchNo As Integer
    
    On Error Resume Next
    
    M = Join(Application.Transpose(Lrange), "&,")
    M = Join(Lrange, "&,")
    M = "&," & M & "&,"
    X = 1
    
    For t = 1 To Mnum
        X = InStr(X, M, "&," & Lvalue & "&,")
        If X < y Then GoTo Line1
        X = X + 1
        y = X
    Next t
    
    NthMatchNEW = Int((Len(Left(M, y)) - Len(Replace(Left(M, y), "&,", ""))) / 2)
    
    Line1:
    If NthMatchNEW = 0 Then NthMatchNEW = "#ERROR"
    
    End Function
    The above code is for RANGE and ARRAY as well..
    It uses fantastic string manipulation.. very very fast..
    Try it for your performance test
    here is one more link for performance appraisals..
    Improving performance in excel
    There are some codes for speed testing, must try..

    Good Luck..
    Regards,
    Vikas Gautam
    Excel-buzz.blogspot.com

    Excel is not a matter of Experience, its a matter of Application.

    Say Thanks, Click * Add Reputation

  14. #14
    Forum Contributor Gregor y's Avatar
    Join Date
    10-24-2011
    Location
    Colorado, USA
    MS-Off Ver
    Excel 2010 32-Bit
    Posts
    280

    Re: NthMatch UDF as An Alternative to Array function...

    Thank you I'm not accustomed to strings being able to hold 2^31 characters (FYI: (2^31)/1048576=2048, should be more then enough room), and I'm definitely going to have a look into the timing functions used on your link.

    Also you may want to consider the following slight variant so that you don't have to escape the "&," delimiter incase it comes up within the data...
    Function NthMatchNEW(ByVal Lvalue As Variant, Lrange As Variant, Mnum As Variant)
        'For ARRAY and RANGE input
        Dim M As Variant, X As Integer, MatchNo As Integer
        Dim D As String: D = Chr(2) 'an unlikely delimiter value
        On Error Resume Next
        
        M = Join(Application.Transpose(Lrange), D)
        M = Join(Lrange, D)
        M = D & M & D
        X = 1
        
        For t = 1 To Mnum
            X = InStr(X, M, D & Lvalue & D)
            If X < y Then GoTo Line1
            X = X + 1
            y = X
        Next t
        
        NthMatchNEW = (y - Len(Replace(Left(M, y), D, ""))) ' \ Len(D)
        
    Line1:
        If NthMatchNEW = 0 Then NthMatchNEW = "#ERROR" 'CVErr(xlErrNum)
    
    End Function

  15. #15
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Re: NthMatch UDF as An Alternative to Array function...

    Thanks for the suggestion Gregor y
    I guess you got what you were looking for..

  16. #16
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Cool Re: NthMatch UDF as An Alternative to Array function...

    Hi KVS and all Experts.
    Have a look, NthMatch Redefined
    Function NthMatch(ByVal Lvalue As Variant, Lrange As Variant, Mnum As Variant)
        Mstr = "|" & Join(Application.Transpose(Lrange), "|") & "|"
        Start = 1
        
        For c = 1 To Mnum
            Found = InStr(Start, Mstr, Lvalue)
            If Found = 0 Then NthMatch = "#N/A": End
            Start = Found + 1
        Next
        
        Temp = Left(Mstr, Found)
        RowNo = Len(Temp) - Len(Replace(Temp, "|", ""))
        NthMatch = RowNo
            
    End Function
    Note:- The file doen't contain the same code. So Copy and paste from here.
    Check the attached file:-
    Last edited by Vikas_Gautam; 01-09-2015 at 07:53 AM.

  17. #17
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Cool Re: NthMatch UDF as An Alternative to Array function...

    Here is another new way,
    may be I have reinvented.
    This time NthMatchM with same set of parameters.
    Function NthMatchM(ByVal Lvalue As Variant, ByRef Lrange As Variant, ByRef Mnum As Variant)
        Dim Arr As Variant
        
        Arr = Lrange 'Passing Lrange to other variable
        For r = 1 To Mnum
            RowNo = Application.Match(Lvalue, Arr, 0)
            If IsError(RowNo) Then NthMatchM = "#N/A": End
            Arr(RowNo, 1) = "##Ex##" 'Match excluded
        Next
    
        NthMatchM = RowNo
        
    End Function
    Note:- I have tested the speed of this code, and its much slower than above one.
    Last edited by Vikas_Gautam; 01-09-2015 at 08:14 AM.

  18. #18
    Forum Expert
    Join Date
    07-20-2011
    Location
    Mysore, India.
    MS-Off Ver
    Excel 2019
    Posts
    8,710

    Re: NthMatch UDF as An Alternative to Array function...

    Pl see the file.
    Try this code also for speed test.
    Function NthMatch1(ByVal Lvalue As Variant, Lrange As Variant, Mnum As Variant)
        Mstr = "|" & Join(Application.Transpose(Lrange), "|") & "|"
        Start = 1
        
        For c = 1 To Mnum
        Found1 = InStr(Start, Mstr, "|" & Left(Lvalue, 1))
            If Found1 > 0 Then
            Start = Found1 + 1
                If Mid(Mstr, Start, Len(Lvalue) + 1) = Lvalue & "|" Then
                Start = Found1 + Len(Lvalue)
                Else
                c = c - 1
                End If
            
            End If
        Next
        
        Temp = Left(Mstr, Found1)
        NthMatch1 = Len(Temp) - Len(Replace(Temp, "|", ""))
            
    End Function
    Attached Files Attached Files
    Last edited by kvsrinivasamurthy; 01-10-2015 at 11:01 AM.

  19. #19
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Re: NthMatch UDF as An Alternative to Array function...

    Hi KVS Sir,
    I acknowledge your code.
    But I tested both and Mine is 3 secs faster than yours. ( with due respect )
    your was 9 secs.
    mine was 6 sec
    I have run both five times.
    The Speed may vary PC to PC.
    I am attaching the file having both the Codes.
    In sheet 2 I have arranged the test.
    2500 rows of data.
    Just select the formula range and run the RangeTimer code in the macro.
    May be you have other ideas so test in your way.
    Attached Files Attached Files

  20. #20
    Forum Expert
    Join Date
    07-20-2011
    Location
    Mysore, India.
    MS-Off Ver
    Excel 2019
    Posts
    8,710

    Re: NthMatch UDF as An Alternative to Array function...

    Hi vikas
    I have tested and found mine was slow. Now I have changed code.Pl check with attached file.
    Attached Files Attached Files
    Last edited by kvsrinivasamurthy; 01-11-2015 at 11:52 AM.

  21. #21
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Cool Re: NthMatch UDF as An Alternative to Array function...

    Hi KVS Sir,
    There is a problem with your code (When I removed last 500 rows of data from reference),
    Pl have a look at Row 670 for explanation.

    I acknowledge the fact that you have the speed a lot by removing unnecessary steps in the code.
    So, I believe the Final version should be.
    Function NthMatch(ByVal Lvalue As Variant, Lrange As Variant, Mnum As Variant)
        Mstr = "|" & Join(Application.Transpose(Lrange), "|") & "|"
        Start = 1
        
        For c = 1 To Mnum
            Start = InStr(Start + 1, Mstr, Lvalue)
            If Start = 0 Then End '<--- This the line which I have included to leave loop.
        Next
        
        Temp = Left(Mstr, Start)
        NthMatch = Len(Temp) - Len(Replace(Temp, "|", "")) '<-- Calculating Row No.
    End Function
    Attached Files Attached Files

  22. #22
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Cool Re: NthMatch UDF as An Alternative to Array function...

    Hi KVS Sir,
    There is a problem with your code (When I removed last 500 rows of data from reference),
    Pl have a look at Row 670 for explanation.

    I acknowledge the fact that you have improved the speed a lot by removing unnecessary steps in the code.
    So, I believe the Final version should be.
    Function NthMatch(ByVal Lvalue As Variant, Lrange As Variant, Mnum As Variant)
        Mstr = "|" & Join(Application.Transpose(Lrange), "|") & "|"
        Start = 1
        
        For c = 1 To Mnum
            Start = InStr(Start + 1, Mstr, Lvalue)
            If Start = 0 Then End '<--- This the line which I have included to leave loop.
        Next
        
        Temp = Left(Mstr, Start)
        NthMatch = Len(Temp) - Len(Replace(Temp, "|", "")) '<-- Calculating Row No.
    End Function

  23. #23
    Forum Expert
    Join Date
    07-20-2011
    Location
    Mysore, India.
    MS-Off Ver
    Excel 2019
    Posts
    8,710

    Re: NthMatch UDF as An Alternative to Array function...

    Yes I found it later and edited the code. With slight change I have given new code . Pl see now.
    Function NthMatch1(ByVal Lvalue As Variant, Lrange As Variant, Mnum As Variant)
        
        Mstr = "|" & Join(Application.Transpose(Lrange), "|") & "|"
        Start = 0
        Shift = Len(Lvalue) + 1
        k = "|" & Lvalue & "|"
            
        For C = 1 To Mnum
            Start = InStr(Start + 1, Mstr, k)
        
            If Start = 0 Then
            NthMatch1 = "#N/A"
            GoTo Line1
            Else
            If C < Mnum Then Start = Start + Shift
            End If
        Next C
        
        Temp = Left(Mstr, Start)
        NthMatch1 = Len(Temp) - Len(Replace(Temp, "|", ""))
    Line1:
    End Function

  24. #24
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Re: NthMatch UDF as An Alternative to Array function...

    Yes, KVS Sir,
    Your is faster but I didn't understand how.
    However, I have come up with one more technique.
    Here is it.
    Function NthMatchE(ByVal Lvalue As Variant, ByVal Lrange As Variant, Mnum As Variant)
    f = "SMALL(IF(" & Lrange.Address & "=""" & Lvalue & """,ROW($1:" & Lrange.Rows.Count & "))," & Mnum & ")"
    NthMatchE = Evaluate(f)
    End Function
    Because when I tried the array construction, it was faster than every other technique.
    So I tried to copy the same behavior using Evaluate Function.
    Yours took 4.15 secs but it takes only 2 sec. (would be more fast on your PC)
    Try it and pls share the results.

  25. #25
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Re: NthMatch UDF as An Alternative to Array function...

    Here is the Code with less words but matches ur speed:-
    Function NthMatch(ByVal Lvalue As Variant, Lrange As Variant, Mnum As Variant)
        Mstr = "|" & Join(Application.Transpose(Lrange), "|")
        Lvalue = "|" & Lvalue
        Start = 0
        
        For c = 1 To Mnum
            Start = InStr(Start + 1, Mstr, Lvalue)
            If Start = 0 Then NthMatch = "#N/A": GoTo 0 '<--- This the line which I have included to leave loop.
        Next
    
        Temp = Left(Mstr, Start)
        NthMatch = Len(Temp) - Len(Replace(Temp, "|", "")) '<-- Calculating Row No.
    0
    End Function

  26. #26
    Forum Expert
    Join Date
    07-20-2011
    Location
    Mysore, India.
    MS-Off Ver
    Excel 2019
    Posts
    8,710

    Re: NthMatch UDF as An Alternative to Array function...

    UDF is not required when ARRAY function is used.
    This array function takes only 0.81 secs for 834 rows.
    =INDEX($B:$B,SMALL(IF($A$1:$A$2500=$F$1,ROW($A$1:$A$2500),""),ROW($A1)))
    Attached Files Attached Files

  27. #27
    Forum Expert Vikas_Gautam's Avatar
    Join Date
    06-04-2013
    Location
    Ludhiana,Punjab, India
    MS-Off Ver
    Excel 2013
    Posts
    1,850

    Re: NthMatch UDF as An Alternative to Array function...

    Yes I agree sir.
    But I have learnt a lot from what we have done so far.
    Thanks for your cooperation.

  28. #28
    Forum Expert
    Join Date
    07-20-2011
    Location
    Mysore, India.
    MS-Off Ver
    Excel 2019
    Posts
    8,710

    Re: NthMatch UDF as An Alternative to Array function...

    Thanks for the healthy discushion
    Kvs

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. Alternative to using an array formula for {=LARGE(IF(... function
    By Rabiah in forum Excel Formulas & Functions
    Replies: 28
    Last Post: 05-30-2014, 05:52 AM
  2. UDF Lookup function as an alternative to array functions & match/index
    By Andrew_Harris in forum Excel Programming / VBA / Macros
    Replies: 0
    Last Post: 10-15-2012, 09:34 PM
  3. [SOLVED] Non array alternative for percentile function
    By vandan_tanna in forum Excel Formulas & Functions
    Replies: 3
    Last Post: 05-22-2012, 11:43 AM
  4. Alternative to an array formula.
    By RunHard in forum Excel Programming / VBA / Macros
    Replies: 7
    Last Post: 07-16-2009, 09:18 AM
  5. Array Formula Alternative
    By smninos in forum Excel General
    Replies: 10
    Last Post: 07-15-2009, 04:31 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts

Search Engine Friendly URLs by vBSEO 3.6.0 RC 1