Multidimensional Model: Dynamic Arrays

This original multidimensional model is at MDM: TBM. To download the Dynamic Array version, click here. 

This version uses dynamic arrays (DAs) for calculations. It does not use them for inputs or outputs. DAs make our calculations automatically adjust to however many instances we have in any dimension. While that is wonderful, I have some concerns with DAs. I both love and hate DAs. 

I LOVE that DAs expand automatically with NO modeler intervention. This makes models built with them incredibly flexible and scalable while decreasing complexity and potential points of failure.

I HATE that DAs don't have names like tables and structured references. 

Structured References are incredibly important. When dealing with complex models, it is hard to keep track of what belongs to what and what impacts what. Cell references make keeping track of that harder because to get any idea of what a reference is, we must go find it and hope it is labeled. Structured references ARE the reference's label so we NEVER have to find the reference to get its label. Its label is IN the formula and that makes the formula self-documenting. 

Names are almost as good as structured references. But unlike structured references, are we must maintain names and it is possible that the name will not agree with the label sitting next to the cell it refers to. To address that, I created a naming convention to mimic structured references. This seemed natural because as I converted the original model to dynamic arrays, I grouped the various array columns identically to the tables on which they were based. They look like tables, they just aren't tables.

Dynamic Array Naming Convention

Unlike structured references which are automatically created, manually creating dynamic named ranges is a huge pain. I have an add-in that automates it for me which makes my work life much better. I intend to make it available on Eloquens.com in a few months so be sure to check there for it in a month or two. Until then, below is the naming convention I use, and that my add-in uses. The explanation is in parent then child order but the way we must enter them is reversed. We must create child names first (individual DAs) then the parents (DA Collections)

Dynamic Array Collection Prefix 

A dynamic array collection is several related dynamic arrays placed together in such a way as to look like a table with columns. The figure above is the first 12 rows of the final calculations collection. Each column has a heading just like each table column has a heading. I use the prefix "tbl" for tables so I decided to use "da" for dynamic array collections. 

Dynamic Array Collection Names 

If my table's description is one word, like Products my table name will be tblProducts. If the table's description is more than one word, I abbreviate the name so Sector Calculations becomes tblSC. Such abbreviated names a referred to in computer circles as Mnemonics which means we have enough information to remember what it refers to without having to spell it out completely.  Remember, this is for the modeler who is intimately familiar with his or her creation, not the end user. Mnemonics work for tables so they will also work DA collections. When I converted tblSC to a dynamic array collection, I named the dynamic array collection: daSC

The formula for a dynamic array collection will be a dynamic named range formula. This formula assumes the first column is a dynamic array and has been named. That provides the dynamic row count. It also assumes that all headings are entered, there are no more than 99 columns, and that the collection ends at the first blank cell after the heading start in the heading row. In this example, the first column is named daSC.Row

=LET(FirstColumn, daSC.Row,

     Rows,        ROWS(FirstColumn),

     Columns,     MATCH(TRUE, ISBLANK(OFFSET(FirstColumn,-1,0,1,99)),0)-1,

     OFFSET(FirstColumn,,,Rows, Columns))


That's a horrible formula but it is fully dynamic and easily replicated, just change daSC.Row to the first column's name.

Dynamic Array Collection Item Names

If a dynamic array is in a collection, each column is named using the collection's name, a period, and then the column name. Thus, if daSC has a "Product ID" column heading, the dynamic array under that column heading is named daSC.Product_ID

NOTE! Excel's names cannot have spaces so if a column heading has spaces I choose to replace spaces with underlines. Another good approach is to use Camelcase which apply proper case to the name and then removes spaces. Thus "Product ID" becomes ProductId

The formula for dynamic arrays is very simple. It is the first cell in the array with # added. Thus, if aSC.Product_ID is in cell A3 its dynamic named range formula is:

=$A$3#

Dynamic Array Collection Parts

For preliminary calculation collections, this part is totally optional and probably not needed. But when needed, we can easily modify the formula and names to more closely mimic all of a table's structured references, specifically [#Headers] and [#All]. 

[#Headers]

Append .Headers to the dynamic array collection's name. Thus the headers for daSC is daSC.Headers. The formula is:

=OFFSET(daSC,-1,0,1)


[#All]

Append .All to the dynamic array collection's name. Thus the headers and data for daSC is daSC.All. This is needed for Pivots and Power Query which are only built over the final calculations collection. The formula is:

=OFFSET(daSC,-1,0,ROWS(daSC)+1)

With names in place, our formulas look very similar to structured references. Let us compare the MSPR Profit formula from the Excel formula version and this DA version.

Structured Reference from Table =[@[MSPR Sales Amount]] + [@[Total Costs]]

DA Named reference from collection =daProcess.MSPR_Sales_Amount + daProcess.Total_Costs

The most noticeable differences are:

The @ sign in structured references explicitly associates these references to the same row. In DAs, the relationship is implicit. I like explicit. But I also like that because the implicit nature of DAs makes the #SPILL range possible and the #SPILL range eliminates the need to copy the formula down every row in a column like we must with structured references. And that means we have just one formula in one cell to audit and maintain. We have zero chance that formulas in a column are inconsistent. 

Summary

Naming removes my primary objection to DAs. What is left is pure goodness - mostly:

Pros


Set PivotTable Data Source to DA Collection

Cons

let

    Source  = Excel.CurrentWorkbook(){[Name="daProcess.All"]}[Content],

    AddHdrs = Table.PromoteHeaders(Source, [PromoteAllScalars=true])

in

    AddHdrs