POI 导出 树形结构

news2024/11/17 17:29:34

 参考文章:(327条消息) Excel树状数据绘制导出_excel导出树形结构_Deja-vu xxl的博客-CSDN博客icon-default.png?t=N6B9https://blog.csdn.net/weixin_45873182/article/details/120132409?spm=1001.2014.3001.5502


    @Override
    public void exportPlus(String yearMonth, HttpServletRequest request ,HttpServletResponse response) {
        try {
            String fileName = "周进度填报.xlsx";
            ServletOutputStream out = response.getOutputStream();
            HSSFWorkbook workbook = new HSSFWorkbook();
            response.setHeader("content-type", "text/plain");
            response.setHeader("content-type", "application/x-msdownload;");
            response.setContentType("text/plain; charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename="  +  URLEncoder.encode(fileName, "UTF-8"));

            String projectId = tokenService.getProjectId(request);
            List<SysDept> deptIdsByProjectId = sysDeptMapper.getDeptIdsByPeojectId(Long.valueOf(projectId));
            List<SysDept> collect = deptIdsByProjectId.stream().filter(s -> s.getEmail() == null).collect(Collectors.toList());

            if(collect.size()>0){
                for (int i = 0; i <collect.size(); i++) {
                    SysDept sysDept = collect.get(i);
                    String email = sysDept.getEmail();
                    if (email == null){
                        exportPlusByProject(sysDept.getDeptId(),yearMonth,workbook, i, sysDept.getDeptName(), out);
                    }
                }
            }
            
            //原理就是将所有的数据一起写入,然后再关闭输入流。
            out = response.getOutputStream();
            workbook.write(out);
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();

        }
    }



    public void exportPlusByProject(Long zhgdDeptId,String yearMonth,HSSFWorkbook workbook, int sheetNum,String sheetTitle,
                                                     String[] headers,List<List<JSONObject>> data,ServletOutputStream out) {
        try {
           

            //存放数据的二维集合,twoDimensional 中每个List是树状结构的一个分支的所有数据
            List<List<JSONObject>> twoDimensional = new ArrayList<>();

            //******************************查询正文数据******************************
            ZhgdWeeklyProgressReport zhgdWeeklyProgressReport = new ZhgdWeeklyProgressReport();
            zhgdWeeklyProgressReport.setZhgdDeptId(zhgdDeptId);
            zhgdWeeklyProgressReport.setCurrentDates(yearMonth);
            ZhgdWeeklyProgressReport zhgdWeeklyProgressReport1 = weeklyProgressReportService.getlastMonthData(zhgdWeeklyProgressReport);
            String fillingTime1 = zhgdWeeklyProgressReport1.getFillingTime();

            LambdaQueryWrapper<ZhgdWeeklyProgressReport> ZhgdWeeklyProgressReportWrapper = new LambdaQueryWrapper<>();
            ZhgdWeeklyProgressReportWrapper.eq(ZhgdWeeklyProgressReport::getZhgdDeptId,zhgdDeptId)
                    .eq(ZhgdWeeklyProgressReport::getCurrentDates,yearMonth)
                    .eq(ZhgdWeeklyProgressReport::getFillingTime,fillingTime1)
                    .eq(ZhgdWeeklyProgressReport::getIsExists,2)
                    .orderByAsc(ZhgdWeeklyProgressReport::)



            //------------------------------静态数据-----------------------------------

            HashMap<String, Object> stringObjectHashMap0 = new HashMap<>();
            stringObjectHashMap0.put("dictLabel","施工驻地,工地实验室");
            stringObjectHashMap0.put("key1","39");
            stringObjectHashMap0.put("key2","0.65%");
            stringObjectHashMap0.put("key3","767731.2");
            stringObjectHashMap0.put("key4","0.23%");

            HashMap<String, Object> stringObjectHashMap1 = new HashMap<>();
            stringObjectHashMap1.put("dictLabel","施工驻地,工地实验室");

            HashMap<String, Object> stringObjectHashMap2 = new HashMap<>();
            stringObjectHashMap2.put("dictLabel","临时工程与设施");

            ArrayList<JSONObject> list0 = new ArrayList<>();
            list0.add(new JSONObject(stringObjectHashMap0));
            list0.add(new JSONObject(stringObjectHashMap1));
            list0.add(new JSONObject(stringObjectHashMap2));

            //---------------------------第二组list----------------------------------
            HashMap<String, Object> stringObjectHashMap10 = new HashMap<>();
            stringObjectHashMap10.put("dictLabel","拌合站(处)");
            stringObjectHashMap10.put("key1","75");
            stringObjectHashMap10.put("key2","1.24%");
            stringObjectHashMap10.put("key3","444767731.2");
            stringObjectHashMap10.put("key4","1.33%");

            HashMap<String, Object> stringObjectHashMap11 = new HashMap<>();
            stringObjectHashMap11.put("dictLabel","拌合站(处)");

            HashMap<String, Object> stringObjectHashMap12 = new HashMap<>();
            stringObjectHashMap12.put("dictLabel","临时工程与设施");

            ArrayList<JSONObject> list1 = new ArrayList<>();
            list1.add(new JSONObject(stringObjectHashMap10));
            list1.add(new JSONObject(stringObjectHashMap11));
            list1.add(new JSONObject(stringObjectHashMap12));

            twoDimensional.add(list0);
            twoDimensional.add(list1);

            //------------------------------结束------------------------------------

            //------------------------------表头-----------------------------------
            //keys 是表头的字段
            List<String> keys = new ArrayList<>();

            //tier 是动态项目清单的总层级
            Integer tier = 3;
            //创建对象
            //创建工作表
            Sheet sheet = workbook.createSheet();
            workbook.setSheetName(sheetNum, sheetTitle);
            sheet.setDefaultColumnWidth(25);
            short s1  = 2 * 256 ;
            sheet.setDefaultRowHeight(s1);

            CellStyle styleTltles = workbook.createCellStyle();
            styleTltles.setFillForegroundColor(IndexedColors.GREEN.getIndex());

            styleTltles.setAlignment(HorizontalAlignment.CENTER);
            styleTltles.setVerticalAlignment(VerticalAlignment.CENTER);
            //下边框
            styleTltles.setBorderBottom(BorderStyle.THIN);
            //左边框
            styleTltles.setBorderLeft(BorderStyle.THIN);
            //上边框
            styleTltles.setBorderTop(BorderStyle.THIN);
            //右边框
            styleTltles.setBorderRight(BorderStyle.THIN);
            //自动换行
            styleTltles.setWrapText(true);

            //间隔行加背景
            setRowBackground(workbook);

            //columnMap 是一个对象,转换成Json
            //*****************************下面数据请求数据库***********************
            LambdaQueryWrapper<ZhgdWeeklyProgressReport> weeklyProgressReportLambdaQueryWrapper = new LambdaQueryWrapper<>();
            weeklyProgressReportLambdaQueryWrapper.eq(ZhgdWeeklyProgressReport::getCurrentDates,yearMonth)
                                                  .eq(ZhgdWeeklyProgressReport::getZhgdDeptId,zhgdDeptId)
                                                  .groupBy(ZhgdWeeklyProgressReport::getFillingTime)
                                                  .groupBy(ZhgdWeeklyProgressReport::getCreateDatetime)
                                                  .orderByAsc(ZhgdWeeklyProgressReport::getCreateDatetime)
                                                  .select(ZhgdWeeklyProgressReport::getFillingTime);

            List<ZhgdWeeklyProgressReport> weeklyProgressReportList = weeklyProgressReportService.list(weeklyProgressReportLambdaQueryWrapper);

            HashMap<String, Object> columnMap = new HashMap<>(5);
            columnMap.put("单价(元)","单价(元)");
            keys.add("单价(元)");
            columnMap.put("总量","总量");
            keys.add("总量");
            if (weeklyProgressReportList.size()>0){
                weeklyProgressReportList.stream().forEach(entity->{
                    String fillingTime = entity.getFillingTime();
                    String s = fillingTime + "日完成工程量";
                    columnMap.put(s,s);
                    keys.add(s);
                });
            }
            
            columnMap.put("完成工程量合计","完成工程量合计");
            keys.add("完成工程量合计");
            if (weeklyProgressReportList.size()>0){
                weeklyProgressReportList.stream().forEach(entity->{
                    String fillingTime = entity.getFillingTime();
                    String s = fillingTime + "日完成产值(万元)";
                    columnMap.put(s,s);
                    keys.add(s);
                });
            }
            columnMap.put("完成产值(万元)合计","完成产值(万元)合计");
            keys.add("完成产值(万元)合计");
            columnMap.put("截止上月累计完成工程量","截止上月累计完成工程量");
            keys.add("截止上月累计完成工程量");
            columnMap.put("截止上月累计完成产值","截止上月累计完成产值");
            keys.add("截止上月累计完成产值");
            columnMap.put("截止本月累计完成工程量","截止本月累计完成工程量");
            keys.add("截止本月累计完成工程量");
            columnMap.put("累计完成总量占比","累计完成总量占比");
            keys.add("累计完成总量占比");
            columnMap.put("截止本月累计完成产值(万元)","截止本月累计完成产值(万元)");
            keys.add("截止本月累计完成产值(万元)");

            //动态创建首行表头
            JSONObject topBean = new JSONObject();
            Row firstRow = sheet.createRow(0);
            JSONObject cm = new JSONObject(columnMap);
            for (int i = 0; i < tier+keys.size(); i++) {
                Cell cell = firstRow.createCell(i);
                if (i<tier){
                    String s="一";
                    switch (i){
                        case 1 : s="二";break;
                        case 2 : s="三";break;
                    }
                    cell.setCellValue(s+"级分类");
                }else {
                    cell.setCellValue(cm.getString(keys.get(i - tier)));
                }
            }

            //动态绘制数据,tier是层级数,根据业务最多三级
            for (int i = 0; i < twoDimensional.size(); i++) {
                Row row = sheet.createRow(i+1);
                List<JSONObject> list = twoDimensional.get(i);

                for (int j = 0; j < keys.size()+tier; j++) {
                    Cell cell = row.createCell(j);
                    if (j<tier){
                        //绘制层级标签
                        if (j==0){
                            JSONObject jsonObject = list.get(tier - 1);
                            cell.setCellValue(jsonObject.getString("dictLabel"));
                            continue;
                        }
                        if (j==1){
                            Map map = list.get(tier - 2);
                            cell.setCellValue((String)map.get("dictLabel"));
                            continue;
                        }
                        if (j==2){
                            Map map = list.get(tier - 3);
                            cell.setCellValue((String)map.get("dictLabel"));
                            continue;
                        }
                    }else {
                        //绘制层级的数据
                        JSONObject bean = new JSONObject(list.get(0));
                        cell.setCellValue(bean.getString(keys.get(j - tier)));
                    }
                }
            }

            //添加总合计行,并合并单元格
            Row totalRow = sheet.createRow(twoDimensional.size()+1);
            for (int j = 0; j < keys.size()+tier; j++) {
                Cell cell = totalRow.createCell(j);
                if (j<tier){
                    cell.setCellValue("合计");
                }else {
                    cell.setCellValue(topBean.getString(keys.get(j - tier)));
                }
            }
            if (tier != 1){
                sheet.addMergedRegion(new CellRangeAddress(twoDimensional.size()+1,twoDimensional.size()+1,0,tier-1));
            }

            //合并相同的单元格
            int lastRowNum = sheet.getLastRowNum();
            int index = 0;
            //根据业务只有标签这几列需要合并
            for (int i = 0; i < tier-1; i++) {
                //比较相邻cell的值是否相同,并记录
                for (int j = 0; j < lastRowNum; j++) {
                    Row row = sheet.getRow(j);
                    Cell cell = row.getCell(i);
                    Cell cell2 = row.getCell(i+1);
                    String stringCellValue = cell.getStringCellValue();
                    String stringCellValueNextRow = cell2.getStringCellValue();
                    if ("合计".equals(stringCellValue)){
                        sheet.addMergedRegion(new CellRangeAddress(j,j,i,i+1));
                        continue;
                    }

                    Row nextRow = sheet.getRow(j+1);
                    Cell nextcell = nextRow.getCell(i);
                    String nextStringCellValue = nextcell.getStringCellValue();
                    if (stringCellValue.equals(nextStringCellValue)){
                        if (j+1 == lastRowNum){
                            if (index != 0){
                                sheet.addMergedRegion(new CellRangeAddress(j-index,j+1,i,i));
                                index = 0;
                            }
                        }else {
                            index++;
                        }
                    }else {
                        if (index != 0){
                            sheet.addMergedRegion(new CellRangeAddress(j-index,j,i,i));
                            index = 0;
                        }
                    }
                    //横向合并
                    // row-- 相邻的如果相同合并
                    if (stringCellValueNextRow.equals(stringCellValue) && j != 0 ){
                        sheet.addMergedRegionUnsafe(new CellRangeAddress(j,j,i,i+1));
                    }

                }
            }

        }catch (Exception e){
            e.printStackTrace();
        }
    }

导出样式

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/803381.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SQL-每日一题【627. 变更性别】

题目 Salary 表&#xff1a; 请你编写一个 SQL 查询来交换所有的 f 和 m &#xff08;即&#xff0c;将所有 f 变为 m &#xff0c;反之亦然&#xff09;&#xff0c;仅使用 单个 update 语句 &#xff0c;且不产生中间临时表。 注意&#xff0c;你必须仅使用一条 update 语句…

Bad owner or permissions on ~/.ssh/config

错误原因&#xff1a;设置本地所有文件的权限为741等。。。 在执行ssh免密码登录时报如下的错误&#xff1a;Bad owner or permissions on ~/.ssh/config。 解决方案&#xff1a; chmod 600 ~/.ssh/config

MySQL笔记——数据库当中的事务以及Java实现对数据库进行增删改查操作

系列文章目录 MySQL笔记——MySQL数据库介绍以及在Linux里面安装MySQL数据库&#xff0c;对MySQL数据库的简单操作&#xff0c;MySQL的外接应用程序使用说明 MySQL笔记——表的修改查询相关的命令操作 MySQL案例——多表查询以及嵌套查询 文章目录 系列文章目录 前言 一…

OpenLayers入门,html原生网页如何使用OpenLayers地图

专栏目录: OpenLayers入门教程汇总目录 前言 尽管现在大部分网页都是使用vue或者react开发了,但是还是有不少开发者使用的是网页原生html进行开发,或者是老项目维护的需要,所以为了照顾使用html原生网页的同学们,本章简单讲解一下如何使用原始html网页情况下使用OpenLay…

网站服务器出错的原因分析和解决方法

​  网站在日常运行的过程中&#xff0c;难免会遇见一些问题&#xff0c;这次我们就来分析关于网站服务器出错、服务器异常的原因以及如何解决网站服务器错误的方法。 如何知道是网站服务器的问题呢? 只要网站不能正常访问运行&#xff0c;那么一定会反馈相关的错误代码和原…

Ubuntu18.04下编译qgc源码

写在前面 在下载前必须说明&#xff0c;根据你的qgc源码版本进行下载&#xff0c;有的源码必须要求Qt是5.15版本以上。 个人所使用开发软件 版本QT5.12.9qgc源码V4.0Ubuntu18.04 QT下载 &#xff08;1&#xff09;我们可以去官网下载官网下载地址具体的下载方法这里不用多说&a…

【Docker 学习笔记】Docker架构及三要素

文章目录 一、Docker 简介二、Docker 架构1. Docker 客户端和服务器2. Docker 架构图3. Docker 运行流程图 三、Docker 三要素1. 镜像&#xff08;Image&#xff09;2. 容器&#xff08;Container&#xff09;3. 仓库&#xff08;Repository&#xff09; 一、Docker 简介 Dock…

【100天精通python】Day19:python文件及目录操作_基本文件操作

目录 专栏导读 1 文件的创建打开和关闭 2.1 使用内置函数open(),close()创建打开和关闭 2.2 使用with语句打开和关闭 2 文件的读取 2.1 读取整个文件read() 2.2 逐行读取文件内容readlines() 3 文件的写入 3.1 直接写入 3.2 写入整个文件 3.3 逐行写入文件 4 文件…

SAP 密码管理(自动登录)

前提&#xff1a; Office excel版本2013及更高版本 SAP系统启用GUI脚本 RZ11: 参数sapgui/user_scripting 修改为 TRUE 一&#xff1a;安装Excel插件&#xff0c;并维护登陆信息 二&#xff1a;登陆系统 插件下载链接&#xff1a; (185条消息) SAP密码管理excle插件资源-C…

windows下使用pytorch进行单机多卡分布式训练

首先&#xff0c;pytorch的版本必须是大于1.7&#xff0c;这里使用的环境是&#xff1a; pytorch1.12cu11.6 四张4090显卡 python3.7.6使用nn.DataParallel进行分布式训练 这一种方式较为简单&#xff1a; 首先我们要定义好使用的GPU的编号&#xff0c;GPU按顺序依次为0,1,2,3…

微信小程序nodejs+vue房屋租赁交易租房平台

本系统功分为用户&#xff0c;经纪人&#xff0c;管理员三个角色&#xff0c;其中用户可以进行注册登陆系统&#xff0c;用户可以查看中介门店&#xff0c;查看经纪人&#xff0c;在线预定房源&#xff0c;在线租赁房源&#xff0c;可以发布求购房源&#xff0c;求租房源&#…

Mac/win开发快捷键、vs插件、库源码、开发中的专业名词

目录 触控板手势&#xff08;2/3指&#xff09; 鼠标右键 快捷键 鼠标选择后shift⬅️→改变选择 mac command⬅️&#xff1a;删除←边的全部内容 commadtab显示下栏 commandshiftz向后撤回 commandc/v复制粘贴 command ⬅️→回到行首/末 commandshift3/4截图 飞…

element dialog弹出框层级错乱问题

需要加modal-append-to-body 默认为true&#xff0c;遮罩层是否插入至 body 元素上&#xff0c;若为 false&#xff0c;则遮罩层会插入至 Dialog 的父元素上。 为false时的HTML结构 为true时的HTML结构 出现弹框层级错乱问题时可以modal-append-to-body是否设置为false了。

【LS科技芯团队成立】基础研究是科学之本、技术之源、创新之魂

目录 LS科技芯团队简介 团队创建人 成立本团队的核心目的 来自各个省份的大佬专家们 加入LS科技芯团队吧&#xff01; LS科技芯团队简介 “LS科技芯”团队于2023年7月25日下午成立。汇聚了来自各个省份的技术博主&#xff0c;涵盖了电子技术&#xff0c;程序设计&#xff0c;…

软件兼容性测试中需注意的关键问题

在进行软件兼容性测试时&#xff0c;有一些关键问题需要特别注意&#xff0c;以确保测试的准确性和全面性。本文将介绍一些在软件兼容性测试中需注意的关键问题&#xff0c;帮助测试人员更好地进行兼容性测试工作。 首先&#xff0c;测试范围&#xff0c;测试人员需要明确测试的…

sql查询语句大全-详细讲解(格式、示例)

目录 范围查询 BETWEEN...AND in 为空 模糊查询 去重查询 AND OR 排序查询 聚合函数 1.count&#xff1a;计算个数 2.max&#xff1a;计算最大值 3.min&#xff1a;计算最小值 4.sum&#xff1a;计算和 5.avg&#xff1a;计算平均数 分组查询 group by 分组后…

vite / nuxt3 项目使用define配置/自定义,可以使用process.env.xxx获取的环境变量

每日鸡汤&#xff1a;每个你想要学习的瞬间&#xff0c;都是未来的你向自己求救 首先可以看一下我的这篇文章了解一下关于 process.env 的环境变量。 对于vite项目&#xff0c;在我们初始化项目之后&#xff0c;在浏览器中打印 process.env&#xff0c;只有 NODE_ENV这个变量&…

【HMS Core】统一扫描连续扫码、闪光灯关闭问题

【问题描述1】 使用Default View Mode进行扫码&#xff0c;如何实现连续扫码 【解决方案】 在默认扫码模式Default View中&#xff0c;功能是集成在SDK内部的&#xff0c;无法设置连续扫码模式等信息。 可以使用Customized View Mode这种模式&#xff0c;它提供了相关的api可…

【一天三道算法题】代码随想录——Day14

一. 有效的括号 题目链接&#xff1a;力扣 思路&#xff1a;无非三种情况&#xff1a; 1. 左侧括号多&#xff0c;右侧少 2. 左右侧一样多&#xff0c;该字符串属于有小括号字符串 3. 右侧括号多&#xff0c;左侧少 那么说白了就是要比较左右括号的数量&#xff0c;谁多&…

KNN背景分割算法

以下代码用OpenCV实现了视频中背景消除和提取的建模&#xff0c;涉及到KNN&#xff08;K近邻算法&#xff09;&#xff0c;真题效果比较好&#xff0c;可以用来进行状态分析。 原理如下&#xff1a; 背景建模&#xff1a;在背景分割的开始阶段&#xff0c;建立背景模型。 前景…