Java基于POI动态合并单元格

news/2024/7/21 6:27:25 标签: java, excel, 开发语言

Java使用poi导出excel

  • 前言
    • 1.Excel和POI对象对应关系:
    • 2.POI创建Excel的步骤
  • 一、引入依赖
  • 二、示例
    • 1.准备数据
    • 2.创建Excel工作簿对象
    • 3.给excel创建表头
    • 4.填充数据
    • 5.浏览器访问下载excel
    • 6.完整代码


前言

有个需求需要后端将数据导出为excel。并且excel中需要合并单元格。于是在网上找到了poi这个包。

首先要根据数据或者excel模板构建出表头。然后将表头和数据想办法进行关联进行循环添加。

效果图:
在这里插入图片描述

1.Excel和POI对象对应关系:

Excel结构POI对象
excel 的文档对象HSSFWorkbook
excel 的表单(sheet)HSSFSheet
excel 的行HSSFRow
excel 的格子单元HSSFCell

2.POI创建Excel的步骤

  1. 生成文档对象HSSHWorkbook。
  2. 通过HSSFWorkbook生成表单HSSFSheet。
  3. 通过HSSFSheet生成行HSSFRow
  4. 通过HSSFRow生成单元格HSSFCell。

一、引入依赖

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

二、示例

1.准备数据

java"> String[] masterHead = {"学号","姓名","专业"};
 String[] childHead = {"课程名称","上课地点","任课教师","上课时间"};
 List<String[]> childList = new ArrayList<>();
 childList.add(new String[]{"Java程序设计","1号楼302","雷老师","2022/8/30 15:53:49"});
 childList.add(new String[]{"数据结构","1号楼305","雷老师","2022/8/30 9:18:28"});
 List<String[]> childList1 = new ArrayList<>();
 childList1.add(new String[]{"计算机网络","2号楼301","方老师","2022/8/30 15:53:49"});
 List<Map<String,List<String[]>>> masterList = new ArrayList<>();
 Map<String,List<String[]>> map = new HashMap();
 map.put("20210211-张晓-计算机与科学",childList);
 map.put("20210211-张2-计算机与科学",childList);
 map.put("20210212-于丽-电子信息工程",childList1);
 masterList.add(map);

2.创建Excel工作簿对象

java"> //创建Excel工作薄对象
 HSSFWorkbook workbook=new HSSFWorkbook();
 //创建Excel工作表对象
 HSSFSheet sheet = workbook.createSheet("wj");
 //设置单元格居中
 HSSFCellStyle cellStyle = workbook.createCellStyle();
 cellStyle.setAlignment(HorizontalAlignment.CENTER);
 //设置边框
 cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
 cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
 cellStyle.setBorderTop(BorderStyle.THIN);//上边框
 cellStyle.setBorderRight(BorderStyle.THIN);//右边框

excel_77">3.给excel创建表头

然后根据需求一行行来给工作表格填充数据,首先是复杂表头,第一行是主表和子表,主表和子表的是合并列,根据主子表头的长度来确定,合并的列数;第二行是表头,根据主子表头的数组来填充。

java"> //创建行的单元格,从0开始
        HSSFRow row = sheet.createRow(0);
        //创建统计单元格
        HSSFCell masterCell=row.createCell(0);
        //赋值
        masterCell.setCellValue("主表");
        masterCell.setCellStyle(cellStyle);
        //合并列
        CellRangeAddress region=new CellRangeAddress(0, 0, 0, masterHead.length-1);
        sheet.addMergedRegion(region);

        //创建详情单元格  从统计单元格的后一格开始创建
        HSSFCell childCell = row.createCell(masterHead.length);
        //赋值
        childCell.setCellValue("子表");
        childCell.setCellStyle(cellStyle);
        //合并列
        region=new CellRangeAddress(0, 0, masterHead.length, masterHead.length+childHead.length-1);
        sheet.addMergedRegion(region);


        //表头 从1开始
        HSSFRow titleRow = sheet.createRow(1);
        //主表头
        for (int i = 0; i < masterHead.length ; i++) {
            HSSFCell msCell = titleRow.createCell(i);
            msCell.setCellStyle(cellStyle);
            msCell.setCellValue(masterHead[i]);
        }
        //子表头
        for (int i = 0; i < childHead.length; i++) {
            HSSFCell chcell = titleRow.createCell(masterHead.length+i);
            chcell.setCellStyle(cellStyle);
            chcell.setCellValue(childHead[i]);
        }

4.填充数据

    //填充数据
        int lastRowIndex = 2; //记录最后行位置
        for (Map<String,List<String[]>> m : masterList){
            for (String key : m.keySet()){
                String[] ms = key.split("-");
                List<String[]> chlist = m.get(key);
                HSSFRow valueRow = sheet.createRow(lastRowIndex);
                for (int i = 0; i < ms.length ; i++) {
                    HSSFCell mscell = valueRow.createCell(i);
                    mscell.setCellStyle(cellStyle);
                    mscell.setCellValue(ms[i]);
                    if (chlist.size()>1){ //子表数量大于1才进行 行合并
                        region=new CellRangeAddress(lastRowIndex, lastRowIndex+chlist.size()-1, i, i);
                        sheet.addMergedRegion(region);
                    }
                }
                for (int i = 0; i < chlist.size(); i++) {
                    String[] chstrs = chlist.get(i);
                    HSSFRow chRow;
                    if (i == 0){ //避免重复创建 覆盖主表数据
                        chRow = valueRow;
                    }else {
                        chRow  = sheet.createRow(lastRowIndex);
                    }
                    lastRowIndex++;
                    for (int j = 0; j < chstrs.length; j++) {
                        HSSFCell chcell = chRow.createCell(ms.length+j);
                        chcell.setCellStyle(cellStyle);
                        chcell.setCellValue(chstrs[j]);
                    }
                }
            }
        }

excel_156">5.浏览器访问下载excel

        //设置下载头部文件信息
        response.setContentType("application/octet-stream; charset=utf-8");//以流的形式对文件进行下载
        response.setHeader("Content-Disposition", "attachment;filename="  + URLEncoder.encode("demo.xls", "UTF-8"));
        workbook.write(response.getOutputStream());
        response.getOutputStream().close();

6.完整代码

 @GetMapping("/")
    public void exportExcel(HttpServletResponse response) throws IOException {
        String[] masterHead = {"学号","姓名","专业"};
        String[] childHead = {"课程名称","上课地点","任课教师","上课时间"};
        List<String[]> childList = new ArrayList<>();
        childList.add(new String[]{"Java程序设计","1号楼302","雷老师","2022/8/30 15:53:49"});
        childList.add(new String[]{"数据结构","1号楼305","雷老师","2022/8/30 9:18:28"});
        List<String[]> childList1 = new ArrayList<>();
        childList1.add(new String[]{"计算机网络","2号楼301","方老师","2022/8/30 15:53:49"});
        List<Map<String,List<String[]>>> masterList = new ArrayList<>();
        Map<String,List<String[]>> map = new HashMap();
        map.put("20210211-张晓-计算机与科学",childList);
        map.put("20210211-张2-计算机与科学",childList);
        map.put("20210212-于丽-电子信息工程",childList1);
        masterList.add(map);


        //创建Excel工作薄对象
        HSSFWorkbook workbook=new HSSFWorkbook();
        //创建Excel工作表对象
        HSSFSheet sheet = workbook.createSheet("wj");
        //设置单元格居中
        HSSFCellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
        cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
        cellStyle.setBorderTop(BorderStyle.THIN);//上边框
        cellStyle.setBorderRight(BorderStyle.THIN);//右边框
        //创建行的单元格,从0开始
        HSSFRow row = sheet.createRow(0);
        //创建统计单元格
        HSSFCell masterCell=row.createCell(0);
        //赋值
        masterCell.setCellValue("主表");
        masterCell.setCellStyle(cellStyle);
        //合并列
        CellRangeAddress region=new CellRangeAddress(0, 0, 0, masterHead.length-1);
        sheet.addMergedRegion(region);

        //创建详情单元格  从统计单元格的后一格开始创建
        HSSFCell childCell = row.createCell(masterHead.length);
        //赋值
        childCell.setCellValue("子表");
        childCell.setCellStyle(cellStyle);
        //合并列
        region=new CellRangeAddress(0, 0, masterHead.length, masterHead.length+childHead.length-1);
        sheet.addMergedRegion(region);


        //表头 从1开始
        HSSFRow titleRow = sheet.createRow(1);
        //主表头
        for (int i = 0; i < masterHead.length ; i++) {
            HSSFCell msCell = titleRow.createCell(i);
            msCell.setCellStyle(cellStyle);
            msCell.setCellValue(masterHead[i]);
        }
        //子表头
        for (int i = 0; i < childHead.length; i++) {
            HSSFCell chcell = titleRow.createCell(masterHead.length+i);
            chcell.setCellStyle(cellStyle);
            chcell.setCellValue(childHead[i]);
        }

        //填充数据
        int lastRowIndex = 2; //记录最后行位置
        for (Map<String,List<String[]>> m : masterList){
            for (String key : m.keySet()){
                String[] ms = key.split("-");
                List<String[]> chlist = m.get(key);
                HSSFRow valueRow = sheet.createRow(lastRowIndex);
                for (int i = 0; i < ms.length ; i++) {
                    HSSFCell mscell = valueRow.createCell(i);
                    mscell.setCellStyle(cellStyle);
                    mscell.setCellValue(ms[i]);
                    if (chlist.size()>1){ //子表数量大于1才进行 行合并
                        region=new CellRangeAddress(lastRowIndex, lastRowIndex+chlist.size()-1, i, i);
                        sheet.addMergedRegion(region);
                    }
                }
                for (int i = 0; i < chlist.size(); i++) {
                    String[] chstrs = chlist.get(i);
                    HSSFRow chRow;
                    if (i == 0){ //避免重复创建 覆盖主表数据
                        chRow = valueRow;
                    }else {
                        chRow  = sheet.createRow(lastRowIndex);
                    }
                    lastRowIndex++;
                    for (int j = 0; j < chstrs.length; j++) {
                        HSSFCell chcell = chRow.createCell(ms.length+j);
                        chcell.setCellStyle(cellStyle);
                        chcell.setCellValue(chstrs[j]);
                    }
                }
            }
        }


  //设置下载头部文件信息
        response.setContentType("application/octet-stream; charset=utf-8");//以流的形式对文件进行下载
        response.setHeader("Content-Disposition", "attachment;filename="  + URLEncoder.encode("demo.xls", "UTF-8"));
        workbook.write(response.getOutputStream());
        response.getOutputStream().close();

    }

http://www.niftyadmin.cn/n/248086.html

相关文章

GaussDB

GaussDB分布式和主备的区别 GaussDB分布式和主备的区别主要在于数据的存储和管理方式以及系统的可用性。 数据存储和管理方式&#xff1a;在主备模式下&#xff0c;数据只存储在主节点上&#xff0c;备节点只是主节点的备份&#xff0c;主节点负责处理所有的数据读写请求&…

MySQL 服务的启动和停止

4.MySQL 服务的启动和停止_mysql数据库启停_头疼小宇的博客-CSDN博客

粒子组件解析

1. GameObject → Create Other → Particle System。 2. 选中 Particle System&#xff0c;可看到下列屬性&#xff1a; 3.Particle System&#xff1a; Duration&#xff1a; 粒子发射时间(设定为5秒&#xff0c;每5秒发射一次粒子)。 Looping&#xff1a;是否循环产生粒子…

看板与 Scrum:有什么区别?

看板和Scrum是项目管理方法论&#xff0c;以小增量完成项目任务并强调持续改进。但是他们用来实现这些目标的过程是不同的。看板以可视化任务和连续流程为中心&#xff0c;而Scrum更多是关于为每个交付周期实施时间表和分配设定角色。 在看板和Scrum之间做出选择并不总是必要…

OpenAI对实现强人工智能AGI的规划:《Planing for AGI and beyond》

OpenAI对实现AGI的长期和短期的计划&#xff1a;《Planing for AGI and beyond》 返回论文和资料目录 原文地址 1.导读 OpenAI最近这些年发布了很多令人印象深刻的模型&#xff0c;毫无疑问&#xff0c;OpenAI已经走在了人工智能领域的最前沿。但是很多人只注意到这些模型&…

酷雷曼一站式图片直播,助力品牌高效传播

传统模式下&#xff0c;摄影师拍摄会议、活动现场的照片后&#xff0c;一般需要7-10天时间才能完成成片交付&#xff0c;而实际上&#xff0c;由于新闻宣传的即时性&#xff0c;照片延迟交付&#xff0c;远远不能满足客户的需求。因此&#xff0c;即时图片直播技术应运而生&…

Efficient Attention: Attention with Linear Complexities

paper: https://arxiv.org/pdf/1812.01243.pdf 这里写目录标题 一、引言二、方法实现高效注意力的解释效率优势 三、实验消融插入层键的维度骨干架构 一、引言 注意机制在计算机视觉和自然语言处理中有着广泛的应用。最近的工作开发了点积注意力机制&#xff0c;并将其应用于…

Kafka Streams基础操作——连接kafka生产者与消费者

目录 1.添加依赖 2.创建两个kafka的topic主题 3.IDEA代码实现一个主题到另一个主题之间的桥梁&#xff1a; 4.运行IDEA代码 5.开启生产者并生产消息 6.开启消费者&#xff0c;就能消费消息 1.添加依赖 <dependency><groupId>org.apache.kafka</groupId&g…