- init
This commit is contained in:
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user