全网最细讲解如何实现导出Excel压缩包文件

news2025/2/24 20:33:48

在这里插入图片描述

写在前面的话

接下来我会使用传统的RESTful风格的方式结合MVC的开发模式给大家介绍一下如何去实现标题的效果。

基本思路讲解

  1. 先从数据库中查询出一组人员信息记录,保存在List list中。
  2. 遍历这个列表,对于每一个人员信息,将其填充到一个Excel模板文件中,生成一个新的Excel文件。这个模板文件在项目的"classpath:excel/demo.xlsx"路径下。填充过程是通过getSheets方法完成的。
  3. 通过传入的InputStream对象(对应Excel模板文件的输入流)创建一个XSSFWorkbook对象,代表整个Excel工作簿。遍历工作簿中的所有工作表(Sheet),对于每一个工作表,遍历其中的所有行(Row),再对每一行中的所有单元格(Cell),进行模板替换。模板替换的过程是:检查当前单元格的类型,如果是字符串类型,检查其中是否包含某个模板标记,如果包含,则替换为对应的人员信息。例如,如果单元格中的文本是"${psnName}",则将其替换为当前人员的名字(t.getSponsorName())。以上过程完成后,返回填充完成的工作簿对象。然后将这个对象写入到一个ByteArrayOutputStream对象中,一起存入列表excelFiles中。
  4. 将所有生成的Excel文件打包成一个zip文件,然后通过HttpServletResponse对象将zip文件写回给客户端

Controller层的代码

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author 舒一笑
 * @since 2023-09-24
 */
@RestController
@RequestMapping("/demo02/personnelInfo")
public class PersonnelInfoController {

  @Autowired
    private IPersonnelInfoService service;

    @PostMapping("/downloadZip")
    @ApiOperation(value = "个人模板压缩包导出")
    public void downloadZip(HttpServletResponse response){
        try {
            service.downloadZip(response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Service层代码

接口层

/**
 * <p>
 *  服务类
 * </p>
 *
 * @author 舒一笑
 * @since 2023-09-24
 */
public interface IPersonnelInfoService extends IService<PersonnelInfo> {

    void downloadZip(HttpServletResponse response);
}

实现类层

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 舒一笑
 * @since 2023-09-24
 */
@Service
public class PersonnelInfoServiceImpl extends ServiceImpl<PersonnelInfoMapper, PersonnelInfo> implements IPersonnelInfoService {


    @Override
    public void downloadZip(HttpServletResponse response) {
        // 数据查询
        List<PersonnelInfo> list = this.list();
        // 文件生成
        List<Map.Entry<String, ByteArrayOutputStream>> excelFiles = new ArrayList<>();
        list.forEach(t ->{
            // 读取excel文件
            try {
                ClassPathResource classPathResource = new ClassPathResource("excel/demo.xlsx");
                InputStream inputStream = classPathResource.getInputStream();
                Workbook workbook = getSheets(t, inputStream);
                ByteArrayOutputStream excelByteArrayOutputStream = new ByteArrayOutputStream();
                workbook.write(excelByteArrayOutputStream);
                // 将每个人的名字作为文件名保存
//                SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
                String format = formatter.format(t.getCreateTime());
                String fileName = t.getSponsorName() + "-"+format;
                excelFiles.add(new AbstractMap.SimpleEntry<>(fileName, excelByteArrayOutputStream));
                inputStream.close();
                excelByteArrayOutputStream.close();
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
        // 压缩导出
        try {
            response.setContentType("application/zip");
            String fileName = URLEncoder.encode("压缩包导出","UTF-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".zip");
            ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
            for (int i = 0; i < excelFiles.size(); i++) {
                Map.Entry<String, ByteArrayOutputStream> excelFileEntry = excelFiles.get(i);
                ZipEntry entry = new ZipEntry(excelFileEntry.getKey() + ".xlsx");
                zos.putNextEntry(entry);
                zos.write(excelFileEntry.getValue().toByteArray());
                zos.closeEntry();
                excelFileEntry.getValue().close();
            }
            zos.finish();
            zos.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 模板替换
     * @param t
     * @param inputStream
     * @return
     * @throws IOException
     */
    private static Workbook getSheets(PersonnelInfo t, InputStream inputStream) throws IOException {
        Workbook workbook = new XSSFWorkbook(inputStream);
        // 遍历所有的sheet
        Iterator<Sheet> sheetIterator = workbook.sheetIterator();
        while (sheetIterator.hasNext()) {
            Sheet sheet = sheetIterator.next();
            // 遍历sheet中所有的行
            Iterator<Row> rowIterator = sheet.rowIterator();
            while (rowIterator.hasNext()) {
                Row row = rowIterator.next();
                // 遍历行中所有的单元格
                Iterator<Cell> cellIterator = row.cellIterator();
                while (cellIterator.hasNext()) {
                    Cell cell = cellIterator.next();
                    // 如果单元格类型是字符串,则查找并替换
                    if (cell.getCellType() == CellType.STRING && cell.getStringCellValue().contains("${psnName}")) {
                        String newCellValue = cell.getStringCellValue().replace("${psnName}", t.getSponsorName()!= null ? t.getSponsorName() : "");
                        cell.setCellValue(newCellValue);
                    } else if (cell.getCellType() == CellType.STRING && cell.getStringCellValue().contains("${psnNum}")) {
                        String newCellValue = cell.getStringCellValue().replace("${psnNum}", t.getSponsorName()!= null ? t.getSponsorName() : "");
                        cell.setCellValue(newCellValue);
                    } else if (cell.getCellType() == CellType.STRING && cell.getStringCellValue().contains("${personTypeName}")) {
                        String newCellValue = cell.getStringCellValue().replace("${personTypeName}", t.getSponsorName() != null ? t.getSponsorName() : "");
                        cell.setCellValue(newCellValue);
                    } else if (cell.getCellType() == CellType.STRING && cell.getStringCellValue().contains("${posName}")) {
                        String newCellValue = cell.getStringCellValue().replace("${posName}", t.getSponsorName() != null ? t.getSponsorName() : "");
                        cell.setCellValue(newCellValue);
                    } else if (cell.getCellType() == CellType.STRING && cell.getStringCellValue().contains("${suitUnitName}")) {
                        String newCellValue = cell.getStringCellValue().replace("${suitUnitName}", t.getSponsorName()!= null ? t.getSponsorName() : "");
                        cell.setCellValue(newCellValue);
                    } else if (cell.getCellType() == CellType.STRING && cell.getStringCellValue().contains("${orgName}")) {
                        String newCellValue = cell.getStringCellValue().replace("${orgName}", t.getSponsorName()!= null ? t.getSponsorName() : "");
                        cell.setCellValue(newCellValue);
                    } else if (cell.getCellType() == CellType.STRING && cell.getStringCellValue().contains("${periodName}")) {
                        String newCellValue = cell.getStringCellValue().replace("${periodName}", t.getSponsorName()!= null ? t.getSponsorName() : "");
                        cell.setCellValue(newCellValue);
                    } else if (cell.getCellType() == CellType.STRING && cell.getStringCellValue().contains("${interviewTime}")) {
                        // 定义日期时间格式
                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
//                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
                        String newCellValue = cell.getStringCellValue().replace("${interviewTime}", formatter.format(t.getCreateTime())!= null ? formatter.format(t.getCreateTime()) : "");
                        cell.setCellValue(newCellValue);
                    } else if (cell.getCellType() == CellType.STRING && cell.getStringCellValue().contains("${performanceReview}")) {
                        String newCellValue = cell.getStringCellValue().replace("${performanceReview}", t.getSponsorName()!= null ? t.getSponsorName() : "");
                        cell.setCellValue(newCellValue);
                    } else if (cell.getCellType() == CellType.STRING && cell.getStringCellValue().contains("${improvePropose}")) {
                        String newCellValue = cell.getStringCellValue().replace("${improvePropose}", t.getSponsorName()!= null ? t.getSponsorName() : "");
                        cell.setCellValue(newCellValue);
                    }else if (cell.getCellType() == CellType.STRING && cell.getStringCellValue().contains("${improvePlan}")) {
                        String newCellValue = cell.getStringCellValue().replace("${improvePlan}", t.getSponsorName()!= null ? t.getSponsorName() : "");
                        cell.setCellValue(newCellValue);
                    }
                }
            }
        }
        return workbook;
    }

}

模板展示

部分业务信息我直接模糊掉了,希望小伙伴理解。
在这里插入图片描述

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

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

相关文章

小白学Python:提取Word中的所有图片,只需要1行代码

#python# 大家好&#xff0c;这里是程序员晚枫&#xff0c;全网同名。 最近在小破站账号&#xff1a;Python自动化办公社区更新一套课程&#xff1a;给小白的《50讲Python自动化办公》 在课程群里&#xff0c;看到学员自己开发了一个功能&#xff1a;从word里提取图片。这个…

pytorch安装教程

写在前面&#xff1a;配置pytorch着实有很多坑&#xff0c;不过最终结果算好的&#xff0c;话不多说&#xff0c;直接上干货。其中想要知道如何解决torch.cuda.is_available(&#xff09;返回false的&#xff0c;直接跳到步骤5pytorch安装。python版本至少是3.6及以上。 1、前…

API 设计/开发/测试工具:Apifox与怎么通过拦截器

目录 一、测试接口如何创建&#xff1f; 二、如何添加body和header&#xff1f; 三、如果项目设置的有拦截器&#xff1f; 四、拦截器概念&#xff1a; 4.1使用拦截器概念 4.2 先写一个配置类WebMvcConfig.java 4.3 AuthInitInterceptor拦截器中实现 一、测试接口如何创建…

Linux 内存workingset Refault Distance算法源码及源码解析

概述 内核mm子系统中有一个workingset.c实现了refault distance算法&#xff0c;发现网络逻辑介绍该算法的文章主要是复制自奔跑吧内核一书中的内容&#xff0c;均比较雷同&#xff0c;讲述的角度比较难以理解&#xff0c;我第一看到的时候琢磨了2天才明白&#xff0c;本文希望…

Python中使用EMD(经验模态分解)

在Python中使用EMD&#xff08;经验模态分解&#xff09;进行信号分解时&#xff0c;通常可以设置信号分解的数目。EMD算法的目标是将信号分解成多个称为“本征模态函数”&#xff08;Intrinsic Mode Functions&#xff0c;简称IMF&#xff09;的成分&#xff0c;每个IMF都代表…

调试(修复错误)

什么是一个软件bug&#xff1f; ● 软件错误:计算机程序中的缺陷或问题。基本上&#xff0c;计算机程序的任何意外或非预期的行为都是软件缺陷。 ● bug在软件开发中是完全正常的! ● 例如&#xff0c;现在我们存在数组&#xff0c;我们现在需要将这个数组颠倒排序 意外的结…

7.15 SpringBoot项目实战 【学生入驻】(上):从API接口定义 到 Mybatis查询 串讲

文章目录 前言一、service层 和 dal层方式一、Example方式方式二、Mybatis XML方式方式三、Mybatis 注解方式 二、web层 StudentController最后 前言 接下来我们实战【学生入驻】&#xff0c;对于C端学生端&#xff0c;一切交互开始于知道 当前学生是否入驻、是否有借阅资格&a…

【重新定义matlab强大系列十五】非线性数据拟合和线性拟合-附实现过程

&#x1f517; 运行环境&#xff1a;Matlab &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 #### 防伪水印——左手の明天 #### &#x1f497; 大家好&#x1f917;&#x1f91…

人绒毛膜促性腺激素(HCG)介绍

人绒毛膜促性腺激素 HCG&#xff09;是妊娠期产生的一种肽类激素&#xff0c;由受孕后不久的胚胎产生&#xff0c;随后由合胞体滋养层&#xff08;胎盘的一部分&#xff09;合成。它的作用是防止卵子黄体的解体&#xff0c;从而维持孕酮的分泌&#xff0c;而孕酮对人类怀孕至关…

常用圆圈字符“圆圈字符替换器”

本文收录了162个常用圆圈字符&#xff0c;文内有“圆圈字符自动替换器”。 (本笔记适合熟悉字符串数据类型的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#x…

分享从零开始学习网络设备配置--任务3.6 使用默认及浮动路由实现网络连通

任务描述 某公司随着规模的不断扩大&#xff0c;现有北京总部和天津分部2个办公地点&#xff0c;分部与总部之间使用路由器互联。该公司的网络管理员经过考虑&#xff0c;决定在总部和分部之间的路由器配置默认路由和浮动路由&#xff0c;减少网络管理&#xff0c;提高链路的可…

PHP8中伪变量“$this->”和操作符“::”的使用-PHP8知识详解

对象不仅可以调用自己的变量和方法&#xff0c;也可以调用类中的变量和方法。PHP8通过伪变量“$this->”和操作符“::”来实现这些功能。 1.伪变量“$this->” 在通过对象名->方法调用对象的方法时&#xff0c;如果不知道对象的名称&#xff0c;而又想调用类中的方法…

互联网医院|互联网医院系统引领医疗科技新风潮

互联网的迅速发展已经改变了人们的生活方式&#xff0c;而医疗领域也不例外。近年来&#xff0c;互联网医院应运而生&#xff0c;为患者和医生提供了更便捷、高效的医疗服务。本文将深入探讨互联网医院的系统特点、功能以及未来的发展方向&#xff0c;为您展现医疗行业的新时代…

代码随想录算法训练营第23期day4| 24. 两两交换链表中的节点 、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II

目录 一、&#xff08;leetcode 24&#xff09;两两交换链表中的节点 二、&#xff08;leetcode 19&#xff09;删除链表的倒数第N个节点 思路 三、&#xff08;leetcode 160&#xff09;链表相交 四、&#xff08;leetcode 142&#xff09;环形链表II 思路 一、&#xf…

使用华为eNSP组网试验⑴-通过Vlan进行网络设备间通讯

在2019年学习网络的时候是从思科产品开始学的&#xff0c;那个时候接触了思科的6506、4506、3750、3550、2950&#xff0c;因为网络设备多&#xff0c;基本上是在多余的设备上直接操作&#xff0c;掌握后再上现场设备中去操作。当时使用了思科的模拟器CISCO Packet Tracer&…

驱动开发练习,platform实现如下功能

实验要求 驱动代码 #include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/mod_devicetable.h> #include <linux/of_gpio.h> #include <linux/unistd.h> #include <linux/interrupt…

google sitemap Sitemap could not be read

google一直也不提示具体原因。直到换个域名&#xff0c;发现可以提交sitemap。去别就是没有www的可以&#xff0c;带www的不行。应为sitemap的地址带www&#xff0c;但是sitemap里面的url内容是不带www&#xff0c;属于非法格式&#xff0c;所以一直报错。更正了sitemap地址后&…

数据库常用指令

检查Linux系统是否已经安装了MySQL&#xff1a; sudo service mysql start

89. 格雷编码

解题思路&#xff1a; 解法一&#xff1a;找规律&#xff0c;2-4位格雷码的码表如下图所示&#xff08;二进制表示&#xff09;&#xff1a; 可以发现&#xff0c;n位格雷码序列可以由n-1位格雷码序列得到&#xff0c;满足递归规则&#xff0c;具体构造规则如下&#xff1a; …

golang 通过案列感受下内存分析

package main // 声音文件所在的包&#xff0c;每个go文件必须有归属的包 import ("fmt" )// 引入程序中需要用的包&#xff0c;为了使用包下的函数&#xff0c;比如&#xff1a;Printinfunc exchangeNum(num1 int, num2 int){var t intt num1num1 num2num2 t }…