refactor(insights): share workbook export and ai defaults
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
createWorkbookArrayBuffer,
|
||||
createWorkbookArrayBufferFromSheets,
|
||||
} from "./workbook-export.js";
|
||||
|
||||
describe("workbook export helpers", () => {
|
||||
it("writes a single-sheet workbook with primitive values", async () => {
|
||||
const buffer = await createWorkbookArrayBuffer("Skills", [
|
||||
["Skill", "Count", "Active"],
|
||||
["TypeScript", 4, true],
|
||||
["Planning", 2, false],
|
||||
]);
|
||||
|
||||
const ExcelJS = await import("exceljs");
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
await workbook.xlsx.load(Buffer.from(buffer));
|
||||
|
||||
const worksheet = workbook.getWorksheet("Skills");
|
||||
expect(worksheet).toBeDefined();
|
||||
expect(worksheet?.getRow(1).values).toEqual([, "Skill", "Count", "Active"]);
|
||||
expect(worksheet?.getRow(2).values).toEqual([, "TypeScript", 4, true]);
|
||||
expect(worksheet?.getRow(3).values).toEqual([, "Planning", 2, false]);
|
||||
});
|
||||
|
||||
it("writes all provided sheets into the workbook", async () => {
|
||||
const buffer = await createWorkbookArrayBufferFromSheets([
|
||||
{
|
||||
name: "Overview",
|
||||
rows: [["Metric", "Value"], ["Resources", 12]],
|
||||
},
|
||||
{
|
||||
name: "People Finder",
|
||||
rows: [["Name", "Skills"], ["Peter Parker", "Staffing, Forecasting"]],
|
||||
},
|
||||
]);
|
||||
|
||||
const ExcelJS = await import("exceljs");
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
await workbook.xlsx.load(Buffer.from(buffer));
|
||||
|
||||
expect(workbook.worksheets.map((sheet) => sheet.name)).toEqual([
|
||||
"Overview",
|
||||
"People Finder",
|
||||
]);
|
||||
expect(workbook.getWorksheet("Overview")?.getRow(2).values).toEqual([, "Resources", 12]);
|
||||
expect(workbook.getWorksheet("People Finder")?.getRow(2).values).toEqual([
|
||||
,
|
||||
"Peter Parker",
|
||||
"Staffing, Forecasting",
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,65 @@
|
||||
type ExcelJsModule = typeof import("exceljs");
|
||||
|
||||
type WorkbookCellValue = boolean | Date | number | string | null | undefined;
|
||||
type WorkbookRow = WorkbookCellValue[];
|
||||
type WorkbookSheet = {
|
||||
name: string;
|
||||
rows: WorkbookRow[];
|
||||
};
|
||||
|
||||
let _excelJs: ExcelJsModule | null = null;
|
||||
|
||||
async function getExcelJS() {
|
||||
if (!_excelJs) {
|
||||
_excelJs = await import("exceljs");
|
||||
}
|
||||
return _excelJs;
|
||||
}
|
||||
|
||||
export async function createWorkbookArrayBuffer(
|
||||
sheetName: string,
|
||||
rows: WorkbookRow[],
|
||||
): Promise<ArrayBuffer> {
|
||||
return createWorkbookArrayBufferFromSheets([{ name: sheetName, rows }]);
|
||||
}
|
||||
|
||||
export async function createWorkbookArrayBufferFromSheets(
|
||||
sheets: WorkbookSheet[],
|
||||
): Promise<ArrayBuffer> {
|
||||
const ExcelJS = await getExcelJS();
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
|
||||
for (const sheet of sheets) {
|
||||
const worksheet = workbook.addWorksheet(sheet.name);
|
||||
for (const row of sheet.rows) {
|
||||
worksheet.addRow(row.map((value) => value ?? ""));
|
||||
}
|
||||
}
|
||||
|
||||
const buffer = await workbook.xlsx.writeBuffer();
|
||||
return buffer as ArrayBuffer;
|
||||
}
|
||||
|
||||
export async function downloadWorkbook(
|
||||
fileName: string,
|
||||
sheetName: string,
|
||||
rows: WorkbookRow[],
|
||||
): Promise<void> {
|
||||
return downloadWorkbookSheets(fileName, [{ name: sheetName, rows }]);
|
||||
}
|
||||
|
||||
export async function downloadWorkbookSheets(
|
||||
fileName: string,
|
||||
sheets: WorkbookSheet[],
|
||||
): Promise<void> {
|
||||
const buffer = await createWorkbookArrayBufferFromSheets(sheets);
|
||||
const blob = new Blob([buffer], {
|
||||
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
});
|
||||
const url = URL.createObjectURL(blob);
|
||||
const anchor = document.createElement("a");
|
||||
anchor.href = url;
|
||||
anchor.download = fileName;
|
||||
anchor.click();
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
Reference in New Issue
Block a user