【问题标题】:Issue with VBA array Filter function: only first result is returnedVBA 数组过滤器函数的问题:只返回第一个结果
【发布时间】:2018-02-23 18:59:46
【问题描述】:

我在使用 VBA 的“过滤器”功能时遇到了一些问题。我正在尝试使用多个后续过滤器逐步减少数组以包含我需要的值。然而,似乎只返回与“匹配”值匹配的第一个元素,而不返回后续元素?

举个例子,当运行下面的代码时,第二个“调试调用”返回“1”,但它应该返回“2”

Function FilterAnArray()

Dim names As Variant
names = Array("Ann Smith", "Barry Jones", "John Smith", "Stephen Brown", "Wilfred Cross")
Debug.Print UBound(names)

Dim smithNames As Variant
smithNames = Filter(names, "Smith")
Debug.Print UBound(smithNames)

End Function

版本信息等

我正在运行 Excel 2016,版本 16.0.8730.2046 - 64 位。 非常感谢您对此问题的任何帮助!

【问题讨论】:

    标签: vba excel


    【解决方案1】:

    它工作得很好。它返回 1,因为您有两个 Smith:

    smithNames 的上限是 1,因为它的数组是从 0 开始的。如果您想要数组元素的计数,并且您不喜欢UBound+1,您可以使用工作表函数:

    Debug.Print WorksheetFunction.CountA(smithNames)


    强烈建议不要选择:

    您可以考虑在模块顶部写Option Base 1。然后数组将是基于 1 的,并且将是您期望的方式。在您的示例中,您会看到为什么不建议使用 Option Base 1。如果你有它,Names 将是 1 basedsmithNames 将是 0 based。这是因为数组的分配方式不同。

    【讨论】:

    • 为什么您认为“错误地”不建议使用选项基数 1?在我看来,有 3 种数组。 1) 总是从 0 开始的数组,比如 split 2) 总是从 1 开始的数组,比如范围和 3) 使用选项 base 隐式设置 3a) 或使用 dim dmy(3 到 7) 显式设置的数组他们有哪个基地。所以这有点取决于你的情况,最好的设置是什么。我喜欢选项基数 1。只是我的 2 美分 ;-)
    • 我遇到的唯一真正的问题是,如果你重用代码并且有一个带有选项 base 1 的模块,而一个没有。所以+1:最好是明确设置界限。
    • @Jochen - 如果您使用 Option Base 1 并将您的代码分享给某人,请准备好迎接很多麻烦。
    • 如果我分享我的代码,我会与选项 base 1 和选项显式分享它;-)
    • @Jochen - Option Explicit 还可以,但 Option Base 1 可能会给您带来问题。但这是另一个主题。
    【解决方案2】:

    Ubound 给出了上界。当您使用基于 0 的数组时,您会得到 5 个条目的结果为 4,而 2 个条目的结果为 1。

    如果您想使用基于 1 的数组而不明确标注每个数组,请在模块开头使用 Option Base 1

    【讨论】:

    • 好的,是的。事实上,这也是我试图修复的更广泛脚本中的错误。抱歉,这真的不是一个非常聪明的问题。你们真的帮助了我!
    【解决方案3】:

    检查一下你应该得到多少个结果然后打印出来,比如:

    Sub foo()
    Dim val As Variant
    Dim names As Variant
    Dim post As Variant
    names = Array("Ann Smith", "Barry Jones", "John Smith", "Stephen Brown", "Wilfred Cross")
    Debug.Print UBound(names)
    
    Dim smithNames As Variant
    smithNames = Filter(names, "Smith")
    
    pos = Application.Match(smithNames, names, False) 'find how many values match "Smith"
    
    If Not IsError(pos) Then
        For x = LBound(pos) To UBound(pos)
            Debug.Print pos(x)
        Next x
    Else
       MsgBox val & " not found!"
    End If
    End Sub
    

    【讨论】:

      猜你喜欢
      • 2011-11-05
      • 2018-12-11
      • 1970-01-01
      • 2020-01-13
      • 2014-04-17
      • 2016-05-23
      • 1970-01-01
      • 2019-04-23
      相关资源
      最近更新 更多