前段时间写过一篇类似的文章,介绍了sheetjs。最近发现了一个更好用的库ExcelJS,它支持高级的样式自定义,并且使用起来也不复杂。实际上sheetjs也支持高级自定义样式,不过需要使用付费版。
下面对比了Exceljs和Sheetjs:
特性 | ExcelJS | SheetJS (xlsx) |
---|---|---|
写入样式 | 支持单元格的样式设置(字体、颜色、边框等) | 不支持样式设置 |
图表支持 | 不支持 | 不支持 |
内存效率 | 适合处理较大文件,支持流式写入与读取 | 处理大文件时内存占用较高,需要手动优化 |
流式操作 | 支持(如流式写入、读取大文件) | 不支持流式操作,适用于小到中型数据集的处理 |
社区与文档 | 文档详尽,社区活跃 | 社区活跃,文档相对较简单 |
适用场景 | 适合需要丰富样式、较大数据集处理的场景 | 适合快速操作小型文件,支持更多文件格式 |
ExcelJS主要用于Node.js环境,它是一个Node.js库。因此,它的核心功能是为Node.js应用程序提供操作Excel文件的接口。虽然ExcelJS本身是为Node.js设计的,但它也提供了在浏览器端使用的版本。
这里我们主要来介绍浏览器端的使用方式,还是通过下载和上传来演示这个库的常规用法,更多功能可以参考文档:
https://github.com/exceljs/exceljs/blob/master/README_zh.md
前端实现Excel导出下载
先来看下功能演示,如下图把表格中的数据下载到excel文件中
export const exportExcel = (data: DataType[] ) => { const headerStyle = { font: { name: 'Arial', family: 4, size: 12, bold: true, // color: { argb: 'FF0000' } }, fill: { type: 'pattern', pattern: 'solid', // fgColor: { argb: 'FFFF00' }, // bgColor: { argb: 'FFFF00' } }, alignment: { vertical: 'middle', horizontal: 'center' }, border: { top: {style: 'thin', color: {argb: '000000'}}, left: {style: 'thin', color: {argb: '000000'}}, bottom: {style: 'thin', color: {argb: '000000'}}, right: {style: 'thin', color: {argb: '000000'}} } }; const headerTitle = ['APP', '名称', '作品数'] const workbook = new ExcelJS.Workbook(); const ws = workbook.addWorksheet("Sheet1") ws.addRow(headerTitle) .eachCell((cell) => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error cell.style = headerStyle }) data.forEach(it=> { ws.addRow(Object.values({ app: it.app, name: it.name, works: it.works })) }) ws.columns = headerTitle.map((header) => ({ header, key: header, width: 20 })) workbook.xlsx.writeBuffer() .then(buffer => { // 创建 Blob 对象 const blob = new Blob([buffer], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}); // 创建下载链接 const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `exceljs.xlsx`; a.click(); // 清理 URL setTimeout(() => { window.URL.revokeObjectURL(url); a.remove(); }, 100); }) .catch(err => console.error('Error creating file:', err));}
这段代码实现的功能是:
使用ExcelJS.Workbook()
创建一个Workbook对象使用addWorksheet("Sheet1")
向Workbook中添加一个sheet使用addRow
方法先加入表头,再使用eachCell为表头单元格设置样式,后面添加数据也是使用这个方法最后通过模拟点击a标签下载xlsx 前端实现Excel上传解析
将上面下载的excel文件再次上传解析
这里使用antd的Upload组件获取到file文件对象,你可以可以使用原生的标签来上传。beforeUpload是上传前调用这个方法, 我们的目的是获取到file对象,没有必要把文件真的上传到服务器,所以返回值为false,表示不再执行后续上传动作了。
<Upload multiple showUploadList={false} action="/" beforeUpload={async (file) => { const excelData = await uploadExcel(file); setTableData([...tableData, ...excelData]) return false; }}> <Button>上传Excel</Button></Upload>
获取到file对象就传递给exceljs来解析文件,代码如下:
export const uploadExcel = async (file: File) => { const arrayBuffer = await file.arrayBuffer() const tableData: DataType[] = []; const workbook = new ExcelJS.Workbook(); try { await workbook.xlsx.load(arrayBuffer); // 获取第一个工作表 const worksheet = workbook.getWorksheet(1); // 读取工作表中的数据 worksheet?.eachRow({includeEmpty: true}, (row, rowNumber) => { console.log(`Row ${rowNumber}:`, row.values); // 去掉表头 if (rowNumber > 1) { tableData.push({ key: rowNumber.toString(), // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error app: row.values[1].trim(), // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error name: row.values[2].trim(), // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error works: row.values[3].trim() }) } }); } catch (error) { console.error('Error loading workbook:', error); } console.log(tableData); return tableData;}
下面解释一下这段代码
使用ExcelJS.Workbook()
创建一个workbook对象使用workbook.xlsx.load(arrayBuffer)
将文件对象解码workbook.getWorksheet(1)
获取到xls文件的第一个sheet使用worksheet?.eachRow
方法获取到每行与单元格 在线调试
仓库和在线访问:https://stackblitz.com/~/github.com/fullee/exceljs-demo
运行演示命令:
cd exceljs-demo/npm inpm run dev