Daniel’s Extreme Lookup Collection

Today’s author is Daniel Wiesenfeld, an Excel and Access Power User who is sharing his Extreme Lookup Collection with us so we can use the Excel User Defined Functions (UDFs) he created to enhance the lookup functionality. His web site danalytics.biz is currently under construction and should be available soon.

In the Visual Basic Editor, insert a Module and paste the following code:

' XVLOOKUP (& XHLOOKUP)
' Works just like a vlookup (and hlookup) except that the user refers to a lookup colum (or row)
' rather than a range,
it is 0 based and the user can "look left" (or "look upward") by using a negative
' column (or row) index.
' There is also an optional argument to allow the user to offset the cell to be returned by any number
' of rows (or columns)
' I do not give users the option to choose between exact or approximate match - it is always exact Function XVLOOKUP(Lookup_Column As Range, Lookup_Value As Variant, Column_Index As Integer, _ Optional Row_Offset As Integer) Dim DCol, DRow As Integer Dim DSheet, strCRange, strARange As String Dim ARange As Range DCol = Lookup_Column.Column DCol = DCol + Column_Index If IsMissing(Row_Offset) Then Row_Offset = 0 End If DSheet = Lookup_Column.Parent.Name strCRange = Lookup_Column.Address DRow = WorksheetFunction.Match(Lookup_Value, Worksheets(DSheet).Range(strCRange), 0) DRow = DRow + (Lookup_Column.Row - 1) + Row_Offset Set ARange = Range(Cells(DRow, DCol), Cells(DRow, DCol)) strARange = ARange.Address XVLOOKUP = Worksheets(DSheet).Range(strARange).Value End Function Public Function XHLOOKUP(Lookup_Row As Range, Lookup_Value As Variant, Row_Index As Integer, _ Optional Column_Offset As Integer) Dim DCol, DRow As Integer Dim DSheet, strRRange, strARange As String Dim ARange As Range DRow = Lookup_Row.Row DRow = DRow + Row_Index If IsMissing(Column_Offset) Then Column_Offset = 0 End If DSheet = Lookup_Row.Parent.Name strRRange = Lookup_Row.Address DCol = WorksheetFunction.Match(Lookup_Value, Worksheets(DSheet).Range(strRRange), 0) DCol = DCol + (Lookup_Row.Column - 1) + Column_Offset Set ARange = Range(Cells(DRow, DCol), Cells(DRow, DCol)) strARange = ARange.Address XHLOOKUP = Worksheets(DSheet).Range(strARange).Value End Function 'XVHLOOKUP 'looks up value in a range based on column and row headers Public Function XVHLOOKUP(Lookup_Range As Range, Row_Header As Variant, Column_Header As Variant) Dim DCol, DRow, TRow, BRow, LCol, RCol As Integer Dim DSheet, strCRange, strRRange, strARange As String Dim CRange, RRange, ARange As Range DSheet = Lookup_Range.Parent.Name TRow = Lookup_Range.Row BRow = TRow + Lookup_Range.Rows.Count - 1 LCol = Lookup_Range.Column RCol = LCol + Lookup_Range.Columns.Count - 1 Set CRange = Range(Cells(TRow, LCol), Cells(BRow, LCol)) strCRange = CRange.Address DRow = WorksheetFunction.Match(Row_Header, Worksheets(DSheet).Range(strCRange), 0) DRow = DRow + Lookup_Range.Row - 1 Set RRange = Range(Cells(TRow, LCol), Cells(TRow, RCol)) strRRange = RRange.Address DCol = WorksheetFunction.Match(Column_Header, Worksheets(DSheet).Range(strRRange), 0) DCol = DCol + Lookup_Range.Column - 1 Set ARange = Range(Cells(DRow, DCol), Cells(DRow, DCol)) strARange = ARange.Address XVHLOOKUP = Worksheets(DSheet).Range(strARange).Value End Function 'XLOOKUP 'Looks up value in a range and returns value of cell that is a specified number of rows and columns
'away from lookup cells
Public Function XLOOKUP(Lookup_Range As Range, Lookup_Value As Variant, _ Row_Offset As Integer, Column_Offset As Integer) Dim DRow, DCol As Integer Dim DSheet, DAddress, strARange As String Dim ARange As Range DRow = Lookup_Range.Find(Lookup_Value).Row DCol = Lookup_Range.Find(Lookup_Value).Column DRow = DRow + Row_Offset DCol = DCol + Column_Offset DSheet = Lookup_Range.Parent.Name Set ARange = Range(Cells(DRow, DCol), Cells(DRow, DCol)) strARange = ARange.Address XLOOKUP = Worksheets(DSheet).Range(strARange) End Function

Office Blogs Comments

Comments: (18) Collapse

  • A quick comment on inline dimensioning of variables:

    In VBA I thought that each variable required its own type declaration, so in the code above only the last variable in each Dim statement will have a type set, any variables before the last one will be of Variant type. I think this is correct?

    I doubt it will prevent the code from working, but it's always helpful catch errors whilst writing the code.

    If I am mistaken then please let me know, but this appears to be the case for me.

  • Unfortunately these functions will not work correctly without being made volatile.

    Since the returned values will not usually be within the Lookup columns Excel will not recalculate the functions when the value being returned changes.

    Also any general-purpose UDF should include error-handling: by convention the function should return #N/A when the value is not found rather than erroring out with #Value.

  • Look's great; any chance we could see some sort of picture demonstration? Personally I am a little confused on the administration of said functions.

  • Sean,

    Good point to correctly declare the variables in line, I should have written:

    Dim DCol As Integer, DRow As Integer

    It does work as is, but your fix would speed it up a bit.

  • Sean,

    Good point to correctly declare the variables in line, I should have written:

    Dim DCol As Integer, DRow As Integer

    It does work as is, but your fix would speed it up a bit.

    Thanks,

    Daniel

  • Charles,

    Your volatility point may be true of the xvlookup, and xhlookup, but I believe the xvhlookup, and xlookup will dynamically update without adding an Application.Volatile statement.

    Thanks, Daniel

  • You might also like to change the type Integer to Long in order to allow for ranges with more than 32767 elements

  • Daniel,

    xlookup needs to be volatile as well since you are doing an OFFSET that could reference outside the Lookup_Range.

    a simpler version of your xvhlookup could look like this (watch for line wrap)

    Public Function XVHLOOKUP2(Lookup_Range As Range, _

       RowLookup_Value As Variant, ColumnLookup_Value As Variant)

       On Error GoTo Fail

       XVHLOOKUP2 = WorksheetFunction.Index(Lookup_Range, _

       WorksheetFunction.Match(RowLookup_Value, Lookup_Range.Columns(1), 0), _

       WorksheetFunction.Match(ColumnLookup_Value, Lookup_Range.Rows(1), 0))

    Exit Function

    Fail:

       XVHLOOKUP2 = CVErr(xlErrNA)

    End Function

  • Why a limited udf when

    =Index(RngToPick,Match(WhatToMatch,ColumnToMatch,MatchTyp)) works for vertical/horizontal tables + Left/Right + Top/Bottom Columns + Exact + Closest (Lower/Higher) matches

  • Daniel , we are not able to understan how to use said function if you can send example please send on tarun.shah@essar.com

  • To All those who want to see examples of these functions in use, I will put up some demos on my site when it is up and running (hopefully a few weeks)...

    I'll update this forum when it is

  • Is it just me or is the text above chopped off a bit on the right end. I could probably figure it out, but it might help some others.

  • Moshe: I see the same chop off, something wrong with the line wrapping here.

  • Thanks I'll be looking for the demo.

  • I'd be interested to see the demo as well.  And while you're at it, put it on youtube.

1 2  Next >
Comments

Comments: (loading) Collapse