UNPKG

@sparta-utils/excel-validate-helper

Version:

Excel 读取、校验、错误标注和导出工具库

77 lines (76 loc) 3.08 kB
import ExcelJS from 'exceljs'; export class ExcelReader { static async read(file, options = {}) { const { dataStartRow = 4, sheetIndex = 0, onProgress, mapHeaders, mapRow, filterEmptyRows = true, progressStep = 5 } = options; if (!file) { throw new Error('未传入文件'); } if (!file.name.toLowerCase().endsWith('.xlsx')) { throw new Error('请上传一个 .xlsx 格式的 Excel 文件'); } if (dataStartRow < 1) { throw new Error('数据起始行必须大于等于 1'); } if (sheetIndex < 0) { throw new Error('工作表索引不能为负'); } try { const workbook = new ExcelJS.Workbook(); const buffer = await file.arrayBuffer(); await workbook.xlsx.load(buffer); const worksheet = workbook.worksheets[sheetIndex]; if (!worksheet) { throw new Error(`Excel 中未找到第 ${sheetIndex + 1} 个工作表`); } const totalRows = worksheet.actualRowCount; // 读取表头 const headerRow = worksheet.getRow(dataStartRow - 1); let headers = []; if (Array.isArray(headerRow.values)) { headers = headerRow.values .slice(1) .map((v) => (v != null ? v.toString() : '')); } if (mapHeaders) { headers = headers.map(mapHeaders); } const data = []; let lastProgress = -1; worksheet.eachRow((row, rowNumber) => { if (rowNumber >= dataStartRow) { let rowData = Array.isArray(row.values) ? row.values.slice(1) : []; // 过滤空行 if (filterEmptyRows) { const isEmpty = rowData.every((v) => v === null || v === undefined || v === ''); if (isEmpty) { return; } } if (mapRow) { rowData = mapRow(rowData); } rowData.unshift(rowNumber); // 加行号 data.push(rowData); if (onProgress) { const currentProgress = Math.floor((rowNumber / totalRows) * 100); if (currentProgress - lastProgress >= progressStep) { lastProgress = currentProgress; onProgress(currentProgress); } } } }); return { headers, data, totalRows, sheetName: worksheet.name, fileName: file.name }; } catch (error) { console.error('Excel 读取失败:', error); throw new Error('读取 Excel 文件失败,请确认文件格式是否正确'); } } }