簡體   English   中英

具有多個條件的索引/匹配函數查找數組

[英]Index/Match Function Lookup Array with multiple criteria

我查看了此情況,但找不到有效的答復。

我需要編寫一個宏,該宏在表中搜索特定的名稱(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。 我試圖避免僅使用record函數,因為它會以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創建的命名范圍填充的每個搜索項(名稱,材料,顏色)創建一個下拉菜單,並繼續使用上面顯示的數組公式執行實際查找。

有關如何從excel向VBA數組填充唯一值的信息,請參見Jean-FrançoisCorbett的答案。

使用Table與合並結構化引用 ,你可以添加更多的項目到你的底Table ,它會自動神奇地擴大到包括他們。 設置VBA代碼以在Table更改時構建唯一值的新列表(並將它們存儲在命名范圍內,例如NamesListMaterialsListColorList )。

另一種選擇是僅使用數據透視表。

編輯: 這是Range構建唯一值列表的另一種不錯的方法

您錯誤地使用了Application.Match函數和VBA的一些基礎知識。 簡而言之,該函數不能像公式那樣工作。

AFAIK Application.Match需要一個值來尋找,以及一維單元格范圍來尋找它,並返回數組中單元格的索引。 因此,聽起來您將需要對每一列進行多次操作。 當然,我找不到任何可接受的文檔

正確的用法是:

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")

您實際上正在嘗試比較Ranges。 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”匹配的行的子范圍

我可以稍后提供。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM