+ Reply to Thread
Results 1 to 5 of 5

Using a VBA UDF in an array formula

Hybrid View

  1. #1
    Registered User
    Join Date
    08-31-2017
    Location
    Spokane Washington
    MS-Off Ver
    14 and up. All components
    Posts
    4

    Using a VBA UDF in an array formula

    I am trying to use a user defined formula within an array formula and keep getting an error message. I am trying to replicate a formula which returns a covariance matrix in a logistic regression problem. The matrix formula is X'WX where X' is the transpose of X. The X matrix is a matrix of independent variables of dimension n x K where n is the number of observations and k is the number of variables. A very simplified example of the situation is attached which has 3 independent variables in columns A, B, and C. The W matrix is a diagonal matrix of dimension n x n. The diagonal entries of this matrix are the product of three separate column vectors and the off diagonal values are all zeros. I have written a user defined formula to fill the W matrix. The values for the W matrix are in columns D, E, and F. The actual array formula is "=MMULT(TRANSPOSE(A2:C6),MMULT(DIAGONAL(D2:D6,E2:E6,F2:F6),A2:C6))" where DIAGONAL is the user defined function. The code for this function is shown below. The function as written always returns #VALUE in each cell. The subroutine to test the function on the example worksheet is below the function. Note that both of these routines must be in a general VBA module. They cannot be in a spreadsheet module. Any help would be appreciated.

    Public Function Diagonal(rngA As Range, rngB As Range, rngC As Range) As Variant

    Dim TempArray() As Variant
    Dim I, J As Integer
    Dim intN As Integer
    Dim bolEqual
    Dim strA, strB, strC As String
    Dim strD, strE, strF As String


    strA = Split(rngA.Address, "$")(1)
    strB = Split(rngB.Address, "$")(1)
    strC = Split(rngC.Address, "$")(1)
    intN = Split(rngA.Address, "$")(4)

    ReDim TempArray(1 To intN, 1 To intN)

    For I = 1 To intN
    For J = 1 To intN
    If I = J Then
    strF = strC & Format(I + 1)
    TempArray(I, J) = ActiveSheet.Range(strD).Value * ActiveSheet.Range(strE).Value * ActiveSheet.Range(strF).Value
    Else
    TempArray(I, J) = 0#
    End If
    Next J
    Next I
    Diagonal = TempArray

    End Function

    Private Sub TestUDF()


    Dim strFormula As String
    Dim strRange As String

    strRange = "G7:I9"
    strFormula = "=MMULT(TRANSPOSE(A2:C6),MMULT(DIAGONAL(D2:D6,E2:E6,F2:F6),A2:C6))"

    ActiveSheet.Range(strRange).FormulaArray = strFormula


    End Sub
    Attached Files Attached Files

  2. #2
    Forum Guru
    Join Date
    04-13-2005
    Location
    North America
    MS-Off Ver
    2002/XP, 2007, 2024
    Posts
    16,396

    Re: Using a VBA UDF in an array formula

    Since I don't have access to the add-in file, I copied the code (you should edit your post to put the code in code tags -- this forum can be strict about those kind of things) into a module and ran it from the file (I assume the code here is the same as is in the add-in). When I ran the UDF in this way, the UDF fails. I added a stop statement to the top of the UDF, and discovered that it aborts on the TempArray(I,J)=ActiveSheet.Range(... statement. Looking at the variables just before that statement, I see that StrE and StrD are both empty, so this statement fails.

    I'm not sure what this statement is trying to do. I would have expected this statement to be looking at the arrays/ranges that were passed to the UDF -- not trying to go back to the spreadsheet for additional information. Before we can worry about how the UDF output is interacting with the MMULT() functions, we need to get a valid output from the UDF, which, I'm hoping, just means figuring out what that statement is supposed to be doing and then correcting it.
    Quote Originally Posted by shg
    Mathematics is the native language of the natural world. Just trying to become literate.

  3. #3
    Registered User
    Join Date
    08-31-2017
    Location
    Spokane Washington
    MS-Off Ver
    14 and up. All components
    Posts
    4

    Re: Using a VBA UDF in an array formula

    My apologies. As Mr. Shorty pointed out, there were two lines missing from my code. I have modified the file and inserted the missing statements. I have attached this macro enabled file which includes the corrected macro and a short subroutine called TestUDF that can be called from the developer tab to run the macro.
    Attached Files Attached Files

  4. #4
    Forum Guru
    Join Date
    04-13-2005
    Location
    North America
    MS-Off Ver
    2002/XP, 2007, 2024
    Posts
    16,396

    Re: Using a VBA UDF in an array formula

    When multiplying matrices, the number of columns of the first matrix must be the same as the number of rows in the second matrix. Diagonal() is returning a 6x6 matrix. MMULT() is then trying to multiply that 6x6 matrix by a 5x3 matrix which is not possible.

    If I go into Diagonal() and replace the intN statement so that it is 5 (intN=5), the MMULT() formula in G7:I9 runs without error. If we can get Diagonal() to correctly determine the size of the output array, everything should work fine.

    I'm not certain of the strategy here. The current strategy is to parse the Range.Address property and determine the size of the input vectors using the spreadsheet row number. It seems that this would only work when the input range includes spreadsheet row 1. In this case, your input ranges are starting in row 2. I would normally prefer to count the number of rows rather than read the address string for this. Something like intN=rngA.rows.count. Then I can pass any vector from anywhere in the spreadsheet to the function.

    Bonus observation: I cannot think of any good reason to use ActiveSheet to bring any information into a UDF. Sure it works okay as long as sheet1 is the active sheet, but the formula will error or return unexpected results as soon as you navigate to a different tab in the workbook or a different workbook. ActiveSheet means whatever sheet is currently active at runtime, which may or may not be the same sheet where you have entered the UDF. You have passed the necessary information to the function in rngA, rngB, rngC. I would refer to those object variables rather than Active sheet.
    For I = 1 To intN
            For J = 1 To intN
                If I = J Then
                    'strD = strA & Format(I + 1)
                    'strE = strB & Format(I + 1)
                    'strF = strC & Format(I + 1)
                    'TempArray(I, J) = ActiveSheet.Range(strD).Value * ActiveSheet.Range(strE).Value * ActiveSheet.Range(strF).Value
                    TempArray(I,J)=rngA.cells(I,1)*rngB.Cells(I,1)*rngC.Cells(I,1)
                Else
                    TempArray(I, J) = 0#
                End If
            Next J
        Next I
    This obviates the need for the strA etc. variables and allows VBA to correctly calculate the UDF even when this sheet is not the active sheet.

    See how that fits into your broader project.

  5. #5
    Registered User
    Join Date
    08-31-2017
    Location
    Spokane Washington
    MS-Off Ver
    14 and up. All components
    Posts
    4

    Re: Using a VBA UDF in an array formula

    This fixes the problem. Thanks for your response MrShorty. I forgot that the address would return a value 1 larger than it should be because the values start in row 2. I am using addresses because in the software the computations are performed on a hidden sheet with formulas that use range references. Thank you for your prompt response and finding my error.

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. Array summing inventory of a specific part (array formula) EXCEL 2007
    By fdirosa in forum Excel Formulas & Functions
    Replies: 3
    Last Post: 11-07-2018, 12:51 PM
  2. Replies: 3
    Last Post: 04-02-2016, 08:16 PM
  3. Can I make the row lookup array/range part in an array formula variable?
    By OLLY-7 in forum Excel Formulas & Functions
    Replies: 4
    Last Post: 07-18-2014, 09:06 AM
  4. Array formula + Array formula with criteria that lookups a Table
    By anrichards22 in forum Excel Programming / VBA / Macros
    Replies: 3
    Last Post: 09-16-2013, 11:41 AM
  5. Replace hard coded array in formula with link to input array
    By David Brown in forum Excel Formulas & Functions
    Replies: 8
    Last Post: 01-08-2011, 07:45 AM
  6. Converting 3x10 array to a 1X30 array to run a Match formula
    By NBVC in forum Excel Formulas & Functions
    Replies: 6
    Last Post: 04-08-2009, 07:45 AM
  7. [SOLVED] Tricky array formula issue - Using array formula on one cell, then autofilling down a range
    By aspenbordr in forum Excel Programming / VBA / Macros
    Replies: 0
    Last Post: 07-27-2005, 11:05 AM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts

Search Engine Friendly URLs by vBSEO 3.6.0 RC 1