92 lines
2.5 KiB
TypeScript
92 lines
2.5 KiB
TypeScript
import XLSX from "xlsx";
|
|
import { mkdir, readdir, writeFile } from "node:fs/promises";
|
|
import path from "node:path";
|
|
|
|
const INPUT_DIR = process.env.BIZMAX_OUTPUT_DIR ?? path.resolve(process.cwd(), "output");
|
|
const CSV_DIR = process.env.BIZMAX_CSV_DIR ?? path.join(INPUT_DIR, "csv");
|
|
const CSV_NAME = process.env.BIZMAX_CSV_NAME ?? "bizmax-all.csv";
|
|
|
|
function toText(value: unknown): string {
|
|
if (value == null) {
|
|
return "";
|
|
}
|
|
return String(value);
|
|
}
|
|
|
|
function escapeCsv(value: string): string {
|
|
if (/[",\n\r]/.test(value)) {
|
|
return `"${value.replace(/"/g, "\"\"")}"`;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function rowToCsv(row: string[]): string {
|
|
return row.map(escapeCsv).join(",");
|
|
}
|
|
|
|
async function main(): Promise<void> {
|
|
const entries = await readdir(INPUT_DIR, { withFileTypes: true });
|
|
const xlsxFiles = entries
|
|
.filter((entry) => entry.isFile() && entry.name.toLowerCase().endsWith(".xlsx"))
|
|
.map((entry) => path.join(INPUT_DIR, entry.name))
|
|
.sort();
|
|
|
|
if (xlsxFiles.length === 0) {
|
|
throw new Error(`No .xlsx files found in ${INPUT_DIR}`);
|
|
}
|
|
|
|
const outputRows: string[] = [];
|
|
let wroteHeader = false;
|
|
|
|
for (const xlsxFile of xlsxFiles) {
|
|
const workbook = XLSX.readFile(xlsxFile, { cellDates: false });
|
|
|
|
for (const sheetName of workbook.SheetNames) {
|
|
const worksheet = workbook.Sheets[sheetName];
|
|
const rows = XLSX.utils.sheet_to_json<unknown[]>(worksheet, {
|
|
header: 1,
|
|
raw: false,
|
|
defval: "",
|
|
});
|
|
|
|
if (rows.length === 0) {
|
|
continue;
|
|
}
|
|
|
|
const headerRow = (rows[0] ?? []).map(toText);
|
|
if (!wroteHeader) {
|
|
outputRows.push(
|
|
rowToCsv(["source_file", "source_sheet", ...headerRow]),
|
|
);
|
|
wroteHeader = true;
|
|
}
|
|
|
|
for (const row of rows.slice(1)) {
|
|
const values = (row as unknown[]).map(toText);
|
|
outputRows.push(
|
|
rowToCsv([
|
|
path.basename(xlsxFile),
|
|
sheetName,
|
|
...values,
|
|
]),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!wroteHeader) {
|
|
throw new Error(`No worksheet rows found in ${INPUT_DIR}`);
|
|
}
|
|
|
|
await mkdir(CSV_DIR, { recursive: true });
|
|
const outputPath = path.join(CSV_DIR, CSV_NAME);
|
|
await writeFile(outputPath, `${outputRows.join("\n")}\n`, "utf8");
|
|
process.stdout.write(`${outputPath}\n`);
|
|
}
|
|
|
|
main().catch((error: unknown) => {
|
|
const message = error instanceof Error ? error.message : String(error);
|
|
process.stderr.write(`${message}\n`);
|
|
process.exitCode = 1;
|
|
});
|