Home » excel » excel – Easiest way to have a function report 2 outputs

excel – Easiest way to have a function report 2 outputs

Posted by: admin May 14, 2020 Leave a comment

Questions:

I have a very rudimentary question about functions in VBA. Basically, I would like to create a function that would return 2 outputs, a scalar and a matrix. A user should be able to both store these results into separate variables in VBA and display them in Excel spreadsheet.

My approaches:

  • I could obviously use 2 different functions but this is not elegant and involves redundant computation

  • I created a class that has 2 properties and then defined my function as an instance of that class, storing my scalar and matrix as those properties. The problem is that in this case I don’t know how to display my results easily in Excel.

    • I could however create 2 additional functions that would just read the respective (scalar or a matrix) output of the first function but this would again result in redundant computations.

I am afraid I am missing something really basic here and hope you can offer me some guidelines… Thanks a lot for your help 🙂

How to&Answers:

You can create a class with these two properties and return a new instance of this class as return value. Then your calling code would have to read both properties.

Answer:

You could use ByRef. Probably not the best plan though.

Sub Example(ByRef A As String, ByRef B As String)
A = A & "Hello"
B = B & "World!"
End Sub

Sub test()
Dim A As String
Dim B As String

    A = "Test"
    B = "Test"

    Example A, B

    Debug.Print A & " " & B

End Sub

Edit

If your trying to make a UDF available on the worksheet then you can disregard me completely.

If you’re calling this (whatever your solution is) from the worksheet I think you will always have multiple (2) calls to the function. You might be able to cache the results of your function assuming it wont change frequently.
It wont stop the call, but it will stop some excess calculations.

Private Cache As Object

Public Function MonsterFunction(ByVal A As Integer, ByVal B As Integer, Optional ByVal Add As Boolean = False) As Variant
Dim Key As String
Dim Result As Integer

Key = CStr(A) & IIf(Add, "+", "-") & CStr(B)

If Cache Is Nothing Then
    Set Cache = CreateObject("Scripting.Dictionary")
End If

If Cache.Exists(Key) Then
    MonsterFunction = Cache(Key)
Else
    If Add Then
        Result = A + B
    Else
        Result = A - B
    End If

    Cache.Add Key, Result
    MonsterFunction = Result
End If

End Function

Answer:

The easiest way? Probably:

Function TwoOutputs() As Variant()

    Dim matrix(1 To 2, 1 To 3) As Variant

    matrix(1, 1) = "Did"
    matrix(1, 2) = "it"
    matrix(1, 3) = "work?"

    matrix(2, 1) = "Yes"
    matrix(2, 2) = "it"
    matrix(2, 3) = "did!"

    TwoOutputs = Array("scalar", matrix)

End Function

Then to access whichever attribute you want, you can:

  • Within VBA (0 will return the scalar, 2 will return the matrix):

    Sub tst()
    
        Dim FunctionResult() As Variant
        Dim i As Long
        Dim j As Long
    
        FunctionResult = TwoOutputs
    
        MsgBox "Scalar: " & FunctionResult(0)
    
        For i = LBound(FunctionResult(1), 1) To UBound(FunctionResult(1), 1)
            For j = LBound(FunctionResult(1), 2) To UBound(FunctionResult(1), 2)
                MsgBox "Matrix loc(" & i & ", " & j & "): " & FunctionResult(1)(i, j)
            Next j
        Next i
    
    End Sub