import fs from "node:fs/promises"; import path from "node:path"; import { FileBlob, SpreadsheetFile } from "@oai/artifact-tool"; const sourceDir = "/Users/lingniu/Library/Mobile Documents/com~apple~CloudDocs/rsync/2026/07/27"; const workDir = "/Users/lingniu/project/ai-coding/lingniu-vehicle-ingest/tmp/gps-mileage-import-019fa1ac-db39-7933-bb0e-30dd63cc25bd"; const names = (await fs.readdir(sourceDir)) .filter((name) => name.endsWith(".xlsx")) .sort((a, b) => a.localeCompare(b, "zh-CN")); const manifest = []; for (const name of names) { const filePath = path.join(sourceDir, name); const input = await FileBlob.load(filePath); const workbook = await SpreadsheetFile.importXlsx(input); const sheet = workbook.worksheets.getItemAt(0); const usedRange = sheet.getUsedRange(true); const values = usedRange?.values ?? []; const rowCount = values.length; const colCount = values.reduce((max, row) => Math.max(max, row.length), 0); const topRows = values.slice(0, 8).map((row) => row.slice(0, Math.min(colCount, 40)).map((value) => { if (value instanceof Date) return value.toISOString(); return value ?? null; }), ); const preview = await workbook.render({ sheetName: sheet.name, range: `A1:${columnName(Math.min(Math.max(colCount, 1), 40))}${Math.min( Math.max(rowCount, 1), 15, )}`, scale: 1, format: "png", }); const previewName = `${String(manifest.length + 1).padStart(2, "0")}-${safeName( name, )}.png`; await fs.writeFile( path.join(workDir, previewName), new Uint8Array(await preview.arrayBuffer()), ); manifest.push({ name, sheet: sheet.name, rowCount, colCount, firstRow: topRows[0] ?? [], topRows, preview: previewName, }); } await fs.writeFile( path.join(workDir, "source-manifest.json"), `${JSON.stringify(manifest, null, 2)}\n`, "utf8", ); console.log( JSON.stringify( manifest.map(({ name, sheet, rowCount, colCount, firstRow, preview }) => ({ name, sheet, rowCount, colCount, firstRow, preview, })), null, 2, ), ); function safeName(name) { return name .replace(/\.xlsx$/i, "") .replace(/[^\p{L}\p{N}._-]+/gu, "_") .slice(0, 100); } function columnName(index) { let value = index; let result = ""; while (value > 0) { value -= 1; result = String.fromCharCode(65 + (value % 26)) + result; value = Math.floor(value / 26); } return result || "A"; }