Excel两个数组之间的绝对差的VBA计算

时间:2019-05-03 16:57:46

标签: excel vba

很抱歉在这里的长度,但是我的VBA知识非常有限,我想明确一点。

尝试缩短和加快Excel VBA函数的功能,其中一项计算将价格值(“ Y0”)和先前价格值(“ Y1”)之间的一系列“ N”个数字绝对差求和。算术公式如下:

Sum( ABS(Y0 - Y1) + ABS(Y1 - Y2) + ABS(Y2 - Y3) + . . . )

Sum( ABS(Price - Price.Offset(-1, 0)) + Abs(Price.Offset(-1, 0) + . . . )

编码单独参考的价格变化既麻烦又缓慢。在Excel中,以下数组公式为N = 10数组中的一个单元格计算正确的结果:

{ =Sum(Abs($I15:$I24-($I14:$I23))) }

此公式计算N = 10期间I列中价格序列中的绝对差之和。数组中的两个范围偏移1个周期。

此计算所得的值是函数计算中使用的比率的分母。我希望VBA计算绝对差的数组和而不是算术序列。

我已经能够返回数组中N个周期的两个范围的地址,但是未能成功获取绝对差之和的数组计算。

很明显,我根本没有正确使用数组计算。我可以得到数组的总和,但不能得到超出的总和,而不能得到绝对差的总和。任何帮助将不胜感激。

'波动率公式{= SUM(ABS(Y:Yn)-(Y1:Yn1)))}

RRange =范围(RAddress)

R1Range =范围(R1Address)

R = Application.WorksheetFunction.Sum(Abs(RRange-R1Range))

我想在 VBA函数中计算以下Excel 数组公式 array

{ =SUM(ABS($I15:$I24-($I14:$I23))) }

2 个答案:

答案 0 :(得分:2)

您可以为此使用Evaluate-适用于数组公式:

Dim result
result = Sheet1.Evaluate("SUM(ABS($I15:$I24-($I14:$I23)))")

Sheet1是对具有数据的工作表的引用。 请勿使用Application.Evaluate格式,该格式将在ActiveSheet的上下文中计算公式。

enter image description here

enter image description here

答案 1 :(得分:0)

VBA解决方案

除了@TimWilliam绝对有效的解决方案之外,我还演示了您帖子中想要的 VBA 数组方法(使用相同的范围引用以进行更好的比较)。您应该可以将此示例代码转换为函数。 顺便说一句,仅通过VBA循环遍历数组而不是单元格会更快

Option Explicit                            ' declaration head of code module

Sub GetAbsDiffSum()
  Dim rng As Range, v(), i&, newVal#, oldVal#
  Set rng = Sheet1.Range("A1:A10")         ' range reference via worksheet's code name
' create 1-based 2-dim datafield array and transpose it to 1-dim "flat" array
  v = Application.Transpose(rng)
' remember first value for next comparison
  oldVal = v(1): v(1) = ""                ' [0](delete first value)
' calculate via array loop                ' --- important: don't change order of assignments!
  For i = 2 To UBound(v)                  '     start loop from 2nd row (1-based array: equals LBound(v) + 1)
      newVal = Abs(v(i) - oldVal)         ' [1] calculate absolute difference using remembered value
      oldVal = v(i)                       ' [2] remember current value for next comparison
      v(i) = newVal                       ' [3] overwrite current array value with absolute difference
  Next i
  Debug.Print "result = " & Application.Sum(v), _
              "equals sum of " & Join(v, ", ")
End Sub

旁注

当您在对Tim的方法的评论中提到#Value!"错误时,您可以研究以下MS支持站点,尝试检测对错误单元格的可能单元格引用,并在执行代码之前更正问题:How to correct a value error

根据评论进行编辑,2019年5月6日

显然,您的问题是创建一个用户定义的 function ,其中包括一个灵活的 range 参数,可以从工作表中的某个单元格中调用它(例如=AbsDiffs(A1:A10)=AbsDiffs(Sheet1!A1:A10))。

传递的rng参数不需要在函数中进行进一步限定...并且不要忘记返回函数结果(请参见[4]部分)

请注意将所有要比较的值包含在范围定义中。 假设给定范围为A1:A10,该函数将首先开始计算Abs(A2-A1),然后计算Abs(A3-A2),...以Abs(A10-A9)结尾并求和。

Option Explicit                      ' declaration head of your code module

Function AbsDiffs(rng As Range) As Double
  Dim v(), i&, newVal#, oldVal#
' create 1-based 2-dim datafield array and transpose it to 1-dim "flat" array
  v = Application.Transpose(rng)
' remember first value for next comparison
  oldVal = v(1): v(1) = ""                ' [0](delete first value)
' calculate via array loop                ' --- important: don't change order of assignments!
  For i = 2 To UBound(v)                  '     start loop from 2nd row (1-based array: equals LBound(v) + 1)
      newVal = Abs(v(i) - oldVal)         ' [1] calculate absolute difference using remembered value
      oldVal = v(i)                       ' [2] remember current value for next comparison
      v(i) = newVal                       ' [3] overwrite current array value with absolute difference
  Next i
  AbsDiffs = Application.Sum(v)           ' [4] return function result
End Function