【问题标题】:VBA How to check if an Array contains a string in a RangeVBA如何检查数组是否包含范围内的字符串
【发布时间】:2020-04-27 08:12:40
【问题描述】:

我正在尝试编写一个小循环来检查所选范围是否包含数组中的任何值。

Sub test()
    Dim DirArray As Variant
    Dim i As Integer

    'define array
    DirArray = Sheets("Blad1").Range("A1:A311").Value

    'Loop trough array
    For i = 1 To UBound(DirArray)
        'Activate the sheet with the Range
        Sheets("Blad1").Activate

        'Go through range of values
        If DirArray = Cells(i, 2) Then
            MsgBox "it contains the value"
        End If
    Next i
End Sub

我认为我使用Cells(i,2) 会出错,它说类型不匹配。我已经看了很长时间了,我想我错过了一些明显的东西。

任何帮助或反馈将不胜感激!

【问题讨论】:

  • 您不能将数组与任何东西进行比较。使用两个嵌套循环。
  • 你必须在循环中指定数组的具体元素,但是使用 MATCH 来避免循环的需要。

标签: arrays excel vba loops


【解决方案1】:
Sub test()
    Dim i As Integer, z, DirArray As Variant
    With Sheets("Blad1")
        'Define array
        DirArray = .Range("A1:A311").Value
        'Loop trough array
        For i = 1 To UBound(DirArray)
            '// Use Excel's Match function:
            '// if the value of 'z' is not Error, then match is found.
            '// Note that if you use WorksheetFunction.Match instead of
            '// Application.Match and the value won't be found, then
            '// error will be raised, in which case you need to use error handler.
            '// To avoid this ceremony, use Application.Match since it won't raise
            '// error, but the value of 'z' will just contain Error.
            z = Application.Match(.Cells(i, 2), DirArray, 0)
            If Not IsError(z) Then
                MsgBox "it contains the value"
            End If
        Next i
    Next
End Sub

【讨论】:

  • 如果 OP 只想知道DirArray 中的任何值是否存在于它们的 B 列等效项中,则可以完全不使用任何循环。无论哪种方式。在您的情况下,您也可以这样做:If Application.Count(Application.Match(.Cells(i,2), DirArray, 0)) > 0 Then MsgBox "it contains the value"。这将消除对额外IsError 检查的需要。 +1
  • @JvdV 我猜 OP 需要根据数组值检查列 B 中的所有值。
  • 是的,我的意思是也可以这样做,没有任何循环,只要 OP 只对存在的事实感兴趣。
  • @JvdV 您仍然有两个循环,一个可见,循环i,另一个隐藏在Application.Match 内。您也不能调用 Application.Count(Application.Match()),因为 Application.Match 返回一个数字。
  • @GSerg, Application.Match 可以返回结果数组。我在下面写了一个答案来证明这一点。
【解决方案2】:

仅用于演示实践,我想向您展示不需要任何(可见的)循环来比较两个一维数组以返回 if any 中的元素在另一个数组中找到一个数组。

为此,我们可以使用以下代码:

Sub Test()

Dim arr1 As Variant: arr1 = Array("A", "B", "C", "D")
Dim arr2 As Variant: arr2 = Array("D", "E", "B")

With Application
    If .Count(.Match(arr2, arr1, 0)) > 0 Then
        MsgBox "It contains values from arr1"
    Else
        MsgBox "It does not contain values from arr1"
    End If
End With

End Sub

这实际上是做什么的? Application.Match 能够比较两个数组,所以在这种情况下你可以有效地想到:

.Match({"D", "E", "B"}, {"A", "B", "C", "D"}, 0)

它将第一个数组中的每个元素与第二个数组中的所有元素进行比较,最重要的是,它会自行返回一个数组,结果如下:

Results = {4, Error 2042, 2}

正如@JohnyL 还解释的那样,使用Application.Match 不会在未找到值时引发运行时错误,它将继续并将未找到的匹配项放入数组本身,而不是在结果中显示错误。

现在检查是否有任何结果,我们需要Application.Count 来返回结果数组中数值的数量。

.Count({4, Error 2042, 2})

在这种情况下,结果将是2,告诉我们(大于零)有两个值匹配。


这对 OP 有何帮助?

在他的例子中,我们需要一个函数来直接从Range 对象返回两个一维数组。 Op 似乎将 Range("A1:A311")Range("B1:B311") 进行比较,因此我们可以尝试以下操作:

Sub Test2()

Dim arr1 As Variant: arr1 = Sheets("Blad1").Range("A1:B311").Value

With Application
    If .Count(.Match(.Index(arr1, 0, 1), .Index(arr1, 0, 2), 0)) > 0 Then
        MsgBox "It contains values from arr1"
    Else
        MsgBox "It does not contain values from arr1"
    End If
End With

End Sub

我使用的唯一额外方法是 Application.Index 直接从完整的二维数组分割两个一维数组。

如果 A 和 B 列的大小不同,则另一种技术是使用 Application.Transpose。您可以将它们拉入一个单独的变体变量中,然后将它们Transpose 一次拉入一维数组中。

【讨论】:

  • Application.Match() 函数不太为人所知的可能性的精细演示:+)
猜你喜欢
  • 1970-01-01
  • 2014-06-04
  • 2020-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-05
  • 2018-05-04
  • 2012-08-11
相关资源
最近更新 更多