使用easypoi导出复杂表头excel

最近有一个业务需要,导出业务数据,多表头,如下图
在这里插入图片描述
是多表头的。
使用easypoi可以根据注解导出单一表头的数据,也可以自定义模板导出复杂表头的数据。自定义模板将每一个单元表格数据都是一个map,根据key找到对应的行,如果对应的表头是单一表头,value就是数据,如果是复杂表头,则value可以是List,根据key确定复杂表头对应的子行。
具体的数据结构如下:

[
    {
        "简单表头1": "数据1"
    },
    {
        "简单表头2": "数据2"
    },
    {
        "二级复杂表头1": [
            {
                "二级表子标题1": "二级数据1"
            },
            {
                "二级表子标题2": "二级数据2"
            }
        ]
    },
    {
        "三级复杂表头1": [
            {
                "二级表子标题1": [
                    {
                        "二级表子标题1": "二级数据1"
                    },
                    {
                        "二级表子标题2": "二级数据2"
                    }
                ]
            },
            {
                "二级表子标题2": "二级数据2"
            }
        ]
    }
]

了解了easypoi创建复杂表头的数据结构,接下来看一下easypoi的方法:

  /**
     * 根据Map创建对应的Excel
     * @param entity
     *            表格标题属性
     * @param entityList
     *            Map对象列表
     * @param dataSet
     *            Excel对象数据List
     */
    public static Workbook exportExcel(ExportParams entity, List<ExcelExportEntity> entityList,
                                       Collection<?> dataSet) {
        Workbook workbook = getWorkbook(entity.getType(),dataSet.size());;
        new ExcelExportService().createSheetForMap(workbook, entity, entityList, dataSet);
        return workbook;
    }

使用上面的方法,自定义列表对象。简单介绍一下上面的方法,ExportParams entity 是创建导出的excel的基本属性的,比如文件名称,文件的sheetName;
List entityList 方法注释上解释的是 Map对象列表,在创建复杂表头的时候,我们需要创建多个ExcelExportEntity
在这里插入图片描述
通过看源码,可以看出来,ExcelExportEntity是根据key来映射到对应的Excel的表头的。

实现多表头的代码:

 public void export(HttpServletResponse response) {

        //表头设置
        List<ExcelExportEntity> colList = new ArrayList<ExcelExportEntity>();

        ExcelExportEntity colEntity = new ExcelExportEntity("日期", "dt");
        colEntity.setNeedMerge(true);
        colList.add(colEntity);

        colEntity = new ExcelExportEntity("产品PV", "pv");
        colEntity.setNeedMerge(true);
        colList.add(colEntity);

        colEntity = new ExcelExportEntity("产品UV", "uv");
        colEntity.setNeedMerge(true);
        colList.add(colEntity);

        ExcelExportEntity group_1 = new ExcelExportEntity("业务数据", "businessData");
        List<ExcelExportEntity> exportEntities = new ArrayList<>();
        for (int i = 1; i < 5; i++) {
            exportEntities.add(new ExcelExportEntity("数据" + i, "data" + i));
        }
        group_1.setList(exportEntities);
        colList.add(group_1);

        //文件数据
        List<Map<String, Object>> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Map<String, Object> valMap = new HashMap<String, Object>();
            valMap.put("dt", "日期" + i);
            valMap.put("pv", "pv" + i);
            valMap.put("uv", "uv" + i);
            {
                List<Map<String, Object>> list_1 = new ArrayList<Map<String, Object>>();
                Map<String, Object> valMap_1 = new HashMap<String, Object>();
                for (int j = 1; j < 5; j++) {
                    valMap_1.put("data" + j, "数据" + j);
                }
                list_1.add(valMap_1);

                valMap.put("businessData", list_1);
            }

        }

        //导出
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("数据表", "数据"), colList, list);
        setResponseHeader(response, LocalDateTime.now().toString());
        write(workbook, response);
    }
/**
     * 设置导出文件头
     *
     * @param response 相应servlet
     * @param fileName 文件名称--不能是中文
     */
    private static void setResponseHeader(HttpServletResponse response, String fileName) {
        try {
            fileName = new String(fileName.getBytes(), StandardCharsets.UTF_8);
            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xls");
            response.addHeader("Pargam", "no-cache");
            response.addHeader("Cache-Control", "no-cache");
        } catch (Exception ex) {
            log.error("", ex);
        }
    }
 /**
     * 将book 导出excel
     *
     * @param book
     * @param response
     */
    private static void write(Workbook book, HttpServletResponse response) {
        try {
            OutputStream os = response.getOutputStream();
            book.write(os);
            os.flush();
            os.close();
        } catch (IOException e) {
            log.error("export excel exception", e);
        }
    }
Java中导出多级表头可以使用POI库和自定义实现,下面分别介绍两种方法: 1. 使用POI库 使用POI库的方法比较简单,只需要创建Workbook对象,然后在其中创建Sheet对象和Row对象,并在Row对象中创建Cell对象,最后将数据写入Cell中即可。其中,多级表头可以通过合并单元格实现,代码示例: ```java Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet1"); Row row = sheet.createRow(0); // 创建第一级表头 Cell cell11 = row.createCell(0); cell11.setCellValue("表头1"); CellRangeAddress region1 = new CellRangeAddress(0, 0, 0, 1); // 合并单元格 sheet.addMergedRegion(region1); Cell cell12 = row.createCell(2); cell12.setCellValue("表头2"); CellRangeAddress region2 = new CellRangeAddress(0, 0, 2, 4); sheet.addMergedRegion(region2); // 创建第二级表头 Row row2 = sheet.createRow(1); Cell cell21 = row2.createCell(0); cell21.setCellValue("子表头1"); Cell cell22 = row2.createCell(1); cell22.setCellValue("子表头2"); Cell cell23 = row2.createCell(2); cell23.setCellValue("子表头3"); Cell cell24 = row2.createCell(3); cell24.setCellValue("子表头4"); Cell cell25 = row2.createCell(4); cell25.setCellValue("子表头5"); // 创建数据 Row row3 = sheet.createRow(2); Cell cell31 = row3.createCell(0); cell31.setCellValue("数据1"); Cell cell32 = row3.createCell(1); cell32.setCellValue("数据2"); Cell cell33 = row3.createCell(2); cell33.setCellValue("数据3"); Cell cell34 = row3.createCell(3); cell34.setCellValue("数据4"); Cell cell35 = row3.createCell(4); cell35.setCellValue("数据5"); FileOutputStream out = new FileOutputStream("test.xlsx"); workbook.write(out); out.close(); ``` 2. 自定义实现 如果不想使用POI库,也可以自己实现导出多级表头的功能。具体实现方法是,通过递归实现多级表头的创建和数据的写入,代码示例: ```java public class ExportExcelUtil { public static void exportExcel(HttpServletResponse response, List<List<Object>> dataList, String fileName) { response.setContentType("application/vnd.ms-excel"); response.setHeader("Content-Disposition", "attachment;filename=" + fileName); try (OutputStream out = response.getOutputStream()) { // 创建工作簿 HSSFWorkbook workbook = new HSSFWorkbook(); // 创建工作表 HSSFSheet sheet = workbook.createSheet("Sheet1"); // 创建表头 createHeader(sheet, dataList); // 填充数据 fillData(sheet, dataList); workbook.write(out); } catch (IOException e) { e.printStackTrace(); } } private static void createHeader(HSSFSheet sheet, List<List<Object>> dataList) { List<Object> headerList = dataList.get(0); int rowCnt = getRowCnt(headerList); // 创建多级表头 createMultiLevelHeader(sheet, headerList, rowCnt, 0); } private static int getRowCnt(List<Object> headerList) { int rowCnt = 1; for (Object obj : headerList) { if (obj instanceof List) { int cnt = getRowCnt((List<Object>) obj); if (cnt > rowCnt) { rowCnt = cnt; } } } return rowCnt; } private static void createMultiLevelHeader(HSSFSheet sheet, List<Object> headerList, int rowCnt, int rowIndex) { HSSFRow row = sheet.getRow(rowIndex); if (row == null) { row = sheet.createRow(rowIndex); } int colIndex = 0; for (Object obj : headerList) { if (obj instanceof List) { List<Object> subHeaderList = (List<Object>) obj; int subRowCnt = getRowCnt(subHeaderList); int subRowIndex = rowIndex + rowCnt - subRowCnt; createMultiLevelHeader(sheet, subHeaderList, subRowCnt, subRowIndex); int colSpan = getColSpan(subHeaderList); HSSFCell cell = row.createCell(colIndex); cell.setCellValue((String) subHeaderList.get(0)); CellRangeAddress region = new CellRangeAddress(rowIndex, rowIndex + rowCnt - 1, colIndex, colIndex + colSpan - 1); sheet.addMergedRegion(region); colIndex += colSpan; } else { HSSFCell cell = row.createCell(colIndex); cell.setCellValue((String) obj); colIndex++; } } } private static int getColSpan(List<Object> headerList) { int colSpan = 0; for (Object obj : headerList) { if (obj instanceof List) { colSpan += getColSpan((List<Object>) obj); } else { colSpan += 1; } } return colSpan; } private static void fillData(HSSFSheet sheet, List<List<Object>> dataList) { int rowIndex = getRowCnt(dataList.get(0)); int colIndex = 0; for (List<Object> rowList : dataList) { HSSFRow row = sheet.createRow(rowIndex++); colIndex = 0; for (Object obj : rowList) { HSSFCell cell = row.createCell(colIndex++); cell.setCellValue((String) obj); } } } } ``` 以上两种方法都可以实现多级表头导出,选择哪种方法取决于具体情况。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值