excelexcel-formuladynamic-arrays

Excel - Aggregate dynamically values in a Table using array formulas (MAP, BYROW, CHOOSECOLS, TEXTJOIN, LAMBDA, FILTER, HSTACK) in a single Cell


I would like to aggregate, merge, compact some values as shown below

The input is a table and the output is dynamic array formulas on a single Cell and has a goal to aggregate other columns based on unique values of the first column

My input is a Table (named TAB)

Name Service Type
02HPP002NZ 1:Basic unix
02HPP002NZ 1:Basic unix
02HPP002NZ 3: Relevant win
02HPP009O4 3: Relevant nt
02HPP001L7 2: Standard unix
02HPP001L7 2: Standard linux
02HPP009O4 1:Basic nt

Desired output using array formulas on a single cell E2

Name Service Type
02HPP002NZ 1:Basic / 3: Relevant unix / win
02HPP009O4 3: Relevant / 1:Basic nt
02HPP001L7 2: Standard unix / linux

The formula I used is bellow:

=LET(
    Names; TAB[Name];
    uNames; UNIQUE(Names);
    aggfunc; LAMBDA(colIdx; MAP(uNames; LAMBDA(x; BYCOL(CHOOSECOLS(TAB;colIdx); LAMBDA(col;TEXTJOIN(" / "; TRUE; UNIQUE(FILTER(col; Names=x))))))));
    HSTACK(
        uNames;
        aggfunc(2);
        aggfunc(3)
    )
)

As you notice, I hardcode "aggfunc(x)" (x is the number of the column of my table to return). I would like to use a single function aggfunc(numCols) and numCols is an array of the number of columns. And the formula should be like the following but unfortunately it doesn't work. It gives an error "#CALC!"

=LET(
    Names; TAB[Name];
    uNames; UNIQUE(Names);
    numCols; SEQUENCE(COLUMNS(TAB[#Data]));
    aggfunc; LAMBDA(colIdx; MAP(uNames; LAMBDA(x; BYCOL(CHOOSECOLS(TAB;colIdx); LAMBDA(col;TEXTJOIN(" / "; TRUE; UNIQUE(FILTER(col; Names=x))))))));
    HSTACK(
        uNames;
        aggfunc(numCols)
    )
)

An alternative formula that use BYROW instead of MAP

=LET(
     a; TAB[Name];
     b; TAB[Type];
     c; TAB[Service];
     ua; UNIQUE(a);
     HSTACK(
       ua;
       BYROW(ua; LAMBDA(x; TEXTJOIN(" / ";TRUE;UNIQUE(FILTER(b;a=x)))));
       BYROW(ua; LAMBDA(x; TEXTJOIN(" / ";TRUE;UNIQUE(FILTER(c;a=x)))))
     )
 )

I have also tried to use PowerQuery but using group by and then add custom columns but as I have a multiple columns, it is very painful to achieve my goal. If it may be interesting for someone, below the steps:

  1. Select any cell in the table
  2. Select the menu Data then From Table/Range (in the left side)
  3. It opens the PowerQuery Editor, you need now to select the column Name (the first column)
  4. In the menu Transform, select Group By. A new window is open, and I fill the fields as shown bellow
  1. Now you have a table with Two columns with titles Name and AGGNAME (Table)
  2. In the menu Add Column, select Custom Column. A new window is open and I enter the following values
  1. You have now 3 columns "Name", "AGGNAME" and "Type".
  2. You need to repeat the Step 6 and change the name Type (in the formula) according to the name of your column.
  3. Once you have inserted all needed new columns, you have to delete the column AGGNAME
  4. Now go to the menu Home and click on Close & Load. And it will create a new table with the same output as I need.

Using PowerQuery becomes a painful if the names of the input table change or if the Table has multiple columns.

My version of Office 365 does not yet include the function "GROUPBY" (Version 2406 Build 16.0.17726.20206) 64-bit.


Solution

  • One approach could be using MAKEARRAY:

    =LET(uNames,UNIQUE(Table1[Name]),
         MAKEARRAY(ROWS(uNames),COLUMNS(Table1),
            LAMBDA(rw,cl,
                   ARRAYTOTEXT(UNIQUE(FILTER(INDEX(Table1,,cl),Table1[Name]=INDEX(uNames,rw)))))))
    

    PS I used Tables. Change these into TAB for your reference. I'm unable to rename table names using the app version of Excel

    Also if you want the separator to be / change ARRAYTOTEXT to TEXTJOIN.