java使用poi导出自定义动态复杂表头

前言:对于普通的导出可以用easyexcel或者poi框架,例如若依框架的导出就是封装好的poi,但是有些场景或者需求比较复杂我们需要自己写。主要功能点就是通过java代码在工作簿上画表头。然后填充数据,demo示例仅提供思路,毕竟都自定义了肯定业务要求很高~~~

	@Override
    public void jobLearningExport(HttpServletResponse response, JobLearningExcelVo jobLearningExcelVo) {
		
		//这里是设置导出格式的
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");

		//这里是每一条数据的主键,复杂点用这个主键一个一个查,简单的就可以一次性查出来了
        Integer[] userIds = xxx;

        //生成表头
        List<HeaderNode> headerNodeList = new ArrayList<>();
        HashMap<Integer, Integer> map = new HashMap<>();
        headerNodeList.add(new HeaderNode("xxx", 0, 0));
        headerNodeList.add(new HeaderNode("xxx", 0, 1));
        headerNodeList.add(new HeaderNode("xxx", 0, 2));
        headerNodeList.add(new HeaderNode("xxx", 0, 3));
        //从第四列开始
        int columnXiLie = 3;
        int columnLearn = 3;
        //查询动态表头(以下是业务逻辑,各位可以自己改动,毕竟需求不一样这里只提供思路)
        for (Integer xiLieId : jobLearningExcelVo.getXiLieIds()) {
            columnXiLie++;
            //根据系列id查询系列名称
            String xiLieName = excelCommonMapper.getXiLieName(xiLieId);
            //根据系列id查询所有的课程
            List<UserLearn> userLearnList = excelCommonMapper.getLearnNameList(xiLieId);
            if (userLearnList != null && userLearnList.size() > 0) {
                //根据系列id查询目录名称
                String directoryName = excelCommonMapper.getDirectoryName(xiLieId);
                headerNodeList.add(new HeaderNode(directoryName, 0, userLearnList.size(), false, columnXiLie));
                //生成系列表头
                headerNodeList.add(new HeaderNode(xiLieName, 1, userLearnList.size(), false, columnXiLie));
                columnXiLie--;
                columnXiLie = columnXiLie + userLearnList.size();
                for (UserLearn userLearn : userLearnList) {
                    columnLearn++;
                    headerNodeList.add(new HeaderNode(userLearn.getLearnName(), 2, columnLearn));
                    map.put(userLearn.getLearnId(), columnLearn);
                }
            } else {
                columnXiLie--;
            }
        }

        SXSSFWorkbook book = new SXSSFWorkbook();
        SXSSFSheet sxssfSheet = book.createSheet("xxx");
        CellStyle headStyle = book.createCellStyle();
        defaultHeadStyle(headStyle);
        //表头层级
        int deep = headerNodeList.stream().map(HeaderNode::getRow).reduce(Integer::max).orElse(1);
        for (int i = 0; i < deep; i++) {
            sxssfSheet.createRow(i);
        }

        //创建单元格
        for (HeaderNode headerNode : headerNodeList) {
            int row = headerNode.getRow();
            int col = headerNode.getColumn();
            SXSSFCell sxssfCell = sxssfSheet.getRow(row).createCell(col);
            sxssfSheet.setColumnWidth(col, headerNode.getWidth() * 256);
            sxssfCell.setCellStyle(headStyle);
            sxssfCell.setCellValue(headerNode.getHeaderName());

            CellRangeAddress region;
            //是否跨列
            if (headerNode.isOverNode()) {
                region = new CellRangeAddress(row, deep, col, col);
            } else {
                region = new CellRangeAddress(row, row, col, (col + headerNode.getOverNodeCount() - 1));
            }
            if (region.getNumberOfCells() > 1) {
                sxssfSheet.addMergedRegionUnsafe(region);
                //合并后设置下边框
                RegionUtil.setBorderTop(BorderStyle.THIN, region, sxssfSheet);
                RegionUtil.setBorderLeft(BorderStyle.THIN, region, sxssfSheet);
                RegionUtil.setBorderBottom(BorderStyle.THIN, region, sxssfSheet);
                RegionUtil.setBorderRight(BorderStyle.THIN, region, sxssfSheet);
            }
        }

        //获取用户数据(其实就是每一行的数据)
        if (userIds.length > 0) {
            List<UserBasicVo> userBasicVoList = excelCommonMapper.getUserBasicVoList(userIds);
            int rowUser = 2;
            for (UserBasicVo userBasicVo : userBasicVoList) {
                rowUser++;
                SXSSFRow row = sxssfSheet.createRow(rowUser);
                row.createCell(0).setCellValue(userBasicVo.getDealerName());
                row.createCell(1).setCellValue(userBasicVo.getRoleName());
                row.createCell(2).setCellValue(userBasicVo.getUserName());
                row.createCell(3).setCellValue(userBasicVo.getPhoneNumber());
                //查询是否通过
                List<UserLearn> userLearnList = excelCommonMapper.getStudyStatus(userBasicVo.getUserId(), jobLearningExcelVo.getXiLieIds());
                for (UserLearn userLearn : userLearnList) {
                    row.createCell(map.get(userLearn.getLearnId())).setCellValue(userLearn.getStudyStatus());
                }
            }
        }

        try {
            book.write(response.getOutputStream());
            System.out.println("----Excle文件已生成------");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(book);
        }
    }

    private static void defaultHeadStyle(CellStyle headStyle) {
        headStyle.setBorderTop(BorderStyle.THIN);
        headStyle.setBorderLeft(BorderStyle.THIN);
        headStyle.setBorderBottom(BorderStyle.THIN);
        headStyle.setBorderRight(BorderStyle.THIN);

        headStyle.setAlignment(HorizontalAlignment.CENTER);
        headStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        headStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        headStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
    }

实体类HeaderNode

@Data
public class HeaderNode implements Serializable {

    private static final long serialVersionUID = 3731735396808031009L;

    /**
     * 标题头
     */
    private String headerName;

    /**
     * 层级
     */
    private int row;

    /**
     * 非叶子节点列跨度
     */
    private int overNodeCount;

    /**
     * 当前列没有子节点
     */
    private boolean overNode = true;

    /**
     * 列
     */
    private int column;

    /**
     * 宽度
     */
    private int width = 15;

    public HeaderNode() {
    }

    public HeaderNode(String headerName, int row, int column) {
        this.headerName = headerName;
        this.row = row;
        this.column = column;
    }

    public HeaderNode(String headerName, int row, int overNodeCount, boolean overNode, int column) {
        this.headerName = headerName;
        this.row = row;
        this.overNodeCount = overNodeCount;
        this.overNode = overNode;
        this.column = column;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现动态表头导出,你需要先确定表头的数据和结构,然后使用 POI动态生成表头和数据。 以下是实现动态表头导出的基本步骤: 1. 创建工作簿对象 XSSFWorkbook。 ```java XSSFWorkbook workbook = new XSSFWorkbook(); ``` 2. 创建工作表对象 XSSFSheet。 ```java XSSFSheet sheet = workbook.createSheet("Sheet1"); ``` 3. 创建表头行对象 XSSFRow。 ```java XSSFRow headerRow = sheet.createRow(0); ``` 4. 创建表头单元格对象 XSSFCell。 ```java XSSFCell headerCell = headerRow.createCell(0); ``` 5. 设置表头单元格的值和样式。 ```java headerCell.setCellValue("表头1"); XSSFCellStyle headerCellStyle = workbook.createCellStyle(); headerCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); headerCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); headerCellStyle.setAlignment(HorizontalAlignment.CENTER); headerCell.setCellStyle(headerCellStyle); ``` 6. 动态生成表头和数据。 ```java // 假设表头和数据都保存在一个 Map 对象中 Map<String, List<String>> dataMap = new HashMap<>(); // 生成表头 int columnIndex = 0; for (String header : dataMap.keySet()) { XSSFCell headerCell = headerRow.createCell(columnIndex++); headerCell.setCellValue(header); XSSFCellStyle headerCellStyle = workbook.createCellStyle(); headerCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); headerCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); headerCellStyle.setAlignment(HorizontalAlignment.CENTER); headerCell.setCellStyle(headerCellStyle); } // 生成数据 int rowIndex = 1; for (List<String> dataList : dataMap.values()) { XSSFRow dataRow = sheet.createRow(rowIndex++); columnIndex = 0; for (String data : dataList) { XSSFCell dataCell = dataRow.createCell(columnIndex++); dataCell.setCellValue(data); } } ``` 7. 导出 Excel 文件。 ```java try (FileOutputStream outputStream = new FileOutputStream("data.xlsx")) { workbook.write(outputStream); } ``` 以上就是实现动态表头导出的基本步骤。你可以根据自己的需求自定义表头和数据的生成逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值