I have this UDF
which I use to lookup dates and return values based on the condition.
Basically two(2) conditions only, either <
or >
the date.
Also, I just use built-in Excel Functions as well and just added some conditions.
Public Function CLOOKUP(lookup_value, table_array As Range, column_index As Long, _
rv_operator, reference_value, Optional range_lookup, _
Optional return_index) As Variant
Dim NT_array, S_array
Dim ORGLOOKUP, REFLOOKUP
Dim row_count As Long, row_less As Long
With Application.WorksheetFunction
If column_index > 0 And column_index <= table_array.Columns.Count Then
On Error Resume Next
ORGLOOKUP = .VLookup(lookup_value, table_array, column_index, range_lookup)
If Err.number <> 0 Then CLOOKUP = CVErr(xlErrNA): Exit Function
On Error GoTo 0
Select Case rv_operator
Case "<"
Do While ORGLOOKUP > reference_value
Set NT_array = table_array.Resize(, 1)
row_count = .CountA(NT_array)
Set S_array = table_array.Resize(row_count)
row_less = .Match(lookup_value, NT_array, 0)
Set table_array = S_array.Offset(row_less, 0).Resize(row_count - row_less)
On Error Resume Next
ORGLOOKUP = .VLookup(lookup_value, table_array, column_index, range_lookup)
If Err.number <> 0 Then CLOOKUP = CVErr(xlErrNA): Exit Function
On Error GoTo 0
Loop
Case ">"
Do While ORGLOOKUP < reference_value
Set NT_array = table_array.Resize(, 1)
row_count = .CountA(NT_array)
Set S_array = table_array.Resize(row_count)
row_less = .Match(lookup_value, NT_array, 0)
Set table_array = S_array.Offset(row_less, 0).Resize(row_count - row_less)
On Error Resume Next
ORGLOOKUP = .VLookup(lookup_value, table_array, column_index, range_lookup)
If Err.number <> 0 Then CLOOKUP = CVErr(xlErrNA): Exit Function
On Error GoTo 0
Loop
Case Else
CLOOKUP = CVErr(xlErrNA)
End Select
Select Case True
Case IsMissing(return_index)
CLOOKUP = ORGLOOKUP
Case Else
If return_index <= table_array.Columns.Count Then
REFLOOKUP = .VLookup(lookup_value, table_array, return_index, range_lookup)
CLOOKUP = REFLOOKUP
Else
CLOOKUP = CVErr(xlErrNA)
End If
End Select
Else
CLOOKUP = CVErr(xlErrNA)
End If
End With
End Function
It works fine but I want to optimize it a bit to improve calculation speed.
Usually I'm using this to lookup 10k rows in an excel file with 600k or more rows.
It takes 5~8 mins in a sorted data.
If someone can point me to the right direction on how to optimize this function, that would be great.
Edit1:
HERE is the workbook link.
Two(2) Sheets, Data Source and Data for Lookup, self-explanatory I guess.
I also included the function in the WB.
I used the function to populate the values on the Data for Lookup Sheet under the Manufacturing Date column and just leave the first cell with the actual formula to avoid problems in opening it.
For those who are not keen, here's the syntax on how to use the function:
lookup_value - what you are looking for
table_array - where you're looking
column_index - column from which you want to get information based on your lookup_value
rv_operator - criteria whether the value to return is less than or greater than the reference_value
reference_value - where your returned value is compared
range_lookup - exact or approximate match
return_index - alternative column index, just in case you need to return data aside from what get from the column_index
Remember that I use this to get DATES
so the column_index
always contains a date as well as the reference_value
.
That is the reason there is a return_index
since I may need to recover information that fall under the conditions but not actually interested in the dates.
So for example in my sample workbook, I need to get the manufacturing date of serial number 096364139403422056
but it shoud be less than the reference value 1/4/2014
.
There are more than one occurence of this serial number so I need to get the closest to the reference value.
The result should be 11/15/2013
using the function: =CLOOKUP(B2,'Source Data'!A:B,2,"<",A2,0)
Hope above explanation helps you guys a bit.
Btw, this can also be achieved using Array Formulas
.
I just made this formula for the benefit of the other users who are not well versed with AF's
.