如何进行正确的关键字搜索

时间:2019-05-06 14:03:21

标签: excel vba excel-formula

如果我在单元格值“ TFO_xyz”中搜索术语“ tfo”,则结果应为TRUE。 如果我在“ TFO系统”单元格中搜索“ tfo”一词,则结果应为TRUE。

如果我在单元格值“ spring TFO”中搜索“ tfo”一词,则结果应为TRUE。

但是如果我在单元格值“ Platform”中选中“ tfo”,那么我希望结果为FALSE

我使用了公式=IF(COUNTIF(A2,"*tfo*"),"TRUE","FALSE"),但是当我在“平台”一词中选中“ tfo”时,这不会给出FALSE的结果。

注意:

平台应该为假,因为tfo出现在一个单词之间。我正在使用像tfo <‌space> America或TFO_America或<‌space> TFO系统中的单词tfo的单元格值,将结果视为True。但是,我希望平台和投资组合这两个字为FALSE结果,因为在这两个词中,术语tfo出现在字母之间。

6 个答案:

答案 0 :(得分:0)

尝试一下:

Dim x As Long: x = 1

With Sheet1

    Do While x <= .Cells(.Rows.Count, 1).End(xlUp).Row

        If VBA.Left(.Cells(x, 1).Value, 3) = "tfo" Or VBA.Right(.Cells(x, 1).Value, 3) = "tfo" Then

            .Cells(x, 2).Value = True

        End If

        x = x + 1

    Loop

End With

答案 1 :(得分:0)

我在您的问题中看到了两个维度:

  • 关键字在文本中(开头,中间,结尾)出现在哪里
  • 分隔单词的字符是什么。

第一个是固定大小,您需要处理三种情况。第二个取决于您要接受作为分隔符的字符数。下面我假设您接受空格和下划线,但是,您可以通过插入更多的SUBSTITUTE函数调用来扩展此集合。

在我的表中,$ A2是您在其中搜索关键字的单元格,而B $ 1包含关键字。

要标准化分隔符,您需要公式:

B2=SUBSTITUTE($A2,"_"," ")

要检查字符串是否以关键字开头:

C2=--(LEFT($B2,LEN(B$1)+1)=B$1&" ")

要检查字符串是否以关键字结尾:

D2=--(RIGHT($B2,LEN(B$1)+1)=" "&B$1)

要检查关键字是否在字符串中间:

E2=--(LEN(SUBSTITUTE(UPPER($B2)," "&UPPER(B$1)&" ",""))<LEN($B2))

要评估以上三种情况:

F2=--(0<$C2+$D2+$E2)

如果要使用单个单元格,请将公式合并为:

G2=--(0<--(LEFT(SUBSTITUTE($A2,"_"," "),LEN(B$1)+1)=B$1&" ")+--(RIGHT(SUBSTITUTE($A2,"_"," "),LEN(B$1)+1)=" "&B$1)+--(LEN(SUBSTITUTE(UPPER(SUBSTITUTE($A2,"_"," "))," "&UPPER(B$1)&" ",""))<LEN(SUBSTITUTE($A2,"_"," "))))

最后它不是很可读,但是我认为没有一种更简单的使用公式的解决方案。

注意:如果要修改定界符接受的字符集,请向B2添加更多SUBSTITUTE函数调用,然后将F2的公式复制到记事本中,并将$ C2替换为C2的公式,依此类推。 ,然后将$ B2替换为更新的B2公式。

更新

基于罗恩·罗森菲尔德(Ron Rosenfelds)评论tigeravatar的答案的想法,可以简化公式(可以将开头,中间,结尾的情况结合起来):

=--(LEN(SUBSTITUTE(" "&UPPER($B2)&" "," "&UPPER(B$1)&" ",""))<LEN($B2))

将$ B2替换为其公式后:

=--(LEN(SUBSTITUTE(" "&UPPER(SUBSTITUTE($A2,"_"," "))&" "," "&UPPER(B$1)&" ",""))<LEN(SUBSTITUTE($A2,"_"," ")))

答案 2 :(得分:0)

尝试以下公式。假设单词tfo将在开头或结尾 只需确保在公式中我有“ A2”的位置放置适当的单元格名称即可

=IF(OR(PROPER(LEFT(A2,3))="tfo",PROPER(RIGHT(A2,3))="tfo"),TRUE,FALSE)

下面的测试用例:

enter image description here

答案 3 :(得分:0)

如果TFO位于文本字符串中任何给定单词的开头或结尾,或者单独出现,则此公式将返回true。它还会检查文本字符串中的每个单词,因此TFO可以位于开头,中间或结尾。该公式假定,如果单词以TFO开头或结尾,则结果应为TRUE(tfoAmerica的情况是这样,因此相同的规则也适用于tform),否则为FALSE。

=OR(ISNUMBER(SEARCH({" tfo","tfo "}," "&SUBSTITUTE(A2,"_"," ")&" ")))

结果如下:

enter image description here

编辑

如果仅是自己找到TFO,则结果应为TRUE,则此版本的公式就足够了:

=ISNUMBER(SEARCH(" tfo "," "&SUBSTITUTE(A2,"_"," ")&" "))

显示第二版结果的图像:

enter image description here

答案 4 :(得分:0)

我的建议是花一些时间来了解您的数据并创建白名单。 由于没有简单的方法可以正确地对字符串进行模糊搜索。

Function TFO_Search(strText As String) As Boolean

Dim ArryString      As Variant
Dim ArryWhitelist   As Variant

' Create a White-List Array
ArryWhitelist = Array("TFO_", "TFO ", "_TFO", " TFO", "tfoAmerica")

For Each ArryString In ArryWhitelist
If InStr(UCase(strText), UCase(ArryString)) > 0 Then  'force to UPPER CASE
    TFO_Search = True
    Exit Function
Else
    TFO_Search = False
End If
Next

End Function

答案 5 :(得分:0)

如果您可以依靠VBA,则regex是更灵活的解决方案。

关于如何在VBA中使用它们进行了很好的总结:How to use Regular Expressions (Regex) in Microsoft Excel both in-cell and loops

针对您的关键字搜索问题,我写了以下内容:

Option Explicit

' Include: Tools > References > Microsoft VBScript Regular Expressions 5.5 (C:\Windows\SysWOW64\vbscript.dll\3)


Public Function SearchKeyWord(strHay As String, strNail As String, Optional strDelimiters As String = " _,.;/", Optional lngNthOccurrence As Long = 1) As Long ' Returns 1-based index of nth occurrence or 0 if not found
    Dim strPattern As String: strPattern = CreatePattern(strNail, strDelimiters)
    Dim rgxKeyWord As RegExp: Set rgxKeyWord = CreateRegex(strPattern, True)
    Dim mtcResult As MatchCollection: Set mtcResult = rgxKeyWord.Execute(strHay)
    If (0 <= lngNthOccurrence - 1) And (lngNthOccurrence - 1 < mtcResult.Count) Then
        Dim mthResult As Match: Set mthResult = mtcResult(lngNthOccurrence - 1)
        SearchKeyWord = mthResult.FirstIndex + Len(mthResult.SubMatches(0)) + 1
    Else
        SearchKeyWord = 0
    End If
End Function

Private Function CreateRegex(strPattern As String, Optional blnIgnoreCase As Boolean = False, Optional blnMultiLine As Boolean = True, Optional blnGlobal As Boolean = True) As RegExp
    Dim rgxResult As RegExp: Set rgxResult = New RegExp
    With rgxResult
        .Pattern = strPattern
        .IgnoreCase = blnIgnoreCase
        .MultiLine = blnMultiLine
        .Global = blnGlobal
    End With
    Set CreateRegex = rgxResult
End Function

Private Function CreatePattern(strNail As String, strDelimiters As String) As String
    Dim strDelimitersEscaped As String: strDelimitersEscaped = RegexEscape(strDelimiters)
    Dim strPattern As String: strPattern = "(^|[" & strDelimitersEscaped & "]+)(" & RegexEscape(strNail) & ")($|[" & strDelimitersEscaped & "]+)"
    CreatePattern = strPattern
End Function

Private Function RegexEscape(strOriginal As String) As String
    Dim strEscaped As String: strEscaped = vbNullString
    Dim i As Long: For i = 1 To Len(strOriginal)
        Dim strChar As String: strChar = Mid(strOriginal, i, 1)
        Select Case strChar
        Case ".", "$", "^", "{", "[", "(", "|", ")", "*", "+", "?", "\"
            strEscaped = strEscaped & "\" & strChar
        Case Else
            strEscaped = strEscaped & strChar
        End Select
    Next i
    RegexEscape = strEscaped
End Function

一旦在模块中具有以上所述,就可以插入如下公式:

=SearchKeyWord($A1,"tfo")

其中A1包含“ tfo美国”。

作为第三个参数,您可以指定要将哪些字符视为定界符,默认情况下它们是空格,下划线,逗号,点,分号和斜杠。

返回值是关键字第n次出现的位置,其中n是第四个参数的值(默认值:1),如果找不到则为0。

要检查A1中是否存在关键字,请将结果与0(表示未找到)进行比较:

=--(SearchKeyWord($A1,"tfo")<>0)