【问题标题】:Index/Match Function Lookup Array with multiple criteria具有多个条件的索引/匹配函数查找数组
【发布时间】:2014-08-08 19:04:59
【问题描述】:

我查看了但找不到针对这种特定情况的有效响应。

我需要编写一个宏,在表格中搜索特定名称(A 列)、材料(B 列)和颜色(C 列)组合,然后从 D 列返回价格。

我可以输入公式(数组)

=INDEX(Sht1!A1:D5552,MATCH(1,(Sht1!A1:A5552=A1)*(Sht1!B1:B5552=B1)*(Sht1!G1:G5552=C1),0),4)

其中 A1 具有我要搜索的项目的名称,B1 具有材料,C1 具有颜色,并且值返回就好了。但是,我已将其设置为在名称/材料/颜色之间快速选择,并且我希望能够快速拉出价格,因此我尝试编写一个宏以在单击按钮时运行。

我遇到的问题是转置 MATCH(1,(Sht1!A1:A5552=A1)(Sht1!B1:B5552=B1)(Sht1!C1:C5552=C1), 0)部分进入VBA。我试图避免只使用记录功能,因为它会以 R1C1 格式吐出一个 .ForumlaArray,这在未来很难解释和更新。

我试过了

Application.Index(Sht1.Range("A1:D5552"), _
  Application.Match(1, Sht1.Range("A1:A5552") = Range("A1") & _
  "*" & Sht1.Range("B1:B5552") = Range("B1") & "*" & Sht1.Range("C1:C5552") = _
  Range("C1"), 0), 4)

但是得到一个类型不匹配

我也尝试放入 .ForumlaArray 但出现“无法设置范围类的 FormulaArray 属性”错误(因为它需要 R1C1 格式)

"=INDEX(Sht1!A1:D5552,MATCH(1,(Sht1!A1:A5552=A1)*(Sht1!B1:B5552=B1)*(Sht1!C1:C5552=C1),0),4)"

我的变量设置略有不同,但我正在尝试简化这些示例以使其更易于解释。

【问题讨论】:

  • 我认为 VBA 对于您在这里尝试做的事情来说太过分了。只是为了确保:您的预期解决方案是能够选择名称、材料和颜色,并在单击按钮时返回价格,对吗?您认为 VBA 的哪些方面可以让您更快地选择这些?
  • 我很困惑 VBA 如何让这变得更快?您不需要更新包含正在搜索的名称、材质和颜色的单元格吗?
  • 我有一个包含 600 多个名称的列表,每个名称都有多种材料/类型(超过 5000 种可能性)。此外,我有 6 个单独的价目表。我正在制作一个带有相关下拉列表的表单,以便轻松找到名称/垫子/颜色,然后是一个按钮,该按钮将填写规格,然后列出该项目的每个列表中的价格。我正在设置它,所以如果我需要来自多个列表的 6 件商品的价格,我可以轻松地选择它们并拉出价格。我假设 VBA 是最简单的方法。

标签: vba excel


【解决方案1】:

您错误地使用了Application.Match 函数和一些VBA 基础知识。简而言之,函数不像公式那样起作用。

AFAIK Application.Match 获取要查找的值,以及要查找的一维单元格范围并返回数组中单元格的索引。所以听起来你需要为每一列做多次。当然,我在上面找不到任何acceptable documentation

正确的用法是:

row_index = Application.Match(Sht1.Range("A1").Value, Sht1.Range("A1:A5552"), 0)
price_value = Sht1.Cells(row_index, "D").Value

但这只会返回第一个匹配项,而不是全部。如果您所做的只是在 VBA 中复制公式,则 VBA 不会提高性能。其他海报是正确的,可能需要采用不同的方法。


您遇到的其他一些基本问题主要源于您获取公式字符串并尝试将其直接转换为 Application.Match,而这是 AFAIK 无法做到的。

您正在尝试指定匹配的条件,如下所示:

Sht1.Range("A1:A5552") = Range("A1")

您真正在做的是尝试比较范围。 VBA 在将其传递给Application.Match 之前尝试将其评估为布尔值。这将返回类型错误,因为范围的维度不同。

如果您还没有这样做:Sht1 需要声明为 Worksheet 对象并设置为 ActiveWorkbook.Sheets("Sht1")

Dim Sht1 As WorkSheet
Set Sht1 = ActiveWorkbook.Sheets("Sht1")

您不能简单地希望变量Sht1 已经引用了工作表“Sht1”。

然后你试着像这样把它们串起来。

Sht1.Range("A1:A5552") = Range("A1") & "*" & _
Sht1.Range("B1:B5552") = Range("B1") & "*" & _
Sht1.Range("C1:C5552") = Range("C1")

我想您知道& 用于字符串连接,但您尝试连接字符串"*" 与未定义的布尔值/范围。

VBA 解决方案

如果您想要使用 VBA 的解决方案,您可以遍历所有行直到找到匹配项:

Function FindProduct(name As String, material As String, color As String) As String

    Dim product_sheet As WorkSheet
    Set product_sheet = GetProductSheet() ' Workbooks(BOOK_NAME).Sheets(SHEET_NAME)

    Dim row_index as Long
    For row_index = 2 To product_sheet.UsedRange.Rows.Count

        If product_sheet.Cells(row_index, NAME_COL).Value = name _
        And product_sheet.Cells(row_index, MATERIAL_COL).Value = material _
        And product_sheet.Cells(row_index, COLOR_COL).Value = color Then

            FindProduct = product_sheet.Cells(row_index, PRODUCT_COL).Value
            Exit Function

        End If

    Next row_index

End Function

或者如果性能是一个问题:

  • 保持您的数据按“A”、“B”、“C”列排序(在本示例中,按此顺序)。
  • 在“A”列中查找匹配的行范围
  • 从该范围中,找到与列“B”匹配的行的子范围
  • 在该范围内,返回与列“C”匹配的行的子范围

稍后我可能会提供。

【讨论】:

  • 本质上我的问题归结为如何格式化 Application.Match 函数。如果公式格式化为 Match(Lookup_value, Lookup_array, [col]) 我想测试它的 Lookup_array 的多个条件,以便返回一个布尔真值 (1) 作为 Lookup_value 以便 Match 会给我行号索引函数。
  • Sht1 已定义,我没有记录它以使示例更简单。如果我不能组合这些函数,那么我会将 Match 值记录为一个变量,然后分别编写引用该变量的 Index 函数,这样会更好吗?非常感谢您的意见。
  • 首先我认为 INDEX 函数返回一个索引而不是一个值。我从不使用并且您不需要它来进行 VBA。您根本不能将Application.Match 与多个条件一起使用。见vba-index-match-function-with-multiple-criteria。我建议您对数据进行排序并遍历,直到找到匹配项。
【解决方案2】:

我认为采用完全不同的方法会更好。我不会让 VBA 进行查找,而是使用 VBA 来维护表列中唯一值的列表,每个列都包含在一个命名范围中。然后使用数据验证为由 VBA 创建的命名范围填充的每个搜索项(名称、材料、颜色)创建一个下拉菜单,并继续使用您上面提供的数组公式来执行实际查找。

请参阅 Jean-François Corbett 的回答,了解如何Populate unique values in to VBA array from excel

Tablestructured references 结合使用,您可以在Table 的底部添加更多条目,它会自动扩展以包含它们。当Table 更改时,设置您的 VBA 代码以构建新的唯一值列表(并将它们存储在命名范围中,例如 NamesListMaterialsListColorList)。

另一种选择是简单地使用数据透视表。

编辑:Here's another nice approachRange 构建唯一值列表。

【讨论】:

  • 感谢您的提醒!我完全不熟悉这种方法,所以我将不得不修改它以了解它是如何工作的。
猜你喜欢
  • 2017-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-15
  • 2019-09-04
  • 2020-09-13
  • 1970-01-01
  • 2020-06-26
相关资源
最近更新 更多