JS导出复杂多级表头的Excel

使用方式

1、安装依赖

npm install xlsx-js-style

2、复制代码文件exportExcel.js至工程
https://github.com/EnthuDai/export-excel-in-one-line

3、在引入excel.js后调用

Excel.export(columns, dataSource, '导出文件名')

4、代码demo

代码示例

5、效果

页面excel
在这里插入图片描述在这里插入图片描述

适用范围

对于使用vue ant-design 组件库中table组件的场景,可直接将table的 columnsdata-source导出文件名称 作为参数传入export方法,调用即可导出相同格式的excel文件。

Excel.export(this.demoColumn, this.demoData, '测试数据')

对于其他场景,需要对数据格式适配至ant-design table相同格式,具体为:

  1. 表头格式需符合以下条件
  • 标题的key为 title
  • 数据字段key为 dataIndex
  • 子表头key为 children

如:

	[
        {title:'类别',dataIndex:'type'},
        {title:'总计',children:[
            {title:'销量',children:[
                {title:'今天', dataIndex:'today'},
                {title:'昨天', dataIndex:'yesterday'}]
            }
          ]
        },
        {title:'趋势',children:[
            {title:'上涨率',dataIndex:'raise'},
            {title:'上涨金额', dataIndex:'raiseAmount'}
          ]
        }
      ]
  1. 数据格式格式需符合以下条件
  • 数据项key为表头格式中对应项 dataIndex 的值
  • 子数据key为children

如:

	[
        {type:'笔', today:100, yesterday: 200, raise:'20%', raiseAmount:20, children:[
            {type:'毛笔',today:50, yesterday: 100, raise:'20%', raiseAmount:10},
            {type:'钢笔',today:50, yesterday: 100, raise:'20%', raiseAmount:10}
          ]},
        {type:'墨', today:100, yesterday: 200, raise:'20%', raiseAmount:20},
        {type:'纸', today:100, yesterday: 200, raise:'20%', raiseAmount:20},
        {type:'砚', today:100, yesterday: 200, raise:'20%', raiseAmount:20},
      ]

实现原理

原理基本参考了使用xlsx.js导出有复杂表头的excel这篇文章,其该文合并表头方法doMerges 存在bug,实测中会出现问题。所以该组件中使用了树中递归处理的算法计算合并项,解决问题的同时也提高了代码的简洁程度。
实现过程:

  1. 根据表头描述 columns 生成全为空的表头二维数组,二维数组行数为 columns 中子项树的最深深度,列数为 columns 中所有子项树的叶子节点数之和。分别通过 columnHeight(columns)、columnWidth(columns)方法递归求得。
    在这里插入图片描述
  2. columns 中title填入对应位置,也是循环+递归实现。此间分两种情况
    1. 无children的叶子节点

      {title:'类别',dataIndex:'type'}
      

      在数组左上角第一项填入 title,合并单元格时需要向下合并所有单元格,记录下合并的起始和终点项的偏移量 {s:{r:0,c:0},e:{r:0,c:2}}

      在这里插入图片描述
      2.有children的节点

       {
           title:'总计',children:[
             {title:'销量',children:[
                 {title:'今天', dataIndex:'today'},
                 {title:'昨天', dataIndex:'yesterday'}]
          }
        ]
      }
      

      在这里插入图片描述
      在二维数组剩余的部分(红框区域)中,左上角第一项填入title,并记录下横向合并的起终点偏移量,横向合并的数目为该项的children数组中所有节点的叶节点总数。
      然后对 向下的剩余部分(绿框区域)递归操作。

      3.最终得到表头区域数据
      在这里插入图片描述

      合并excel单元格的数据描述
      在这里插入图片描述

  3. 其余部分就是填入数据调api即可,可以参考使用xlsx.js导出有复杂表头的excel这篇文章,此处空白太小所以不再赘述。

源码地址:

https://github.com/EnthuDai/export-excel-in-one-line
如果该内容对你有帮助,帮忙star一下项目呀

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Java导出Excel多级表头可以使用Apache POI库,递归创建表头行,设置单元格样式和合并单元格,实现复杂多级表头。 首先,创建一个方法用于递归创建表头,并返回表头行的最终行数。方法参数为表头数据、Excel Sheet对象、起始行、最后一列、当前级别。在方法内部,根据当前级别创建表头行并设置样式,根据下一级别的数据递归创建子表头行,最后合并单元格并返回创建的最终行数。 其次,调用上述方法创建所有表头行后,根据数据填充Excel表格并设置单元格样式。最后将数据写入Excel文件并保存即可。 示例代码: private static int createHeader(List<List<String>> headerData, Sheet sheet, int startRow, int lastCol, int level) { int endRow = startRow; Row row = sheet.createRow(startRow); row.setHeightInPoints(25f); CellStyle style = sheet.getWorkbook().createCellStyle(); Font font = sheet.getWorkbook().createFont(); font.setBold(true); style.setFont(font); for (int i = 0; i < headerData.size(); i++) { Cell cell = row.createCell(i); cell.setCellValue(headerData.get(i).get(0)); cell.setCellStyle(style); if (headerData.get(i).size() > 1) { int rowspan = createHeader(headerData.get(i).subList(1, headerData.get(i).size()), sheet, startRow + 1, lastCol, level + 1); sheet.addMergedRegion(new CellRangeAddress(startRow, startRow + rowspan - 1, i, i)); } else { endRow = Math.max(endRow, startRow); } } if (level == 0) { for (int i = headerData.size(); i <= lastCol; i++) { Cell cell = row.createCell(i); cell.setCellStyle(style); } } return endRow - startRow + 1; } public static void writeExcel(List<List<String>> headerData, List<List<Object>> data, String filePath) throws IOException { Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet(); int lastCol = headerData.get(0).size() - 1; int lastRow = createHeader(headerData, sheet, 0, lastCol, 0); CellStyle style = sheet.getWorkbook().createCellStyle(); style.setBorderBottom(BorderStyle.THIN); style.setBorderLeft(BorderStyle.THIN); style.setBorderRight(BorderStyle.THIN); style.setBorderTop(BorderStyle.THIN); for (int i = 0; i < data.size(); i++) { Row row = sheet.createRow(lastRow + i); List<Object> rowData = data.get(i); for (int j = 0; j <= lastCol; j++) { Cell cell = row.createCell(j); cell.setCellValue(rowData.get(j).toString()); cell.setCellStyle(style); } } FileOutputStream outputStream = new FileOutputStream(filePath); workbook.write(outputStream); outputStream.close(); }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值