1
Trying to copy the function of vlookup in VBA, the best I can come up with is this:
Function VBALOOKUP(LUcell As Variant, LUArray As Range, LUColi As Long, OutColi As Long) As Variant
Dim Y() As Variant
Dim X As Long
'cycle through each cell in range and check if = to lookup cell then return value with same index in outcol
Y = LUArray
For X = LBound(Y) To UBound(Y)
If LUcell = Y(X, LUColi) Then
VBALOOKUP = Y(X, OutColi)
Exit For
End If
Next X
Erase Y
End Function
It works , but is incredibly slow (about 100x slower than the worksheet function).
It seems like maybe a way to speed it up would be to sort lookup array alphabetically and somehow jump to a later point in the list? I have no expertise here, but it seems like looking at each individual cell to check if its equal to the lookup value, before then going onto the next cell just can't be the most efficient way to do it, and can't be how the actual vlookup function works.
If you're wondering "why not just use vlookup", I'm writing a script in VBA that at one point performs something similar to a vlookup (although the specific situation is a little more complicated, and returns multiple values not just 1). Rather than ask stackexchange to write all my code for me, I thought I'd get to the heart of the issue. Plus, I believe this question will be helpful for future reference for many more people than one about my specific task would be.
I think this question is more about VBa, and not so much Excel (despite it being very well worded and clear). Scripting questions are OK here if the focus is Excel functionality. As such I've voted to migrate this question to Stack Overflow as I think it will be more suited for you, despite your statement about not asking them there :) – Dave – 2016-09-22T10:04:25.903
Search the internet for
Binary Search
. You'll also need a quick sorting routine. Thequicksort
algorithm works well if you don't need a stable sort, although you could also do your sorting using VBA on a temporary and/or hidden worksheet.. – Ron Rosenfeld – 2016-09-22T10:23:21.707VBA isn't a language optimized for speed. It compiles during run time, accessing cells take time for it... Your question is nicely worded, but I don't think answer would bring you closer to your problem's solution. Please describe your real problem with some sample data and we'll try to help. You may even solve it with array formula, without using VBA. – Máté Juhász – 2016-09-22T10:33:06.880
@Dave Perhaps it would be better at stackoverflow – Some_Guy – 2016-09-22T10:37:25.140
@MátéJuhász I've tried to minimise accessing cells as much as by putting the range into an array outside of the for loop, but this is still very slow – Some_Guy – 2016-09-22T10:38:19.807
Oh, with regard to sorting, if you are using strings, you should probably use a VBA sort routine and not use Excel's sort. The reason being that some have stated that the Excel sort order is different than that derived using VBA's
<
and>
operators. – Ron Rosenfeld – 2016-09-22T10:39:08.960@Some_Guy: that's still only part of the problem. You can't prevent run time compiling. Without knowing your real problem we can't really help. This may help understanding my concerns: http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem
– Máté Juhász – 2016-09-22T10:42:36.623@RonRosenfeld thanks, that's a good tip. Lets assume the array is already sorted alphanumerically. How would I use this to write code that is more efficient. Lets say MY array is "aaa, aab ,aac... zzy, zzz. If LUcell is if I'm looking up "zza" it seems horribly inefficient to cycle through 17,000 values before getting there, surely there would be a way of writing the code that would be smarter in the approach, somehow jump around until it finds the right point? – Some_Guy – 2016-09-22T10:47:03.877
@MátéJuhász I'm sure that there are ways to drastically speed up this code, even with the inherent limitations of VBA. I refuse to believe the most sensible way of writing a lookup function is "am I in row 1? no. OK. Am I in row 2? no. am I in.... am I in row 20,000, YES. Return value." . There's just no way that's what the native vlookup function is doing. – Some_Guy – 2016-09-22T10:50:15.707
If last parameter of worksheet function VLOOKUP is
TRUE
, then it uses log search, which is of course much faster. However if it'sFALSE
, then you need to check all items (or do some mapping / sorting before). – Máté Juhász – 2016-09-22T10:53:06.3932
@Some_Guy Once you've sorted the array, in the same sort order that VBA would use, then, as I wrote, you implement a VBA Binary Search routine -- many are documented on the internet. Also see This binary search algorithm on SO
– Ron Rosenfeld – 2016-09-22T10:55:45.143@RonRosenfeld thanks so much, I'm looking at this now. Sorry, I somehow missed that in your first comment. It seems that exactly what I need to do is a binary search, and I've been using a "linear search" up to this point. This is completely new territory for me. – Some_Guy – 2016-09-22T11:20:04.337
@dave what statement about not asking them were you referring to? – Some_Guy – 2016-09-22T11:20:49.810
@Some_Guy Also, don't overlook the point I made, and also made in the thread to which I linked, about the sorting algorithm being different in VBA and Excel. This will cause the VBA binary search to occasionally fail to find something if strings are sorted in Excel order. – Ron Rosenfeld – 2016-09-22T11:32:09.813
@RonRosenfeld I'll make sure I don't forget it, thanks – Some_Guy – 2016-09-22T11:33:00.457
@Dave I guess that was pretty ambiguous, I was referring to you guys! Whether here or on SO, I'm always worried about being taken as asking "here's my really specific problem which will take a bunch of VBA to solve, could you write it for me?" – Some_Guy – 2016-09-22T11:34:40.313
@Some_Guy, you've demonstrated the code, you've come up with an issue about performance, it's a good question (hence why I gave the +1) – Dave – 2016-09-22T13:13:06.733
1Personally, I'd delete this question and re-ask it at Stack Overflow. You've already got 3 close votes and I assume they're all going to vote to migrate, not actually close! Also, what does it matter if some one leaves a snobby comment like "do it yourself, or get a book". You know if you've made the effort or not :) – Dave – 2016-09-23T12:44:51.323