【问题标题】:Wildcard search in array数组中的通配符搜索
【发布时间】:2015-05-12 06:41:06
【问题描述】:

我有一个数组,其中包含一堆常用术语,用于表示该字段正在等待采购订单。然后我有一个循环向后遍历一大列数据,删除单元格中的值与数组中的任何项都不匹配的任何行。为此,我使用一个函数(我在网上找到)来测试该值是否存在于数组中。

到目前为止一切顺利,只要单元格中的值与数组中的值完全匹配。出错的地方是如果单元格包含对常用术语之一的轻微变化(即“TBC - 稍后会跟进”,甚至只是“TBC”而不是“TBC”)

我需要一种方法来获取单元格中的值并对数组中的值进行通配符搜索。我不会粘贴我所有的代码(现在这是一个开发中期的混乱),但如果我们可以在下面实现它,我可以应用它。

Sub TestFilterArray()
MyArray = Array("tbc", "awaiting po", "po to follow")
If IsInArray("tbc xyz", MyArray) = False Then
    MsgBox "No! Item is not in the array"
Else
    MsgBox "Yes! Item is in the array"
End If
End Sub

Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
  IsInArray = UBound(Filter(arr, stringToBeFound)) > -1
End Function

这当前返回“否!...”,因为“tbc xyz”不在数组中,但如果有意义的话,我希望它返回“是!...”,因为“tbc *”在那里。

感谢任何帮助。

【问题讨论】:

  • 部分匹配要使用哪些规则?例如,如果stringToBeFound 只是po,那么应该返回True 还是False?如果是返回True,那么MyArray的多词短语中哪些词我们考虑,哪些忽略?
  • 感谢您参与帮助@RonRosenfeld 非常好的一点!理想情况下,stringToBeFound 中的整个字符串都应在两端使用通配符。所以“等待 po - xyz”将返回 true,但“等待 xyz po”将返回 false。
  • 查看我的答案中的代码
  • MyArray 中的字符串是 contains 搜索词,因此我们正在检查 StringToBeFound 中的值是否 contains 任何字符串存储在MyArray 内。因此,stringToBeFound 中的“po”将返回 False,因为“po”不包含“等待 po”或“po to follow”。 "123 awaiting po" 将返回 True 作为字符串 "123 awaiting po" 包含 字符串 "awaiting po"。希望有帮助..

标签: arrays vba excel


【解决方案1】:
Function IsInArray2(StringToBeFound As String, MyArray As Variant) As Boolean
IsInArray2 = False
For i = LBound(MyArray) To UBound(MyArray)
    If "*" & MyArray(i) & "*" Like StringToBeFound Then IsInArray2 = True 'will match MyArray to any substring of StringToBeFound
Next
End Function

考虑到运行时考虑,它变成了

Function IsInArray2(StringToBeFound As String, MyArray As Variant) As Boolean
IsInArray2 = False
For i = LBound(MyArray) To UBound(MyArray)
    If "*" & MyArray(i) & "*" Like StringToBeFound Then
        IsInArray2 = True 'will match MyArray to any substring of StringToBeFound
        Exit Function
    End If
Next
End Function

谢谢你的评论。回首往事,是的,Like 声明反其道而行之,抱歉。让我用一个案例和冗余匹配器和一个测试来弥补它的重要性。

Function IsInArray2(stringToBeFound As String, MyArray As Variant) As Boolean
IsInArray2 = False
For i = LBound(MyArray) To UBound(MyArray)
    If LCase(stringToBeFound) Like LCase("*" & Replace(MyArray(i), " ", "*") & "*") Then
        IsInArray2 = True 'will match MyArray to any substring of StringToBeFound
        Exit Function
    End If
Next
End Function

Sub TestFilterArray()
MyArray = Array("coca cola gmbh", "awaiting po", "po to follow")
If IsInArray2("Coca Cola Deutschland GmbH", MyArray) = False Then
    MsgBox "No! Item is not in the array"
Else
    MsgBox "Yes! Item is in the array"
End If
End Sub

【讨论】:

  • 谢谢!这看起来很棒,我可以看到它应该如何工作,但由于某种原因它仍然返回“不!......”。单步执行,在 if 语句中,它不会在 Like 运算符上返回 true,因此跳过 Then 到 Next... 有什么想法吗?
  • 剥离到它的基本级别,立即窗口中的以下内容返回“no” - If "tbc" Like "tbc" Then MsgBox "Yes" Else MsgBox "no "
【解决方案2】:

此代码似乎可以满足您的要求:

Option Explicit

Sub TestFilterArray()
Dim MyArray As Variant
MyArray = Array("tbc", "awaiting po", "po to follow")
If arrMatch("tbc xyz", MyArray) = False Then
    MsgBox "No! Item is not in the array"
Else
    MsgBox "Yes! Item is in the array"
End If
End Sub

    Function arrMatch(stringToSearch As String, Arr As Variant) As Boolean
    Dim sS As String, sF As String
    Dim I As Long

sS = " " & Trim(stringToSearch) & " "
For I = LBound(Arr) To UBound(Arr)
    sF = "*" & Trim(Arr(I)) & "*"
    If sS Like sF Then
        arrMatch = True
        Exit Function
    End If
Next I

arrMatch = False
End Function

【讨论】:

  • 感谢@ronrosenfeld,它在给定参数下效果很好。但是,当我将 if arrMatch("tbc xyz" 更改为 if arrMatch("tbc-xyz" 时,我又回到了不匹配的状态......
  • 从您的规范中我不清楚您是否还希望匹配 MyArray 中的字符串,因为它们是较长字符串的一部分。但这很容易改变。
  • 再次感谢@ronrosenfeld。这很好用,其他人的回答也是如此。我希望我能选择两个作为正确答案!
猜你喜欢
  • 2011-12-10
  • 1970-01-01
  • 1970-01-01
  • 2019-03-15
  • 1970-01-01
  • 1970-01-01
  • 2016-10-31
  • 2011-07-10
  • 1970-01-01
相关资源
最近更新 更多