VBA Расчет абсолютных различий между двумя массивами Excel - PullRequest
0 голосов
/ 03 мая 2019

Я прошу прощения за длину здесь, но мои знания VBA очень ограничены, и я хочу быть ясным.

Попытка сократить и ускорить работу функции Excel VBA, в которой одно из вычислений суммирует серию абсолютных разностей числа «N» между значением цены («Y0») и предыдущим значением цены («Y1»). Арифметическая формула выглядит так:

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))) }

Эта формула вычисляет сумму абсолютных разностей в ценовом ряду в столбце I для N = 10 периодов. Два диапазона в массиве смещены на 1 период.

Значение этого расчета является знаменателем в соотношении, используемом при вычислении функции. Я бы хотел, чтобы VBA вычислял массив абсолютных разностей, а не арифметический ряд.

Мне удалось вернуть адреса для обоих диапазонов для N периодов в массиве, но мне не удалось получить в массиве вычисление суммы абсолютных разностей.

Понятно, что я не использую вычисления массива должным образом, если вообще. Я могу получить сумму массивов, но не намного дальше и не сумму абсолютных разностей по мере необходимости. Любая помощь будет принята с благодарностью.

'Формула волатильности {= SUM (ABS (Y: Yn) - (Y1: Yn1)))}

RRange = Range (RAddress)

R1Range = Range (R1Address)

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

Я бы хотел вычислить следующую формулу массива Excel и массив в VBA-функции .

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

Ответы [ 2 ]

2 голосов
/ 03 мая 2019

Вы можете использовать Evaluate для этого - он отлично работает для формул массива:

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

Где Sheet1 - это ссылка на рабочий лист с данными. Не используйте форму Application.Evaluate, которая будет оценивать формулу в контексте ActiveSheet.

enter image description here

enter image description here

0 голосов
/ 04 мая 2019

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

Примечание

Поскольку вы упоминаете об ошибке #Value!" в своем комментарии к подходу Тима, вы можете изучить следующий сайт поддержки MS, попытаться обнаружить возможную ссылку на ячейку на ячейку с ошибкой и исправить проблему перед выполнением кода: Как исправить ошибку значения .

Редактировать из-за комментариев / 5-6 2019

Очевидно, ваша задача - создать пользовательскую функцию , включающую гибкий аргумент 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...