[英]Using Index and Match in Excel VBA VLookup function
I have an excel formula that I use often that does a VLookup
. 我有一个excel公式,我经常使用它做一个VLookup
。 It has an embedded Index/Match
that gives the last numeric value in the "M" Column. 它有一个嵌入的Index/Match
,它给出“M”列中的最后一个数值。
The Worksheet formula is this: 工作表公式是这样的:
=VLOOKUP(INDEX($M$10:$M75,MATCH(9.99999999999999E+307,$M$10:$M75)),Data,4)
Cell $M75
being the cell of the row this formula is in. There are numeric, non-numeric and blank cells in Column M but the ID's that I want are always numeric. 单元格$M75
是此公式所在行的单元格。列M中有数字,非数字和空白单元格,但我想要的ID始终为数字。
So I am trying to write a custom function that would let me simply write =current()
所以我试着写一个自定义函数,让我简单地写=current()
Here is what I have: 这是我有的:
Function Current()
Dim LookupRange As Variant
Dim indexVar As Variant
LookupRange = Range("$M$1:M" & ActiveCell.Row)
indexVar = Application.Index(Range(LookupRange), Application.Match(9.99999999999999E+307, Range(LookupRange)))
Current = Application.WorksheetFunction.VLookup(indexVar, Worksheets("Info").Range("Data"), 4)
End Function
I have tried using different variable types (String, Long, Variant) but I can't seem to get the function to work. 我尝试使用不同的变量类型(String,Long,Variant),但我似乎无法使函数工作。
I don't know if this is enough info but can anyone see if I am missing something? 我不知道这是否足够信息,但任何人都可以看到我是否遗漏了什么?
I only get #VALUE!
我只得到#VALUE!
Using Excel 2013 on Windows 7 在Windows 7上使用Excel 2013
There are some problems with this code that are at odds with your description. 此代码存在一些与您的描述不一致的问题。
LookupRange
is a variant array. LookupRange
是一个变体数组。 When I test this, it raises a 1004 Method 'Range' of object '_Global' failed
error in the assignment to indexVar
. 当我测试它时,它在indexVar
的赋值中引发了1004 Method 'Range' of object '_Global' failed
错误的1004 Method 'Range' of object '_Global' failed
。 Dim LookupRange As String
per your comments, I also get a Type Mismatch
error. 如果我根据你的评论Dim LookupRange As String
,我也会收到Type Mismatch
错误。 Since LookupRange
should be a range, I declare it as a range, and use the Set
keyword in the assignment statement. 由于LookupRange
应该是一个范围,我将其声明为范围,并在赋值语句中使用Set
关键字。
Set lookupRange = Range("$M$10:$M" & ActiveCell.Row)
lookupRange
. 您对lookupRange
的分配可能存在拼写错误。 In your formula, originally you use $M$1
, but in the function you use $M$10
. 在你的公式中,最初使用$M$1
,但在函数中你使用$M$10
。 If you start this range at $M$10
, and try to evaluate the formula in any cell between row 1-9, you will get an error. 如果您以$M$10
开始此范围,并尝试在第1-9行之间的任何单元格中评估公式,则会出现错误。
On a related note, if there are no numeric values in the lookupRange
, this will return an error, eg, putting Current()
in cell M2
makes a lookup range of M1:M2
, wherein I have no numeric data. 在相关的说明中, 如果 lookupRange
中没有数值 ,则这将返回错误,例如,将单元格M2
Current()
置于M1:M2
的查找范围内,其中我没有数字数据。
I am not sure how you want to handle this, but my answer includes one way to avoid that error. 我不确定你想怎么处理这个,但我的答案包括一种避免这种错误的方法。 You can modify as needed. 您可以根据需要进行修改。 Finally: 最后:
ActiveCell.Row
seems like a bad idea, since this formula may recalculate with undesired results. 依赖ActiveCell.Row
似乎是一个坏主意,因为这个公式可能会重新计算不良结果。 Instead, make this a required argument for the formula, which you can then call from the worksheet like: =Current(Row())
. 相反,将其设为公式的必需参数,然后可以从工作表调用,如: =Current(Row())
。
Putting it all together, I think this should work, and I provide an example/escape for the match not found error. 把它们放在一起,我认为这应该工作,我提供了一个示例/转义匹配未找到错误。 : :
Public Function Current(r As Long)
Const bigNumber As Double = 9.99999999999999E+307
Dim wsInfo As Worksheet: Set wsInfo = Worksheets("Info")
Dim lookupRange As Range
Dim indexVar As Long
Dim myVal As Variant
Set lookupRange = Range("$M$1:$M" & r)
If Not Application.WorksheetFunction.Sum(lookupRange) = 0 Then
indexVar = Application.Index(lookupRange, Application.Match(bigNumber, lookupRange))
myVal = Application.WorksheetFunction.VLookup(indexVar, wsInfo.Range("Data"), 4)
Else:
myVal = "No numbers found in: " & lookupRange.Address
End If
Current = myVal
End Function
UPDATE FROM COMMENTS 评论的更新
You can add Application.Volatile
link before the variable declarations. 您可以在变量声明之前添加Application.Volatile
链接 。 This should force re-calculation: 这应该强制重新计算:
whenever calculation occurs in any cells on the worksheet. 只要在工作表上的任何单元格中进行计算。
However, this will not force calculation when values on other worksheets (eg, your Worksheets("Info")
is another worksheet) change. 但是,当其他工作表上的值(例如,您的Worksheets("Info")
是另一个工作表)更改时,这不会强制计算。
To force recalculation every time you active the sheet containing the =Current(Row())
function, you could put this in the worksheet's code module: 要在每次激活包含=Current(Row())
函数的工作表时强制重新计算,可以将其放在工作表的代码模块中:
Private Sub Worksheet_Activate()
Me.Calculate
End Sub
This is probably as close as you can get -- to replicating the native VLOOKUP
functionality without actually using a VLOOKUP
formula. 这可能就像你可以得到的那样 - 复制本机VLOOKUP
功能而不实际使用VLOOKUP
公式。
Additional notes: 补充笔记:
Favoring correctly/strongly-typed variables, I declare indexVar as Long
and create a double-precision variable for 9.99999999999999E+307
(it's just easier to work with this way). 偏好正确/强类型变量,我将indexVar as Long
声明indexVar as Long
并为9.99999999999999E+307
创建一个双精度变量(这样更容易使用)。 I also create a worksheet object variable, again, I find them easier to work with. 我还创建了一个工作表对象变量,我再次发现它们更容易使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.