I have a report that vertically stacks yearly data made of two columns:
A year is made of 4 rows corresponding to 4 quarters. As the reports vertically stacks data every year, 4 new rows are added every new year.
I would like to horizontally stack each 3 sets (2022, 2023 and 2024) of 4 rows with adjacent column #2 data. The result is a table of 4 rows and 3*2=6 columns.
Start table in cell A1:
| YEAR & QUARTER | $ AMOUNT |
|---|---|
| 2022 Q1 | 1000 |
| 2022 Q2 | 2000 |
| 2022 Q3 | 3000 |
| 2022 Q4 | 4000 |
| 2023 Q1 | 500 |
| 2023 Q2 | 1000 |
| 2023 Q3 | 800 |
| 2023 Q4 | 1500 |
| 2024 Q1 | 1500 |
| 2024 Q2 | 2000 |
| 2024 Q3 | 3000 |
| 2024 Q4 | 4500 |
Desired output:
| 2023 | $ AMOUNT | 2024 | $ AMOUNT | 2025 | $ AMOUNT |
|---|---|---|---|---|---|
| 2022 Q1 | 1000 | 2023 Q1 | 500 | 2024 Q1 | 1500 |
| 2022 Q2 | 2000 | 2023 Q2 | 1000 | 2024 Q2 | 2000 |
| 2022 Q3 | 3000 | 2023 Q3 | 800 | 2024 Q3 | 3000 |
| 2022 Q4 | 4000 | 2023 Q4 | 1500 | 2024 Q4 | 4500 |
I do not need to generate the header row. I thought it would be simple:
=wraprows(tocol(A2:B13);8)
I still cannot make it:
=wrapcols(torow(wrapcols(torow(A2:B13);2));4)
I would join the two columns and wrap the result but how do I split later on?
=let(
list1;byrow(A1:B12;lambda(x;join("|";x)));
wrapcols(list1;4)
)
One way is to use Makearray. You move down four rows in the input each time you move across to the next pair of columns in the output, and for odd columns of the output take input from the left-hand column, or for even columns of the output take input from the right-hand column.
=makearray(4,6,lambda(r,c,index(A1:B12,r+4*quotient(c-1,2),iseven(c)+1)))
| Input | Output | |||||||
|---|---|---|---|---|---|---|---|---|
| A1 | 11 | A1 | 11 | B1 | 21 | C1 | 31 | |
| A2 | 12 | A2 | 12 | B2 | 22 | C2 | 32 | |
| A3 | 13 | A3 | 13 | B3 | 23 | C3 | 33 | |
| A4 | 14 | A4 | 14 | B4 | 24 | C4 | 34 | |
| B1 | 21 | |||||||
| B2 | 22 | |||||||
| B3 | 23 | |||||||
| B4 | 24 | |||||||
| C1 | 31 | |||||||
| C2 | 32 | |||||||
| C3 | 33 | |||||||
| C4 | 34 |
A more general form of the formula where you could adjust rows and columns would be (for three columns of input and nine columns of output)
=makearray(4,9,lambda(r,c,index(A15:C26,r+4*quotient(c-1,3),mod(c-1,3)+1)))
If you wanted to make the formula even more general, but assuming for now that the data divides exactly by the required number of columns , you could try this:
=let(range,A2:B13,inCols,columns(range),inRows,rows(range),reps,3,outRows,inRows/reps,outCols,inCols*reps,makearray(outRows,outCols,lambda(r,c,index(range,r+inRows/reps*quotient(c-1,inCols),mod(c-1,inCols)+1))))
Or for the case where the data doesn't divide exactly into the required number of columns,
=let(range,A2:B12,inCols,columns(range),inRows,rows(range),reps,3,outRows,roundup(inRows/reps),outCols,inCols*reps,iferror(makearray(outRows,outCols,lambda(r,c,index(range,r+outRows*quotient(c-1,inCols),mod(c-1,inCols)+1)))))
Maybe this is nearer to OP's requirement, where the number of rows of output is fixed (four quarters per column) and the number of columns is adjusted to match the number of rows of data provided.
=let(range,A2:B13,inCols,columns(range),inRows,rows(range),outRows,4,outCols,roundup(inRows/outRows)*inCols,iferror(makearray(outRows,outCols,lambda(r,c,index(range,r+outRows*quotient(c-1,inCols),mod(c-1,inCols)+1)))))