如何使用工作表函数过滤数组?

时间:2017-07-10 16:52:24

标签: vba excel-vba excel

我正在寻找一种方法来过滤具有评估表达式的数组,例如:

Dim arr1(), arr2(), arr3()

arr1 = Array(1, 2, 3, 4, 5)           ' > [1, 2, 3, 4, 5]

arr2 = Map(arr1, "Values() * 2")      ' > [2, 4, 6, 8, 10]

arr3 = Filter(arr2, "Values() > 6")   ' > [8, 10]

我已经使用UDF和Map实现了Application.Evaluate("INDEX(expression, )")功能,但我努力使其适用于Filter

Private arr_()

Public Function Values() As Variant()
  Values = arr_
End Function

Public Function Map(arr(), expression As String) As Variant()
  arr_ = arr
  Map = Application.Evaluate("INDEX(" & expression & ",)")
End Function

Public Function Filter(arr(), expression As String) As Variant()
  arr_ = arr
  Filter = Application.Evaluate("INDEX(Values(), " & expression & ")")
End Function

除了循环/移动每个值之外,还有其他方法吗? Maby与VLOOKUP

2 个答案:

答案 0 :(得分:1)

虽然我是数组的忠实粉丝,并将大部分工作委托给Excel的内置插件,但对于这个,我发现最合适的是在VBA中完成主要工作,使用Excel来Evaluate个别项目的表达。

Public Function FilterArr(arr(), expression As String)
  Dim match As Boolean, i As Long, val
  ReDim ret(LBound(arr) To UBound(arr))
  i = LBound(arr) - 1
  On Error Resume Next
  For Each val In arr
    match = False
    match = Application.Evaluate(val & expression)
    If match Then
      i = i + 1
      ret(i) = val
    End If
  Next
  If i >= LBound(arr) Then
    ReDim Preserve ret(LBound(arr) To i)
    FilterArr = ret
  End If
End Function
Sub test()
  Dim arr1(), arr2(), arr3()
  arr1 = Array(10, 20, 30, 40, 50)
  arr3 = FilterArr(arr1, ">25")   ' <--- usage like this
  ' arr3 = (30, 40, 50)
End Sub

P.S。一个有趣的扩展是允许使用AND的多个标准(即ParamArray编辑在一起)。未来工作的良好候选人......

答案 1 :(得分:1)

首先将功能更改为以下内容......

Public Function Filter(arr(), sValues As String, sCriteria As String) As Variant()
  Dim Cnt As Long
  arr_ = arr
  Cnt = Application.Evaluate("SUMPRODUCT(--(" & sValues & sCriteria & "))")
  If Cnt > 0 Then
    Filter = Application.Evaluate("TRANSPOSE(INDEX(SMALL(IF(" & sValues & sCriteria & "," & _
        sValues & "),ROW(INDEX(A:A,1):INDEX(A:A," & Cnt & "))),0))")
  Else
    Filter = Array()
  End If
End Function

然后这样称呼它......

arr3 = Filter(arr2, "Values()", ">6")