poi實現對樹形結構數據導出excel併合並表格

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")));
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章