dv/frontend/src/adapters/gateways/SheetJSFileParser.ts

59 lines
1.7 KiB
TypeScript

import * as XLSX from 'xlsx';
import { type IFileParser, type ParsedSheet } from '@/application/ports/output/IFileParser';
export class SheetJSFileParser implements IFileParser {
async parse(file: File): Promise<ParsedSheet[]> {
const extension = file.name.substring(file.name.lastIndexOf('.')).toLowerCase();
if (extension === '.json') {
return this.parseJSON(file);
}
const buffer = await file.arrayBuffer();
const workbook = XLSX.read(buffer, { type: 'array' });
const sheets: ParsedSheet[] = [];
for (const sheetName of workbook.SheetNames) {
const worksheet = workbook.Sheets[sheetName];
const jsonData = XLSX.utils.sheet_to_json<Record<string, any>>(worksheet, {
defval: '',
});
const range = XLSX.utils.decode_range(worksheet['!ref'] ?? 'A1');
const columns: string[] = [];
for (let col = range.s.c; col <= range.e.c; col++) {
const cellAddress = XLSX.utils.encode_cell({ r: range.s.r, c: col });
const cell = worksheet[cellAddress];
columns.push(cell ? String(cell.v) : `Column${col + 1}`);
}
sheets.push({
sheetName,
columns,
rows: jsonData,
});
}
return sheets;
}
getSupportedFormats(): string[] {
return ['.xlsx', '.xls', '.csv', '.json'];
}
private async parseJSON(file: File): Promise<ParsedSheet[]> {
const text = await file.text();
const parsed = JSON.parse(text);
const dataArray: Record<string, any>[] = Array.isArray(parsed) ? parsed : [parsed];
const columns = dataArray.length > 0 ? Object.keys(dataArray[0]) : [];
return [
{
sheetName: file.name.replace(/\.json$/i, ''),
columns,
rows: dataArray,
},
];
}
}