VBA – 在 Variant数组上运行WorksheetFunction?

我需要在单个inputmatrix中连续运行内置的Excel函数。

问题是,input[range]是我所假设的,一个指针常量。

所以,我可以在[range]input上做一个WorkSheetFunction计算,并把输出放到一个variables中。

但是,我确实需要在变体数据上运行更多的传递。 我有一个更高级的计算,将使用标准的Excel函数,如平均和中位数的数据运行4个变换。

这是我的代码

 Public Function RankECDF(ByRef r_values As Range, Optional ByVal zeroFlag As Boolean = 0) As Variant() Dim i As Integer, j As Integer, N As Integer, M As Integer Dim total As Integer Dim y() As Variant N = r_values.Rows.Count M = r_values.Columns.Count y = r_values.Value 'copy values from sheet into an array Dim V() As Variant Dim AltV As Variant Dim OutV As Variant Dim OutAltV As Variant 'quite possible to makes the Variant larger to hold the "other arrays" ReDim V(1 To N, 1 To M) ReDim AltV(1 To N, 1 To M) ReDim OutV(1 To N, 1 To M) ReDim OutAltV(1 To N, 1 To M) 'first pass just checks for zero's. Could speed this process up by implementing the zeroFlag check to skip the double loop total = WorksheetFunction.Sum(r_values) For R = 1 To N For C = 1 To M If y(R, C) = "" Then V(R, C) = "" AltV(R, C) = 0 Else 'would error if cell was "" 'V(R, C) = WorksheetFunction.Average(WorksheetFunction.Rank(y(R, C), r_values, 1), WorksheetFunction.CountIf(r_values, "<=" & y(R, C))) / WorksheetFunction.Count(r_values) V(R, C) = y(R, C) AltV(R, C) = y(R, C) End If Next C Next R 'second loop does rankecdf conversions For RA = 1 To N For CA = 1 To M 'OutV(RA, CA) = 1 'OutV(RA, CA) = WorksheetFunction.Rank(V(RA, CA), V, 1) 'OutAltV(RA, CA) = 2 'OutAltV(RA, CA) = WorksheetFunction.Average(WorksheetFunction.Rank(y(RA, CA), r_values, 1), WorksheetFunction.CountIf(r_values, "<=" & y(RA, CA))) / WorksheetFunction.Count(r_values) Next CA Next RA If (zeroFlag) Then RankECDF = AltV 'RankECDF = OutAltV(1 to N, 1 to M) Else RankECDF = V 'RankECDF = OutV(N, M) End If End Function 

这个问题可以在这里find:

 OutV(RA, CA) = WorksheetFunction.Rank(V(RA, CA), V, 1) 

 WorksheetFunction.Rank(y(R, C), r_values, 1) 

你不能把一个数组放在arg1 。 做就是了:

 i = y(R, C) 

然后:

 WorksheetFunction.Rank(i, r_values, 1) 

它为我工作得很好

从评论中更新,我看到我最初假定的答案误解了这个问题:

作为一般规则,纯粹在内存中进行数组和执行计算比您想象的要快。 对于一个例子,我曾经使用Application.Match函数来查找数组中值的索引位置,而不是简单的powershell迭代。 事实certificate,迭代速度要快得多(快10倍!)的方法。 检查出Tim的答案是关于匹配string数组中的值的问题。

我怀疑这是排名/sorting相同。 工作表function很贵。 For/Next不是,相对而言。

至于从数组中sorting的具体需求,还有一些自定义函数的例子,它们对数组,集合,字典等进行sorting和sorting。我最终使用了一堆Chip Pearson的数组帮助函数 ,他有很多这样的函数 。 这真的很酷sh!t像倒序一个数组,sorting数组,确定一个数组是否被分配(我使用这个很多 )或空,或所有的数字,等等。大约有30个。

这里是sorting数组的代码 。

注:我没有发布他的代码,因为它有很多。 尽pipe看起来令人望而生畏,因为重新发明轮子有很多代码,但它确实工作并节省了很多麻烦,而且非常有用。 我甚至没有在Excel中使用这些function,因为我现在在PowerPoint中完成了大部分开发工作 – 我认为所有这些模块在我的末端都调用了零或几乎为零的debuggingfunction。 他们真的很好。

获得排名

一旦数组“sorting”,那么确定其中的任何值的排名是微不足道的,只需要一些调整,因为你可能需要适当处理关系。 处理关系的一个常见方法是“跳过”下一个值,所以如果对于第二位有双向平行关系,那么等级将会是{1,2,2,4,5,6等}

 Function GetRank(arr As Variant, val As Variant) 'Assumes arr is already sorted ascending and is a one-dimensional array Dim rank As Long, i As Long Dim dictRank As Object Set dictRank = CreateObject("Scripting.Dictionary") rank = 0 For i = LBound(arr) To UBound(arr) rank = rank + 1 If dictRank.Exists(arr(i)) Then 'Do nothing, handles ties Else 'store the Key as your value, and the Value as the rank position: dictRank(arr(i)) = rank End If If arr(i) = val Then Exit For Next GetRank = rank End Function