This commit is contained in:
wkh
2026-08-29 17:47:12 +02:00
commit c7885067e7
53 changed files with 13458 additions and 0 deletions
+69
View File
@@ -0,0 +1,69 @@
/**
* Reference helpers: A1 <-> (col,row) conversion and range expansion.
*
* All coordinates the engine uses internally are 0-based. The A1 notation
* exposed to the user is 1-based for rows and letter-based for columns
* (A=0, B=1, ..., Z=25, AA=26, ...).
*/
const CELL_RE = /^\$?([A-Za-z]{1,3})\$?([0-9]{1,7})$/;
/** "A" -> 0, "B" -> 1, "Z" -> 25, "AA" -> 26 ... */
export function colToNumber(letters: string): number {
let n = 0;
const up = letters.toUpperCase();
for (let i = 0; i < up.length; i++) {
n = n * 26 + (up.charCodeAt(i) - 64); // 'A' -> 1
}
return n - 1;
}
/** 0 -> "A", 25 -> "Z", 26 -> "AA" ... */
export function numberToCol(n: number): string {
let s = '';
let x = n + 1;
while (x > 0) {
const rem = (x - 1) % 26;
s = String.fromCharCode(65 + rem) + s;
x = Math.floor((x - 1) / 26);
}
return s;
}
/** True if `text` looks like a bare cell reference (e.g. "A1", "$B$2", "aa10"). */
export function looksLikeCell(text: string): boolean {
return CELL_RE.test(text);
}
/** Parse "A1" -> { col: 0, row: 0 }. Throws for malformed input. */
export function parseA1(text: string): { col: number; row: number } {
const m = CELL_RE.exec(text);
if (!m) throw new Error(`Bad cell reference: ${text}`);
return { col: colToNumber(m[1]), row: Number(m[2]) - 1 };
}
/** Build "A1" from 0-based coordinates. */
export function toA1(col: number, row: number): string {
return `${numberToCol(col)}${row + 1}`;
}
/**
* Expand a rectangular range (given by two corners, any order) into the list of
* cell coordinates it covers, row-major.
*/
export function expandRange(
a: { col: number; row: number },
b: { col: number; row: number },
): Array<{ col: number; row: number }> {
const c0 = Math.min(a.col, b.col);
const c1 = Math.max(a.col, b.col);
const r0 = Math.min(a.row, b.row);
const r1 = Math.max(a.row, b.row);
const out: Array<{ col: number; row: number }> = [];
for (let r = r0; r <= r1; r++) {
for (let c = c0; c <= c1; c++) {
out.push({ col: c, row: r });
}
}
return out;
}