精华内容
下载资源
问答
  • poi实现对树形结构数据导出excel并合并表格

    千次阅读 热门讨论 2020-04-04 10:19:34
    poi实现对树形结构数据导出excel并合并表格 最近好像得罪了poi,遇到的都是导出word、Excel、pdf的问题。下面我记录一下poi对树形结构的处理,前面先梳理整体思路,文章末尾会贴上完整代码。 首先我们看一下模板和...

    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")));
            }
        }
    }
    
    
    展开全文
  • 1,效果图 界面显示 导出效果 2,数据格式 4,引入文件 xlsx.full.min.js ... //树形表格 <div> <table id="fapztable" lay-filter="faptool" style="margin-bottom: 0px;"></table&g

    1,效果图

    界面显示
    在这里插入图片描述

    导出效果
    在这里插入图片描述

    2,数据格式

    在这里插入图片描述
    注意:一条记录里面不能出现 id 和 parentId 同值得情况,否则收缩数据得箭头不会出来

    4,引入文件

    xlsx.full.min.js

    5,代码

    
     //触发按钮
     <button type="button" onclick="exportcalcdetail()">导出结果</button>
      
     //树形表格
     <div>
    	<table id="fapztable" lay-filter="faptool" style="margin-bottom: 0px;"></table>
     </div>
     
    
    
    //树形表格
     function fpgrid(data) {
            var treeTable = layui.treeGrid;
            //第2个实例
            treeTable.render({
                elem: '#fapztable',
                height: "full-30",
                idField: 'id',
                size: 'sm', //小尺寸的表格
                page: true, //开启分页
                limits: [15, 30, 50, 100, 200, 500, 5000, 10000, 20000, 50000],
                limit: 20000,
                sort: true,
                totalRow: true,
                totalRowAll: true,
                /*cellMinWidth: 100,*/
                treeId: 'id', //树形id字段名称
                treeUpId: 'parentId',//树形父id字段名称
                treeShowName: 'unitclass',//以树形式显示的字段
                cols: [
                    [ //表头
                        {field: 'unitclass', title: '分摊类别', width: 140, align: 'left', halign: 'center'},
                        {field: 'UNITCODE', title: '核算单元代码', width: 140, align: 'left', halign: 'center'},
                        {field: 'UNITNAME',title: '核算单元名称',width: 200,align: 'left',halign: 'center'},
                    ]
                ],
                data: data ? data : [],
                filter: {
                    bottom: false
                },
                done: function () {
                    layui.soulTable.render(this)
                    // $("[data-field='ID']").css('display','none');
                }
            });
    
            treeTable.on('rowDouble(faptool)', function (obj) {
                obj.tr.addClass('layui-bg-orange').siblings().removeClass('layui-bg-orange');
            })
        }
        
    
    
    //引入文件
    <script type="text/javascript" src="${ctx}/static/js/xlsx.full.min.js"></script>
    
    
    //导出功能函数
    
    <script>
        function exportcalcdetail() {
            var wopts = {
                bookType: 'xlsx',
                bookSST: false,
                type: 'binary'
            };
            var workBook = {
                SheetNames: ['Sheet1'],
                Sheets: {},
                Props: {}
            };
            function json2Excel() {
                //待展示的数据,可能是从后台返回的json数据或者是自己定义的object fapztable
                var dataList = layui.treeGrid.cache['fapztable'].data.list;
                //var dataexport = JSON.parse(JSON.stringify(dataList));
                var  dataexport =  new Array();
                for (var  i=0; i< dataList.length; i++) {
                    var ObjOneThis = dataList[i];
                    var ObjOne={};
                    //字段信息
                    ObjOne.unitclass=ObjOneThis.unitclass;
                    ObjOne.UNITCODE=ObjOneThis.UNITCODE;
                    ObjOne.UNITNAME=ObjOneThis.UNITNAME;
                    dataexport.push(ObjOne);
                }
    
                //展示的顺序,把data中对象的属性按照你想要的顺序排放就可以了
                var header = ["unitclass", "UNITCODE","UNITNAME"];
                //展示的名称
                var headerDisplay = {unitclass:"分摊类别", UNITCODE:"核算单元代码", UNITNAME:"核算单元名称"};
                //将表头放到原始数据里面去,要保证表头在数组的最前面
                var newData = [headerDisplay, ...dataexport];
    
                //加了一句skipHeader:true,这样就会忽略原来的表头
                workBook.Sheets['Sheet1'] = XLSX.utils.json_to_sheet(newData, {header:header, skipHeader:true});
    
                //1、XLSX.utils.json_to_sheet(data) 接收一个对象数组并返回一个基于对象关键字自动生成的“标题”的工作表,
                // 默认的列顺序由使用Object.keys的字段的第一次出现确定
                //2、将数据放入对象workBook的Sheets中等待输出
                //workBook.Sheets['Sheet1'] = XLSX.utils.json_to_sheet(dataSource)
    
                //3、XLSX.write() 开始编写Excel表格
                //4、changeData() 将数据处理成需要输出的格式
                //saveAs(new Blob([changeData(XLSX.write(workBook, wopts))], {type: 'application/octet-stream'}))
                openDownloadDialog(new Blob([changeData(XLSX.write(workBook, wopts))], {type: 'application/octet-stream'}),'文件名.xlsx');
            }
    
            function openDownloadDialog(url, saveName) {
                if (typeof url == 'object' && url instanceof Blob) {
                    url = URL.createObjectURL(url); // 创建blob地址
                }
                var aLink = document.createElement('a');
                aLink.href = url;
                aLink.download = saveName || ''; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
                var event;
                if (window.MouseEvent) event = new MouseEvent('click');
                else {
                    event = document.createEvent('MouseEvents');
                    event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
                }
                aLink.dispatchEvent(event);
            }
    
            function changeData(s) {
    
                //如果存在ArrayBuffer对象(es6) 最好采用该对象
                if (typeof ArrayBuffer !== 'undefined') {
    
                    //1、创建一个字节长度为s.length的内存区域
                    var buf = new ArrayBuffer(s.length);
    
                    //2、创建一个指向buf的Unit8视图,开始于字节0,直到缓冲区的末尾
                    var view = new Uint8Array(buf);
    
                    //3、返回指定位置的字符的Unicode编码
                    for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
                    return buf;
    
                } else {
                    var buf = new Array(s.length);
                    for (var i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
                    return buf;
                }
            }
            json2Excel();
        }
    </script>
    
    
    展开全文
  • Java 树形结构数据生成导出excel文件

    千次阅读 2021-02-25 14:58:28
    树形结构数据生成导出excel文件
    1. 效果

    2. 用法

      String jsonStr = "{\"name\":\"aaa\",\"children\":[{\"name\":\"bbb\",\"children\":[{\"name\":\"eee\"},{\"name\":\"fff\",\"children\":[{\"name\":\"iii\"},{\"name\":\"jjj\",\"children\":[{\"name\":\"qqq\"},{\"name\":\"ttt\"}]}]},{\"name\":\"www\"}]},{\"name\":\"ccc\",\"children\":[{\"name\":\"ggg\"},{\"name\":\"hhh\",\"children\":[{\"name\":\"kkk\",\"children\":[{\"name\":\"ttt\"},{\"name\":\"mmm\"}]},{\"name\":\"uuu\"}]},{\"name\":\"ooo\"}]},{\"name\":\"ddd\",\"children\":[{\"name\":\"ggg\"},{\"name\":\"hhh\",\"children\":[{\"name\":\"kkk\"},{\"name\":\"uuu\"}]}]}]}";
      Map tree = JSONObject.parseObject(jsonStr, Map.class);
      tree2Excel(tree, "E:\\" + System.currentTimeMillis() + ".xls", "name", "children");

       

    3. 源码
       

      package pers.xxx.demo.tree2excel;
      
      import org.apache.poi.hssf.usermodel.HSSFWorkbook;
      import org.apache.poi.ss.usermodel.*;
      import org.apache.poi.xssf.usermodel.XSSFWorkbook;
      
      import java.io.Closeable;
      import java.io.File;
      import java.io.FileOutputStream;
      import java.io.IOException;
      import java.util.List;
      import java.util.Map;
      
      /**
       * 树形结构数据导出excel工具
       * <p>
       * Created by lzy on 2021/2/24 14:09
       */
      @SuppressWarnings("ALL")
      public class Tree2ExcelUtil {
      
          /**
           * 树形结构数据生成excel文件
           *
           * @param tree     树形数据
           * @param filePath 文件路径
           * @return
           */
          public static boolean tree2Excel(Map tree, String filePath) {
              return tree2Excel(tree, filePath, null, null);
          }
      
          /**
           * 树形结构数据生成excel文件
           *
           * @param tree         树形数据
           * @param filePath     文件路径
           * @param lableName    标签Key名称
           * @param childrenName 子节点Key名称
           * @return
           */
          public static boolean tree2Excel(Map tree, String filePath, String lableName, String childrenName) {
              if (isBlank(filePath)) {
                  System.err.println("文件名称不能为空");
                  return false;
              }
              try {
                  doSame(tree, lableName, childrenName);
                  createExcel(filePath, tree);
                  return true;
              } catch (IOException e) {
                  e.printStackTrace();
              }
              return false;
          }
      
          /**
           * 树形结构数据生成Workbook对象
           *
           * @param tree    树形数据
           * @param fileSuf 文件后缀,xls/xlsx
           * @return
           */
          public static Workbook tree2Worbook(Map tree, String fileSuf) {
              return tree2Worbook(tree, fileSuf, null, null);
          }
      
          /**
           * 树形结构数据生成Workbook对象
           *
           * @param tree         树形数据
           * @param fileSuf      文件后缀,xls/xlsx
           * @param lableName    标签Key名称
           * @param childrenName 子节点Key名称
           * @return
           */
          public static Workbook tree2Worbook(Map tree, String fileSuf, String lableName, String childrenName) {
              if (isBlank(fileSuf)) {
                  System.err.println("必须指定文件后缀");
                  return null;
              }
              try {
                  doSame(tree, lableName, childrenName);
                  return procesData(tree, fileSuf);
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return null;
          }
      
      
          //具体实现
      
          /**
           * 标识最大列
           */
          private static int maxCol = 0;
          private static String lableName = "lable";
          private static String childrenName = "children";
          private static final String COL = "col";
          private static final String ROW = "row";
          private static final String ROW_OFT = "rowOft";
          private static final String ROW_SIZE = "rowSize";
      
      
          private static void doSame(Map tree, String lableName, String childrenName) {
              if (!isBlank(lableName)) {
                  Tree2ExcelUtil.lableName = lableName;
              }
              if (!isBlank(childrenName)) {
                  Tree2ExcelUtil.childrenName = childrenName;
              }
              coreAlgoCol(tree, 1);
              coreAlgoRow(tree);
          }
      
          /**
           * 主要算法,计算列的坐标,计算每个节点所占行
           *
           * @param tree  数据
           * @param col   递增的列
           * @param trees 把高级别向下传递计算递增的行高
           */
          private static void coreAlgoCol(Map tree, int col, Map... trees) {
              tree.put(COL, col);
              Object childrenObj = tree.get(childrenName);
              if (childrenObj != null) {
                  List<Map> children = (List<Map>) childrenObj;
                  if (children.size() > 0) {
                      int size = children.size() * 2 - 1;
                      tree.put(ROW_SIZE, size);
                      int len = trees != null ? trees.length + 1 : 1;
                      Map[] arrData = new Map[len];
      
                      if (trees != null && trees.length > 0) {
                          for (int i = 0; i < trees.length; i++) {
                              Map tree1 = trees[i];
                              tree1.put(ROW_SIZE, toInt(tree1.get(ROW_SIZE), 1) + size - 1);
                              arrData[i] = tree1;
                          }
                      }
                      arrData[len - 1] = tree;
                      for (Map tree1 : children) {
                          int newCol = col + 1;
                          if (newCol > maxCol) {
                              maxCol = newCol;
                          }
                          coreAlgoCol(tree1, newCol, arrData);
                      }
                  }
              }
          }
      
          /**
           * 主要算法,计算行的坐标
           *
           * @param tree
           */
          private static void coreAlgoRow(Map tree) {
              if (toInt(tree.get(ROW)) == 0) {
                  tree.put(ROW, Math.round(toInt(tree.get(ROW_SIZE), 1) / 2.0f));
              }
              Object childrenObj = tree.get(childrenName);
              if (childrenObj != null) {
                  List<Map> children = (List<Map>) childrenObj;
                  if (children.size() > 0) {
                      int tempOft = toInt(tree.get(ROW_OFT));
                      for (Map tree1 : children) {
                          int rowSize = toInt(tree1.get(ROW_SIZE), 1);
                          tree1.put(ROW_OFT, tempOft);
                          tree1.put(ROW, tempOft + Math.round(rowSize / 2.0f));
                          tempOft += rowSize + 1;
                          coreAlgoRow(tree1);
                      }
                  }
              }
          }
      
          /**
           * 创建excel文件
           *
           * @param filePath 文件路径,具体路径到文件名
           * @param tree     数据
           * @throws IOException
           */
          private static void createExcel(String filePath, Map tree) throws IOException {
              File file = new File(filePath);
              boolean bfile = file.createNewFile();
              // 复制模板到新文件
              if (bfile) {
                  Workbook wk = procesData(tree, filePath);
                  if (wk != null) {
                      FileOutputStream fos = null;
                      try {
                          fos = new FileOutputStream(file);
                          wk.write(fos);
      
                          fos.flush();
                      } finally {
                          closeStream(fos);
                          wk.close();
                      }
                  }
              }
          }
      
      
          /**
           * 处理excel数据
           *
           * @param tree 数据
           * @return 工作表对象
           */
          private static Workbook procesData(Map tree, String fileName) {
      
              Workbook wk = null;
              if (fileName.endsWith("xls")) {
                  wk = new HSSFWorkbook();
              }
              if (fileName.endsWith("xlsx")) {
                  wk = new XSSFWorkbook();
              }
              if (wk == null) {
                  System.err.println("文件名称不正确");
                  return null;
              }
      
              //创建一个sheet页
              Sheet sheet = wk.createSheet("Sheet1");
      
              int colSize = maxCol * 2 + 2;
              int rowSize = toInt(tree.get(ROW_SIZE), 1);
              for (int i = 0; i <= rowSize; i++) {
                  Row row = sheet.createRow(i);
                  for (int j = 0; j <= colSize; j++) {
                      row.createCell(j);
                  }
              }
              //配置单元格背景色
              CellStyle style1 = wk.createCellStyle();
              style1.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex());
              style1.setFillPattern(FillPatternType.SOLID_FOREGROUND);
              CellStyle style2 = wk.createCellStyle();
              style2.setFillForegroundColor(IndexedColors.LIGHT_YELLOW.getIndex());
              style2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
      
              dealCell(sheet, tree, style1, style2);
      
              return wk;
          }
      
          /**
           * 根据计算好的坐标填充每一个单元格
           *
           * @param sheet  #
           * @param tree   数据
           * @param style1 单元格格式
           * @param style2 单元格格式
           */
          private static void dealCell(Sheet sheet, Map tree, CellStyle style1, CellStyle style2) {
              Row row = sheet.getRow(toInt(tree.get(ROW)));
              int oftCol = (toInt(tree.get(COL)) - 1) * 2 + 1;
              Cell cell = row.getCell(oftCol);
              cell.setCellStyle(style1);
              cell.setCellValue(String.valueOf(tree.get(lableName)));
      
              sheet.setColumnWidth(oftCol, 256 * 20);
      
              Object childrenObj = tree.get(childrenName);
              if (childrenObj != null) {
                  List<Map> children = (List<Map>) childrenObj;
                  if (children.size() > 0) {
                      int size = children.size();
      
                      int startRow = toInt(children.get(0).get(ROW));
                      int endRow = toInt(children.get(size - 1).get(ROW));
                      int col = oftCol + 1;
                      sheet.setColumnWidth(col, 256);
                      for (; startRow <= endRow; startRow++) {
                          sheet.getRow(startRow).getCell(col).setCellStyle(style2);
                      }
      
                      for (Map child : children) {
                          dealCell(sheet, child, style1, style2);
                      }
                  }
              }
          }
      
          private static int toInt(Object val) {
              return toInt(val, 0);
          }
      
          private static int toInt(Object val, Integer defVal) {
              try {
                  return Integer.parseInt(String.valueOf(val));
              } catch (NumberFormatException ignored) {
              }
              return defVal;
          }
      
          private static boolean isBlank(String str) {
              return str == null || str.trim().length() == 0;
          }
      
          /**
           * 关闭流
           *
           * @param closeables 不定长数组 流对象
           */
          public static void closeStream(Closeable... closeables) {
              for (Closeable closeable : closeables) {
                  if (closeable != null) {
                      try {
                          closeable.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }
      
      }

       

    展开全文
  • 形成树形结构: 如上图所示:我遇到的excel表的结构: 导入到数据库中,是有多个表组成的!我要实现把这些数据提取出来西港城一个树形而机构的List,然后转为json,导入数据库。 献上我的核心代码: // 获取...

    在开发中遇到一个问题,就是有一张excel表中的数据时多层级的,不是普通一行一行的,而是,一行对应多行,多行之中的每一行在对应多行数据。形成树形结构:

    如上图所示:我遇到的excel表的结构:

    导入到数据库中,是有多个表组成的!我要实现把这些数据提取出来西港城一个树形而机构的List,然后转为json,导入数据库。

    献上我的核心代码:

    // 获取Excel内容
      public static List<?> getContent(Sheet sheet) {
        List<Map> list = new ArrayList<>();
        List<Map> cbfList = new ArrayList<>();
        List<Map> dkxxList = new ArrayList<>();
        List<Map> familyList = new ArrayList<>();
        List<Map> cbfList98=new ArrayList<>();
        List<Integer> cbfRowsIndex=new ArrayList<Integer>();
        Map map=new HashMap();
        List<String> titles=new ArrayList<>();
        // Excel数据总行数
        int rowCount = sheet.getLastRowNum();//getPhysicalNumberOfRows();
        //int columnCount = sheet.getRow(2).getPhysicalNumberOfCells();获取不为空的总列数 getPhysicalNumberOfCells()
        int columnCount =sheet.getRow(2).getLastCellNum() - sheet.getRow(2).getFirstCellNum();
        for(int x=0;x<sheet.getRow(2).getPhysicalNumberOfCells();x++){
          //titles.add(getValue(sheet.getRow(0).getCell(x)));
          if (StringUtils.isNotNull(getCellValue(sheet.getRow(2),x) != null))
          {
            String value =getCellValue(sheet.getRow(2),x).toString();
            System.out.println(value);
            titles.add(value);
          }
          else
          {
            titles.add(null);
          }
        }
        System.out.println("数据字段列表"+JsonUtil.beanToJson(titles));
        // 遍历首行前三列为发包方数据信息,固定第五行开始为数据行
        Row rowFbf =sheet.getRow(5);
        Map mapFbf=new HashMap();
        for (int j = 0; j <=2; j++) {
          Cell cell = rowFbf.getCell(j);
          if (cell != null && cell.getCellTypeEnum() != CellType.BLANK) {
            mapFbf.put(titles.get(j), getCellValue(rowFbf, j).toString());
          }
        }
        list.add(mapFbf);
        //下面开始进行正式的数据提取,嵌套lsit,Map形式展示数据
        for (int i = 5; i<=rowCount; i++){
          Row cbfRow=sheet.getRow(i);
          Map mapCbf=new HashMap();
          int cbfRowIndex = 0;
          for(int j=3;j<=8;j++){
            if(StringUtil.isNotEmpty(getCellValue(cbfRow,j).toString())){
              cbfRowIndex=i;
              mapCbf.put(titles.get(j),getCellValue(cbfRow,j).toString());
              mapCbf.put("cbfRowIndex",cbfRowIndex);
              //System.out.println(getCellValue(row,3).toString());
            }
          }
          //System.out.println("承包方数据的列数:"+titles.indexOf("gsshr"));
          for(int j=titles.indexOf("cbfdcrq");j<=titles.indexOf("gsshr");j++){
            //if(StringUtil.isNotEmpty(getCellValue(cbfRow,j).toString())){
              mapCbf.put(titles.get(j),getCellValue(cbfRow,j).toString());
            //}
          }
          //System.out.println(cbfids);
          //下面时提取98年承包方信息数据
          int cbf98index= titles.indexOf("yhzmc98");
          Map map98=new HashMap();
          for(int x=cbf98index;x<=columnCount;x++){
            if(StringUtil.isNotEmpty(getCellValue(cbfRow,x).toString())){
              mapCbf.put(titles.get(x),getCellValue(cbfRow,x).toString());
            }
          }
          //cbfList98.add(map98);
          int columnIndex=titles.indexOf("cbfmc");
          Map dkMap =new HashMap();
          for(int n=titles.indexOf("sfkbdk");n<=titles.indexOf("dkbdh");n++){
            //if(StringUtil.isNotEmpty(getCellValue(cbfRow, n).toString())){
            dkMap.put(titles.get(n), getCellValue(cbfRow, n).toString());
            dkMap.put("dkRowIndex",i);
            //}
          }
          dkxxList.add(dkMap);
          //System.out.println("第" + (i+1) + "条承包方地块数据:"+dkMap);
          Map familiyMap=new HashMap();
          for(int z=titles.indexOf("cyxm");z<=titles.indexOf("cybdrq");z++){
            familiyMap.put(titles.get(z),getCellValue(cbfRow,z));
            familiyMap.put("familyRowIndex",i);
          }
          familyList.add(familiyMap);
          //System.out.println("第" + (i+1) + "条家庭成员数据:"+familyList);
          if(mapCbf.get("elcbdkzs")!=null&&mapCbf.get("cbfRowIndex")!="0") {
            //System.out.println("承包方数据行:"+mapCbf.get("cbfRowIndex"));
            cbfList.add(mapCbf);
            //System.out.println("第" + (i+1) + "条承包方数据:" + JsonUtil.beanToJson(cbfList));
          }
        }
        //System.out.println("总行数:"+sheet.getLastRowNum());
        //System.out.println("承包方所有数据:"+cbfList);
        List<Map> allCbfList =cbfList;
        for(int y=0;y<cbfList.size();y++){
          List dkList=new ArrayList<>();
          List famList=new ArrayList<>();
          Map cbfMap=cbfList.get(y);
          //System.out.println("每个承包方的Map数据:"+cbfMap);
          int cbfRowNum=Integer.parseInt(String.valueOf(cbfMap.get("cbfRowIndex")));
          //System.out.println("数据:"+cbfRowNum);
          if(y==cbfList.size()-1){
            int allRowCount=sheet.getLastRowNum();
            for(int m=cbfRowNum-5;m<=allRowCount-5;m++){
              //System.out.println("承包方每一行的序号:"+m);
              //System.out.println("总行数"+allRowCount);
              int dkRowIndex=Integer.parseInt(String.valueOf(dkxxList.get(m).get("dkRowIndex")));
              if(m==(dkRowIndex-5)){
                if(StringUtil.isNotEmpty(dkxxList.get(m).get("dklb").toString())) {
                  dkxxList.get(m).remove("dkRowIndex");
                  dkList.add(dkxxList.get(m));
                }
                //dkList.addAll(dkxxList);
              }
              int familyRowIndex=Integer.parseInt(String.valueOf(familyList.get(m).get("familyRowIndex")));
              if(m==(familyRowIndex-5)){
                if(StringUtil.isNotEmpty(familyList.get(m).get("cyxm").toString())) {
                  familyList.get(m).remove("familyRowIndex");
                  famList.add(familyList.get(m));
                }
                //famList.addAll(familyList);
              }
            }
          }else{
            Map cbfMap2=cbfList.get(y+1);
            //System.out.println("本条数据:"+cbfMap);
            //System.out.println("下一条数据:"+cbfMap2);
            int cbfRowNum2=Integer.parseInt(String.valueOf(cbfMap2.get("cbfRowIndex")));
            for(int m=cbfRowNum-5;m<cbfRowNum2-5;m++){
              //System.out.println("承包方每一行的详细"+m);
              //System.out.println("所有地块信息的总数:"+dkxxList.size());
              int dkRowIndex=Integer.parseInt(String.valueOf(dkxxList.get(m).get("dkRowIndex")));
              //System.out.println("地块信息的行数:"+dkRowIndex);
              if(m==(dkRowIndex-5)){
                if(StringUtil.isNotEmpty(dkxxList.get(m).get("dklb").toString())) {
                  dkxxList.get(m).remove("dkRowIndex");
                  dkList.add(dkxxList.get(m));
                }
                //dkList.addAll(dkxxList);
                //System.out.println("map数据"+dkxxList.get(m));
              }
              int familyRowIndex=Integer.parseInt(String.valueOf(familyList.get(m).get("familyRowIndex")));
              if(m==(familyRowIndex-5)){
                if(StringUtil.isNotEmpty(familyList.get(m).get("cyxm").toString())){
                  familyList.get(m).remove("familyRowIndex");
                  famList.add(familyList.get(m));
                }
                //famList.addAll(familyList);
                //System.out.println("map数据"+famList);
              }
            }
          }
          //去除列表中为空的项
          //famList.removeAll(Collections.singleton(""));
          //dkList.removeAll(Collections.singleton(""));
          cbfMap.put("jtcyxx",famList);
          cbfMap.put("dkxx",dkList);
          cbfList.get(y).putAll(cbfMap);
          cbfList.get(y).remove("cbfRowIndex");
          System.out.println("承包方数据带家庭成员和地块信息:"+cbfMap);
        }
        //cbfList =getCbfList(cbfList,sheet,dkxxList,familyList);
        //去除隶属列表中为空的项
        cbfList.removeAll(Collections.singleton(null));
        map.put("allcbf",cbfList);
        list.add(map);
        //System.out.println("第" + i + "条承包方数据:" + JsonUtil.beanToJson(list));
        logger.info("所有数据:"+list);
        return list;
      }

    首先,Java对excel的操作用有两种:jxl和poi,这里我用的是poi,所以我准备开始思路:第一行的前三列为第一层数据,然后及接着后面二层数据为承包方户主信息,第三层数据为家庭 成员信息还有地块信息。

    展开全文
  • 1、首先创建一个el-table表,注意ref添加后续有用(其他可自行添加) 2、其次就是创建表单中的行(行内可自行添加template模版) 给其一个type属性(可设置selection、index、expand,具体可上官网查)这里我们用到的...
  • NPOI导出树形结构的EXCEL通用方法

    千次阅读 2018-01-15 15:16:15
    我们先定义几个单元格颜色,以便导出的EXCEL看起来比较赏心悦目。 #region ISheet单元格样式  ///  /// 返回单元格颜色样式  ///  /// 传入的颜色HSSFColor.Blue.Index  /// ISheet  ///  public...
  • java poi导出树形结构到excel文件

    千次阅读 2020-12-08 16:48:05
    } /** * * @Title: buildTree * @Description: 构建树形结构 * @return * List * @throws * @Author XX */ public List buildTree() { List TestDomains = new ArrayList(); List rootNodes = getRootNodes(); for ...
  • 业务场景:xlsx表格当中有5个层级,在导入项目中时要确保页面展示的结构为树形,但是有一些的零部件从属(父类编号)是一样的,这样就给导入表格的程序导致分别不出有一些的零部件是在哪一级的父类下面,所以导入...
  • Vue 使用js-xlsx导出、树形数据合并

    千次阅读 2019-01-14 10:37:28
    Vue 使用js-xlsx导出、树形数据合并 前言:本文档是经过网上查询资料,结合自己的业务整理出来的知识点,希望对看到文档的人有帮助。 实现功能:1.vue使用xlsx基本导出 2.导出合并单元格 已树形数据为例。 数据...
  • 创建监听器,增强数据结构,以的形式返回前端 import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import ...
  • 文章目录一、表结构设计,导入导出模板。二、递归查询结构1.思路如下2.代码示例二、新增结构思路如下三.结构修改。思路如下四、递归删除... Excel表格项目名字段从第一张表获取,忽略即可。 表仅截取几个
  • jQuery Table,这是一个操作简单的jQuery插件,可帮助你将数据创建成可排序的表格。 源码http://codecanyon.net/item/jquery-table/2392027?ref=lvraa/演示...
  • 解压并将其jar文件放入项目lib文件夹下(没有可以自己创建一个) 并在项目配置的库中加入对该jar文件的依赖 4. 前期准备结束,接下来开始写代码 5. 首先准备一个Excel表,并将其转为.csv格式 6. 将
  • Element-ui组件库Table表格导出Excel表格

    万次阅读 多人点赞 2019-04-03 15:45:45
    Element组件库中的el-table表格导出需要的主要是两个依赖:(xlsx 和 file-saver) npm install --save xlsx file-saver <template> <div class="table"> <!--给表格添加一个id,...
  • 基于Vue的Element框架如何快速导出Excel表格 文章目录基于Vue的Element框架如何快速导出Excel表格前言一、如何使用?二、使用步骤1.引入库2.代码总结 前言 转载了别人写的文章链接:...
  • 本文介绍通过Java程序在Excel创建分组的方法,可对行或列分组进行分组并设置明细数据是否展开或折叠。设置数据分组并展开或折叠时,可通过以下方法: 方法一: 通过方法sheet.groupByRows(int firstRow, int lastRow...
  • 在开发过程中,经常会遇到树型的分类结构,而项目后期会根据分类对数据进行统计,不管是后台拼接table还是前后台分离开发方式,总是不能避免对树型结构的表头创建及同项单元格的合并问题,而后面的计算统计列也可能...
  • vue-admin-template-master组件学习-Tree 树形控件(1) 最终效果 一、前端部署 1)router路由 在router文件夹中的index.js中添加路由 { path: '/subject', component: Layout, redirect: '/subject/info', ...
  • 获取如图所示的Excel数据 一. 导入Excel文件 1. 获取Excel文件的地址 String filePath = "Excel的位置"; 2. 获取Excel文件 File excelFile = new File(filePath); 3. 创建工作簿对象 WorkBook wb = ...
  • 其实本来我是想将数据爬取到excel之后再增加一些数据库操作,然后用flash建立一个网站将数据导入这个网站中…还想着下个模板优化一下网站界面实现数据可视化来着… 但!!!当我万分激动地上号我的pycharm,使用pip...
  • 在对数据字段进行分类管理时,利用动态折叠数据是一个很好的方法,也就是点击数据前面的加号才展开对应下面的数据,如下图。那这样的效果在制作报表时该如何实现呢? 下面以报表工具FineReport为例介绍。 ...
  • `create_time` timestamp NULL DEFAULT NULL COMMENT '创建时间', `update_time` timestamp NULL DEFAULT NULL COMMENT '修改时间', PRIMARY KEY (`area_id`) ) ENGINE=InnoDB AUTO_INCREMENT=3424 DEFAULT ...
  • C# NPOI 导出Excel模板 下拉框 级联下拉框 级联选择, 导出模板下载 源码在后面,前面稍微说一下咋回事 首先明白Excel 中 的数据引用咋回事,然后知道INDIRECT 这个函数。 自行搜索 我的需求是 设备类型 分为 ...
  • //加载配置文件(不用Properties读,在配置文件中的表头顺序即为创建Excel表格的顺序) InputStreamReader reader = new InputStreamReader(new FileInputStream("table.properties"), "UTF-8"); BufferedReader ...
  • 创建Excel导入、导出工具类 import com.sec.data.platform.config.ExcelColumn; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.CharUtils; import org.apache.commons.lang3....
  • WPS Excel做多级下拉菜单列表

    千次阅读 2020-06-01 15:35:48
    WPS Excel做多级下拉菜单列表 最近做表格数据需要做一个三级别关联下拉菜单,之前只知道一列下拉菜单是用数据有效性做,三级别的没做过,查了资料,记录一下。 1.一级下拉菜单 选中要添加下拉菜单的数据列,在...
  • //获取树形result的json字符串 string outputFilePath = paths01 + "\\" + "OCR识别" + Path.GetFileNameWithoutExtension(file) + ".xls";//要保存到的output文件夹 HttpWebRequest request = (HttpWebRequest)...
  • 主要解决excel动态模板下拉联动问题: 如图: 下拉联动处理代码: 下拉长度在255以内: private static DataValidation setDataValidation(Sheet sheet, String[] textList, int firstRow, int endRow, int ...
  • 首先介绍POI: Apache POI是Apache软件基金会的开放...HSSF - 提供读写Microsoft Excel格式档案的功能。 XSSF - 提供读写Microsoft Excel OOXML格式档案的功能。 HWPF - 提供读写Microsoft Word格式档案的功...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,532
精华内容 1,012
关键字:

创建excel树形表格