SPB Git

Repository Public

tools-sheet.ts 1.9 KB 34 lines typescript

1// XLSX reader used only inside the sandboxed child process (no configuration, no database).2export interface SheetPreview { sheets: { name: string; rows: string[][]; totalRows: number; totalColumns: number; truncated: boolean }[]; truncatedSheets: boolean }3const MAX_SHEETS = 30, MAX_ROWS = 1000, MAX_COLS = 60, MAX_CELL = 500;4/** Body of the child process started by sheetPreview (sheet-child.ts). */5export async function sheetChild(input: string, output: string): Promise<void> {6  const { default: ExcelJS } = await import('exceljs');7  const { writeFile } = await import('node:fs/promises');8  const wb = new ExcelJS.Workbook();9  await wb.xlsx.readFile(input);10  const cell = (v: unknown): string => {11    if (v === null || v === undefined) return '';12    if (v instanceof Date) return v.toISOString().replace('T00:00:00.000Z', '');13    if (typeof v === 'object') {14      const o = v as { result?: unknown; text?: unknown; richText?: { text: string }[]; error?: unknown; hyperlink?: unknown };15      if (o.richText) return o.richText.map((t) => t.text).join('');16      if ('result' in o) return cell(o.result);17      if ('text' in o) return cell(o.text);18      if ('error' in o) return String(o.error);19      return '';20    }21    return String(v);22  };23  const sheets = wb.worksheets.slice(0, MAX_SHEETS).map((ws) => {24    const rows: string[][] = [];25    const cols = Math.min(ws.columnCount, MAX_COLS);26    for (let r = 1; r <= Math.min(ws.rowCount, MAX_ROWS); r++) {27      const row = ws.getRow(r);28      rows.push(Array.from({ length: cols }, (_, c) => cell(row.getCell(c + 1).value).slice(0, MAX_CELL)));29    }30    return { name: ws.name, rows, totalRows: ws.rowCount, totalColumns: ws.columnCount, truncated: ws.rowCount > MAX_ROWS || ws.columnCount > MAX_COLS };31  });32  await writeFile(output, JSON.stringify({ sheets, truncatedSheets: wb.worksheets.length > MAX_SHEETS } satisfies SheetPreview));33}34
Files main
Menu

Theme