46 lines
1.5 KiB
JavaScript
46 lines
1.5 KiB
JavaScript
/* ObsiGate — XLSX A1 reference helpers (#154-A5).
|
|
*
|
|
* Pure functions (no DOM, no i18n): safe to unit-test in Node and shared by the
|
|
* viewer. Extracted from frontend/js/viewer.js without behaviour change.
|
|
*/
|
|
|
|
/** Parse an A1 reference ("B12") into its 1-based (row, col) parts. */
|
|
export function parseRef(ref) {
|
|
const m = /^([A-Z]+)(\d+)$/.exec(ref || "");
|
|
if (!m) return null;
|
|
let col = 0;
|
|
for (const ch of m[1]) col = col * 26 + (ch.charCodeAt(0) - 64);
|
|
return { row: Number(m[2]), col };
|
|
}
|
|
|
|
/** Column number (1-based) → letters ("A", "Z", "AA"). */
|
|
export function columnName(col) {
|
|
let name = "";
|
|
while (col > 0) {
|
|
const rem = (col - 1) % 26;
|
|
name = String.fromCharCode(65 + rem) + name;
|
|
col = Math.floor((col - 1) / 26);
|
|
}
|
|
return name;
|
|
}
|
|
|
|
/** Find a rendered cell inside a sheet panel by (row, col). */
|
|
export function findTd(panel, row, col) {
|
|
return panel.querySelector(`td[data-cell="${columnName(col)}${row}"]`);
|
|
}
|
|
|
|
/** Sheet prefix of a range ref ("'Mon onglet'!$A$1" → "Mon onglet"), or null. */
|
|
export function sheetOfRef(ref) {
|
|
const s = String(ref || "");
|
|
if (!s.includes("!")) return null;
|
|
return s.split("!")[0].replace(/^'|'$/g, "");
|
|
}
|
|
|
|
/** First cell of a range ref ("Data!$A$1:$B$5" → "A1"), or null. */
|
|
export function firstCellOfRange(ref) {
|
|
const s = String(ref || "");
|
|
const body = s.includes("!") ? s.split("!").pop() : s;
|
|
const m = /([A-Za-z]+)\$?(\d+)/.exec(body);
|
|
return m ? `${m[1].toUpperCase()}${m[2]}` : null;
|
|
}
|