VBA - эквивалентная операция фигурной скобки {} - PullRequest
4 голосов
/ 10 июля 2020

В VBA для excel я могу просто использовать такую ​​формулу, как =SUM(X*{Y,Z}), чтобы суммировать умноженные результаты, однако передача ее в VBA не является 1: 1, поскольку она не поддерживает фигурные скобки для целей массива. Использование соответствующей настройки, такой как Result = Application.Worksheetfunction.Sum(X * Array(Y, Z)), приводит к ошибке несоответствия типа.

Я знаю, что могу просто использовать функцию оценки или индивидуально умножать и складывать после, особенно проверяя, есть ли способ выполнить sh указанное выше в методе сопоставления 1: 1.

Ответы [ 3 ]

0 голосов
/ 10 июля 2020

Вместо использования .Product() или .SumProduct() вы можете написать свои собственные функции для алгебры массивов.

Поместите следующее в модуль

Public Function FactorArray(ByVal factor As Double, ByRef a() As Variant) As Variant()
    Dim i_1 As Long, i_2 As Long, i As Long
    i_1 = LBound(a, 1)
    i_2 = UBound(a, 2)
    
    Dim result() As Variant
    ReDim result(i_1 To i_2)
    For i = i_1 To i_2
        result(i) = factor * a(i)
    Next i
    FactorArray = result
End Function

Public Function AddArrays(ByRef a() As Variant, ByRef b() As Variant) As Variant()
    Dim i_1 As Long, i_2 As Long, i As Long
    Dim j_1 As Long, j_2 As Long, n As Long
    i_1 = LBound(a, 1)
    i_2 = UBound(a, 2)
    j_1 = LBound(b, 1)
    j_2 = UBound(b, 2)
    
    n = WorksheetFunction.Min(i_2 - i_1 + 1, j_2 - j_1 + 1)
    
    Dim result() As Variant
    ReDim result(0 To n-1)
    For i = 0 To n-1
        result(i) = a(i + i_1) + b(i + i_2)
    Next i
    AddArrays = result
End Function

Public Function SubArrays(ByRef a() As Variant, ByRef b() As Variant) As Variant()
    SubArrays = AddArrays(a, FactorArray(-1, b))
End Function

Public Function DivArray(ByRef a() As Variant, ByVal divisor As Double) As Variant()
    DivArray = FactorArray(1 / divisor, a)
End Function

И затем используйте его как

Dim arr as Variant, res as Variant
arr = Array(1,2,3,4)
res = FactorArray(X, arr)
WorksheetFunction.Sum(res)

Конечно, для вашего конкретного c примера вы можете вычесть X и просто выполнить скалярное умножение.

Dim arr as Variant, res as Variant
arr = Array(1,2,3,4)
res = X*WorksheetFunction.Sum(arr)
0 голосов
/ 11 июля 2020

Подход с использованием функции MMULT()

  1. Если вы хотите умножить, например, {10,1,30} на единственный коэффициент , вы 'пришлось бы повторить множитель во втором аргументе в другом массиве:
    Dim a = Array(10, 1, 30)
    b = WorksheetFunction.MMult(a, Application.Transpose(Array(1, 1, 1)))
    Debug.Print b(1)     ' 41
Также можно было бы определить отдельный массив с соответствующими индивидуальными факторами для каждого базового элемента:
    Dim a = Array(10, 1, 30)
    Dim b: b = WorksheetFunction.MMult(a, Application.Transpose(Array(1, 1.5, 1)))
    Debug.Print b(1)     ' 41.5

A гибкая функция , содержащая обе версии (для любых массивов на основе нуля или 1, заполнение отсутствующих факторов в версии 2. нулевыми значениями по умолчанию ) может быть:

Function SumPro(a, factor, Optional missingFactor As Long = 0)
'Purp: sum products of array items multiplied by a) a single value or b) a set of factors in a 1-dim array
'Note: assumes "flat" 1-dim array(s)
'      fills up missing factors with zero values by default (missingFactor = 0)
    Dim n As Long: n = UBound(a) - LBound(a) + 1        ' items count independant from base start
    Dim b: ReDim b(1 To n, 1 To 1)                      ' provide for sufficient 1-based factor items
    Dim i As Long                                       ' counter
    If Not IsArray(factor) Then                         ' a) := single value
        For i = 1 To UBound(b): b(i, 1) = factor: Next  '       insert as many factors as array items
    Else                                                ' b) := already a factor array
        For i = LBound(factor) To UBound(factor)
            b(i - LBound(factor) + 1, 1) = factor(i)    '       collect existing factors
        Next
        For i = i - LBound(factor) + 1 To UBound(b)
            b(i, 1) = missingFactor                     '       complete missing factor items
        Next
    End If
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' calculate SumProduct (without Evaluate)
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Dim tmp: tmp = Application.MMult(a, b)              ' execute MMULT() function
' return function result
    SumPro = tmp(1)                                     ' return result
End Function

Пример вызова

 Dim a: a = Array(10, 1, 30)     ' base values
 Dim b: b = Array(1, 1.15)       ' zero-based factors, third factor left free ~> changes to zero by default
 debug.print SumPro(a, b)        ' ~> 11.15 as it multiplies only first two items with 10*1 + 1*1.15 + 30*0 = 11.15

Для единственного множителя достаточно передать число в качестве второго аргумента:

 Debug.Print SumPro(a, 2)
0 голосов
/ 10 июля 2020

WorksheetFunction.SumProduct может использоваться, не требует дополнительных функций .

Debug.Print Application.WorksheetFunction.SumProduct(Array(y, z), Array(x, x))

Обратите внимание, что вам просто нужно express ваш единственный фактор как массив с той же формой, что и целевой массив.

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