Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions lambdas/maps/ADDRESSES.lambda
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* FUNCTION NAME: ADDRESSES
DESCRIPTION:*//**Returns the A1-style addresses of cells in a range as text, shape-matching the input range.*/
/* REVISIONS: Date Developer Description
2026-05-20 Claude Initial version
*/
ADDRESSES = LAMBDA(
// Parameter Declarations
[cells],
// Help
LET(Help, TEXTSPLIT(
"FUNCTION: →ADDRESSES(cells)¶" &
"DESCRIPTION: →Returns the A1-style addresses of cells in a range as text, shape-matching the input range.¶" &
"VERSION: →May 20 2026¶" &
"PARAMETERS: →¶" &
" cells →(Required) A cell or range reference. Output shape matches the input shape. Addresses are returned in relative form (no $ anchors), matching CELLTOPOS / MOVECELL / POSTOCELL conventions.¶" &
"EXAMPLE: →¶" &
"Formula →=ADDRESSES(F28:H30)¶" &
"Result →3x3 grid of ""F28"" through ""H30""",
"→", "¶"
),
// Check inputs
Help?, ISOMITTED(cells),
// Procedure
result, ADDRESS(ROW(cells), COLUMN(cells), 4),
IF(Help?, Help, result)
)
);
39 changes: 39 additions & 0 deletions lambdas/maps/ADDRESSES.tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
tests:
- name: single cell F28
setup:
names:
- { name: "testRng", refers_to: "F28" }
args: ["=testRng"]
expected: "F28"

- name: 3x3 grid F28:H30
setup:
names:
- { name: "testRng", refers_to: "F28:H30" }
args: ["=testRng"]
expected: [["F28", "G28", "H28"], ["F29", "G29", "H29"], ["F30", "G30", "H30"]]

- name: column B5:B10
setup:
names:
- { name: "testRng", refers_to: "B5:B10" }
args: ["=testRng"]
expected: [["B5"], ["B6"], ["B7"], ["B8"], ["B9"], ["B10"]]

- name: row B5:D5
setup:
names:
- { name: "testRng", refers_to: "B5:D5" }
args: ["=testRng"]
expected: [["B5", "C5", "D5"]]

- name: multi-letter column AA1
setup:
names:
- { name: "testRng", refers_to: "AA1" }
args: ["=testRng"]
expected: "AA1"

- name: help text
args: []
expected_type: array
42 changes: 42 additions & 0 deletions lambdas/maps/CELLDIST.lambda
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* FUNCTION NAME: CELLDIST
DESCRIPTION:*//**Returns the grid distance between two A1-style cell addresses (Manhattan, Chebyshev, or Euclidean).*/
/* REVISIONS: Date Developer Description
2026-05-20 Claude Initial version
*/
CELLDIST = LAMBDA(
// Parameter Declarations
[cell1],
[cell2],
[metric],
// Help
LET(Help, TEXTSPLIT(
"FUNCTION: →CELLDIST(cell1, cell2, [metric])¶" &
"DESCRIPTION: →Returns the grid distance between two A1-style cell addresses (Manhattan, Chebyshev, or Euclidean).¶" &
"VERSION: →May 20 2026¶" &
"PARAMETERS: →¶" &
" cell1 →(Required) First cell address as text (e.g. ""F28""). Also accepts an array of addresses.¶" &
" cell2 →(Required) Second cell address as text (e.g. ""G26""). Also accepts an array of addresses. When both are arrays, Excel broadcasts naturally: same-shape inputs pair element-wise, column × row produces a 2D distance grid.¶" &
" metric →(Optional) Distance metric: 0 Manhattan (default, 4-directional), 1 Chebyshev (8-directional, diagonals count as 1), 2 Euclidean (straight-line).¶" &
"EXAMPLE: →¶" &
"Formula →=CELLDIST(""F28"", ""G26"")¶" &
"Result →3",
"→", "¶"
),
// Check inputs
Help?, ISOMITTED(cell1),
// Procedure
safeMult, 16385,
met, IF(ISOMITTED(metric), 0, metric),
posA, CELLTOPOS(cell1, safeMult),
posB, CELLTOPOS(cell2, safeMult),
rowA, INT(posA / safeMult),
rowB, INT(posB / safeMult),
colA, MOD(posA, safeMult),
colB, MOD(posB, safeMult),
dR, ABS(rowA - rowB),
dC, ABS(colA - colB),
result, IF(met = 2, SQRT((rowA - rowB)^2 + (colA - colB)^2),
IF(met = 1, IF(dR > dC, dR, dC), dR + dC)),
IF(Help?, Help, result)
)
);
90 changes: 90 additions & 0 deletions lambdas/maps/CELLDIST.tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
tests:
- name: Manhattan F28 to G26 (default)
args: ["F28", "G26"]
expected: 3

- name: Manhattan AH27 to S34
args: ["AH27", "S34"]
expected: 22

- name: Manhattan AL33 to N15
args: ["AL33", "N15"]
expected: 42

- name: Manhattan X15 to Z4
args: ["X15", "Z4"]
expected: 13

- name: Manhattan AC36 to AS42
args: ["AC36", "AS42"]
expected: 22

- name: Manhattan AS7 to U16
args: ["AS7", "U16"]
expected: 33

- name: same cell is zero
args: ["E5", "E5"]
expected: 0

- name: Chebyshev X15 to Z4 (metric 1)
args: ["X15", "Z4", "=1"]
expected: 11

- name: Chebyshev diagonal F5 to H7
args: ["F5", "H7", "=1"]
expected: 2

- name: Chebyshev pure horizontal A1 to E1
args: ["A1", "E1", "=1"]
expected: 4

- name: Euclidean A1 to A4 (metric 2)
args: ["A1", "A4", "=2"]
expected: 3

- name: Euclidean A1 to B2 (metric 2)
args: ["A1", "B2", "=2"]
expected: 1.4142135623730951

- name: Euclidean A1 to D5 (3-4-5 triangle)
args: ["A1", "D5", "=2"]
expected: 5

- name: handles absolute references
args: ["$F$28", "$G$26"]
expected: 3

- name: handles sheet prefix
args: ["Sheet1!F28", "Sheet1!G26"]
expected: 3

- name: cell containing address string
setup:
cells:
- address: "C3"
values: "F28"
- address: "C4"
values: "G26"
args: ["=C3", "=C4"]
expected: 3

- name: vertical array zip same-shape
args: ['={"F28";"AH27";"X15"}', '={"G26";"S34";"Z4"}']
expected: [[3], [22], [13]]

- name: horizontal array zip same-shape
args: ['={"F28","X15"}', '={"G26","Z4"}']
expected: [[3, 13]]

- name: cartesian column x row broadcast
args: ['={"A1";"B2"}', '={"C3","D4"}']
expected: [[4, 6], [2, 4]]

- name: cartesian column x row Chebyshev
args: ['={"A1";"B2"}', '={"C3","D4"}', "=1"]
expected: [[2, 3], [1, 2]]

- name: help text
args: []
expected_type: array
28 changes: 28 additions & 0 deletions lambdas/maps/COLNUM.lambda
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* FUNCTION NAME: COLNUM
DESCRIPTION:*//**Returns the column number of an A1-style cell address passed as text. Like COLUMN() but accepts strings.*/
/* REVISIONS: Date Developer Description
2026-05-20 Claude Initial version
*/
COLNUM = LAMBDA(
// Parameter Declarations
[address],
// Help
LET(Help, TEXTSPLIT(
"FUNCTION: →COLNUM(address)¶" &
"DESCRIPTION: →Returns the column number of an A1-style cell address passed as text. Like COLUMN() but accepts strings. Handles multi-letter columns (AA, BZ, XFD).¶" &
"VERSION: →May 20 2026¶" &
"PARAMETERS: →¶" &
" address →(Required) A1 address text (e.g. ""AA17""), or an array/range of such. Sheet prefixes, $ anchors, and ranges are tolerated (first cell used). Result lifts element-wise.¶" &
"EXAMPLE: →¶" &
"Formula →=COLNUM(""AA17"")¶" &
"Result →27",
"→", "¶"
),
// Check inputs
Help?, ISOMITTED(address),
// Procedure
safeMult, 100000,
result, MOD(CELLTOPOS(address, safeMult), safeMult),
IF(Help?, Help, result)
)
);
52 changes: 52 additions & 0 deletions lambdas/maps/COLNUM.tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
tests:
- name: simple address A1
args: ["A1"]
expected: 1

- name: multi-letter column AA1
args: ["AA1"]
expected: 27

- name: column Z
args: ["Z1"]
expected: 26

- name: max column XFD
args: ["XFD1"]
expected: 16384

- name: column AB
args: ["AB12"]
expected: 28

- name: absolute reference dollars stripped
args: ["$E$5"]
expected: 5

- name: sheet-prefixed address
args: ["Sheet1!AA17"]
expected: 27

- name: lowercase address
args: ["aa17"]
expected: 27

- name: cell containing address string
setup:
cells:
- address: "C3"
values: "AA17"
args: ["=C3"]
expected: 27

- name: vertical array of addresses lifts
args: ['={"A1";"Z1";"AA1"}']
expected: [[1], [26], [27]]

- name: horizontal array of addresses lifts
args: ['={"A1","Z1","AA1"}']
expected: [[1, 26, 27]]

- name: help text
args: []
expected_type: array
30 changes: 30 additions & 0 deletions lambdas/maps/COLOF.lambda
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* FUNCTION NAME: COLOF
DESCRIPTION:*//**Extracts the column number from an encoded position integer (as produced by CELLTOPOS).*/
/* REVISIONS: Date Developer Description
2026-05-20 Claude Initial version
*/
COLOF = LAMBDA(
// Parameter Declarations
[pos],
[mult],
// Help
LET(Help, TEXTSPLIT(
"FUNCTION: →COLOF(pos, [mult])¶" &
"DESCRIPTION: →Extracts the column number from an encoded position integer (as produced by CELLTOPOS).¶" &
"VERSION: →May 20 2026¶" &
"PARAMETERS: →¶" &
" pos →(Required) Encoded position (row*mult+col). Also accepts an array/range of positions — result lifts element-wise.¶" &
" mult →(Optional) Multiplier used during encoding. Default: 100000 (matches CELLTOPOS). Must match the mult used to encode pos.¶" &
"EXAMPLE: →¶" &
"Formula →=COLOF(1700017)¶" &
"Result →17",
"→", "¶"
),
// Check inputs
Help?, ISOMITTED(pos),
// Procedure
m, IF(ISOMITTED(mult), 100000, mult),
result, MOD(pos, m),
IF(Help?, Help, result)
)
);
40 changes: 40 additions & 0 deletions lambdas/maps/COLOF.tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
tests:
- name: simple position Q17
args: ["=1700017"]
expected: 17

- name: column 5 from position E5
args: ["=500005"]
expected: 5

- name: top-left A1
args: ["=100001"]
expected: 1

- name: multi-letter column AB
args: ['=CELLTOPOS("AB12")']
expected: 28

- name: composed with CELLTOPOS XFD
args: ['=CELLTOPOS("XFD16384")']
expected: 16384

- name: custom mult 50
args: ["=526", "=50"]
expected: 26

- name: custom mult matches CELLTOPOS custom mult
args: ['=CELLTOPOS("Z10", 50)', "=50"]
expected: 26

- name: vertical array of positions lifts
args: ['={100001;500005;1700017}']
expected: [[1], [5], [17]]

- name: horizontal array of positions lifts
args: ['={100001,500005,1700017}']
expected: [[1, 5, 17]]

- name: help text
args: []
expected_type: array
28 changes: 28 additions & 0 deletions lambdas/maps/ROWNUM.lambda
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* FUNCTION NAME: ROWNUM
DESCRIPTION:*//**Returns the row number of an A1-style cell address passed as text. Like ROW() but accepts strings.*/
/* REVISIONS: Date Developer Description
2026-05-20 Claude Initial version
*/
ROWNUM = LAMBDA(
// Parameter Declarations
[address],
// Help
LET(Help, TEXTSPLIT(
"FUNCTION: →ROWNUM(address)¶" &
"DESCRIPTION: →Returns the row number of an A1-style cell address passed as text. Like ROW() but accepts strings.¶" &
"VERSION: →May 20 2026¶" &
"PARAMETERS: →¶" &
" address →(Required) A1 address text (e.g. ""Q17""), or an array/range of such. Sheet prefixes, $ anchors, and ranges are tolerated (first cell used). Result lifts element-wise.¶" &
"EXAMPLE: →¶" &
"Formula →=ROWNUM(""Q17"")¶" &
"Result →17",
"→", "¶"
),
// Check inputs
Help?, ISOMITTED(address),
// Procedure
safeMult, 100000,
result, INT(CELLTOPOS(address, safeMult) / safeMult),
IF(Help?, Help, result)
)
);
Loading
Loading