poi实现对树形结构数据导出excel并合并表格

2 篇文章 1 订阅

poi实现对树形结构数据导出excel并合并表格


最近好像得罪了poi,遇到的都是导出word、Excel、pdf的问题。下面我记录一下poi对树形结构的处理,前面先梳理整体思路,文章末尾会贴上完整代码。
首先我们看一下模板和效果图吧:

在这里插入图片描述

在这里插入图片描述
怎么样,效果还行吧,有没有达到你心目中的标准?如果你也遇到了这样的问题,那么请静下心来花费几分钟时间,我会详细的梳理出自己的思路,希望能够帮助到你。

1.主要逻辑!

1.首先,我们来看一下树形结构的数据、正如效果图一样,我这里处理的是一个三层结构。

---- 祖先节点(包含祖先节点id,祖先节点name,children,total(当前对象的第三级子节点的数量))
  ---父亲节点(包含祖先节点id,祖先节点name,本身的id,本身的name,children)
     ----子节点(包含上面两个祖先的数据和自己本身的数据,无children)
数据是提前处理好了的,在代码里的体现就是一个集合List ,StatisticsByPartVo是一个java bean对象,是个树形结构。
2.因为涉及到表格的合并,我再提一下关键的代码

sheet0.addMergedRegion(new CellRangeAddress(Parma1,Parma2,Parma3,Parma4));

四个参数分别表示
Parma1:要合并的开始行
Parma2:要合并的结束行
Parma3:要合并的开始列
Parma4:要合并的结束列
举个例子,因为坐标都是从(0,0)开始的,我要合并三行四列,参数就是(2,2,3,3)

现在开始整理一下整体思路:循环整个list集合,用HSSFRow 来创建行,用HSSFCell来创建一行的一个元素,在循环的过程中,将需要合并的数据的坐标,单独用一个List<Map<String,String>>stepList 保存起来,Map里面的数据就是坐标的四个Parma,循环完数据之后,再单独循环坐标集合,统一调用上面的一行代码搞定合并,(记得合并是最后来做的事情)
怕一段文字太多影响你们阅读,我上面说的是总体思路,下面我再简单说一下针对我这个demo和数据的逻辑。
1.循环整个list,得到当前对象StatisticsByPartVo,取到StatisticsByPartVo的total,根据total的值和当前rowNum的值,来为第一级添加坐标,我代码里添加了两次,因为序号也是跟第一级一起合并的。
2.循环当前对象StatisticsByPartVo的children,也是一个集合,得到当前对象secondChild,在循环secondChild的children,分别创建行列,在secondChild的children循环完毕后,为第二级添加坐标,代码的231行,其中注意rowNum和curNum等计数器的变化和位置,如果这个有错也会导致表格格式不对。
3.循环完之后,循环计步集合,合并表格,整体完毕

        for(Map<String,Integer>map:stepList){
            sheet0.addMergedRegion(new CellRangeAddress(map.get("startIndexRow"), map.get("endIndexRow"), map.get("startIndexCol"), map.get("endIndexCol")));
        }

以上就是我的整体思路,如果你也被这个问题困扰,不如跟着我的思路走一下,整体代码和逻辑都不复杂,如果我的文章能够帮助你解决掉问题,别吝啬你的小指头给作者点个赞哦。

下面贴上完整逻辑代码,关键地方已经打上注释,欢迎下方留言,有不对的地方欢迎指出。转载请附上原文链接。

2.完整代码

package cdcb.govpublic.base.entity;

import cdcb.util.PropertiesUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author wq
 * @date 2020/4/2.
 */
public class StatisticsByPartView {
    public StatisticsByPartView() {
    }
    public static void buildExcelDocument(Map<String, Object> mode, HttpServletRequest request, HttpServletResponse response,String year) throws Exception {
        String path = PropertiesUtils.getValueByKey("excelPath", request.getServletContext().getRealPath("/"));
        String excelModelPath = path + "static/template/listByPart.xls";
        File excel = new File(excelModelPath);
        FileInputStream is = new FileInputStream(excel);
        Workbook workbook = new HSSFWorkbook(is);
        is.close();
        String excelName = year+"年政府网各栏目数据报送情况汇总表";
        //这个方法就是主要创建逻辑方法
        setWorkBookValue(workbook, mode,excelName);
        String userAgent = request.getHeader("User-Agent");
        userAgent = userAgent == null ? "" : userAgent.toLowerCase();
        if (!userAgent.contains("msie") && !userAgent.contains("trident")) {
            excelName = new String(excelName.getBytes(), "iso-8859-1");
        } else {
            excelName = URLEncoder.encode(excelName, "UTF-8");
        }
        response.setContentType("application/octet-stream");
        response.setHeader("Content-disposition", "attachment;filename=\"" + excelName + ".xls\"");
        OutputStream ouputStream = response.getOutputStream();
        workbook.write(ouputStream);
        ouputStream.flush();
        ouputStream.close();
    }

    private static void setWorkBookValue(Workbook wbs, Map<String, Object> model,String excelName) {
        List<StatisticsByPartVo> list = (List)model.get("list");
        HSSFCellStyle style = (HSSFCellStyle)wbs.createCellStyle();
        style.setVerticalAlignment((short)1);
        style.setAlignment((short)2);
        style.setWrapText(false);
        style.setBorderBottom((short)1);
        style.setBorderRight((short)1);
        style.setBorderTop((short)1);
        style.setBorderLeft((short)1);
        //这里设置style2的目的是给下面的循环做判断,如果数据为零则加粗标红
        HSSFCellStyle style2 = (HSSFCellStyle) wbs.createCellStyle();
        style2.setVerticalAlignment((short) 1);
        style2.setAlignment((short) 2);
        style2.setWrapText(false);
        style2.setBorderBottom((short) 1);
        style2.setBorderRight((short) 1);
        style2.setBorderTop((short) 1);
        style2.setBorderLeft((short) 1);
        Font ztFont = wbs.createFont();
        ztFont.setColor(Font.COLOR_RED);
        ztFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        style2.setFont(ztFont);
        //创建工作簿
        HSSFSheet sheet0 = (HSSFSheet)wbs.getSheetAt(0);
        //记录步数的集合
        List<Map<String,Integer>>stepList = new ArrayList<>();
        //下面几行是为了替换模板第一行标题的文字
        HSSFRow headRow = sheet0.getRow(0);
        HSSFCell headCell = headRow.getCell(0);
        headCell.setCellValue(excelName);
        sheet0.createFreezePane(0,3,0,3);
        
        //因为模板的起始行是第三行,所以这里定义为3
        int rowNum = 3;
        for(int i = 0; i < list.size(); ++i) {
            Map<String,Integer>map2 = new HashMap<>();
            Map<String,Integer>map3 = new HashMap<>();
            StatisticsByPartVo vo = list.get(i);
            //为当前对象的第一级和序号列添加步数
            if(vo.getTotal()>1){
                map2.put("startIndexRow",rowNum);
                map2.put("endIndexRow",vo.getTotal()+rowNum-1);
                map2.put("startIndexCol",0);
                map2.put("endIndexCol",0);
                map3.put("startIndexRow",rowNum);
                map3.put("endIndexRow",vo.getTotal()+rowNum-1);
                map3.put("startIndexCol",1);
                map3.put("endIndexCol",1);
                stepList.add(map2);
                stepList.add(map3);
            }
            //循环第二级
            int curNum = rowNum;
            for(int k=0;k<vo.getChildren().size();k++){
                StatisticsByPartVo secondChild = vo.getChildren().get(k);
                Map<String,Integer>map4 = new HashMap<>();
				//创建第二级和第三级
                for (int j = 0; j < secondChild.getChildren().size(); j++) {
                    StatisticsByPartVo third = secondChild.getChildren().get(j);
                    HSSFRow rowi = sheet0.createRow(curNum +j);
                    HSSFCell col0 = rowi.createCell(0);
                    col0.setCellStyle(style);
                    HSSFCell col1 = rowi.createCell(1);
                    col1.setCellStyle(style);
                    //创建第一级的数据,下面判断原因:因为要合并,合并内容的数据只需要创建一次就好,其他的为空
                    if(j==0){
                        col1.setCellValue(vo.getFirstName());
                        col0.setCellValue((double)(i + 1));
                    }else{
                        col1.setCellValue("");
                        col0.setCellValue("");
                    }
                    //创建第二级的数据
                    HSSFCell col2 = rowi.createCell(2);
                    col2.setCellStyle(style);
                    if(j == 0){
                        col2.setCellValue(third.getSecondName());
                    }else{
                        col2.setCellValue("");
                    }
                    HSSFCell col3 = rowi.createCell(3);
                    col3.setCellValue(third.getThirdName());
                    col3.setCellStyle(style);
					//下面都是创建第三级的数据了
                    HSSFCell col4 = rowi.createCell(4);
                    col4.setCellValue(third.getMonth1());
                    if(third.getMonth1() == 0){
                        col4.setCellStyle(style2);
                    }else{
                        col4.setCellStyle(style);
                    }

                    HSSFCell col5 = rowi.createCell(5);
                    col5.setCellValue(third.getMonth2());
                    if(third.getMonth2() == 0){
                        col5.setCellStyle(style2);
                    }else{
                        col5.setCellStyle(style);
                    }

                    HSSFCell col6 = rowi.createCell(6);
                    col6.setCellValue(third.getMonth3());
                    if(third.getMonth3() == 0){
                        col6.setCellStyle(style2);
                    }else{
                        col6.setCellStyle(style);
                    }

                    HSSFCell col7 = rowi.createCell(7);
                    col7.setCellValue(third.getMonth4());
                    if(third.getMonth4() == 0){
                        col7.setCellStyle(style2);
                    }else{
                        col7.setCellStyle(style);
                    }

                    HSSFCell col8 = rowi.createCell(8);
                    col8.setCellValue(third.getMonth5());
                    if(third.getMonth5() == 0){
                        col8.setCellStyle(style2);
                    }else{
                        col8.setCellStyle(style);
                    }

                    HSSFCell col9 = rowi.createCell(9);
                    col9.setCellValue(third.getMonth6());
                    if(third.getMonth6() == 0){
                        col9.setCellStyle(style2);
                    }else{
                        col9.setCellStyle(style);
                    }

                    HSSFCell col10 = rowi.createCell(10);
                    col10.setCellValue(third.getMonth7());
                    if(third.getMonth7() == 0){
                        col10.setCellStyle(style2);
                    }else{
                        col10.setCellStyle(style);
                    }

                    HSSFCell col11 = rowi.createCell(11);
                    col11.setCellValue(third.getMonth8());
                    if(third.getMonth8() == 0){
                        col11.setCellStyle(style2);
                    }else{
                        col11.setCellStyle(style);
                    }

                    HSSFCell col12 = rowi.createCell(12);
                    col12.setCellValue(third.getMonth9());
                    if(third.getMonth9() == 0){
                        col12.setCellStyle(style2);
                    }else{
                        col12.setCellStyle(style);
                    }

                    HSSFCell col13 = rowi.createCell(13);
                    col13.setCellValue(third.getMonth10());
                    if(third.getMonth10() == 0){
                        col13.setCellStyle(style2);
                    }else{
                        col13.setCellStyle(style);
                    }

                    HSSFCell col14 = rowi.createCell(14);
                    col14.setCellValue(third.getMonth11());
                    if(third.getMonth11() == 0){
                        col14.setCellStyle(style2);
                    }else{
                        col14.setCellStyle(style);
                    }

                    HSSFCell col15 = rowi.createCell(15);
                    col15.setCellValue(third.getMonth12());
                    if(third.getMonth12() == 0){
                        col15.setCellStyle(style2);
                    }else{
                        col15.setCellStyle(style);
                    }

                    HSSFCell col16 = rowi.createCell(16);
                    col16.setCellValue(third.getTotal());
                    if(third.getTotal() == 0){
                        col16.setCellStyle(style2);
                    }else{
                        col16.setCellStyle(style);
                    }
                }
                //记录第二级合并的步数
                if(secondChild.getChildren().size()>1){
                    map4.put("startIndexRow",curNum);
                    map4.put("endIndexRow",secondChild.getChildren().size()+curNum-1);
                    map4.put("startIndexCol",2);
                    map4.put("endIndexCol",2);
                    stepList.add(map4);
                }
                curNum+=secondChild.getChildren().size();
            }
            rowNum += vo.getTotal();
        }
        //循环合并表格
        for(Map<String,Integer>map:stepList){
            sheet0.addMergedRegion(new CellRangeAddress(map.get("startIndexRow"), map.get("endIndexRow"), map.get("startIndexCol"), map.get("endIndexCol")));
        }
    }
}

  • 13
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
树形结构数据导出Excel 可以使用 JavaPOI 库来实现POI 是一组用于处理 Microsoft Office 文档的 Java 库,包括 Excel、Word、PowerPoint 等文档格式。 具体实现如下: 1. 在 pom.xml 中添加以下依赖: ```xml <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> ``` 2. 创建 Excel 文件并写入数据。这里以树形结构数据为例,假设已经从数据库中查询到了树形结构数据,可以使用递归的方式将数据写入 Excel 表格中。 ```java public void exportToExcel(List<Node> nodeList, String filePath) throws IOException { Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet(); int rowIndex = 0; for (Node node : nodeList) { rowIndex = writeNodeToExcel(sheet, node, rowIndex, 0); } FileOutputStream outputStream = new FileOutputStream(filePath); workbook.write(outputStream); workbook.close(); } private int writeNodeToExcel(Sheet sheet, Node node, int rowIndex, int level) { Row row = sheet.createRow(rowIndex++); Cell cell = row.createCell(level); cell.setCellValue(node.getName()); for (Node child : node.getChildren()) { rowIndex = writeNodeToExcel(sheet, child, rowIndex, level + 1); } return rowIndex; } ``` 以上代码中,`Node` 表示树形结构中的一个节点,包含了节点名称和子节点列表。`exportToExcel` 方法接收一个节点列表和一个文件路径作为参数,将节点列表写入 Excel 文件中。`writeNodeToExcel` 方法递归地将节点和子节点写入 Excel 表格中,其中 `level` 参数表示节点的层级。 3. 调用 `exportToExcel` 方法将数据导出Excel 文件。 ```java List<Node> nodeList = // 从数据库中查询树形结构数据 String filePath = "/path/to/excel.xlsx"; exportToExcel(nodeList, filePath); ``` 以上就是将树形结构数据导出Excel 的方法,代码中省略了异常处理等细节,请根据实际情况进行补充。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值