36 lines
1.2 KiB
TypeScript
36 lines
1.2 KiB
TypeScript
export type ExcelValue = string | number | boolean | Date | null | undefined;
|
|
|
|
export type ExcelExportOptions = {
|
|
fileName: string;
|
|
sheetName: string;
|
|
headers: string[];
|
|
rows: ExcelValue[][];
|
|
};
|
|
|
|
function safeFileName(value: string): string {
|
|
return value.replace(/[\\/:*?"<>|]/g, "_").replace(/\.xlsx$/i, "");
|
|
}
|
|
|
|
function safeSheetName(value: string): string {
|
|
return value.replace(/[\\/*?:\[\]]/g, "_").slice(0, 31) || "Sheet1";
|
|
}
|
|
|
|
export async function exportRowsToExcel({ fileName, sheetName, headers, rows }: ExcelExportOptions): Promise<void> {
|
|
const { default: writeExcelFile } = await import("write-excel-file/browser");
|
|
const headerRow = headers.map((value) => ({
|
|
value,
|
|
fontWeight: "bold" as const,
|
|
backgroundColor: "#EDF6FF",
|
|
align: "center" as const,
|
|
}));
|
|
const columns = headers.map((header, index) => {
|
|
const maxLength = Math.max(header.length * 2, ...rows.map((row) => String(row[index] ?? "").length));
|
|
return { width: Math.min(42, Math.max(12, maxLength + 3)) };
|
|
});
|
|
await writeExcelFile([headerRow, ...rows], {
|
|
sheet: safeSheetName(sheetName),
|
|
stickyRowsCount: 1,
|
|
columns,
|
|
}).toFile(`${safeFileName(fileName)}.xlsx`);
|
|
}
|