Home » excel » excel – VBA: Summing a matrix

# excel – VBA: Summing a matrix

Questions:

Why doesn’t this function work?

Type `=funtest(2.1)` in Excel and it’ll give me `#VALUE!`.

``````Public Function funtest(a As Double) As Double

Dim z, j, i As Integer
Dim matrix(3, 3, 3) As Double

For z = 0 To 3 Step 1
For j = 0 To 3 Step 1
For i = 0 To 3 Step 1

matrix(z, j, i) = a

Next i, j, z

funtest = Application.WorksheetFunction.Sum(matrix)

End Function
``````

`WorksheetFunction.Sum` will work with either a range or a 2 dimentional array. It errors because you are passing it a 3 dimensional array.

So, this works

``````Public Function funtest(a As Double) As Double
Dim z As Long, j As Long, i As Long
Dim matrix() As Double

ReDim matrix(0 To 3, 0 To 4)
For j = LBound(matrix, 1) To UBound(matrix, 1)
For i = LBound(matrix, 2) To UBound(matrix, 2)
matrix(j, i) = a
Next i, j

funtest = Application.WorksheetFunction.Sum(matrix)
End Function
``````

Note I have modified your declarations slighly, see note at end of answer.

To sum higher dimensional arrays you will need to do some looping.

One option (which may or may not suit your overal requirements) is to declare your array slightly differently, as a so called `Jagged Array`.

``````Public Function funtest2(a As Double) As Double
Dim z As Long, j As Long, i As Long
Dim matrix() As Variant
Dim InnerMatrix(0 To 4, 0 To 4) As Double

' Dimension Jagged Array
ReDim matrix(0 To 4)
For i = LBound(matrix, 1) To UBound(matrix, 1)
matrix(i) = InnerMatrix
Next

For z = LBound(matrix) To UBound(matrix)
For j = LBound(matrix(z), 1) To UBound(matrix(z), 1)
For i = LBound(matrix(z), 2) To UBound(matrix(z), 2)
matrix(z)(j, i) = a
Next i, j, z

' Sum matrix
For z = LBound(matrix) To UBound(matrix)
funtest2 = funtest2 + Application.WorksheetFunction.Sum(matrix(z))
Next
End Function
``````

This is an array of 2 dimensional arrays. The `Sum` is then applied to each of the inner arrays in turn. This way, at least you are only looping one dimension and not all three.

Note on `Dim` and `Integer`
You must specify all `As Type`‘s, otherwise variables default to `Variant`
In your code `z` and `j` will be `Variants`

Also, using `Integer` rather than `Long` is actually counter productive on a 32 bit OS: `Long`‘s will be slightly faster.

I’m going to take you literally when you say “I’m trying to solve the simple case of a (3,3,3) matrix with each element equal to some double, a”. This will do that:

``````Public Function funtest(a As Double) As Double
funtest = 4*4*4*a
End Function
``````

First, when you get `#VALUE!` this means there is an error, it can mean using a matrix that is not valid.

To answer your question, your code does not work because your syntax is not correct. The following function creates a matrix from values.

``````Function FQ_matrix_create(StartValue As Double, Interval As Double,
nrow As Long, ncol As Long) As Double()
Dim M() As Double
' Creates matrix with sequential element values with given row and
' column sizes. Fills matrix row-wise with numbers.
' - set Interval = 0 for constant element values
' - error input arguments nrow and ncol are not positive integers
``````

To SUM the Values use:

``````Function FQ_matrix_element_sum(M() As Double, SumOption As
MatrixDirection) As Double()
' Returns the sum of elements of matrix M, either row or column wise
' - Rowwise sum returns a horizontal 1xNcol matrix
' - Columnwise sum returns a vertical 1 xNrow matrix
' - Element sum (all elements) returns a 1x1 matrix
' - error if M is not a matrix
' - error if SumOption is not 1 (nRowWiseSum) or 2 (nColWiseSum) or
3 (nElementSum)
``````