59 lines
1.7 KiB
TypeScript
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,
|
|
},
|
|
];
|
|
}
|
|
}
|