如何使用EasyExcel生成多列表组合填充的复杂Excel示例

news2024/12/26 21:07:37

作者:Funky_oaNiu

    • 一、(需求)生成的表格效果:
    • 二、搞一个模板文件
    • 三、建立对应的表格实体类
    • 四、开始填充
    • 五、Vue3前端发起请求下载
    • 六、官方文档及AI问答

一、(需求)生成的表格效果:

其中只有顶部日期、中间表格数据、底部总计数据,是通过模板填充的
表头、绿色区域、列名、背景颜色、四个表格的结构是模板中定义好的
本文主要可学习如何填充数据
在这里插入图片描述

二、搞一个模板文件

这模板文件是自己编写的,占位符使用{xx}的形式,注意观察一下表格和外部的站位符区别,表格是{data1.xxx}这种形式,用来标识不同表格
在这里插入图片描述

三、建立对应的表格实体类

@Data
public class FillData {
    private String name;
    private double number;
    private Date date;
}

四、开始填充

这里是SpringBoot项目,写在Controller里的,仔细看代码注释,这里就不过多描述了

@Operation(summary = "导出excel")
@GetMapping("/export-excel")
public void exportExcel(PsbLoc psbLoc, HttpServletResponse response) throws IOException {
    // 读取资源文件(这样打成jar模板文件也在里面,防止模板文件被修改导致功能不可用,文件是在src/main/resources/excelTemplates下的)
    ClassPathResource resource = new ClassPathResource("excelTemplates"+File.separator+"productReceiveSendTemplate.xlsx");
    // 组织并填充模板数据
    ByteArrayOutputStream byteArrayOutputStream = compositeFill(resource.getInputStream());

    // 这里文件名不起作用是因为前端是写死的
    String fileName = "多列表" + System.currentTimeMillis() + ".xlsx";
    // 设置响应头,告诉浏览器这是一个下载的文件,这里文件名
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

    // 将文件内容写入响应输出流,浏览器可以直接触发下载
    response.getOutputStream().write(byteArrayOutputStream.toByteArray());
    response.getOutputStream().flush();
}

private ByteArrayOutputStream compositeFill(InputStream templateInputStream) throws IOException {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    // 使用EasyExcel的模板填充功能,在这里指定合并单元格,这里应该是easyExcel的bug,第一列无法合并,其他列都可以,所以第一列单独用原生poi进行合并
    try (ExcelWriter excelWriter = EasyExcel.write(byteArrayOutputStream).withTemplate(templateInputStream)
            // 这里的参数就是圈了个合并区域,在这个正方形内的单元格都会合并,要注意索引是从0开始的,并且区域内不能存在已经合并的单元格否则报错
            .registerWriteHandler(new OnceAbsoluteMergeStrategy(2, 14, 9, 9))
            .registerWriteHandler(new OnceAbsoluteMergeStrategy(15, 27, 9, 9))
            .build()) {
        WriteSheet writeSheet = EasyExcel.writerSheet().build();
        // 防止上面两个表格覆盖下面两个表格,每一行都采用新增一行的方式
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
        // 使用模板填充,必须使用FillWrapper,这是官方要求,并且每行两个表格只能有一个表格设置增行,否则会存在一个表格有空行,这里是造的测试数据
        excelWriter.fill(new FillWrapper("data1", makeTestData(1)), fillConfig, writeSheet);
        excelWriter.fill(new FillWrapper("data2", makeTestData(2)), writeSheet);
        excelWriter.fill(new FillWrapper("data3", makeTestData(3)), fillConfig, writeSheet);
        excelWriter.fill(new FillWrapper("data4", makeTestData(4)), writeSheet);

        // 设置表格外的填充数据,例如总计、日期等数据
        HashMap<String, Object> map = new HashMap<>();
        map.put("date", "2024年11月15日");
        map.put("allInStaockQty", 1);
        map.put("allOutStockQty", 2);
        map.put("allConvertStockQty", 3);
        map.put("allStockQty", 4);
        map.put("convertCenterStockQty", 5);
        map.put("mixOutStockQty", 6);
        map.put("endItem1", 7);
        map.put("endItem2", 8);
        map.put("endItem3", 9);
        map.put("endItem4", 10);
        map.put("endItem5", 11);
        excelWriter.fill(map, writeSheet);
    }
    // 合并单元格,由于easyExcel自带的OnceAbsoluteMergeStrategy合并策略bug,这里需要用poi合并一下
    return mergeCells(byteArrayOutputStream);
}

public ByteArrayOutputStream mergeCells(ByteArrayOutputStream inputStream) {
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(inputStream.toByteArray());
         Workbook workbook = new XSSFWorkbook(byteArrayInputStream)) {
        // 获取第一个工作表
        Sheet sheet = workbook.getSheetAt(0);

        // 合并第1列第3行到第15行,注意行索引从0开始
        CellRangeAddress range1 = new CellRangeAddress(2, 14, 0,0);
        sheet.addMergedRegion(range1);

        // 合并第1列第16行到第28行,注意行索引从0开始
        CellRangeAddress range2 = new CellRangeAddress(15, 27, 0, 0);
        sheet.addMergedRegion(range2);

        // 设置合并单元格的样式
        CellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        // 将修改后的内容写入 ByteArrayOutputStream
        workbook.write(outputStream);
        // 刷新一下,确保数据完全写入
        outputStream.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return outputStream;
}

private List<FillData> makeTestData(Integer listIndx) {
        List<FillData> list = ListUtils.newArrayList();
        for (int i = 0; i < 10; i++) {
            FillData fillData = new FillData();
            list.add(fillData);
            fillData.setName("张三"+listIndx);
            fillData.setNumber(5.2);
            fillData.setDate(new Date());
        }
        return list;
    }

五、Vue3前端发起请求下载

const handleExport = async () => {
  try {
  	// 这里的确认框、loading框代码就省略了
    // 发起导出
    const data = await ReportTestApi.testReport(queryParams)
    download.excel(data, '测试模板填充.xlsx')
  } catch {
  } finally {
    exportLoading.value = false
  }
}

const download = {
  // 下载 Excel 方法
  excel: (data: Blob, fileName: string) => {
    download0(data, fileName, 'application/vnd.ms-excel')
  },
  // 下载 Word 方法
  word: (data: Blob, fileName: string) => {
    download0(data, fileName, 'application/msword')
  },
  // 下载 Zip 方法
  zip: (data: Blob, fileName: string) => {
    download0(data, fileName, 'application/zip')
  },
  // 下载 Html 方法
  html: (data: Blob, fileName: string) => {
    download0(data, fileName, 'text/html')
  },
  // 下载 Markdown 方法
  markdown: (data: Blob, fileName: string) => {
    download0(data, fileName, 'text/markdown')
  }
}

const download0 = (data: Blob, fileName: string, mineType: string) => {
  // 创建 blob
  const blob = new Blob([data], { type: mineType })
  // 创建 href 超链接,点击进行下载
  window.URL = window.URL || window.webkitURL
  const href = URL.createObjectURL(blob)
  const downA = document.createElement('a')
  downA.href = href
  downA.download = fileName
  downA.click()
  // 销毁超连接
  window.URL.revokeObjectURL(href)
}

六、官方文档及AI问答

直接拉到下面,看“多列表组合填充”
https://easyexcel.opensource.alibaba.com/docs/current/quickstart/fill#%E6%A8%A1%E6%9D%BF-2
easyExcel官方问答AI,对比了一下,其他AI都没有它答的好
无疑: https://answer.opensource.alibaba.com/docs/intro

客官点个赞再走呗

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

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

相关文章

AdaBoost 二分类问题

代码功能 生成数据集&#xff1a; 使用 make_classification 创建一个模拟分类问题的数据集。 数据集包含 10 个特征&#xff0c;其中 5 个是有用特征&#xff0c;2 个是冗余特征。 数据集划分&#xff1a; 将数据分为训练集&#xff08;70%&#xff09;和测试集&#xff08;3…

权限相关知识

1.Linux权限的概念 在说Linux权限的概念之前我来问大家一个问题&#xff0c;你们觉得什么是权限&#xff1f; 权限平时的体现呢&#xff0c;就比如不是校长的亲戚就不能逛办公室&#xff0c;没充会员的爱奇艺看不了VIP影视剧&#xff0c;没成会员的的蛋糕店拿不到会员价等等等…

Python爬虫项目 | 一、网易云音乐热歌榜歌曲

文章目录 1.文章概要1.1 实现方法1.2 实现代码1.3 最终效果 2.具体讲解2.1 使用的Python库2.2 代码说明2.2.1 创建目录保存文件2.2.2 爬取网易云音乐热歌榜单歌曲 2.3 过程展示 3 总结 1.文章概要 学习Python爬虫知识&#xff0c;实现简单的一个小案例&#xff0c;网易云音乐热…

苍穹外卖-后端部分

软件开发整体介绍 前端搭建 在非中文目录中双击nginx.exe然后浏览器访问localhost即可 后端搭建 基础准备 导入初始文件 使用git进行版本控制 创建本地仓库和远程仓库,提交Git 连接数据库 连接数据库把资料中的文件放入运行即可 前后端联调测试 苍穹外卖项目接口文档…

3D电子商务是什么?如何利用3D技术提升销售转化?

在数字化浪潮席卷全球的今天&#xff0c;网上购物已成为消费者日常生活中不可或缺的一部分。然而&#xff0c;尽管其便捷性无可比拟&#xff0c;但传统电商模式中的“看不见、摸不着”问题始终困扰着消费者与商家。商品是否符合期望、尺寸是否合适、颜色是否真实……这些不确定…

EXCEL延迟退休公式

如图&#xff1a; A B为手工输入 C2EOMONTH(A2,B2*12) D2EOMONTH(C2,IF(C2>DATEVALUE("2025-1-1"),INT((DATEDIF(DATEVALUE("2025-1-1"),C2,"m")4)/4),0)) E2EOMONTH(A2,B2*12IF(EOMONTH(A2,B2*12)>DATEVALUE("2025-1-1"),INT(…

OpenSSL 自签名

参考文档&#xff1a;unigui开发人员工作手册2021 参考文章&#xff1a;保姆级OpenSSL下载及安装教程-CSDN博客 下载 Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions 进入后向下拉找到下载位置&#xff0c;建议下载二进制版本的精简版&#xff0c…

DevOps工程技术价值流:加速业务价值流的落地实践与深度赋能

DevOps的兴起&#xff0c;得益于敏捷软件开发的普及与IT基础设施代码化管理的革新。敏捷宣言虽已解决了研发流程中的诸多挑战&#xff0c;但代码开发仅是漫长价值链的一环&#xff0c;开发前后的诸多问题仍亟待解决。与此同时&#xff0c;虚拟化和云计算技术的飞跃&#xff0c;…

R语言贝叶斯分析:INLA 、MCMC混合模型、生存分析肿瘤临床试验、间歇泉喷发时间数据应用|附数据代码...

全文链接&#xff1a;https://tecdat.cn/?p38273 多模态数据在统计学中并不罕见&#xff0c;常出现在观测数据来自两个或多个潜在群体或总体的情况。混合模型常用于分析这类数据&#xff0c;它利用不同的组件来对数据中的不同群体或总体进行建模。本质上&#xff0c;混合模型是…

Python酷库之旅-第三方库Pandas(218)

目录 一、用法精讲 1021、pandas.DatetimeIndex.inferred_freq属性 1021-1、语法 1021-2、参数 1021-3、功能 1021-4、返回值 1021-5、说明 1021-6、用法 1021-6-1、数据准备 1021-6-2、代码示例 1021-6-3、结果输出 1022、pandas.DatetimeIndex.indexer_at_time方…

从基础到进阶,Dockerfile 如何使用环境变量

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 什么是 Dockerfile 环境变量?🔖1. `ENV` 指令🔖2. `ARG` 指令🔖语法:🔖使用 `ARG` 的例子:📝 如何使用环境变量提高 Dockerfile 的灵活性🔖1. 动态配置环境🔖2. 配置不同的运行环境🔖3. 多…

2002.6 Partitioning the UMLS semantic network.划分 UMLS 语义网络

Partitioning the UMLS semantic network | IEEE Journals & Magazine | IEEE Xplore 问题 统一医学语言系统&#xff08;UMLS&#xff09;语义网络中的语义类型&#xff08;ST&#xff09;在知识表示和应用中存在不足&#xff0c;例如 ST 的组织方式缺乏直观性和可解释性…

帽子矩阵--记录

帽子矩阵&#xff08;Hat Matrix&#xff09;并不是由某一位具体的科学家单独发明的&#xff0c;而是逐渐在统计学和线性代数的发展过程中形成的。帽子矩阵的概念最早出现在20世纪初的统计学文献中&#xff0c;尤其是在回归分析的研究中得到了广泛应用。然而&#xff0c;具体是…

vue面试题8|[2024-11-14]

问题1&#xff1a;什么是渐进式框架? vue.js router vuex element ...插件 vue.js 渐0 router 渐1 vuex 渐2 vue.js只是一个核心库&#xff0c;比如我再添加一个router或者vuex&#xff0c;不断让项目壮大&#xff0c;就是渐进式框…

web与网络编程

使用HTTP协议访问Web 通过发送请求获取服务器资源的Web浏览器等&#xff0c;被成为客户端(client)。 Web使用一种名为HTTP(超文本传输协议)的协议作为规范&#xff0c;完成从客户端到服务器端等一系列运作流程。 可以说&#xff0c;Web时建立在HTTP协议上通信的。 网络基础T…

docker 部署freeswitch(非编译方式)

一&#xff1a;安装部署 1.拉取镜像 参考&#xff1a;https://hub.docker.com/r/safarov/freeswitch docker pull safarov/freeswitch 2.启动镜像 docker run --nethost --name freeswitch \-e SOUND_RATES8000:16000 \-e SOUND_TYPESmusic:en-us-callie \-v /home/xx/f…

opencv kdtree pcl kdtree 效率对比

由于项目中以一个环节需要使用kdtree ,对性能要求比较严苛&#xff0c;所以看看那个kdtree效率高一些。对比了opencv和pcl。 #include <array> #include <deque> #include <fstream> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp…

ab (Apache Bench)的使用

Apache Bench&#xff08;ab&#xff09;是一个用于基准测试HTTP Web服务器的命令行工具&#xff0c;广泛用于评估和优化Web服务器的性能。以下是关于Apache Bench的详细介绍&#xff0c;包括其功能、使用方法、常用参数和输出结果解析。 功能 性能测试&#xff1a;通过模拟多…

【数据分享】全国农产品成本收益资料汇编(1953-2024)

数据介绍 一、《全国农产品成本收益资料汇编 2024》收录了我国2023年主要农产品生产成本和收益资料及 2018年以来六年的成本收益简明数据。其中全国性数据均未包括香港、澳门特别行政区和台湾省数据。 二、本汇编共分七个部分,即:第一部分,综合;第二部分,各地区粮食、油料;第…

基于OpenCV的图片人脸检测研究

目录 摘要 第一章 引言 第二章 基于 OpenCV 的图片人脸检测 2.1 实现原理 2.2 代码实现与分析 2.3 代码详细分析 第三章 实验结果与分析 第四章 OpenCV 人脸检测的优势与局限性 4.1 优势 4.2 局限性 第五章 结论 第六章 未来展望 参考文献 摘要 人脸检测是计算机视…