Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 210
Default modifiying a custom lookup function


A former collegue created a custom function which would work like vlookup but
find the specified instance of the data being searched instead of being
limited to just the first instance.
Example: VWLookup(PolicyDataSource,"Anderson",5,3)

This would find the 3rd instance of Anderson in the named range
"PolicyDataSource" and pull in the data from the 5th column.

Is there a way to customize this function to allow for an additional
criteria to search on? For example, if column 3 is policy_status and I want
to filter for 'Active'.

Any help is appreciated!


Public Function VWLookup(Table_Array As Object, _
Lookup_Value As Variant, Col_Index_Num As Integer, _
Match_Number As Integer) As Variant

Dim i, j As Integer

On Error GoTo ErrorCatch

For i = 1 To Match_Number
j = Application.Match(Lookup_Value,
Table_Array.Resize(Table_Array.Rows.Count, 1), 0)

If i = Match_Number Then
VWLookup = Application.VLookup(Lookup_Value, Table_Array,
Col_Index_Num, 0)
Exit Function
End If

Set Table_Array = Table_Array.Offset(j,
0).Resize(Table_Array.Rows.Count - j)

Next i

ErrorCatch:
VWLookup = "N/A"
End Function

  #2   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 210
Default modifiying a custom lookup function

Any takers on this? I could certainly use the help - I don't know how to
modify this myself...

"Robin" wrote:

A former collegue created a custom function which would work like vlookup but
find the specified instance of the data being searched instead of being
limited to just the first instance.
Example: VWLookup(PolicyDataSource,"Anderson",5,3)

This would find the 3rd instance of Anderson in the named range
"PolicyDataSource" and pull in the data from the 5th column.

Is there a way to customize this function to allow for an additional
criteria to search on? For example, if column 3 is policy_status and I want
to filter for 'Active'.

Any help is appreciated!


Public Function VWLookup(Table_Array As Object, _
Lookup_Value As Variant, Col_Index_Num As Integer, _
Match_Number As Integer) As Variant

Dim i, j As Integer

On Error GoTo ErrorCatch

For i = 1 To Match_Number
j = Application.Match(Lookup_Value,
Table_Array.Resize(Table_Array.Rows.Count, 1), 0)

If i = Match_Number Then
VWLookup = Application.VLookup(Lookup_Value, Table_Array,
Col_Index_Num, 0)
Exit Function
End If

Set Table_Array = Table_Array.Offset(j,
0).Resize(Table_Array.Rows.Count - j)

Next i

ErrorCatch:
VWLookup = "N/A"
End Function

  #3   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 35,218
Default modifiying a custom lookup function

What version of excel are you using?

If you're using xl2002 or higher, then you can try this.

The code includes .find() and that can't be used in xl2k and below in UDF's
called from worksheet cells.

Option Explicit
Public Function VLookupIfs(TableRng As Range, _
WhichCol As Long, _
WhichMatch As Long, _
ParamArray myParms() As Variant) As Variant

Dim iCtr As Long
Dim HowManyParms As Long
Dim HowManyColsInTable As Long
Dim OkToContinue As Boolean
Dim HowManyMatches As Long
Dim myFormula As String
Dim QtMark As String
Dim FoundCell As Range
Dim AfterCell As Range
Dim PossibleMatch As Boolean
Dim fCtr As Long
Dim myVal As Variant
Dim MatchStartingCol As Long
Dim UseThisRng As Range

HowManyParms = UBound(myParms) - LBound(myParms) + 1

Set TableRng = TableRng.Areas(1)
Set UseThisRng = Nothing
On Error Resume Next
Set UseThisRng = Intersect(TableRng.Parent.UsedRange.EntireRow, TableRng)
On Error GoTo 0

If UseThisRng Is Nothing Then
VLookupIfs = CVErr(xlErrRef)
Exit Function
End If

Set TableRng = UseThisRng

HowManyColsInTable = TableRng.Columns.Count

OkToContinue = True
If HowManyParms Mod 2 = 0 Then
'ok, it's an even number
Else
VLookupIfs = CVErr(xlErrRef)
OkToContinue = False
End If

WhichCol = CLng(WhichCol)
If WhichCol < 1 Then
VLookupIfs = CVErr(xlErrRef)
OkToContinue = False
End If

WhichMatch = CLng(WhichMatch)
If WhichMatch < 1 Then
VLookupIfs = CVErr(xlErrRef)
OkToContinue = False
End If

For iCtr = LBound(myParms) To UBound(myParms) Step 2
If IsNumeric(myParms(iCtr)) = False Then
OkToContinue = False
Exit For
Else
If myParms(iCtr) HowManyColsInTable Then
OkToContinue = False
Exit For
Else
myParms(iCtr) = CDbl(myParms(iCtr))
End If
End If
Next iCtr

If OkToContinue = False Then
VLookupIfs = CVErr(xlErrRef)
Exit Function
End If

For iCtr = LBound(myParms) To UBound(myParms) Step 2
myFormula = myFormula & "--(" & _
TableRng.Columns(myParms(iCtr)).Address(external:= True) & "="
If TypeName(myParms(iCtr + 1)) = "String" Then
QtMark = """"
Else
QtMark = ""
End If
myFormula = myFormula & QtMark & myParms(iCtr + 1) & QtMark & "),"
Next iCtr

If myFormula = "" Then
'do nothing, something wrong
Else
'remove the trailing comma
myFormula = "sumproduct(" & Left(myFormula, Len(myFormula) - 1) & ")"
End If

HowManyMatches = TableRng.Parent.Evaluate(myFormula)

If WhichMatch HowManyMatches Then
VLookupIfs = "Not enough matches"
Exit Function
End If

With TableRng.Columns(myParms(LBound(myParms)))
MatchStartingCol = .Column
fCtr = 0
Set AfterCell = .Cells(.Cells.Count)
Do
Set FoundCell = .Cells.Find(what:=myParms(LBound(myParms) + 1), _
After:=AfterCell, _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)

PossibleMatch = True
For iCtr = LBound(myParms) + 2 To UBound(myParms) Step 2
If lcase(FoundCell.Offset(0, myParms(iCtr) - MatchStartingCol) _
.Value) = lcase(myParms(iCtr + 1)) Then
'keep looking
Else
'a difference in one of the other columns
PossibleMatch = False
Exit For
End If
Next iCtr

If PossibleMatch = False Then
'don't increment match counter
Else
fCtr = fCtr + 1
End If

If fCtr = WhichMatch Then
'whew! done looking
myVal = FoundCell.Offset(0, WhichCol - MatchStartingCol).Value
Exit Do
Else
'keep looking after this match
Set AfterCell = FoundCell
End If
Loop
End With

VLookupIfs = myVal

End Function

========
The first portion of the code tries to do some rudimentary validity checks (but
not very many!).

The second portion builds a formula that it can use (=sumproduct) that can be
used to see how many matches there are in that table. If there are not enough,
you'll get an error. (Another validity check.)

Then the third portion does all the work. It does a .find to find the each
match in the "first" column that you specified. Then it looks at the other
columns to see if they matched the other specs. If they do, a fCtr variable is
incremented (all the columns have to match to increment that counter).

When the fCtr variable hits the number of the match you specified, then it picks
out the value from the column you want retrieved.

There is a small design error though.

=sumproduct() will distinguish between a number 3 and the text 3 (like '3). But
the .find() won't. You could check to see if the data types are the same (use
typename), but I didn't bother.

You'd use it in the worksheet cell like:

=vlookupifs('Sheet 999'!A1:Z99, 3, 7, 4, "A", 17, "Z", 26, 22)

Look in Sheet 999 A1:Z999
Bring back the 3rd column of that range (column C since I started in column A)
For the 7th match where
column 4 (D) = A
column 17 (Q) = "Z" (text)
column 26 (Z) = 22 (a number)

By using paramarray in this line:

Public Function VLookupIfs(TableRng As Range, _
WhichCol As Long, _
WhichMatch As Long, _
ParamArray myParms() As Variant) As Variant

You can continue adding pairs of columns/criteria (30 parms total, so about 13
more criteria parms).

============
If you're using xl2k or below, I think I'd keep as many validation checks, but
then just cycle through the columns looking for matches.



Robin wrote:

Any takers on this? I could certainly use the help - I don't know how to
modify this myself...

"Robin" wrote:

A former collegue created a custom function which would work like vlookup but
find the specified instance of the data being searched instead of being
limited to just the first instance.
Example: VWLookup(PolicyDataSource,"Anderson",5,3)

This would find the 3rd instance of Anderson in the named range
"PolicyDataSource" and pull in the data from the 5th column.

Is there a way to customize this function to allow for an additional
criteria to search on? For example, if column 3 is policy_status and I want
to filter for 'Active'.

Any help is appreciated!


Public Function VWLookup(Table_Array As Object, _
Lookup_Value As Variant, Col_Index_Num As Integer, _
Match_Number As Integer) As Variant

Dim i, j As Integer

On Error GoTo ErrorCatch

For i = 1 To Match_Number
j = Application.Match(Lookup_Value,
Table_Array.Resize(Table_Array.Rows.Count, 1), 0)

If i = Match_Number Then
VWLookup = Application.VLookup(Lookup_Value, Table_Array,
Col_Index_Num, 0)
Exit Function
End If

Set Table_Array = Table_Array.Offset(j,
0).Resize(Table_Array.Rows.Count - j)

Next i

ErrorCatch:
VWLookup = "N/A"
End Function


--

Dave Peterson
Reply
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules

Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
Creating a custom function to interpret another custom engine func Ryan Excel Programming 0 March 3rd 08 07:18 PM
Custom Lookup Function Greg[_23_] Excel Programming 5 December 17th 05 10:05 AM
VBA Custom function for lookup Sami82 Excel Worksheet Functions 9 September 12th 05 03:20 PM
[Help Needed] Custom Lookup Function [email protected] Excel Programming 1 August 11th 05 01:16 AM
Modifiying a text number ( 12345 ) to have exactly 6 digit with a 0 in front simon.guertin Excel Programming 4 August 28th 03 06:55 PM


All times are GMT +1. The time now is 03:44 AM.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Copyright ©2004-2024 ExcelBanter.
The comments are property of their posters.
 

About Us

"It's about Microsoft Excel"