80 lines
1.9 KiB
TypeScript
80 lines
1.9 KiB
TypeScript
import XLSXModule from "xlsx";
|
|
|
|
const XLSX =
|
|
(
|
|
XLSXModule as typeof import("xlsx") & {
|
|
default?: typeof import("xlsx");
|
|
}
|
|
).default ?? (XLSXModule as typeof import("xlsx"));
|
|
|
|
export type WorksheetCellValue = boolean | Date | number | string | null;
|
|
export type WorksheetMatrix = WorksheetCellValue[][];
|
|
|
|
function normalizeWorksheetCellValue(value: unknown): WorksheetCellValue {
|
|
if (value === undefined || value === null) {
|
|
return null;
|
|
}
|
|
|
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
return value;
|
|
}
|
|
|
|
if (value instanceof Date) {
|
|
return value;
|
|
}
|
|
|
|
return String(value);
|
|
}
|
|
|
|
export async function readWorksheetMatrix(
|
|
workbookPath: string,
|
|
sheetName: string,
|
|
): Promise<WorksheetMatrix> {
|
|
const workbook = XLSX.readFile(workbookPath, {
|
|
cellDates: true,
|
|
dense: true,
|
|
});
|
|
const worksheet = workbook.Sheets[sheetName];
|
|
if (!worksheet) {
|
|
throw new Error(`Worksheet "${sheetName}" not found in workbook "${workbookPath}"`);
|
|
}
|
|
|
|
const rows = XLSX.utils.sheet_to_json<(WorksheetCellValue | null)[]>(worksheet, {
|
|
header: 1,
|
|
raw: true,
|
|
defval: null,
|
|
});
|
|
|
|
return rows.map((row) => row.map((value) => normalizeWorksheetCellValue(value)));
|
|
}
|
|
|
|
export function getCellString(
|
|
rows: WorksheetMatrix,
|
|
rowNumber: number,
|
|
columnNumber: number,
|
|
): string | null {
|
|
const value = rows[rowNumber - 1]?.[columnNumber - 1];
|
|
if (value === null || value === undefined) {
|
|
return null;
|
|
}
|
|
|
|
if (value instanceof Date) {
|
|
return value.toISOString();
|
|
}
|
|
|
|
return String(value);
|
|
}
|
|
|
|
export function toColumnLetter(columnNumber: number): string {
|
|
let current = columnNumber;
|
|
let result = "";
|
|
|
|
while (current > 0) {
|
|
const remainder = (current - 1) % 26;
|
|
result = String.fromCharCode(65 + remainder) + result;
|
|
current = Math.floor((current - 1) / 26);
|
|
}
|
|
|
|
return result;
|
|
}
|