2

I want to abut multiple dynamically sized tables to each other where any one of the tables may be empty.

For example, say I have the following:

enter image description here

where A3 has the following formula:

=LET(
  a, MAKEARRAY(5, A1, LAMBDA(x,y, "hello")),
  b, MAKEARRAY(5, B1, LAMBDA(x,y, "world")),
  c, MAKEARRAY(5, C1, LAMBDA(x,y, "!")),
  final, HSTACK(a,b,c),
  final
)

What I want is to produce the following, if say, B1 is set to 0:

enter image description here

My attempt starts here

If any of A1, B1, or C1 are set to 0, the MAKEARRAY function results in an #VALUE! error instead of elegantly producing a 0x0 array that HSTACK could ignore...

I tried to make up for this by using IFERROR and creating an empty column when a zero was used. Like so:

=LET(
  a, MAKEARRAY(5, A1, LAMBDA(x,y, "hello")),
  b, MAKEARRAY(5, B1, LAMBDA(x,y, "world")),
  c, MAKEARRAY(5, C1, LAMBDA(x,y, "!")),
  err, MAKEARRAY(5, 1, LAMBDA(x,y, "")),
  final, HSTACK(IFERROR(a, err), IFERROR(b, err), IFERROR(c, err)),
  final
)

which produces produces this:

enter image description here

To get rid of the empty column, I tried this using a BYCOL to create a mask and then FILTER:

=LET(
  a, MAKEARRAY(5, A1, LAMBDA(x,y, "hello")),
  b, MAKEARRAY(5, B1, LAMBDA(x,y, "world")),
  c, MAKEARRAY(5, C1, LAMBDA(x,y, "!")),
  err, MAKEARRAY(5, 1, LAMBDA(x,y, "")),
  stack, HSTACK(IFERROR(a, err), IFERROR(b, err), IFERROR(c, err)),
  col_mask, BYCOL(stack, LAMBDA(col, COUNTBLANK(col)<>5)),
  final, FILTER(stack, col_mask)
  final)

which produces #CALC!. I think this is due to the BYCOL(stack,...) function call.

I think Excel can't handle array of arrays because if I split the BYCOL and FILTER into separate cells, this actually works. For example,

enter image description here

where A10 looks like:

=LET(
  col_mask, BYCOL(A3#, LAMBDA(col, COUNTBLANK(col)<>5)),
  final, FILTER(A3#, col_mask),
  final
)

Is it possible to do this in a single cell without VBA?

1
  • Instead of BYCOL(stack, LAMBDA(col, COUNTBLANK(col)<>5)) this use this BYCOL(stack,LAMBDA(α, AND(N(α<>"")))) you need to use AND() and this is similar to use MMULT() as well!! Commented Jul 2 at 19:50

2 Answers 2

1

This is the quick fix to your existing formula:

enter image description here


• Formula used in cell A3

=LET(
     a, MAKEARRAY(5, A1, LAMBDA(x,y, "hello")),
     b, MAKEARRAY(5, B1, LAMBDA(x,y, "world")),
     c, MAKEARRAY(5, C1, LAMBDA(x,y, "!")),
     err, MAKEARRAY(5, 1, LAMBDA(x,y, "")),
     stack, HSTACK(IFERROR(a, err), IFERROR(b, err), IFERROR(c, err)),
     col_mask, BYCOL(stack,LAMBDA(α, AND(N(α<>"")))),
     final, FILTER(stack,col_mask),
     final)

Alternatively, could use the following as well:

=LET(
     ƒx, LAMBDA(α,δ,φ, IFERROR(MAKEARRAY(α, δ, LAMBDA(x,y, φ)),EXPAND("",α,,""))),
     stack, HSTACK(ƒx(5, A1, "Hello"),ƒx(5, B1, "World"),ƒx(5, C1, "!")),
     col_mask, BYCOL(stack, LAMBDA(ε, AND(N(ε<>"")))),
     final, FILTER(stack,col_mask),
     final)

The alternative usage of BYCOL() with MMULT()

MMULT(SEQUENCE(,ROWS(stack)),N(stack<>""))

MAKEARRAY() can be excluded as well:

=LET(
     ƒx, LAMBDA(α,δ,φ, IFERROR(IF(SEQUENCE(α,δ)^0,φ),EXPAND("",α,,""))),
     stack, HSTACK(ƒx(5,A1,"Hellow"),ƒx(5,B1,"World"),ƒx(5,C1,"!")),
     col_max, BYCOL(N(stack<>""),AND),
     final, FILTER(stack,col_max),
     final)
7
  • Can you elaborate on why I needed to use the AND() to collapse the col_mask LAMBDA when used in A3 but not when it was in a different cell (A10)?
    – supernun
    Commented Jul 2 at 20:15
  • 1
    AND() function means here all the columns needs to have a value greater than 1, since we are checking if any of the columns is not equal to blank. using N(stack<>"") Commented Jul 2 at 20:17
  • 1
    @supernun for A10 its different, the BYCOL() finds A10 as a reference range, while when directly used with an BYCOL(stack,LAMBDA( it is pure array. ! This you will understand once you understand the usage of MMULT() ! Commented Jul 2 at 20:19
  • 1
    @supernun i would suggest you to understand the usage of MMULT() function from this post answer Commented Jul 2 at 20:21
  • I simplified my needs down to a single value per table but in a real use-case the LAMBDAs in my original example would be doing something more complicated with the row/column variables passed in. Also each table would be doing different things so your fx definition, while very useful, wouldn't apply to my case.
    – supernun
    Commented Jul 2 at 23:30
1

My proposal is to use a formula like this:

=CHOOSEROWS(CHOOSECOLS($A$1:$C$1,
--TEXTSPLIT(CONCAT(REPT(SEQUENCE(,COLUMNS($A$2:$C$2))&",",
$A$2:$C$2)),",",,TRUE)), SEQUENCE($E$2,,1,0))

Repeat sequence

1
  • I'll take the blame for this for not being clearer in my post. The "hello", "world" and "!" were just stand-ins to make the problem easier to parse. In reality those fields are dynamically generated depending on the row and column of the array (which is why I was using MAKEARRAY). Also, creating three tables (a, b, and c) independently and then HSTACKing them is much easier to parse as a reader. It reads a bit more like a database join operation
    – supernun
    Commented Jul 5 at 20:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .