JAVA 使用POI实现单元格行合并

news2024/12/27 16:00:59

POI实现单元格行合并

  • 实现效果
  • 引入jar
  • 代码实现
    • controller层
    • Service层
    • ServiceImpl层实现类

实现效果

你好! 这是你第一次使用 **Markdown编辑器** 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
如果最后面的三行数据大于1时 那么前面十二行就需要行合并

引入jar

 <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>5.2.2</version>
            </dependency>

代码实现

controller层

@PostMapping(value = "getExcel")
    public  void getExcel(@RequestBody BrucellosisListDTO brucellosisListDTO, HttpServletRequest request, HttpServletResponse response){
        businessTaskBrucellosisService.getExcel(brucellosisListDTO,request,response);
    }

Service层

void getExcel(BrucellosisListDTO brucellosisListDTO, HttpServletRequest request, HttpServletResponse response);

ServiceImpl层实现类

@Override
    public void getExcel(BrucellosisListDTO brucellosisListDTO, HttpServletRequest request, HttpServletResponse response) {
        //数据来源
        List<BrucellosisExportExcel> list = queryExcelList(brucellosisListDTO);
        //数据来源 通过参数传入
        String[] masterHead = {"姓名","养殖户类型","手机号码","人口数","所在区域(省)","所在区域(市)","所在区域(区/县)","所在区域(乡镇)","所在区域(乡村)","防疫负责人","养殖总数","布病人数"};
        String[] childHead = {"布病人员","布病人手机号码","布病人身份证号码"};
        int[] widthColumn = new int[]{20,20,25,15,30,30,30,20,30,30,20,15,25,50,50,50};
        //创建Excel工作薄对象
        XSSFWorkbook workbook=new XSSFWorkbook();
        //创建Excel工作表对象
        Sheet sheet = workbook.createSheet("布病人员统计");

       //设置单元格居中
        CellStyle cellStyle = workbook.createCellStyle();
        //设置边框样式
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 上下居中

        //创建行的单元格,从0开始
        Row row = sheet.createRow(0);
        //创建统计单元格
        Cell masterCell=row.createCell(0);
        //设置第一个表头样式
        CellStyle cellStyleHead = workbook.createCellStyle();
        cellStyleHead.setAlignment(HorizontalAlignment.CENTER);
        cellStyleHead.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyleHead.setBorderBottom(BorderStyle.THIN);
        cellStyleHead.setBorderLeft(BorderStyle.THIN);
        cellStyleHead.setBorderRight(BorderStyle.THIN);
        cellStyleHead.setBorderTop(BorderStyle.THIN);
        cellStyleHead.setFillForegroundColor(IndexedColors.LIGHT_TURQUOISE.getIndex());
        cellStyleHead.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        //赋值
        masterCell.setCellValue("养殖户布病人员基本信息统计");
        masterCell.setCellStyle(cellStyleHead);
        //合并列
        CellRangeAddress region = new CellRangeAddress(0, 0, 0, (masterHead.length+childHead.length-1));
        sheet.addMergedRegion(region);
        row.setHeight((short) (3*200));
        // 设置列宽
        for (int i = 0; i <widthColumn.length; i++) {
            sheet.setColumnWidth((short) i, (short) widthColumn[i] * 200);
        }
        //表头 从1开始 设置第二个表头样式
        Row titleRow = sheet.createRow(1);
        //主表头
        for (int i = 0; i < masterHead.length ; i++) {
            Cell msCell = titleRow.createCell(i);
            msCell.setCellStyle(cellStyleHead);
            msCell.setCellValue(masterHead[i]);
        }
        //子表头
        for (int i = 0; i < childHead.length; i++) {
            Cell chcell = titleRow.createCell(masterHead.length+i);
            chcell.setCellStyle(cellStyleHead);
            chcell.setCellValue(childHead[i]);
        }
        //封装数据
        excelPoi(list,sheet,cellStyle,region);
        String fileName = null;
        try {
            fileName = URLEncoder.encode("患布病人员统计","UTF-8");
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".xlsx");
            response.setHeader("filename", fileName + ".xlsx");
            response.setHeader("Pragma", "public");
            response.setHeader("Cache-Control", "no-store");
            response.addHeader("Cache-Control", "max-age=0");
            response.setHeader("Access-Control-Expose-Headers","Content-Disposition");
            OutputStream os = response.getOutputStream();
            workbook.write(os);
            os.flush();
            os.close();
            workbook.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    //数据封装以及塞值方法
  public void excelPoi(List<BrucellosisExportExcel> list, Sheet sheet,CellStyle cellStyle, CellRangeAddress region){

        //封装父表和子表对象
        Map<String, List<BrucellosisExportExcel>> farmerPhoneMap = list.stream().collect(Collectors.groupingBy(BrucellosisExportExcel::getFarmerPhone));
        Set<String> strings = farmerPhoneMap.keySet();
        List<String> farmerPhoneList = new ArrayList<>(strings);
        List<Map<BrucellosisExportExcel,List<BrucellosisExportExcel>>> masterList = new ArrayList<>();
        Map<BrucellosisExportExcel,List<BrucellosisExportExcel>> map = new HashMap();
        for (int i = 0; i < farmerPhoneList.size(); i++) {
            List<BrucellosisExportExcel> brucellosisExportExcels = farmerPhoneMap.get(farmerPhoneList.get(i));
            //养殖户基本信息
            BrucellosisExportExcel brucellosisExportExcel = brucellosisExportExcels.get(0);
            map.put(brucellosisExportExcel,brucellosisExportExcels);
        }
        masterList.add(map);

        //填充数据
        int lastRowIndex = 2; //记录最后行位置
        for (Map<BrucellosisExportExcel,List<BrucellosisExportExcel>> m : masterList){
            for (BrucellosisExportExcel key : m.keySet()){
                List<BrucellosisExportExcel> chlist = m.get(key);
                Row valueRow = sheet.createRow(lastRowIndex);
                Cell farmerNameCell = valueRow.createCell(0);
                farmerNameCell.setCellStyle(cellStyle);
                farmerNameCell.setCellValue(key.getFarmerName());
                if (chlist.size()>1){ //子表数量大于1才进行 行合并
                    region=new CellRangeAddress(lastRowIndex, lastRowIndex+chlist.size()-1, 0, 0);
                    sheet.addMergedRegion(region);
                }

                Cell farmerTypeNameCell = valueRow.createCell(1);
                farmerTypeNameCell.setCellStyle(cellStyle);
                farmerTypeNameCell.setCellValue(key.getFarmerTypeName());
                if (chlist.size()>1){ //子表数量大于1才进行 行合并
                    region=new CellRangeAddress(lastRowIndex, lastRowIndex+chlist.size()-1, 1, 1);
                    sheet.addMergedRegion(region);
                }

                Cell farmerPhoneCell = valueRow.createCell(2);
                farmerPhoneCell.setCellStyle(cellStyle);
                farmerPhoneCell.setCellValue(key.getFarmerPhone());
                if (chlist.size()>1){ //子表数量大于1才进行 行合并
                    region=new CellRangeAddress(lastRowIndex, lastRowIndex+chlist.size()-1, 2, 2);
                    sheet.addMergedRegion(region);
                }

                Cell populationCell = valueRow.createCell(3);
                populationCell.setCellStyle(cellStyle);
                populationCell.setCellValue(key.getPopulation());
                if (chlist.size()>1){ //子表数量大于1才进行 行合并
                    region=new CellRangeAddress(lastRowIndex, lastRowIndex+chlist.size()-1, 3, 3);
                    sheet.addMergedRegion(region);
                }

                Cell provinceNameCell = valueRow.createCell(4);
                provinceNameCell.setCellStyle(cellStyle);
                provinceNameCell.setCellValue(key.getProvinceName());
                if (chlist.size()>1){ //子表数量大于1才进行 行合并
                    region=new CellRangeAddress(lastRowIndex, lastRowIndex+chlist.size()-1, 4, 4);
                    sheet.addMergedRegion(region);
                }

                Cell cityNameCell = valueRow.createCell(5);
                cityNameCell.setCellStyle(cellStyle);
                cityNameCell.setCellValue(key.getCityName());
                if (chlist.size()>1){ //子表数量大于1才进行 行合并
                    region=new CellRangeAddress(lastRowIndex, lastRowIndex+chlist.size()-1, 5, 5);
                    sheet.addMergedRegion(region);
                }

                Cell areaNameCell = valueRow.createCell(6);
                areaNameCell.setCellStyle(cellStyle);
                areaNameCell.setCellValue(key.getAreaName());
                if (chlist.size()>1){ //子表数量大于1才进行 行合并
                    region=new CellRangeAddress(lastRowIndex, lastRowIndex+chlist.size()-1, 6, 6);
                    sheet.addMergedRegion(region);
                }

                Cell townNameCell = valueRow.createCell(7);
                townNameCell.setCellStyle(cellStyle);
                townNameCell.setCellValue(key.getTownshipName());
                if (chlist.size()>1){ //子表数量大于1才进行 行合并
                    region=new CellRangeAddress(lastRowIndex, lastRowIndex+chlist.size()-1, 7, 7);
                    sheet.addMergedRegion(region);
                }

                Cell streetNameCell = valueRow.createCell(8);
                streetNameCell.setCellStyle(cellStyle);
                streetNameCell.setCellValue(key.getStreetName());
                if (chlist.size()>1){ //子表数量大于1才进行 行合并
                    region=new CellRangeAddress(lastRowIndex, lastRowIndex+chlist.size()-1, 8, 8);
                    sheet.addMergedRegion(region);
                }

                Cell personInChargeNameCell = valueRow.createCell(9);
                personInChargeNameCell.setCellStyle(cellStyle);
                personInChargeNameCell.setCellValue(key.getPersonInChargeName());
                if (chlist.size()>1){ //子表数量大于1才进行 行合并
                    region=new CellRangeAddress(lastRowIndex, lastRowIndex+chlist.size()-1, 9, 9);
                    sheet.addMergedRegion(region);
                }

                Cell animalNumCell = valueRow.createCell(10);
                animalNumCell.setCellStyle(cellStyle);
                animalNumCell.setCellValue(key.getAnimalNum());
                if (chlist.size()>1){ //子表数量大于1才进行 行合并
                    region=new CellRangeAddress(lastRowIndex, lastRowIndex+chlist.size()-1, 10, 10);
                    sheet.addMergedRegion(region);
                }

                Cell bruNumCell = valueRow.createCell(11);
                bruNumCell.setCellStyle(cellStyle);
                bruNumCell.setCellValue(key.getBruNum());
                if (chlist.size()>1){ //子表数量大于1才进行 行合并
                    region=new CellRangeAddress(lastRowIndex, lastRowIndex+chlist.size()-1, 11, 11);
                    sheet.addMergedRegion(region);
                }

                for (int i = 0; i < chlist.size(); i++) {
                    BrucellosisExportExcel brucellosisExportExcel = chlist.get(i);
                    Row chRow;
                    if (i == 0){ //避免重复创建 覆盖主表数据
                        chRow = valueRow;
                    }else {
                        chRow  = sheet.createRow(lastRowIndex);
                    }
                    lastRowIndex++;
                    Cell userNameCell = chRow.createCell(12);
                    userNameCell.setCellStyle(cellStyle);
                    userNameCell.setCellValue(brucellosisExportExcel.getUserName());

                    Cell usePhoneCell = chRow.createCell(13);
                    usePhoneCell.setCellStyle(cellStyle);
                    usePhoneCell.setCellValue(brucellosisExportExcel.getUserPhone());

                    Cell idCardCell = chRow.createCell(14);
                    idCardCell.setCellStyle(cellStyle);
                    idCardCell.setCellValue(brucellosisExportExcel.getIdCard());
                }
            }
        }

    }

备注: 由于我这里要合并的列比较多而且牵扯到每一列都不同,所以使用了一行一行去校验和合并的方法;当然 如果需要合并的就只有一行 可以在 excelPoi的第二个for循环里面使用循环合并的方式。

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

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

相关文章

java多线程基本操作方法

目录 一、isAlive&#xff08;&#xff09; 二、 join&#xff08;&#xff09; 三、start和run 四、 volatile() 五、synchronized 1、synchronized 引入 2、死锁 第一种情况&#xff1a;反复加锁 第二种情况 对不同对象嵌套加锁的死锁 3、形成死锁条件 六、wait…

【正点原子FreeRTOS学习笔记】————(10)FreeRTOS时间管理

这里写目录标题 一、延时函数介绍&#xff08;了解&#xff09;二、延时函数解析&#xff08;熟悉&#xff09;三、延时函数演示实验&#xff08;掌握&#xff09; 一、延时函数介绍&#xff08;了解&#xff09; 相对延时&#xff1a;指每次延时都是从执行函数vTaskDelay()开始…

前缀和算法(1)

一维前缀和[模板] 一、题目描述 OJ题目链接&#xff1a;【模板】前缀和_牛客题霸_牛客网 二、思路解析 三、代码 #include <iostream> using namespace std; const int N 100010; long long arr[N], dp[N]; int n, q; int main() {cin >> n >> q;// 读取…

冗余双写方案下数据一致性问题解决及延申问题处理方案

主要整理了采用冗余双写方案后的问题解决方案。 1、问题&#xff1a;冗余双写场景下&#xff0c;如何解决数据一致性问题&#xff1f; 方案一&#xff1a; 直接RPC调用Seata分布式事务框架&#xff0c;采用该方式实现了事务的强一致性&#xff0c;代码逻辑简单的同时业务侵入…

蓝桥杯-正则问题

#include<iostream> #include<string> #include<algorithm> using namespace std;int pos 0, l;//pos当前遍历到的位置&#xff0c;l是正则式的长度 string s;int dfs(){int temp 0, ans 0;//temp保存左半部分 while(pos < l){if(s[pos] (){pos;//跳…

【C语言】C语言基础习题详解(牛客网)二分查找逻辑

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;C语言_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.三目运算符的使用 三目运算符&#xff0c;即a>b?a:b类型的&#xff0c;很多时候适当的使用三目运算符可以使得代码更简洁有序&…

在Python中进行封装

在Python中&#xff0c;封装是一种面向对象编程&#xff08;OOP&#xff09;的特性&#xff0c;它允许我们将数据&#xff08;属性&#xff09;和操作这些数据的方法&#xff08;函数&#xff09;捆绑在一起&#xff0c;形成一个独立的对象。封装的主要目的是隐藏对象的内部状态…

四年创作,心路历程

四年创作&#xff0c;心路历程 前言初识收获日常憧憬 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 前言 今天打开csdn&#xff0c;发现官方发送了一条私信,原来我已经在计算机这…

文件操作(基础知识篇)

1. 文件操作的作用 可以将内存中的数据持久化地存储到文件中。我们所运行的程序的数据是存储在电脑的内存中的&#xff0c;如果不将数据持久化地存储起来&#xff0c;那么在程序退出时&#xff0c;内存中的数据就会随内存的回收而消失。 可以持久化保存数据的&#xff0c;就被…

文件操作(上)(想要了解如何操作文件,那么看这一片就足够了!)

前言&#xff1a;在我们写的程序的的时候&#xff0c;数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失了&#xff0c;等再次运行程序&#xff0c;是看不到上次程序的数据的&#xff0c;那么如果要将数据进行持久化的保存&#xf…

逻辑解析(logical decoding)

pg_create_logical_replication_slot select * from pg_replication_slots; select pg_export_snapshot(); select pg_create_logical_replication_slot(‘logical_slot1’, ‘test_decoding’); CREATE TABLE t_logical(id int4); pg_logical_slot_get_changes SELECT *…

git下载安装教程

git下载地址 有一个镜像的网站可以提供下载&#xff1a; https://registry.npmmirror.com/binary.html?pathgit-for-windows/图太多不截了哈哈&#xff0c;一直next即可。

操作系统的理解|冯·若依曼体系结构|进程的状态

操作系统的理解 冯诺伊曼体系结构为什么必须通过内存然后到cpu存储金字塔冯诺伊曼结构的改进在哪&#xff1f;我们可不可以全部用寄存器来做存储器在硬件数据流动角度学以致用&#xff1a;解释程序运行为什么要加载到内存程序没被运行之前存在哪里&#xff1f; 操作系统概念广义…

H5小程序视频方案解决方案,实现轻量化视频制作

对于许多企业而言&#xff0c;制作高质量的视频仍然是一个技术门槛高、成本高昂的挑战。针对这一痛点&#xff0c;美摄科技凭借其深厚的技术积累和创新能力&#xff0c;推出了面向企业的H5/小程序视频方案解决方案&#xff0c;为企业提供了一种轻量化、高效、便捷的视频制作方式…

flutter布局更新

理论上&#xff0c;某个组件的布局变化后&#xff0c;就可能会影响其他组件的布局&#xff0c;所以当有组件布局发生变化后&#xff0c;最笨的办法是对整棵组件树 relayout&#xff08;重新布局&#xff09;&#xff01;但是对所有组件进行 relayout 的成本还是太大&#xff0c…

目前2024年腾讯云4核8G服务器租用优惠价格表

2024年腾讯云4核8G服务器租用优惠价格&#xff1a;轻量应用服务器4核8G12M带宽646元15个月&#xff0c;CVM云服务器S5实例优惠价格1437.24元买一年送3个月&#xff0c;腾讯云4核8G服务器活动页面 txybk.com/go/txy 活动链接打开如下图&#xff1a; 腾讯云4核8G服务器优惠价格 轻…

车载以太网AVB交换机 TSN交换机 时间敏感网络 6端口 百兆 SW100TSN

SW100 TSN时间敏感网络AVB交换机 为6端口百兆车载以太网交换机&#xff0c;其中包含5通道100BASE-T1泰科MATEnet接口和1个通道100/1000BASE-T标准以太网(RJ45接口)&#xff0c;可以实现纳米级时间同步&#xff0c;车载以太网多通道交换&#xff0c;Bypass数据采集和监控等功能&…

B2 PRO WordPress主题:多功能商用主题,助力资讯、资源、社交、商城、圈子、导航一站式解决

B2 PRO WordPress主题&#xff1a;多功能商用主题&#xff0c;助力资讯、资源、社交、商城、圈子、导航一站式解决 一、产品概述 B2 PRO WordPress主题&#xff0c;作为一款多功能商用主题&#xff0c;致力于为用户提供一站式的内容管理与网站建设服务。它集资讯发布、资源共享…

4.常用CMD命令

扩展一个小点&#xff1a; 在很多资料中都说成是DOS命令&#xff0c;其实是不对的。真正的DOS命令是1981年微软和IBM出品的MS-DOS操作系统中的命令才叫做DOS命令。 而在Windows中&#xff0c;win98之前的操作系统是以非图形化的DOS为基础的&#xff0c;可以叫做DOS命令。到了…

精酿啤酒:特殊酵母的发酵特性与风味表现

Fendi Club啤酒在酿造过程中采用了特殊的酵母&#xff0c;这些酵母具有与众不同的发酵特性和风味表现&#xff0c;为啤酒带来了与众不同的风味和口感。 Fendi Club啤酒使用的酵母种类繁多&#xff0c;包括艾尔酵母和拉格酵母等。这些不同种类的酵母在发酵过程中具有不同的特性和…