在Excel VBA VLookup函数中使用索引和匹配

时间:2013-09-29 21:45:04

标签: excel vba excel-formula vlookup excel-2013

我有一个excel公式,我经常使用VLookup。它有一个嵌入的Index/Match,它给出了“M”列中的最后一个数值。
工作表公式是这样的:

=VLOOKUP(INDEX($M$10:$M75,MATCH(9.99999999999999E+307,$M$10:$M75)),Data,4)

单元格$M75是此公式所在行的单元格。列M中有数字,非数字和空白单元格,但我想要的ID始终为数字。

所以我正在尝试编写一个自定义函数,让我只需编写=current()

这就是我所拥有的:

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

我尝试使用不同的变量类型(String,Long,Variant),但我似乎无法使该函数起作用。
我不知道这是否足够信息,但任何人都可以看到我是否遗漏了什么?
我只得到#VALUE!
在Windows 7上使用Excel 2013

1 个答案:

答案 0 :(得分:3)

此代码存在一些与您的说明不一致的问题。

  • LookupRange是一个变体数组。当我对此进行测试时,它会在分配给1004 Method 'Range' of object '_Global' failed时出现indexVar错误。
  • 如果我根据您的评论Dim LookupRange As String,我也会收到Type Mismatch错误。

由于LookupRange应该是一个范围,我将其声明为范围,并在赋值语句中使用Set关键字。

Set lookupRange = Range("$M$10:$M" & ActiveCell.Row)
  • 您在lookupRange的工作中可能会输错。在您的公式中,您最初使用$M$1,但在函数中使用$M$10

如果您在$M$10开始此范围,并尝试在第1-9行之间的任何单元格中评估公式,则会出现错误。

在相关说明中,如果lookupRange中没有数字,,则会返回错误,例如,将Current()放入单元格M2查找范围为M1:M2,其中我没有数字数据。

enter image description here

我不确定你想怎么处理这个,但我的回答包括避免这个错误的一种方法。您可以根据需要进行修改。最后:

  • 依赖ActiveCell.Row似乎是一个坏主意,因为这个公式可能会重新计算出不良后果。

相反,将其设为公式的必需参数,然后可以从工作表中调用,如:=Current(Row())

总而言之,我认为这应该有效,并且我为匹配未找到错误提供了示例/转义。 :

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

评论更新

您可以在变量声明之前添加Application.Volatile link。这应该强制重新计算:

  

无论何时在工作表上的任何单元格中进行计算。

但是,当其他工作表上的值(例如,您的Worksheets("Info")是另一个工作表)更改时,这不会强制计算。

要在每次激活包含=Current(Row())函数的工作表时强制重新计算,可以将其放在工作表的代码模块中:

Private Sub Worksheet_Activate()
    Me.Calculate
End Sub

这可能会尽可能接近 - 复制原生VLOOKUP功能而不实际使用VLOOKUP公式。

附加说明:

支持正确/强类型的变量,我声明indexVar as Long并为9.99999999999999E+307创建一个双精度变量(用这种方式更容易)。我还创建了一个工作表对象变量,我发现它们更容易使用。