我正在尝试创建一个函数MonstersInLevel(),它根据第一列的值过滤"LevelMonsters“命名范围的第二列。range的第一列表示游戏级别ID,第二列表示出现在该级别中的怪物ID。我的射程是这样的。
如果我调用MonstersInLevel(2),我希望函数返回一个由"2“、"3”和"4“组成的范围。
Function MonstersInLevel(level As Integer) As Range
MonstersInLevel = Application.WorksheetFunction.Filter(Range("LevelMonsters").Columns(2), Range("LevelMonsters").Columns(1) = level)
End Function
我得到:
公式中使用的值的数据类型是错误的。
我像使用Excel公式一样使用FILTER函数。我认为,对于过滤器的标准,Excel和VBA语法有一些不同。
发布于 2021-01-05 16:49:14
只是我自己遇到了这个问题,想把我的解决办法发出去。
我们需要将True
/False
数组返回到工作表函数。为此,我创建了一个函数,该函数接受一个2D数组、列所需的值以及要比较的值。然后返回所需的True
/False
的2d单列数组。
Function myeval(arr() As Variant, clm As Long, vl As Variant) As Variant()
Dim temp() As Variant
ReDim temp(1 To UBound(arr, 1), 1 To 1)
Dim i As Long
For i = 1 To UBound(arr, 1)
temp(i, 1) = arr(i, clm) = vl
Next i
myeval = temp
End Function
因此,在这一特殊情况下,它将被称为:
Function MonstersInLevel(level As Integer) As Variant
MonstersInLevel = Application.WorksheetFunction.Filter(Range("LevelMonsters").Columns(2), myeval(Range("LevelMonsters").Value, 1, level),"""")
End Function
发布于 2021-01-05 18:22:53
通过VBA避免工作表函数中的类型不匹配
请记住,第二个参数反映了一个完全基于工作表逻辑(返回0或1个单元格值/False或True)的动态矩阵条件)。
Variant
Function MonstersInLevel(level As Integer) As Variant
'' Failing assignment:
' MonstersInLevel = Application.WorksheetFunction.Filter(Range("LevelMonsters").Columns(2), _
' Range("LevelMonsters").Columns(1) = level _
' )
MonstersInLevel = Application.WorksheetFunction.Filter( _
Range("LevelMonsters").Columns(2), _
Evaluate(Range("LevelMonsters").Columns(1).Address & "=" & level) _
)
End Function
求完备函数的...or
Function MonstersInLevel(level As Integer) As Variant
Dim expr As String
expr = "=Filter(" & _
Range("LevelMonsters").Columns(2).Address & "," & _
Range("LevelMonsters").Columns(1).Address & "=" & level & _
")"
'Debug.Print expr
MonstersInLevel = Evaluate(expr)
End Function
示例调用将结果写入任何目标
Dim v
v = MonstersInLevel(2)
Sheet1.Range("D2").Resize(UBound(v), UBound(v, 2)) = v
当然,也可以以编程方式编写.Formula2
表达式,甚至可以拆分为溢出范围引用。
增编.//截至1月10日
通过()向后兼容解决方案
“如果你们知道比
Application.WorksheetFunction.Filter
更合适的其他VBA函数,我会没事的。”
为了提供一个向后兼容的替代方案,我演示了基于先前匹配结果(参见Filter()
)的经典(VBA.)[3]
函数(参见[1]
)的以下方法。
注意,Application.Match()
比较了两个(!)数组输入提供了整个可能的结果数组(而不是最频繁执行的单个结果)。非发现由-1
的-1
值标识;将+1
结果添加到一组0和1中。[2]
部分为阳性结果输入了相应的数据。最终,非发现(即0
或零)被一个棘手的负面过滤删除。
getLevels()
函数
Function getLevels(rng As Range, ByVal level As Long)
'Site: https://stackoverflow.com/questions/65630126/how-to-remove-only-the-duplicate-row-instead-of-removing-all-the-rows-that-follo
'[0] get datafield array
Dim v, v2
v = Application.Index(rng.Value2, 0, 1) ' 1st column
v2 = Application.Index(rng.Value2, 0, 2) ' 2nd column
'[1] check data (with Match comparing 2 arrays :-)
Dim results
results = Application.Transpose(Application.Match(v, Array(level), 0))
'[2] rebuild with False/True entries
Dim i As Long
For i = 1 To UBound(results)
results(i) = IsError(results(i)) + 1 ' 0 or 1-values
If results(i) Then results(i) = v2(i, 1) ' get current value if true
Next i
'[3] remove zeros (negative filtering)
results = Filter(results, "0", False)
'[4] return results as vertical 1-based array
getLevels = Application.Transpose(results)
End Function
示例调用
Const LVL = 2 ' define level
With Sheet1 ' change to project's sheet Code(Name)
'define data range (assuming columns A:B)
Dim rng As Range
Set rng = .UsedRange.Resize(, 2)
'function call getLevels()
Dim levels
levels = getLevels(rng, level:=LVL)
'write to target
.Columns("I:I").Clear
.Range("I2").Resize(UBound(levels), 1) = levels
End With
发布于 2021-01-11 17:02:34
没有任何支持VBA功能的解决方案:
Function MonstersInLevel(level As Integer) As Variant
With Application.WorksheetFunction
MonstersInLevel = .Filter(Range("LevelMonsters").Columns(2), _
.IfError(.XLookup(Range("LevelMonsters").Columns(1), level, True), False))
End With
End Function
XLookup返回一个#N/A
或True
数组。IfError用False
替换错误。最后,Filter函数接收作为第二个参数的布尔数组。
编辑
由于@ScottCraner,删除了IfError
函数:
Function MonstersInLevel(level As Integer) As Variant
With Application.WorksheetFunction
MonstersInLevel = .Filter(Range("LevelMonsters").Columns(2), _
.XLookup(Range("LevelMonsters").Columns(1), level, True, False))
End With
End Function
https://stackoverflow.com/questions/62206989
复制相似问题