Files
lead/frontend/src/lib/components/grid/utils.ts
2025-09-05 23:23:26 +10:00

74 lines
1.7 KiB
TypeScript

export type CellValue = number | string | undefined;
export interface CellData {
raw_val: string;
val: CellValue;
}
export interface CellRef {
row: number;
col: number;
str: string;
}
/**
* Zero indexed | A1 == {row: 0, col: 0};
*/
export function refFromStr(ref: string): CellRef {
const match = ref.match(/^([A-Z]+)([0-9]+)$/i);
if (!match) throw new Error('Invalid reference');
const [, letters, rowStr] = match;
let col = 0;
for (let i = 0; i < letters.length; i++) {
col = col * 26 + (letters.charCodeAt(i) - 64); // 'A' = 65 → 1
}
const row = parseInt(rowStr, 10);
return { row: row - 1, col: col - 1, str: ref };
}
/**
* Zero indexed | 0 == A;
*/
export function colToStr(col: number): string {
let result = '';
let n = col;
while (n >= 0) {
const rem = n % 26;
result = String.fromCharCode(65 + rem) + result; // 65 = 'A'
n = Math.floor(n / 26) - 1;
}
return result;
}
/**
* Zero indexed | A1 == {row: 0, col: 0};
*/
export function refFromPos(row: number, col: number): CellRef {
return { row, col, str: colToStr(col) + (row + 1).toString() };
}
export function splitErrorString(errorString: string) {
// Remove the "ERR " prefix.
const content = errorString.substring(4);
// Find the index of the first colon.
const colonIndex = content.indexOf(':');
// If no colon is found, return the whole content as the first element.
if (colonIndex === -1) {
return [content.trim(), ''];
}
// Extract the part before the colon (the error type).
const errorType = content.substring(0, colonIndex).trim();
// Extract the part after the colon (the error message).
const errorMessage = content.substring(colonIndex + 1).trim();
return [errorType, errorMessage];
}