Forum Discussion
WrapRows2Dλ / WrapCols2Dλ: Fast, efficient 2D wrapping without flattening
Background
One of Excel's biggest weaknesses is in working with 2D arrays as objects that can be re-shaped.
WRAPROWS/WRAPCOLS do not accept 2D arrays (#VALUE!) and are strictly for shaping 1D arrays. The usual workarounds involve flattening with TOROW/TOCOL then re-shaping with WRAPROWS/WRAPCOLS, REDUCE used an iterator to stack (do-able but slow), and even MAKEARRAY (do-able, but not instinctive and slow).
The Goal
Fast, efficient 2D wrapping without flattening.
The Approach
Pure deferred i/j indexing with modular math and sequencing.
The function and sample workbook is provided below. I welcome any and all feedback: suggestions for improvement, your approach to 2D shaping, etc.
// Fast, efficient 2D wrapping without flattening
//-----------------------------------------------------------------------------------
//---WrapCols2Dλ---
//-----------------------------------------------------------------------------------
//Author: Patrick H.
//Date: 1/28/2026
//Version: 1.0
//
//Description:
//Wrap a 2D array into column blocks of a specified width while preserving row height.
//The wrapped blocks are stacked vertically in the output.
//Jagged or uneven final blocks are padded with NA() by default, unless a fill value
//is supplied via the optional pad_with parameter.
//
//-----------------------------------------------------------------------------------
//Parameter Description
//array - 2D array to be wrapped (1D arrays not supported)
//new_width - Number of columns in each wrapped block
//
//Optional Description
//pad_with - Fill value used to pad incomplete blocks. If omitted, NA() is used.
//
//Lambda called: Echoλ
WrapCols2Dλ=
LAMBDA(
array,
new_width,
[pad_with],
//Check inputs
LET(
//Shape
h, ROWS(array),
w, COLUMNS(array),
blocks, CEILING(w/new_width,1),
//Optional
pad_with, IF(ISOMITTED(pad_with),NA(),pad_with),
//Total rows when wrapped
r, blocks * h,
//Scenarios
Is1D?, OR(h = 1,w = 1),
IsScalar?, AND(h = 1, w = 1),
InvalidDim?,new_width >= w,
SpillRisk?, r > 1048576,
//Logic gate
IF(IsScalar?,#VALUE!,
IF(Is1D?,#VALUE!,
IF(InvalidDim?,"#WIDTH!",
IF(SpillRisk?,#NUM!,
//Proceed
LET(
//Indices - deferred
modulo, LAMBDA(MOD(SEQUENCE(r),h)),
i, LAMBDA(IF(modulo() = 0, h, modulo()) * SEQUENCE(,new_width,1,0)),
j, LAMBDA(Echoλ(SEQUENCE(r / h,,1,new_width),h) + SEQUENCE(,new_width,0,1)),
//Wrapped array
result, IFERROR(INDEX(array,i(),j()),pad_with),
result
)))))));
//-----------------------------------------------------------------------------------
//---WrapRows2Dλ---
//-----------------------------------------------------------------------------------
//Author: Patrick H.
//Date: 1/28/2026
//Version: 1.0
//
//Description:
//Wrap a 2D array into row blocks of a specified height while preserving column width.
//The wrapped blocks are stacked horizontally in the output.
//Jagged or uneven final blocks are padded with NA() by default, unless a fill value
//is supplied via the optional pad_with parameter.
//
//-----------------------------------------------------------------------------------
//Parameter Description
//array - 2D array to be wrapped (1D arrays not supported)
//new_height - Number of rows in each wrapped block
//
//Optional Description
//pad_with - Fill value used to pad incomplete blocks. If omitted, NA() is used.
//
//Lambda called: Echoλ
WrapRows2Dλ=
LAMBDA(
array,
new_height,
[pad_with],
//Check inputs
LET(
//Shape
h, ROWS(array),
w, COLUMNS(array),
blocks, CEILING(h/new_height,1),
//Optional
pad_with, IF(ISOMITTED(pad_with),NA(),pad_with),
//Total columns when unwrapped
c, blocks * w,
//Scenarios
Is1D?, OR(h = 1,w = 1),
IsScalar?, AND(h = 1, w = 1),
InvalidDim?,new_height >= h,
SpillRisk?, c > 16384,
//Logic gate
IF(IsScalar?,#VALUE!,
IF(Is1D?,#VALUE!,
IF(InvalidDim?,"#HEIGHT!",
IF(SpillRisk?,#NUM!,
//Proceed
LET(
//Indices - deferred
i, LAMBDA(TOROW(Echoλ(SEQUENCE(,blocks,1,new_height),w)) + SEQUENCE(new_height,,0,1)),
modulo, LAMBDA(MOD(SEQUENCE(,w * blocks),w)),
j, LAMBDA(IF(modulo()=0,w,modulo()) * SEQUENCE(new_height,,1,0)),
//Wrapped array
result, IFERROR(INDEX(array,i(),j()),pad_with),
result
)))))));
//-----------------------------------------------------------------------------------
//Echoλ
//-----------------------------------------------------------------------------------
//Author: Patrick H.
//Date: 11/7/2025
//Version: 1.0
//Description:
//Repeat each element in a supplied 1D array by specifying the repeat counts.
//Arrays and scalars are supported.
//-----------------------------------------------------------------------------------
//vector - 1D array or scalar to be echoed
//repeat - 1D array of repeat counts (must be numeric and ≥1)
Echoλ =
LAMBDA(
vector,
repeat,
//Check inputs
IF(OR(ISTEXT(repeat),repeat<=0),#VALUE!,
LET(
//Flatten inputs
vector, TOCOL(vector), repeat, TOCOL(repeat),
//Dimensions and row indexing
V↕, ROWS(vector), R↕,ROWS(repeat),
r, IF(V↕<>R↕,EXPAND(repeat,V↕,,@TAKE(repeat,-1)),
repeat),
i, SEQUENCE(ROWS(r)),
m, MAX(r),
idx, LAMBDA(TOCOL(IF(SIGN(r-SEQUENCE(,m,0,))=1,i,NA()),2)),
//Unwrap idx but defer delivery until function invocation
deliver, LAMBDA(INDEX(vector,idx())),
deliver
))());
Workbook attached and linked in case this forum gobbles it up!
Patrick2788/Excel-Lambda: Excel Lambda modules
Excel-Lambda/Wrap2D Demo.xlsx at main · Patrick2788/Excel-Lambda
Excel Lambda modules. Contribute to Patrick2788/Excel-Lambda development by creating an account on GitHub.