【问题标题】:Formula to Find Match Using Wildcard and Multiple Criteria使用通配符和多个条件查找匹配的公式
【发布时间】:2020-09-27 12:45:36
【问题描述】:

我正在尝试创建一个包含多个条件和通配符的公式,如果找到,它将返回匹配的类别。我认为这将通过一个强大的索引匹配公式来完成,但我正在努力将所有标准纳入一个工作公式。我会用例子更好地解释......

我有两个工作表,工作表“导入数据”和工作表“发票编码”。该公式将在“导入数据”表中输入,在任何一列中,例如公式进入 AD 列。

这是“导入数据”表:

这是“发票编码”表(有超过 500 行并且还在增长,所以这是一个小屏幕截图):

第一步是根据“发票编码”表(通常有多个匹配项)从“进口表”中查找“ACCT”编号(O 列)。然后,第二步将检查“导入数据”表上相应的“INV”,并查看“发票编码”表上的任何通配符发票是否匹配。返回将是“发票编码”表中的“类别”(D 列)。

我将提供一个具体的例子来更好地解释:

在这一行,我想使用 O 列数据,即数字 50000。

在“发票编码”表上查找 50000,它有很多结果。

然后使用上一个屏幕截图中 D 列的 INV,即...

查找它是否与上面“发票编码”表屏幕截图的 C 列中列出的通配符部分匹配。

因此,在此特定示例中,“导入数据”表中的 ACCT 和 INV 与“发票编码”表中的第 178 行匹配。公式的预期结果将是 D 列中的类别;第三方。

到目前为止,这是我所拥有的公式,它不包含使用通配符的部分发票匹配:

=INDEX('Invoice Coding'!A2:E514,MATCH('Import Data'!O2,'Invoice Coding'!A2:A514,0),4)

这在技术上返回一个类别,但它不使用 INV # 与带有通配符的部分 INV,因此返回可能不正确。

我希望我的解释是有道理的。关于我是否可以增强索引匹配公式以包含所有必需的条件查找的任何建议?

作为旁注,然后我将重复此公式并稍作调整,以返回“发票编码”表的 E 列中的子类别。

提前谢谢大家!

【问题讨论】:

  • 我建议一些简化的示例数据,以便能够重现您所追求的。赌对了,我会看到使用SUMPRODUCT 的可能性,包括ISNUMBERFIND 等。
  • 您提到了公式:“这在技术上返回一个类别,但它不使用 INV # 与带有通配符的部分 INV”。原因是:您只是匹配 ACCT 50000 而不是 INV WHFD*。因此,它始终只返回给定 ACCT 50000 的第一个类别。为此,您还需要 MATCH('Import Data'!D2,'Invoice Coding'!C2:C514,1) 或 sumproduct 进行多个匹配,如 JvdV 建议的那样
  • 感谢您的反馈。我对在这种情况下使用 SUMPRODUCT 不是很熟悉。这可能是我已有的公式中的另一个嵌套语句吗?
  • 愿意扩展:“..增强索引匹配公式以包含所有必需的条件查找?”试试这个并分享结果.. > exceljet.net/formula/index-and-match-with-multiple-criteria
  • 嘿,@p._phidot_ 抱歉耽搁了,有一些急需的假期。我查看了您提供的链接,我认为我遵循了它,并根据链接中的信息制作了一个公式。但是,我不确定如何包含通配符搜索,以匹配带有 * 的部分字符串,所以我的结果是#N/A。我当前的公式现在是一个数组公式,{=INDEX('Invoice Coding'!E2:E656,MATCH(1,('Import Data'!O2='Invoice Coding'!A2:A656)*('Import Data'!D2='Invoice Coding'!C2:C656),0))}。感谢您提供的方向,知道如何包含通配符,或者我的数组公式是否全部搞砸了?

标签: excel excel-formula


【解决方案1】:

要回答我自己的问题。我们通过 VBA 找到了适合我们的解决方案。最初我对使用 VBA 感到犹豫,因为我认为与公式相比运行时间要长得多,但我们的解决方案比预期的要快,运行 60,000 行大约需要 30 秒。

所以,我们的 VBA 解决方案:

'***** Declare variables to be used *****
Dim ImportWS As Worksheet, ilastrow As Long, ilooper As Long, FindArray As Variant, CodingWS As Worksheet, clastrow As Long, CodeArray As Variant, clooper As Long, acct As Long, Inv As String, matchfound As Boolean

Application.ScreenUpdating = False
Application.DisplayAlerts = False
    
    'Import Data sheet prep and storing in FindArray
    Set ImportWS = ThisWorkbook.Sheets("Import Data")
    ilastrow = ImportWS.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
    ImportWS.Range("AC1") = "Category"
    ImportWS.Range("AD1") = "Sub Category"
    ImportWS.Range("AE1") = "Billing Name"
    ImportWS.Range("AC2:AE" & ilastrow).ClearContents
    FindArray = ImportWS.Range("AC1:AE" & ilastrow)

    'Storing Coding sheet data into array
    Set CodingWS = ThisWorkbook.Sheets("Invoice Coding")
    clastrow = CodingWS.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
    CodeArray = CodingWS.Range("A1:F" & clastrow)
    
    With ImportWS
        
        'Looping through all rows on Import Data sheet...
        For ilooper = 2 To ilastrow
            
            'Storing GL Acct# and Invoice# for comparison against Coding sheet
            acct = Val(.Range("O" & ilooper))
            Inv = .Range("D" & ilooper)
            
            'matchfound is a boolean that is reset on each row.
            'if a match is found against the Coding sheet it is flipped to true...
            'we stop looking in the following loop...
            'and we commit the cat and subcat to the FindArray variant.
            matchfound = False
            
            'This is our looper for going through the coding table in the following loop.
            clooper = 2
            
            'While we haven't found a match for GL# and Inv...
            'and we haven't reached the end of the table...
            While matchfound = False And clooper <= clastrow
    
                'If acct# matches coding table we perform another check...
                If Val(CodeArray(clooper, 1)) = acct Then
                        
                    '...for partial match on Inv - which accounts for wildcard placement as on the table...

                    If Inv Like CodeArray(clooper, 3) Then
                       'If match is found, matchfound is true, which will stop the next iteration of the loop
                        matchfound = True
                        'and we store the cat and subcat in our FindArray
                        FindArray(ilooper, 1) = CodeArray(clooper, 4)
                        FindArray(ilooper, 2) = CodeArray(clooper, 5)
                        FindArray(ilooper, 3) = CodeArray(clooper, 6)
                    End If
                End If
                
                'If no match, check the next row on the Coding table.
                clooper = clooper + 1
    
            Wend
            
            
        'After we found a match or reached the end of the coding table...
        '...we move on to the next row on the Import Data sheet.
        Next ilooper
        
        'After looping through all rows on the Import Data sheet we commit what we found to columns AC, AD, AE.
        ImportWS.Range("AC1:AE" & ilastrow).Value = FindArray
    
    End With
    
Application.ScreenUpdating = True
Application.DisplayAlerts = True

【讨论】:

    猜你喜欢
    • 2016-12-14
    • 1970-01-01
    • 2015-08-02
    • 1970-01-01
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-08
    相关资源
    最近更新 更多