【问题标题】:Find specifc text in multiple columns in excel在excel的多列中查找特定文本
【发布时间】:2016-08-21 01:42:28
【问题描述】:

我有一个让我困惑了一段时间的公式 - 我觉得我很接近但解决方案正在逃避我,所以我转向你们巫师。这个问题类似于Excel VLOOKUP and SEARCH combination

问题:

我想查找一个值,它是一对由破折号分隔的代码,例如。 01-05 A1-B2 AB-90 , 在 A 和 B 列中,并从 C 返回结果。

问题是我在两列中搜索,其中可能包含多个用逗号分隔的代码:

Col A          Col B           Col C

01             05, B2          Result1
A1             B2              Result2
AB, AC         90, 91, 92      Result3

我在想 =if(isnumber(search( 函数将是关键,但我不知道如何让它检查整个列,一旦找到,检查它旁边的列以获取代码的第二部分。

理想情况下,公式会这样执行,在上面的示例中,如果我要根据条件 01-05 运行此公式,它将返回 Result1

赞赏!

【问题讨论】:

  • 你有什么最新的答案吗?
  • 目前正在测试 OldUgly 的修复,似乎真的很接近,只是解决了问题
  • 下面的两个答案都很接近 - 用户的下面提供了最多的结果,但仍然有一些错误,应该有答案

标签: excel vba search substring vlookup


【解决方案1】:

如果你把你要找的代码放在D列,那么你的公式放在E列,下面的公式就可以完成你要找的……

=IF(OR(ISERROR(FIND(LEFT(D2,2),A2)),ISERROR(FIND(RIGHT(D2,2),B2)),LEN(D2)=0),"",C2)

然后填写。

公式从 A 列的代码中搜索左边的两个字符。如果没有找到,则会引发错误。它还从 B 列中的代码中查找正确的两个字符。如果找不到,则会引发错误。如果您要查找的代码为空白,则不会引发错误,因此我们需要检查这种情况。

因此,如果搜索左侧部分出错,或者搜索右侧部分出错,或者没有要查找的代码,则返回空白。否则,返回结果。

下面是一些例子...


根据 cmets 更新

在 Sheet1 上,数据如下所示...

...在Sheet2上,我们有这样的结果...

其中单元格B2 包含此公式(填写)

{=CONCAT(IF(ISERROR(FIND(LEFT(A2,2),Sheet1!$A$1:$A$3)),"",IF(ISERROR(FIND(RIGHT(A2,2),Sheet1!$B$1:$B$3)),"",IF(LEN(A2)<1,"",Sheet1!$C$1:$C$3))))}

因版本问题而更新

当所有其他方法都失败时,转到 VBA。附件是一个示例函数。它得到与上图相同的结果。它是用 B 列中的公式调用的,填写...

=FindResult(A2,Sheet1!$A$1:$A$3,Sheet1!$B$1:$B$3,Sheet1!$C$1:$C$3)

代码...

Function FindResult(inString As String, LeftRange As Range, RightRange As Range, ReturnRange As Range) As String
Dim strArr() As String
Dim myCellLeft As Range, myCellRight

'initial
FindResult = ""
If LeftRange Is Nothing Then GoTo Done:
If RightRange Is Nothing Then GoTo Done:
If ReturnRange Is Nothing Then GoTo Done:

' get the two halfs
strArr = Split(inString, "-")
If UBound(strArr) < 1 Then GoTo Done:

' Search the left range for the left half, the right range for the right half
For Each myCellLeft In LeftRange
    If InStr(1, myCellLeft.Value, strArr(0)) > 0 Then
        For Each myCellRight In RightRange.Rows(myCellLeft.Row)
            If InStr(1, myCellRight.Value, strArr(1)) > 0 Then
                FindResult = ReturnRange.Rows(myCellLeft.Row)
                Exit For
            End If
        Next myCellRight
        If FindResult <> "" Then Exit For
    End If
Next myCellLeft
' clean up
Done:
Erase strArr
Set myCellLeft = Nothing
Set myCellRight = Nothing
End Function

【讨论】:

  • 所以这很好,但是,它看起来只能在 A2/B2 中搜索 D2 中的条件。我的情况是我在一张纸上有 A、B、C 列,在另一张纸上有 D 和 E 列,我试图为每个代码提取相应的结果(如果存在)。我目前的公式与您的公式类似,但是我希望它搜索所有列 A/B,所以我可以假设,从您上面的示例中,在 D2 中有 AC-92,它仍然会拉结果3
  • 将 D 列和 E 列移动到不同的选项卡非常简单。为了搜索整个集合,您需要使用数组公式。我现在不在电脑旁,但可以稍后查看。
  • @IanSchneider - 这是否更接近您的目标?
  • 看起来它在上面的示例中有效,这与我需要的几乎相同,但是它在我的第一个参数 if(iserror(find(right(.I 'm also not understand the need for concatenate? 看起来它只有一半的功能在那里
  • 这是一个CSE公式,所以它会生成一个数组。如果没有 CONCAT,它会返回第一个数组元素,通常是“”。 CONCAT 将所有答案放在一起 - 通常是 Result1&amp;""&amp;""""&amp;Result2&amp;""""&amp;""&amp;Result3。 CONCAT 应该包含所有内容 - 所以括号可能有问题。
【解决方案2】:

据我所知,“公式”方法非常冗长和繁琐,如下所示:

=IF(
        ISNA(
                   IFERROR(MATCH(LEFT(D1,SEARCH("-",D1)-1),Codes!$A$1:$A$100,0),
                                     IFERROR(MATCH("*"&LEFT(D1,SEARCH("-",D1)-1)&",*",Codes!$A$1:$A$100,0),
                                                       MATCH("*,"&LEFT(D1,SEARCH("-",D1)-1)&"*",Codes!$A$1:$A$100,0)))
                   *
                   IFERROR(MATCH(RIGHT(D1,LEN(D1)-SEARCH("-",D1)),Codes!$B$1:$B$100,0),
                                      IFERROR(MATCH("*"&RIGHT(D1,LEN(D1)-SEARCH("-",D1))&",*",Codes!$B$1:$B$100,0),
                                                        MATCH("*,"&RIGHT(D1,LEN(D1)-SEARCH("-",D1))&"*",Codes!$B$1:$B$100,0)))
                   ),

         "Not Found",

          IF(IFERROR(MATCH(LEFT(D1,SEARCH("-",D1)-1),Codes!$A$1:$A$100,0),
                                   IFERROR(MATCH("*"&LEFT(D1,SEARCH("-",D1)-1)&",*",Codes!$A$1:$A$100,0),
                                                      MATCH("*,"&LEFT(D1,SEARCH("-",D1)-1)&"*",Codes!$A$1:$A$100,0)))
                <>
                IFERROR(MATCH(RIGHT(D1,LEN(D1)-SEARCH("-",D1)),Codes!$B$1:$B$100,0),
                                    IFERROR(MATCH("*"&RIGHT(D1,LEN(D1)-SEARCH("-",D1))&",*",Codes!$B$1:$B$100,0),
                                                      MATCH("*,"&RIGHT(D1,LEN(D1)-SEARCH("-",D1))&"*",Codes!$B$1:$B$100,0))), 

               "Different rows",

                INDEX(Codes!C:C,IFERROR(MATCH(RIGHT(D1,LEN(D1)-SEARCH("-",D1)),Codes!$B$1:$B$100,0),
                                                       IFERROR(MATCH("*"&RIGHT(D1,LEN(D1)-SEARCH("-",D1))&",*",Codes!$B$1:$B$100,0),
                                                                         MATCH("*,"&RIGHT(D1,LEN(D1)-SEARCH("-",D1))&"*",Codes!$B$1:$B$100,0))))
               )
        )

我使用了(希望)更易读的格式并假设:

  • “代码”作为工作表名称,其列“A”(“第一”代码)、“B”(“第二”代码)和“C”(“结果”)列放置

  • 代码对将放置在任何工作表的“D”列中

  • 公式将放置在与上述“D”列单元格相邻的“E”列中

您可能需要考虑如下“VBA”方法

Sub main()
Dim codesSht As Worksheet
Dim cell As Range, found As Range, codesRng As Range
Dim index1 As Long

Set codesSht = ThisWorkbook.Worksheets("Codes") '<== change "codes" sheet reference as per your needs
Set codesRng = codesSht.Range("A:B").SpecialCells(xlCellTypeConstants, xlTextValues)
With ThisWorkbook.Worksheets("Results") '<== change "Results" sheet reference as per your needs
    For Each cell In .Range("D1:D" & .Cells(.Rows.count, "D").End(xlUp).Row).SpecialCells(xlCellTypeConstants, xlTextValues)
        Set found = codesRng.Resize(, 1).Find(What:=Split(cell.Value, "-")(0), LookIn:=xlValues, LookAt:=xlPart)
        If Not found Is Nothing Then
            index1 = found.Row
            Set found = codesRng.Offset(, 1).Resize(, 1).Find(What:=Split(cell.Value, "-")(1), LookIn:=xlValues, LookAt:=xlPart)
            If Not found Is Nothing Then If found.Row = index1 Then cell.Offset(, 1).Value = codesRng(index1, 3)
        End If
    Next cell
End With

End Sub

【讨论】:

  • 嘿,谢谢!虽然这很罗嗦,但效果不错。在我预期但还不错的答案上提出了一些错误。我不相信 VBA 适合我正在尝试做的事情,但我稍后会对其进行测试。
  • VBA 不起作用 - 但是,我删除了不同行结果的代码部分,现在它正在提取与 D 中代码左侧 2 个字符有关的第一个结果 - 例如。是否有D3-16result1D3-02result2,两条线都会拉result1。我认为答案在于 index(match(.
  • 如果您发布的数据在公式和 VBA 方法中都遇到错误,我会看看
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-23
  • 2016-04-23
  • 1970-01-01
相关资源
最近更新 更多