Skip to content

Instantly share code, notes, and snippets.

@RackofLambda
Last active January 28, 2026 08:45
Show Gist options
  • Select an option

  • Save RackofLambda/8c38a707b1194825069bb8a780600ce4 to your computer and use it in GitHub Desktop.

Select an option

Save RackofLambda/8c38a707b1194825069bb8a780600ce4 to your computer and use it in GitHub Desktop.
A collection of Microsoft Excel LAMBDA functions for scanning tables and arrays.
/* List of LAMBDA functions in this collection:
--------------------------------------------
LISTBY --------->> Groups all values from a table or array by distinct item and returns a jagged array of associated lists.
INSTANCENUM ---->> Returns the running count of distinct items in an unordered table or array.
RUNNINGTOT ----->> Returns the running total of values by distinct item in an unordered table or array.
RUNNINGTOT2 ---->> Returns the running total of values by distinct item in an unordered table or array, with the option to prioritize order by date.
JOINROWS ------->> Creates a key identifier row by combining the values of each row in an array on a column-by-column basis.
JOINCOLS ------->> Creates a key identifier field by combining the values of each column in an array on a row-by-row basis.
SCANBYROW ------>> Scans an array in row-major order by applying a LAMBDA to each value and returns an array of intermediate results for each row.
SCANBYCOL ------>> Scans an array in col-major order by applying a LAMBDA to each value and returns an array of intermediate results for each column.
SCAN3 ---------->> Scans up to 3 input arrays by applying a LAMBDA to each value of each array and returns a single array of intermediate results.
SCAN5 ---------->> Scans up to 5 input arrays by applying a LAMBDA to each value of each array and returns a single array of intermediate results.
REDUCE3 -------->> Reduces up to 3 input arrays to an accumulated value by applying a LAMBDA to each value of each array and returns the total accumulated value.
REDUCE5 -------->> Reduces up to 5 input arrays to an accumulated value by applying a LAMBDA to each value of each array and returns the total accumulated value.
EVALS ---------->> Returns all items from a vector of multi-value elements, or a specified item from an array of multi-value elements.
EVALS_NUM ------>> (recursive) Attempts to auto-detect the number of items contained within a multi-value element.
VALS2 ---------->> Stores up to 2 variables in a single element (TYPE 128), which can be recalled by id number as needed.
VALS3 ---------->> Stores up to 3 variables in a single element (TYPE 128), which can be recalled by id number as needed.
VALS4 ---------->> Stores up to 4 variables in a single element (TYPE 128), which can be recalled by id number as needed.
VALS5 ---------->> Stores up to 5 variables in a single element (TYPE 128), which can be recalled by id number as needed.
LTrimChar ------>> (recursive) Removes leading characters from a text string or array.
RTrimChar ------>> (recursive) Removes trailing characters from a text string or array.
TRIMCHAR ------->> Removes leading and/or trailing characters from a text string or array.
BETWEEN -------->> A helper function for writing dynamic criteria to filter a table or array by values that fall within a specified range.
INCLUDE -------->> A helper function for writing dynamic criteria to filter a table or array by text that equals, begins with, ends with, or contains.
LIKE ----------->> A helper function for writing dynamic criteria to filter a table or range using wildcards and comparison operators.
Nz ------------->> Returns a zero-length string or another specified value when a variant is null (derived from a blank cell in a range).
*/
/* FUNCTION NAME: LISTBY
DESCRIPTION: Groups all values from a table or array by distinct item and returns a jagged array of associated lists.
SYNTAX: =LISTBY(row_fields,values,[sort_order],[rotate])
ARGUMENTS: row_fields (required) - the row identifier field(s) that contain the values to group each list by.
values (required) - the value field (vertical vector) that contains the data to be listed.
[sort_order] (integer, optional) - specifies the sort order (default is unsorted, if omitted).
1 - ascending order
-1 - descending order
[rotate] (Boolean, optional) - transposes the results.
0 or FALSE - lists are returned horizontally in rows (default)
1 or TRUE - lists are returned vertically in columns
SAMPLE 1: X Y Z
a c 1
a d 2
b d 3
a c 4
b c 5
a d 6
a c 7
b d 8
=LISTBY(A2:B9,C2:C9)
a c 1 4 7
a d 2 6
b c 5
b d 3 8
=LISTBY(A2:B9,C2:C9,-1,1)
a a b b
c d c d
7 6 5 8
4 2 3
1
SAMPLE 2: "https://www.youtube.com/watch?v=kBhRyXkqefI&t=225"
=LISTBY(Data[Item],Data[Value],,TRUE)
*/
LISTBY = LAMBDA(row_fields,values,[sort_order],[rotate],
LET(
w, COLUMNS(row_fields),
a, SORT(
HSTACK(row_fields, values),
SEQUENCE(, w + NOT(ISOMITTED(sort_order))),
IF(ISOMITTED(sort_order), sort_order, HSTACK(EXPAND(1,, w, 1), sort_order))
),
b, GROUPBY(TAKE(a,, w), TAKE(a,, -1), ROWS, 0, 0),
k, TAKE(b,, -1),
j, SEQUENCE(, MAX(k)),
i, DROP(VSTACK(0, SCAN(, k, SUM)), -1),
x, HSTACK(DROP(b,, -1), IF(k >= j, INDEX(a, i + j, COLUMNS(a)), "")),
IF(rotate, TRANSPOSE(x), x)
)
);
/* FUNCTION NAME: INSTANCENUM
DESCRIPTION: Returns the running count of distinct items in an unordered table or array.
SYNTAX: =INSTANCENUM(key_fields,[horizontal],[last_to_first])
ARGUMENTS: key_fields (required) - the identifier column(s) or row(s) to be scanned.
[horizontal] (Boolean, optional) - specifies the orientation of the table.
0 or FALSE - vertical (default)
1 or TRUE - horizontal
[last_to_first] (Boolean, optional) - specifies the scan order.
0 or FALSE - first-to-last: scans from top-to-bottom or left-to-right (default)
1 or TRUE - last-to-first: scans from bottom-to-top or right-to-left
SAMPLE 1: X Y Z =INSTANCENUM(A2:A9) =INSTANCENUM(A2:A9,,TRUE)
a c 1 1 5
a d 2 2 4
b d 3 1 3
a c 4 3 3
b c 5 2 2
a d 6 4 2
a c 7 5 1
b d 8 3 1
=DROP(PIVOTBY(A2:B9,INSTANCENUM(A2:B9),C2:C9,SINGLE,0,0,,0),1)
a c 1 4 7
a d 2 6
b c 5
b d 3 8
=DROP(PIVOTBY(INSTANCENUM(A2:B9,,1),A2:B9,C2:C9,SINGLE,0,0,,0),,1)
a a b b
c d c d
7 6 5 8
4 2 3
1
SAMPLE 2: X a a a b a b a a
Y c d c c c d c d
=INSTANCENUM(B1:I2,TRUE)
1 1 2 1 3 1 4 2
=INSTANCENUM(B1:I2,1,1)
4 2 3 1 2 1 1 1
*/
INSTANCENUM = LAMBDA(key_fields,[horizontal],[last_to_first],
IF(
horizontal,
LET(
vec, IF(ROWS(key_fields) = 1, key_fields, BYCOL(key_fields, LAMBDA(x, TEXTJOIN("|", 0, x)))),
arr, VSTACK(vec, SEQUENCE(, COLUMNS(vec))),
srt, IF(last_to_first, SORT(arr, {1,2}, {1,-1}, 1), SORT(arr,,, 1)),
key, TAKE(srt, 1),
SORTBY(SCAN(0, key = DROP(HSTACK("", key),, -1), LAMBDA(a,v, 1 + a * v)), DROP(srt, 1))
),
LET(
vec, IF(COLUMNS(key_fields) = 1, key_fields, BYROW(key_fields, LAMBDA(x, TEXTJOIN("|", 0, x)))),
arr, HSTACK(vec, SEQUENCE(ROWS(vec))),
srt, IF(last_to_first, SORT(arr, {1,2}, {1,-1}), SORT(arr)),
key, TAKE(srt,, 1),
SORTBY(SCAN(0, key = DROP(VSTACK("", key), -1), LAMBDA(a,v, 1 + a * v)), DROP(srt,, 1))
)
)
);
/* FUNCTION NAME: RUNNINGTOT
DESCRIPTION: Returns the running total of values by distinct item in an unordered table or array.
SYNTAX: =RUNNINGTOT(key_fields,values,[horizontal],[last_to_first])
ARGUMENTS: key_fields (required) - the identifier column(s) or row(s) to be scanned.
values (required) - the value field to be totalled.
[horizontal] (Boolean, optional) - specifies the orientation of the table.
0 or FALSE - vertical (default)
1 or TRUE - horizontal
[last_to_first] (Boolean, optional) - specifies the scan order.
0 or FALSE - first-to-last: scans from top-to-bottom or left-to-right (default)
1 or TRUE - last-to-first: scans from bottom-to-top or right-to-left
SAMPLE 1: X Y Z =RUNNINGTOT(A2:B9,C2:C9) =RUNNINGTOT(A2:B9,C2:C9,,TRUE)
a c 8 8 24
a d 3 3 4
a c 5 13 16
b c 2 2 2
a c 4 17 11
b d 6 6 6
a c 7 24 7
a d 1 4 1
SAMPLE 2: X a a a b a b a a
Y c d c c c d c d
Z 8 3 5 2 4 6 7 1
=RUNNINGTOT(B1:I2,B3:I3,TRUE)
8 3 13 2 17 6 24 4
=RUNNINGTOT(B1:I2,B3:I3,1,1)
24 4 16 2 11 6 7 1
*/
RUNNINGTOT = LAMBDA(key_fields,values,[horizontal],[last_to_first],
IF(
horizontal,
LET(
vec, IF(ROWS(key_fields) = 1, key_fields, BYCOL(key_fields, LAMBDA(x, TEXTJOIN("|", 0, x)))),
arr, VSTACK(vec, values, SEQUENCE(, COLUMNS(vec))),
srt, IF(last_to_first, SORT(arr, {1,3}, {1,-1}, 1), SORT(arr,,, 1)),
key, TAKE(srt, 1),
vλl, MAP(key = DROP(HSTACK("", key),, -1), CHOOSEROWS(srt, 2), LAMBDA(b,v, LAMBDA(a, v + a * b))),
SORTBY(SCAN(0, vλl, LAMBDA(a,λ, λ(a))), TAKE(srt, -1))
),
LET(
vec, IF(COLUMNS(key_fields) = 1, key_fields, BYROW(key_fields, LAMBDA(x, TEXTJOIN("|", 0, x)))),
arr, HSTACK(vec, values, SEQUENCE(ROWS(vec))),
srt, IF(last_to_first, SORT(arr, {1,3}, {1,-1}), SORT(arr)),
key, TAKE(srt,, 1),
vλl, MAP(key = DROP(VSTACK("", key), -1), CHOOSECOLS(srt, 2), LAMBDA(b,v, LAMBDA(a, v + a * b))),
SORTBY(SCAN(0, vλl, LAMBDA(a,λ, λ(a))), TAKE(srt,, -1))
)
)
);
/* FUNCTION NAME: RUNNINGTOT2
DESCRIPTION: Returns the running total of values by distinct item in an unordered table or array, with the option to prioritize order by date.
SYNTAX: =RUNNINGTOT2(key_fields,values,[date_field],[horizontal],[last_to_first])
ARGUMENTS: key_fields (required) - the identifier column(s) or row(s) to be scanned.
values (required) - the value field to be totalled.
[date_field] (optional) - the field to sort by (ascending order; not affected by [last-to-first]).
[horizontal] (Boolean, optional) - specifies the orientation of the table.
0 or FALSE - vertical (default)
1 or TRUE - horizontal
[last_to_first] (Boolean, optional) - specifies the scan order.
0 or FALSE - first-to-last: scans from top-to-bottom or left-to-right (default)
1 or TRUE - last-to-first: scans from bottom-to-top or right-to-left
EXAMPLES: *Same as RUNNINGTOT shown above, but with the option to sort by date first.*
*/
RUNNINGTOT2 = LAMBDA(key_fields,values,[date_field],[horizontal],[last_to_first],
IF(
horizontal,
LET(
vec, IF(ROWS(key_fields) = 1, key_fields, BYCOL(key_fields, LAMBDA(x, TEXTJOIN("|", 0, x)))),
cId, SEQUENCE(, COLUMNS(vec)),
arr, VSTACK(vec, values, cId),
srt, IF(
ISOMITTED(date_field),
IF(last_to_first, SORT(arr, {1,3}, {1,-1}, 1), SORT(arr,,, 1)),
IF(last_to_first, SORTBY(arr, vec, 1, date_field, 1, cId, -1), SORTBY(arr, vec, 1, date_field, 1))
),
key, TAKE(srt, 1),
vλl, MAP(key = DROP(HSTACK("", key),, -1), CHOOSEROWS(srt, 2), LAMBDA(b,v, LAMBDA(a, v + a * b))),
SORTBY(SCAN(0, vλl, LAMBDA(a,λ, λ(a))), TAKE(srt, -1))
),
LET(
vec, IF(COLUMNS(key_fields) = 1, key_fields, BYROW(key_fields, LAMBDA(x, TEXTJOIN("|", 0, x)))),
rId, SEQUENCE(ROWS(vec)),
arr, HSTACK(vec, values, rId),
srt, IF(
ISOMITTED(date_field),
IF(last_to_first, SORT(arr, {1,3}, {1,-1}), SORT(arr)),
IF(last_to_first, SORTBY(arr, vec, 1, date_field, 1, rId, -1), SORTBY(arr, vec, 1, date_field, 1))
),
key, TAKE(srt,, 1),
vλl, MAP(key = DROP(VSTACK("", key), -1), CHOOSECOLS(srt, 2), LAMBDA(b,v, LAMBDA(a, v + a * b))),
SORTBY(SCAN(0, vλl, LAMBDA(a,λ, λ(a))), TAKE(srt,, -1))
)
)
);
/* FUNCTION NAME: JOINROWS
DESCRIPTION: Creates a key identifier row by combining the values of each row in an array on a column-by-column basis.
SYNTAX: =JOINROWS(array,[delimiter])
ARGUMENTS: array (required) - the row(s) to be joined.
[delimiter] (optional) - the character(s) inserted between each value (default is "|").
EXAMPLES: =JOINROWS(A2:H4)
=JOINROWS(A2:H4,", ")
=INDEX(return_arr,SEQUENCE(ROWS(return_arr)),XMATCH(JOINROWS(lookup_vals),JOINROWS(lookup_arr)))
*/
JOINROWS = LAMBDA(array,[delimiter],
IF(
ROWS(array) = 1,
array,
LET(
k, IF(ISOMITTED(delimiter), "|", delimiter),
BYCOL(array, LAMBDA(x, TEXTJOIN(k, 0, x)))
)
)
);
/* FUNCTION NAME: JOINCOLS
DESCRIPTION: Creates a key identifier field by combining the values of each column in an array on a row-by-row basis.
SYNTAX: =JOINCOLS(array,[delimiter])
ARGUMENTS: array (required) - the column(s) to be joined.
[delimiter] (optional) - the character(s) inserted between each value (default is "|").
EXAMPLES: =JOINCOLS(A2:C9,", ")
=JOINCOLS(Table1[[Region]:[Department]])
=INDEX(return_arr,XMATCH(JOINCOLS(lookup_vals),JOINCOLS(lookup_arr)),SEQUENCE(,COLUMNS(return_arr)))
*/
JOINCOLS = LAMBDA(array,[delimiter],
IF(
COLUMNS(array) = 1,
array,
LET(
k, IF(ISOMITTED(delimiter), "|", delimiter),
BYROW(array, LAMBDA(r, TEXTJOIN(k, 0, r)))
)
)
);
/* FUNCTION NAME: SCANBYROW
DESCRIPTION: Scans an array in row-major order by applying a LAMBDA to each value and returns an array of intermediate results for each row.
SYNTAX: =SCANBYROW(initial_value,array,function)
ARGUMENTS: initial_value (semi-required) - the starting value for the accumulator (referenced in the first iteration of each row).
array (required) - the array to be scanned.
function (required) - a custom LAMBDA function with 2 parameters (accumulator, current_value) or an eta-reduced LAMBDA.
REMARKS: Maintains the same high-level of efficiency with both range and array objects.
EXAMPLES: =SCANBYROW(,A2:H100,LAMBDA(a,v,IF(v="",a,v)))
=SCANBYROW("",A2:H100,LAMBDA(a,v,IF(v="",a,v)))
=SCANBYROW(,SEQUENCE(10,4),SUM)
=SCANBYROW(0,SEQUENCE(50000,10),SUM)
=SCANBYROW(10,TRANSPOSE(SEQUENCE(4,10)),LAMBDA(a,v,a+2*v))
=SCANBYROW(,CHAR(SEQUENCE(5,5,65)),CONCAT)
=SCANBYROW("",CHAR(SEQUENCE(5,5,65)),LAMBDA(a,v,TEXTJOIN("|",,a,v)))
SAMPLE 1: "https://techcommunity.microsoft.com/discussions/excelgeneral/accumulating-arrays/3045626"
=DROP(SCANBYROW(,HSTACK(initial,array),SUM),,1)
=DROP(SCANBYROW(,HSTACK(invested,1+growth),PRODUCT),,1)
SAMPLE 2: "https://techcommunity.microsoft.com/discussions/ExcelGeneral/using-scan-function-with-oddly-shaped-arrays/4384192"
=DROP(SCANBYROW(,HSTACK(B5:B7,1+D5:F7),PRODUCT),,1)*ISNUMBER(D5:F7)
=IF(ISBLANK(C11:G13),"",DROP(SCANBYROW(,HSTACK(B11:B13,1+C11:G13),PRODUCT),,1))
*/
SCANBYROW = LAMBDA(initial_value,array,function,
LET(
rs, CHAR(30),
DROP(
SCAN(
initial_value,
EXPAND(array,, COLUMNS(array) + 1, rs),
LAMBDA(a,v, IF(IFERROR(v = rs, 0), initial_value, IF(ISOMITTED(a), v, function(a, v))))
),,
-1
)
)
);
/* FUNCTION NAME: SCANBYCOL
DESCRIPTION: Scans an array in col-major order by applying a LAMBDA to each value and returns an array of intermediate results for each column.
SYNTAX: =SCANBYCOL(initial_value,array,function)
ARGUMENTS: initial_value (semi-required) - the starting value for the accumulator (referenced in the first iteration of each column).
array (required) - the array to be scanned.
function (required) - a custom LAMBDA function with 2 parameters (accumulator, current_value) or an eta-reduced LAMBDA.
REMARKS: Maintains the same high-level of efficiency with both range and array objects.
EXAMPLES: =SCANBYCOL(,A2:H100,LAMBDA(a,v,IF(v="",a,v)))
=SCANBYCOL("",A2:H100,LAMBDA(a,v,IF(v="",a,v)))
=SCANBYCOL(,SEQUENCE(4,10),SUM)
=SCANBYCOL(0,SEQUENCE(50,10000),SUM)
=SCANBYCOL(10,TRANSPOSE(SEQUENCE(10,4)),LAMBDA(a,v,a+2*v))
=SCANBYCOL(,CHAR(TRANSPOSE(SEQUENCE(5,5,65))),CONCAT)
=SCANBYCOL("",CHAR(TRANSPOSE(SEQUENCE(5,5,65))),LAMBDA(a,v,TEXTJOIN("|",,a,v)))
SAMPLE 1: "https://www.mrexcel.com/board/threads/running-totals-in-2d-dynamic-array.1267671/"
=SCANBYCOL(0,TOROW(Table12[Possible Numbers])=Table11[Numbers],SUM)
SAMPLE 2: "https://techcommunity.microsoft.com/discussions/excelgeneral/fill-blanks-down-up-or-both-in-columns---similar-to-power-query/3993011"
=LET(
init, BYCOL(Table2, LAMBDA(col, IFERROR(TAKE(TRIMRANGE(col, 1), 1), ""))),
DROP(SCANBYCOL(, VSTACK(init, Table2), LAMBDA(a,v, IF(v = "", a, v))), 1)
)
*/
SCANBYCOL = LAMBDA(initial_value,array,function,
LET(
rs, CHAR(30),
DROP(
TRANSPOSE(
SCAN(
initial_value,
TRANSPOSE(EXPAND(array, ROWS(array) + 1,, rs)),
LAMBDA(a,v, IF(IFERROR(v = rs, 0), initial_value, IF(ISOMITTED(a), v, function(a, v))))
)
),
-1
)
)
);
// ALTERNATIVE DEFINITION (requires SCANBYROW):
SCANBYCOL = LAMBDA(initial_value,array,function,
TRANSPOSE(
SCANBYROW(initial_value, TRANSPOSE(array), function)
)
);
/* FUNCTION NAME: SCAN3
DESCRIPTION: Scans up to 3 input arrays by applying a LAMBDA to each value of each array and returns a single array of intermediate results.
PREREQUISITES: VALS2, VALS3
SYNTAX: =SCAN3(initial_value,array,function_or_array2,[function_or_array3],[function])
ARGUMENTS: initial_value (required) - the starting value for the accumulator (referenced in the first iteration).
array (required) - the first array to be scanned.
function_or_array2, [function_or_array3] - a LAMBDA with a parameter for the accumulator plus one for each array specified, or another array to be scanned.
[function] (optional) - a custom LAMBDA function with 4 parameters, to be used only when all 3 arrays have been specified.
REMARKS: [1] When multiple arrays have been specified, initial_value CANNOT be omitted. Use "", 0, or another appropriate value to initialize the procedure.
If initial_value is omitted, the first iteration of SCAN will ignore the function argument altogether and return the first value in the array,
which will be an uncalled LAMBDA function (TYPE 128) after VALS2 or VALS3 has been applied, causing the first iteration to return #CALC!.
[2] initial_value, array and function_or_array2 are required; all subsequent arguments are optional.
[3] If only 1 array is specified, the LAMBDA function should be entered in the function_or_array2 argument.
[4] If only 2 arrays are specified, the LAMBDA function should be entered in the [function_or_array3] argument.
[5] Maintains the same high-level of efficiency with both range and array objects.
EXAMPLES: =SCAN3(0,WEEKDAY(Table1[Date],2)<>1,IF(Table1[Stat?],0,Table1[Hours]),LAMBDA(acc,add,hrs,acc*add+hrs))
=SCAN3("",B2:M6,EXPAND(EXPAND(1,ROWS(B2:M6),,1),,COLUMNS(B2:M6),0),LAMBDA(a,v,b,IF(v="",IF(b,"",a),v)))
=TRANSPOSE(SCAN3("",TRANSPOSE(Table2),EXPAND(EXPAND(1,COLUMNS(Table2),,1),,ROWS(Table2),0),LAMBDA(a,v,b,IF(v="",IF(b,"",a),v))))
SAMPLE 1: "https://stackoverflow.com/questions/79228362/restarting-and-resuming-a-running-total-for-multiple-values"
=SCAN3(0,Table2[Price],Table2[Brand]=DROP(Table2[[#All],[Brand]],-1),LAMBDA(a,v,b,v+a*b))
SAMPLE 2: "https://www.excelforum.com/excel-formulas-and-functions/1436539-looping-like-scan-but-multiple-in-and-outputs.html"
=MAP(
SCAN3(
VALS3(, 170, -8.75),
{10;8;8;7;10;13;15;0;0;0;15},
{20;19;19;18;17;19;20;22;23;21;20},
LAMBDA(a,in,ex,
LET(
q, a(2) + a(3) + in,
t, q / 500 * 25 + 15,
v, (t - ex) * -2.5,
VALS3(t, q, v)
)
)
),
LAMBDA(a, a(1))
)
*/
SCAN3 = LAMBDA(initial_value,array,function_or_array2,[function_or_array3],[function],
LET(
num, 3 - ISOMITTED(function_or_array3) - ISOMITTED(function),
fnλ, CHOOSE(num, function_or_array2, function_or_array3, function),
CHOOSE(
num,
SCAN(initial_value, array, fnλ),
SCAN(initial_value, MAP(array, function_or_array2, VALS2),
LAMBDA(acc,val, fnλ(acc, val(1), val(2)))),
SCAN(initial_value, MAP(array, function_or_array2, function_or_array3, VALS3),
LAMBDA(acc,val, fnλ(acc, val(1), val(2), val(3))))
)
)
);
/* FUNCTION NAME: SCAN5
DESCRIPTION: Scans up to 5 input arrays by applying a LAMBDA to each value of each array and returns a single array of intermediate results.
PREREQUISITES: VALS2, VALS3, VALS4, VALS5
SYNTAX: =SCAN5(initial_value,array,function_or_array2,[function_or_array3],[function_or_array4],[function_or_array5],[function])
ARGUMENTS: initial_value (required) - the starting value for the accumulator (referenced in the first iteration).
array (required) - the first array to be scanned.
function_or_array2, [function_or_array3], ... - a LAMBDA with a parameter for the accumulator plus one for each array specified, or another array to be scanned.
[function] (optional) - a custom LAMBDA function with 6 parameters, to be used only when all 5 arrays have been specified.
REMARKS: [1] When multiple arrays have been specified, initial_value CANNOT be omitted. Use "", 0, or another appropriate value to initialize the procedure.
If initial_value is omitted, the first iteration of SCAN will ignore the function argument altogether and return the first value in the array,
which will be an uncalled LAMBDA function (TYPE 128) after VALS2, VALS3, etc. has been applied, causing the first iteration to return #CALC!.
[2] initial_value, array and function_or_array2 are required; all subsequent arguments are optional.
[3] If only 1 array is specified, the LAMBDA function should be entered in the function_or_array2 argument.
[4] If only 2 arrays are specified, the LAMBDA function should be entered in the [function_or_array3] argument.
[5] If only 3 arrays are specified, the LAMBDA function should be entered in the [function_or_array4] argument.
[6] If only 4 arrays are specified, the LAMBDA function should be entered in the [function_or_array5] argument.
[7] Maintains the same high-level of efficiency with both range and array objects.
EXAMPLES: *Same as SCAN3 shown above, but with 2 extra arguments for additional input arrays.*
*/
SCAN5 = LAMBDA(initial_value,array,function_or_array2,[function_or_array3],[function_or_array4],[function_or_array5],[function],
LET(
num, 5 - ISOMITTED(function_or_array3) - ISOMITTED(function_or_array4) - ISOMITTED(function_or_array5) - ISOMITTED(function),
fnλ, CHOOSE(num, function_or_array2, function_or_array3, function_or_array4, function_or_array5, function),
CHOOSE(
num,
SCAN(initial_value, array, fnλ),
SCAN(initial_value, MAP(array, function_or_array2, VALS2),
LAMBDA(acc,val, fnλ(acc, val(1), val(2)))),
SCAN(initial_value, MAP(array, function_or_array2, function_or_array3, VALS3),
LAMBDA(acc,val, fnλ(acc, val(1), val(2), val(3)))),
SCAN(initial_value, MAP(array, function_or_array2, function_or_array3, function_or_array4, VALS4),
LAMBDA(acc,val, fnλ(acc, val(1), val(2), val(3), val(4)))),
SCAN(initial_value, MAP(array, function_or_array2, function_or_array3, function_or_array4, function_or_array5, VALS5),
LAMBDA(acc,val, fnλ(acc, val(1), val(2), val(3), val(4), val(5))))
)
)
);
/* FUNCTION NAME: REDUCE3
DESCRIPTION: Reduces up to 3 input arrays to an accumulated value by applying a LAMBDA to each value of each array and returns the total accumulated value.
PREREQUISITES: VALS2, VALS3
SYNTAX: =REDUCE3(initial_value,array,function_or_array2,[function_or_array3],[function])
ARGUMENTS: initial_value (required) - the starting value for the accumulator (referenced in the first iteration).
array (required) - the first array to be reduced.
function_or_array2, [function_or_array3] - a LAMBDA with a parameter for the accumulator plus one for each array specified, or another array to be reduced.
[function] (optional) - a custom LAMBDA function with 4 parameters, to be used only when all 3 arrays have been specified.
REMARKS: [1] When multiple arrays have been specified, initial_value should NOT be omitted. Use "", 0, or another appropriate value to initialize the procedure.
If initial_value is omitted, the first iteration of REDUCE will ignore the function argument altogether and return the first value in the array,
which will be an uncalled LAMBDA function (TYPE 128) after VALS2 or VALS3 has been applied, causing the first iteration to return #CALC!.
[2] initial_value, array and function_or_array2 are required; all subsequent arguments are optional.
[3] If only 1 array is specified, the LAMBDA function should be entered in the function_or_array2 argument.
[4] If only 2 arrays are specified, the LAMBDA function should be entered in the [function_or_array3] argument.
[5] Maintains the same high-level of efficiency with both range and array objects.
SAMPLE 1: "https://www.reddit.com/r/excel/comments/1m1t4ml/can_you_convert_a_recursive_formula_from_using_a/"
=REDUCE3(
"My leetspeak Admin Password",
{"A","a","e","i","o","u","l","S","s","y"},
{4,"@",3,"!",0,2,1,5,"\$",7},
LAMBDA(acc,pat,rep, REGEXREPLACE(acc, pat, rep))
)
*/
REDUCE3 = LAMBDA(initial_value,array,function_or_array2,[function_or_array3],[function],
LET(
num, 3 - ISOMITTED(function_or_array3) - ISOMITTED(function),
fnλ, CHOOSE(num, function_or_array2, function_or_array3, function),
CHOOSE(
num,
REDUCE(initial_value, array, fnλ),
REDUCE(initial_value, MAP(array, function_or_array2, VALS2),
LAMBDA(acc,val, fnλ(acc, val(1), val(2)))),
REDUCE(initial_value, MAP(array, function_or_array2, function_or_array3, VALS3),
LAMBDA(acc,val, fnλ(acc, val(1), val(2), val(3))))
)
)
);
/* FUNCTION NAME: REDUCE5
DESCRIPTION: Reduces up to 5 input arrays to an accumulated value by applying a LAMBDA to each value of each array and returns the total accumulated value.
PREREQUISITES: VALS2, VALS3, VALS4, VALS5
SYNTAX: =REDUCE5(initial_value,array,function_or_array2,[function_or_array3],[function_or_array4],[function_or_array5],[function])
ARGUMENTS: initial_value (required) - the starting value for the accumulator (referenced in the first iteration).
array (required) - the first array to be reduced.
function_or_array2, [function_or_array3], ... - a LAMBDA with a parameter for the accumulator plus one for each array specified, or another array to be reduced.
[function] (optional) - a custom LAMBDA function with 6 parameters, to be used only when all 5 arrays have been specified.
REMARKS: [1] When multiple arrays have been specified, initial_value should NOT be omitted. Use "", 0, or another appropriate value to initialize the procedure.
If initial_value is omitted, the first iteration of REDUCE will ignore the function argument altogether and return the first value in the array,
which will be an uncalled LAMBDA function (TYPE 128) after VALS2, VALS3, etc. has been applied, causing the first iteration to return #CALC!.
[2] initial_value, array and function_or_array2 are required; all subsequent arguments are optional.
[3] If only 1 array is specified, the LAMBDA function should be entered in the function_or_array2 argument.
[4] If only 2 arrays are specified, the LAMBDA function should be entered in the [function_or_array3] argument.
[5] If only 3 arrays are specified, the LAMBDA function should be entered in the [function_or_array4] argument.
[6] If only 4 arrays are specified, the LAMBDA function should be entered in the [function_or_array5] argument.
[7] Maintains the same high-level of efficiency with both range and array objects.
EXAMPLES: *Same as REDUCE3 shown above, but with 2 extra arguments for additional input arrays.*
*/
REDUCE5 = LAMBDA(initial_value,array,function_or_array2,[function_or_array3],[function_or_array4],[function_or_array5],[function],
LET(
num, 5 - ISOMITTED(function_or_array3) - ISOMITTED(function_or_array4) - ISOMITTED(function_or_array5) - ISOMITTED(function),
fnλ, CHOOSE(num, function_or_array2, function_or_array3, function_or_array4, function_or_array5, function),
CHOOSE(
num,
REDUCE(initial_value, array, fnλ),
REDUCE(initial_value, MAP(array, function_or_array2, VALS2),
LAMBDA(acc,val, fnλ(acc, val(1), val(2)))),
REDUCE(initial_value, MAP(array, function_or_array2, function_or_array3, VALS3),
LAMBDA(acc,val, fnλ(acc, val(1), val(2), val(3)))),
REDUCE(initial_value, MAP(array, function_or_array2, function_or_array3, function_or_array4, VALS4),
LAMBDA(acc,val, fnλ(acc, val(1), val(2), val(3), val(4)))),
REDUCE(initial_value, MAP(array, function_or_array2, function_or_array3, function_or_array4, function_or_array5, VALS5),
LAMBDA(acc,val, fnλ(acc, val(1), val(2), val(3), val(4), val(5))))
)
)
);
/* FUNCTION NAME: EVALS
DESCRIPTION: Returns all items from a vector of multi-value elements, or a specified item from an array of multi-value elements.
PREREQUISITES: EVALS_NUM
SYNTAX: =EVALS(vals_vector,[num],[exclusive])
ARGUMENTS: vals_vector (required) - the vector or array of multi-value elements to be evaluated (derived using VALS2, VALS3, etc.).
[num] (optional) - the total number of items or the exclusive id number of the item to be extracted from each element (auto-detect, if omitted).
[exclusive] (Boolean, optional) - specifies which items are to be extracted from each element.
0 or FALSE - all items from 1 to the specified [num] (default)
1 or TRUE - the specified id [num] only
SAMPLE 1: "https://www.excelforum.com/excel-formulas-and-functions/1436539-looping-like-scan-but-multiple-in-and-outputs.html"
=EVALS(
SCAN3(
VALS3(, 170, -8.75),
{10;8;8;7;10;13;15;0;0;0;15},
{20;19;19;18;17;19;20;22;23;21;20},
LAMBDA(a,in,ex,
LET(
q, a(2) + a(3) + in,
t, q / 500 * 25 + 15,
v, (t - ex) * -2.5,
VALS3(t, q, v)
)
)
)
)
SAMPLE 2: "https://www.mrexcel.com/board/threads/create-variable-interest-rate-amortization-schedule-using-dynamic-arrays.1269465/"
=LET(
yrs, 2,
ppy, 12,
amt, 50000,
dur, ppy * yrs,
tbl, {1,0.03125;7,0.0475;23,0.0375},
VALS7, LAMBDA([_1],[_2],[_3],[_4],[_5],[_6],[_7],LAMBDA(x,CHOOSE(x,_1,_2,_3,_4,_5,_6,_7))),
VSTACK(
{"Period","Beg Bal","Rate","Payment","Interest","Principal","End Bal"},
EVALS(
SCAN(
VALS7(,,,,,, amt),
SEQUENCE(dur),
LAMBDA(a,v,
LET(
beg, a(7),
apr, VLOOKUP(v, tbl, 2, 1),
ppr, apr / ppy,
pmt, -PMT(ppr, dur - v + 1, beg),
int, beg * ppr,
ppl, pmt - int,
end, beg - ppl,
VALS7(v, beg, apr, pmt, int, ppl, end)
)
)
)
)
)
)
*/
EVALS = LAMBDA(vals_vector,[num],[exclusive],
LET(
num, IF(ISOMITTED(num), EVALS_NUM(@vals_vector), num),
IF(
exclusive,
MAP(vals_vector, LAMBDA(val, val(num))),
LET(
k, IF(COLUMNS(vals_vector) = 1, SEQUENCE(, num), SEQUENCE(num)),
MAP(IFNA(vals_vector, k), IFNA(k, vals_vector), LAMBDA(val, x, val(x)))
)
)
)
);
/* FUNCTION NAME: EVALS_NUM
DESCRIPTION: (recursive) Attempts to auto-detect the number of items contained within a multi-value element.
SYNTAX: =EVALS_NUM(val,[k])
ARGUMENTS: val (required) - the multi-value element to be evaluated (derived using VALS2, VALS3, etc.).
[k] (integer, internal use only) - the id number of the current iteration.
REMARKS: May return incorrect results if an item contains a #VALUE! error.
EXAMPLES: *Not applicable (for internal use with the EVALS function shown above).*
*/
EVALS_NUM = LAMBDA(val,[k],
LET(
k, IF(ISOMITTED(k), 3, k + 1),
IF(IFNA(ERROR.TYPE(@+val(k)), 0) = 3, k - 1, EVALS_NUM(val, k))
)
);
/* FUNCTION NAME: VALS2
DESCRIPTION: Stores up to 2 variables in a single element (TYPE 128), which can be recalled by id number as needed.
SYNTAX: =VALS2([value1],[value2])
ARGUMENTS: [value1], [value2] - the value, cell, range or array to be stored for later use; both arguments are optional.
EXAMPLES: =LET(
lbl, VALS2(Table1[Dept.], Table1[[#Headers],[Jan]:[Mar]]),
HSTACK(TOCOL(lbl({1})), TOCOL(lbl({2})), TOCOL(Table1[[Jan]:[Mar]]))
)
SAMPLE 1: "https://www.reddit.com/r/excel/comments/1m1t4ml/can_you_convert_a_recursive_formula_from_using_a/"
=REDUCE(
"My leetspeak Admin Password",
MAP({"A","a","e","i","o","u","l","S","s","y"}, {4,"@",3,"!",0,2,1,5,"\$",7}, VALS2),
LAMBDA(acc,val, REGEXREPLACE(acc, val(1), val(2)))
)
SAMPLE 2: "https://techcommunity.microsoft.com/discussions/excelgeneral/formula-to-count-the-number-of-cells-including-the-one-which-repeats-itself/4137759"
=MAP(
SCAN(VALS2(), A2:A200, LAMBDA(λ,v, LET(a, LAMBDA(x, IF(ISOMITTED(x), v, x))(λ(1)),
IF(AND(COUNTIF(a:v, v) = 2, v <> ""), VALS2(, COUNT(a:v)), VALS2(a, ""))))),
LAMBDA(λ, λ(2))
)
*/
VALS2 = LAMBDA([value1],[value2],
LAMBDA(x, CHOOSE(x, value1, value2))
);
/* FUNCTION NAME: VALS3
DESCRIPTION: Stores up to 3 variables in a single element (TYPE 128), which can be recalled by id number as needed.
SYNTAX: =VALS3([value1],[value2],[value3])
ARGUMENTS: [value1], [value2], ... - the value, cell, range or array to be stored for later use; all arguments are optional.
EXAMPLES: *Same as VALS2 shown above, but with 1 extra argument for an additional variable.*
*/
VALS3 = LAMBDA([value1],[value2],[value3],
LAMBDA(x, CHOOSE(x, value1, value2, value3))
);
/* FUNCTION NAME: VALS4
DESCRIPTION: Stores up to 4 variables in a single element (TYPE 128), which can be recalled by id number as needed.
SYNTAX: =VALS4([value1],[value2],[value3],[value4])
ARGUMENTS: [value1], [value2], ... - the value, cell, range or array to be stored for later use; all arguments are optional.
EXAMPLES: *Same as VALS2 shown above, but with 2 extra arguments for additional variables.*
*/
VALS4 = LAMBDA([value1],[value2],[value3],[value4],
LAMBDA(x, CHOOSE(x, value1, value2, value3, value4))
);
/* FUNCTION NAME: VALS5
DESCRIPTION: Stores up to 5 variables in a single element (TYPE 128), which can be recalled by id number as needed.
SYNTAX: =VALS5([value1],[value2],[value3],[value4],[value5])
ARGUMENTS: [value1], [value2], ... - the value, cell, range or array to be stored for later use; all arguments are optional.
EXAMPLES: *Same as VALS2 shown above, but with 3 extra arguments for additional variables.*
*/
VALS5 = LAMBDA([value1],[value2],[value3],[value4],[value5],
LAMBDA(x, CHOOSE(x, value1, value2, value3, value4, value5))
);
/* FUNCTION NAME: LTrimChar
DESCRIPTION: (recursive) Removes leading characters from a text string or array.
SYNTAX: =LTrimChar(text,char,[case_sensitive])
ARGUMENTS: text (required) - the value or array to be cleaned.
char (required) - the character(s) to be trimmed.
[case_sensitive] (Boolean, optional) - specifies case-sensitivity.
0 or FALSE - not case-sensitive (default)
1 or TRUE - case-sensitive
EXAMPLES: =LTrimChar(A2:A10,"0")
=LTrimChar(A2:A10,0,TRUE)
=LTrimChar(A2:A10,"CON")
=LTrimChar(A2:A10,"CON",1)
*/
LTrimChar = LAMBDA(text,char,[case_sensitive],
LET(
arr, LEFT(text, LEN(char)),
opt, NOT(case_sensitive),
tst, IF(opt, arr = char, EXACT(arr, char)),
IF(OR(tst), LTrimChar(IF(tst, TEXTAFTER(text, char,, opt), text), char, case_sensitive), text)
)
);
/* FUNCTION NAME: RTrimChar
DESCRIPTION: (recursive) Removes trailing characters from a text string or array.
SYNTAX: =RTrimChar(text,char,[case_sensitive])
ARGUMENTS: text (required) - the value or array to be cleaned.
char (required) - the character(s) to be trimmed.
[case_sensitive] (Boolean, optional) - specifies case-sensitivity.
0 or FALSE - not case-sensitive (default)
1 or TRUE - case-sensitive
EXAMPLES: =RTrimChar(A2:A10,"0")
=RTrimChar(A2:A10,0,TRUE)
=RTrimChar(A2:A10,"x")
=RTrimChar(A2:A10,"x",1)
*/
RTrimChar = LAMBDA(text,char,[case_sensitive],
LET(
arr, RIGHT(text, LEN(char)),
opt, NOT(case_sensitive),
tst, IF(opt, arr = char, EXACT(arr, char)),
IF(OR(tst), RTrimChar(IF(tst, TEXTBEFORE(text, char, -1, opt), text), char, case_sensitive), text)
)
);
/* FUNCTION NAME: TRIMCHAR
DESCRIPTION: Removes leading and/or trailing characters from a text string or array.
PREREQUISITES: LTrimChar, RTrimChar
SYNTAX: =TRIMCHAR(text,[char],[trim_mode],[case_sensitive])
ARGUMENTS: text (required) - the value or array to be cleaned.
[char] (optional) - the character(s) to be trimmed (default is "0").
[trim_mode] (integer, optional) - determines which characters should be trimmed.
0 - None
1 - Leading
2 - Trailing
3 - Both (default)
[case_sensitive] (Boolean, optional) - specifies case-sensitivity.
0 or FALSE - not case-sensitive (default)
1 or TRUE - case-sensitive
EXAMPLES: =TRIMCHAR(A2:A10)
=TRIMCHAR(A2:A10,,1)
=TRIMCHAR(A2:A10,"x",2)
=TRIMCHAR(A2:A10,{"CB","0"},1)
=TRIMCHAR(A2:A10,{0,"x"},2,TRUE)
=MAP(A2:A10,TRIMCHAR)
*/
TRIMCHAR = LAMBDA(text,[char],[trim_mode],[case_sensitive],
REDUCE(
text,
IF(ISOMITTED(char), "0", char),
LAMBDA(txt,chr,
CHOOSE(
IF(ISOMITTED(trim_mode), 3, trim_mode) + 1,
txt,
LTrimChar(txt, chr, case_sensitive),
RTrimChar(txt, chr, case_sensitive),
RTrimChar(LTrimChar(txt, chr, case_sensitive), chr, case_sensitive)
)
)
)
);
/* FUNCTION NAME: BETWEEN
DESCRIPTION: A helper function for writing dynamic criteria to filter a table or array by values that fall within a specified range.
SYNTAX: =BETWEEN(field,[value1],[value2],[incl_mode])
ARGUMENTS: field (required) - the column to filter by.
[value1] (optional) - sets the lower bound of the range (ignored if omitted).
[value2] (optional) - sets the upper bound of the range (ignored if omitted).
[incl_mode] (integer, optional) - specifies whether the range is inclusive of value1 and/or value2.
0 - greater than value1 and less than value2
1 - greater than or equal to value1 and less than value2
2 - greater than value1 and less than or equal to value2
3 - greater than or equal to value1 and less than or equal to value2 (default)
EXAMPLES: =FILTER(Table1,BETWEEN(Table1[Year],2022))
=FILTER(Table1,BETWEEN(Table1[Year],,2018))
=FILTER(Table1,BETWEEN(Table1[Year],2020,2024))
=FILTER(Table1,BETWEEN(Table1[Price],10000.01,24999.99))
=FILTER(Table1,BETWEEN(Table1[Price],10000,25000,0))
=FILTER(Table1,BETWEEN(Table1[Price],10000,24999.99))
=FILTER(Table1,BETWEEN(Table1[Price],10000,25000,1))
=FILTER(Table1,BETWEEN(Table1[Price],10000.01,25000))
=FILTER(Table1,BETWEEN(Table1[Price],10000,25000,2))
*/
BETWEEN = LAMBDA(field,[value1],[value2],[incl_mode],
LET(
i, IF(ISOMITTED(incl_mode), 3, incl_mode),
CHOOSE(
1 + ISBLANK(value1) + ISBLANK(value2) * 2,
CHOOSE(
1 + i,
(field > value1) * (field < value2),
(field >= value1) * (field < value2),
(field > value1) * (field <= value2),
(field >= value1) * (field <= value2)
),
IF(i > 1, field <= value2, field < value2),
IF(MOD(i, 2), field >= value1, field > value1),
EXPAND(1, ROWS(field),, 1)
)
)
);
/* FUNCTION NAME: INCLUDE
DESCRIPTION: A helper function for writing dynamic criteria to filter a table or array by text that equals, begins with, ends with, or contains.
SYNTAX: =INCLUDE(field,criteria,[incl_mode],[case_sensitive])
ARGUMENTS: field (required) - the column to filter by.
criteria (required) - the condition(s) to filter by; accepts multiple conditions to "filter by list".
[incl_mode] (integer, optional) - specifies the type of filter to be applied.
0 - Equals... (default)
1 - Begins with...
2 - Ends with...
3 - Contains...
[case_sensitive] (Boolean, optional) - specifies case-sensitivity.
0 or FALSE - not case-sensitive (default)
1 or TRUE - case-sensitive
EXAMPLES: =FILTER(Table1,INCLUDE(Table1[Type],"used"))
=FILTER(Table1,INCLUDE(Table1[Year],{2025,2026}))
=FILTER(Table1,INCLUDE(Table1[Stock No.],"U",1,TRUE))
=FILTER(Table1,INCLUDE(Table1[Make],{"GM","chev"},1))
=FILTER(Table1,INCLUDE(Table1[VIN],{"208233"},2))
=FILTER(Table1,INCLUDE(Table1[VIN],{208233,208236},2,1))
=FILTER(Table1,INCLUDE(Table1[Exterior Color],"blue",3))
=FILTER(Table1,INCLUDE(Table1[Model],{"Sierra","Silver"},3,1))
*/
INCLUDE = LAMBDA(field,criteria,[incl_mode],[case_sensitive],
IF(
AND(ISBLANK(criteria)),
EXPAND(1, ROWS(field),, 1),
LET(
arr, SORT(TOROW(criteria, 1),,, 1),
opt, 1 + (COLUMNS(arr) = 1) + AND(case_sensitive) * 2,
CHOOSE(
incl_mode + 1,
CHOOSE(
opt,
ISNUMBER(XMATCH(field, arr,, 2)),
field = arr,
BYROW(EXACT(field, arr), OR),
EXACT(field, arr)
),
CHOOSE(
opt,
BYROW(LEFT(field, LEN(arr)) = arr, OR),
LEFT(field, LEN(arr)) = arr,
BYROW(EXACT(LEFT(field, LEN(arr)), arr), OR),
EXACT(LEFT(field, LEN(arr)), arr)
),
CHOOSE(
opt,
BYROW(RIGHT(field, LEN(arr)) = arr, OR),
RIGHT(field, LEN(arr)) = arr,
BYROW(EXACT(RIGHT(field, LEN(arr)), arr), OR),
EXACT(RIGHT(field, LEN(arr)), arr)
),
CHOOSE(
opt,
BYROW(ISNUMBER(SEARCH(arr, field)), OR),
ISNUMBER(SEARCH(arr, field)),
BYROW(ISNUMBER(FIND(arr, field)), OR),
ISNUMBER(FIND(arr, field))
)
)
)
)
);
/* FUNCTION NAME: LIKE
DESCRIPTION: A helper function for writing dynamic criteria to filter a table or range using wildcards and comparison operators.
SYNTAX: =LIKE(range,criteria,[and_or])
ARGUMENTS: range (required) - the table column(s) to filter by; accepts multiple columns; must be a range reference.
criteria (required) - the condition(s) to filter by; accepts multiple conditions, wildcards and comparison operators.
[and_or] (TYPE:=128, optional) - an eta-reduced LAMBDA that specifies the logic used when multiple conditions are present.
OR - returns TRUE if at least one condition is met (default)
XOR - returns TRUE if only one condition is met
AND - returns TRUE if all conditions are met
EXAMPLES: =FILTER(Table1,LIKE(Table1[Year],">2022"))
=FILTER(Table1,LIKE(Table1[Year],"<=2018"))
=FILTER(Table1,LIKE(Table1[Year],{">=2020","<=2024"},AND))
=FILTER(Table1,LIKE(Table1[Type],"used"))
=FILTER(Table1,LIKE(Table1[Year],{"2025","2026"}))
=FILTER(Table1,LIKE(Table1[Stock No.],"U*"))
=FILTER(Table1,LIKE(Table1[Make],{"GM*","chev*"}))
=FILTER(Table1,LIKE(Table1[Stock No.],"*A"))
=FILTER(Table1,LIKE(Table1[VIN],"*20823?"))
=FILTER(Table1,LIKE(Table1[Exterior Color],"*blue*"))
=FILTER(Table1,LIKE(Table1[Model],{"*sierra*","*silver*"}))
=FILTER(Table1,LIKE(Table1[Model],"silver*hd"))
=FILTER(Table1,LIKE(Table1[[Model]:[Exterior Color]],{"sierra*","*blue*"},AND))
*/
LIKE = LAMBDA(range,criteria,[and_or],
LET(
fnλ, IF(
TYPE(criteria) = 64,
LET(
and_or, IF(ISOMITTED(and_or), OR, and_or),
LAMBDA(rng, and_or(COUNTIF(rng, criteria)))
),
LAMBDA(rng, COUNTIF(rng, criteria))
),
BYROW(range, fnλ)
)
);
/* FUNCTION NAME: Nz
DESCRIPTION: Returns a zero-length string or another specified value when a variant is null (derived from a blank cell in a range).
SYNTAX: =Nz(range,[value_if_blank])
ARGUMENTS: range (required) - the range to be evaluated.
[value_if_blank] (optional) - the value to be returned if a cell within the range is blank (default is "").
EXAMPLES: =LTrimChar(Nz(A2:A100),"x")
=Nz(TRIMCHAR(A2:A100,"x",2,1))
=FILTER(Table1,LIKE(Table1[Make],TEXTSPLIT(Nz(B4,"<>λ")," ")))
=FILTER(Table1,LIKE(Table1[Year],{">=";"<="}&Nz(B1:B2,{0;9999}),AND))
*/
Nz = LAMBDA(range,[value_if_blank],
IF(
ISBLANK(range),
IF(ISOMITTED(value_if_blank), "", value_if_blank),
range
)
);
@RackofLambda
Copy link
Author

@harun24hr I'm glad you liked them. Thanks again for all of your feedback and support!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment