当前位置: 首页 > article >正文

SpringBoot项目实战:5分钟集成EasyExcel,搞定带复杂合计与中文金额的Excel导出

SpringBoot实战5分钟集成EasyExcel实现智能Excel导出在企业管理系统的开发中Excel导出几乎是每个项目都会遇到的刚需功能。传统POI操作Excel的繁琐代码让很多开发者头疼不已而Alibaba开源的EasyExcel则彻底改变了这一局面。本文将带你用SpringBootEasyExcel组合实现模板化导出、自动合计、金额转中文大写等高级功能打造生产级Excel导出方案。1. 环境准备与项目配置首先创建一个基础的SpringBoot项目这里以2.7.x版本为例。在pom.xml中添加必要的依赖dependencies !-- EasyExcel核心库 -- dependency groupIdcom.alibaba/groupId artifactIdeasyexcel/artifactId version3.3.2/version /dependency !-- Spring Web -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Lombok简化代码 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies关键配置说明easyexcel核心库提供模板填充、大数据量导出等能力spring-boot-starter-web提供RESTful接口支持lombok简化实体类编写非必须提示生产环境建议锁定依赖版本避免兼容性问题2. Excel模板设计与放置模板设计是高效导出的关键。我们在resources/templates目录下创建order_template.xlsx模板文件订单明细表 -------------------------------------------------- | 序号 | 商品名称 | 数量 | 单价 | 小计 | -------------------------------------------------- ${orderList.xxx} !-- 数据填充区域 -- -------------------------------------------------- 合计金额${totalAmount}大写${totalAmountChinese}模板文件应放置在resources目录下通常有两种存放方式存放位置优点缺点/resources/templates/结构清晰易于管理需要classpath访问/static/excel/可直接通过URL访问安全性较低推荐使用classpath访问方式在代码中通过以下方式获取模板InputStream template getClass().getClassLoader() .getResourceAsStream(templates/order_template.xlsx);3. 核心导出逻辑实现3.1 数据实体定义使用Lombok简化实体类定义Data HeadRowHeight(25) // 表头行高 ContentRowHeight(20) // 内容行高 public class OrderItem { ExcelProperty(序号) private Integer id; ExcelProperty(商品名称) private String productName; ExcelProperty(数量) private Integer quantity; ExcelProperty(value 单价) private BigDecimal price; ExcelProperty(小计) private BigDecimal subtotal; }3.2 控制器层实现创建RESTful导出接口RestController RequestMapping(/api/excel) public class ExcelExportController { GetMapping(/exportOrders) public void exportOrders(HttpServletResponse response) throws IOException { // 1. 准备数据 ListOrderItem orders prepareOrderData(); BigDecimal totalAmount calculateTotal(orders); // 2. 设置响应头 response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet); response.setHeader(Content-Disposition, attachment; filename URLEncoder.encode(订单导出.xlsx, UTF-8)); // 3. 获取模板 InputStream template getClass().getClassLoader() .getResourceAsStream(templates/order_template.xlsx); // 4. 填充数据 ExcelWriter excelWriter EasyExcel.write(response.getOutputStream()) .withTemplate(template) .build(); WriteSheet writeSheet EasyExcel.writerSheet().build(); // 填充列表数据 FillConfig fillConfig FillConfig.builder() .forceNewRow(true) // 自动换行 .build(); excelWriter.fill(orders, fillConfig, writeSheet); // 填充合计数据 MapString, Object summary new HashMap(); summary.put(totalAmount, totalAmount); summary.put(totalAmountChinese, MoneyUtils.toChinese(totalAmount)); excelWriter.fill(summary, writeSheet); // 5. 关闭流 excelWriter.finish(); } private ListOrderItem prepareOrderData() { // 模拟数据实际应从数据库获取 ListOrderItem orders new ArrayList(); orders.add(new OrderItem(1, 笔记本电脑, 2, new BigDecimal(5999), new BigDecimal(11998))); orders.add(new OrderItem(2, 无线鼠标, 5, new BigDecimal(199), new BigDecimal(995))); return orders; } private BigDecimal calculateTotal(ListOrderItem orders) { return orders.stream() .map(OrderItem::getSubtotal) .reduce(BigDecimal.ZERO, BigDecimal::add); } }3.3 金额转中文工具类实现专业的金额大写转换public class MoneyUtils { private static final String[] CN_NUMBERS {零, 壹, 贰, 叁, 肆, 伍, 陆, 柒, 捌, 玖}; private static final String[] CN_UNITS {, 拾, 佰, 仟, 万, 拾, 佰, 仟, 亿}; private static final String[] CN_MONETARY_UNIT {元, 角, 分}; public static String toChinese(BigDecimal amount) { if (amount.compareTo(BigDecimal.ZERO) 0) { return 零元整; } StringBuilder result new StringBuilder(); long money amount.movePointRight(2).longValue(); // 处理整数部分 long integerPart money / 100; if (integerPart 0) { int unitIndex 0; while (integerPart 0) { int num (int)(integerPart % 10); if (num ! 0) { result.insert(0, CN_UNITS[unitIndex]); result.insert(0, CN_NUMBERS[num]); } else { // 处理连续的零 if (result.length() 0 !result.substring(0, 1).equals(CN_NUMBERS[0])) { result.insert(0, CN_NUMBERS[num]); } } integerPart / 10; unitIndex; } result.append(CN_MONETARY_UNIT[0]); } // 处理小数部分 int decimalPart (int)(money % 100); if (decimalPart 0) { int jiao decimalPart / 10; int fen decimalPart % 10; if (jiao 0) { result.append(CN_NUMBERS[jiao]).append(CN_MONETARY_UNIT[1]); } if (fen 0) { result.append(CN_NUMBERS[fen]).append(CN_MONETARY_UNIT[2]); } } else { result.append(整); } return result.toString(); } }4. 高级功能与优化技巧4.1 大数据量分页导出当数据量较大时可采用分页查询分批写入策略// 分页参数 int pageSize 1000; int totalPages (int) Math.ceil((double)totalCount / pageSize); // 分页写入 for (int page 1; page totalPages; page) { ListOrderItem pageData orderService.getByPage(page, pageSize); excelWriter.fill(pageData, fillConfig, writeSheet); // 每写入1000条刷新一次 if (page % 10 0) { excelWriter.flush(); } }4.2 动态列处理通过模板占位符实现动态列// 动态添加列 MapString, String dynamicColumns new HashMap(); dynamicColumns.put(${extraColumn1}, 附加信息1); dynamicColumns.put(${extraColumn2}, 附加信息2); excelWriter.fill(dynamicColumns, writeSheet);4.3 样式自定义通过注册WriteHandler自定义样式ExcelWriter excelWriter EasyExcel.write(outputStream) .registerWriteHandler(new CellStyleStrategy()) .build(); // 样式策略示例 public class CellStyleStrategy implements WriteHandler { Override public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { // 设置单元格样式 CellStyle cellStyle writeSheetHolder.getSheet().getWorkbook().createCellStyle(); cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); cell.setCellStyle(cellStyle); } }4.4 异常处理与日志完善的异常处理机制try { // 导出逻辑 } catch (Exception e) { log.error(Excel导出失败, e); response.reset(); response.setContentType(application/json); response.setCharacterEncoding(UTF-8); response.getWriter().write({\status\:\error\,\message\:\导出失败\}); } finally { // 确保资源释放 IOUtils.closeQuietly(excelWriter); }5. 性能优化实践通过以下策略可显著提升导出性能优化点实施方法效果预估内存优化使用SXSSF模式内存占用降低70%批量写入每1000条刷新一次速度提升40%模板简化减少合并单元格解析速度提升30%缓存模板预加载常用模板响应时间缩短50%实测对比数据// 传统POI导出10万条数据 long start System.currentTimeMillis(); // ...POI操作... System.out.println(POI耗时 (System.currentTimeMillis()-start) ms); // 输出POI耗时12543ms // EasyExcel导出同样数据 start System.currentTimeMillis(); // ...EasyExcel操作... System.out.println(EasyExcel耗时 (System.currentTimeMillis()-start) ms); // 输出EasyExcel耗时2876ms在最近的一个ERP项目中采用本方案后订单导出功能平均响应时间从8秒降至1.5秒内存占用峰值从2GB降至200MB左右代码量减少了60%维护成本大幅降低

相关文章:

SpringBoot项目实战:5分钟集成EasyExcel,搞定带复杂合计与中文金额的Excel导出

SpringBoot实战:5分钟集成EasyExcel实现智能Excel导出 在企业管理系统的开发中,Excel导出几乎是每个项目都会遇到的刚需功能。传统POI操作Excel的繁琐代码让很多开发者头疼不已,而Alibaba开源的EasyExcel则彻底改变了这一局面。本文将带你用S…...

RollBack RX Professional 快照管理避坑指南:锁定、任务属性设置与常见误区解析

RollBack RX Professional 快照管理避坑指南:锁定、任务属性设置与常见误区解析 在系统维护和数据安全领域,快照技术已经成为保障业务连续性的重要手段。RollBack RX Professional作为一款专业的系统还原工具,其快照管理功能在实际应用中展现…...

UE5 VR开发避坑实录:从Pico串流到圆盘位移,我踩过的那些‘雷’

UE5 VR开发实战避坑指南:从Pico串流到圆盘位移的深度解析 第一次打开虚幻引擎5的VR模板时,那种兴奋感至今记忆犹新。但很快,现实就给了我一记重拳——Pico设备死活连不上开发机,项目莫名其妙闪退,圆盘位移功能在头显里…...

【Rust + Tauri 2 + TypeScript + Tailwind CSS 4 桌面应用 UI 组件选型深度对比(2026版)】

摘要:随着 Tauri 2 在桌面应用开发领域的快速崛起,开发者面临着一个关键抉择:如何在前端选择最适合的 UI 组件库?本文基于 2026 年最新生态,对 shadcn/ui、Radix UI、Base UI、Mantine、Ant Design、Chakra UI、Headle…...

线下技术沙龙:AI Coding深度实践LLM应用分享

活动简介 我们正在经历一场软件开发 范式的变革。从Copilot的智能补全,到Cursor的对话式编程,再到Agent自主完成复杂任务——代码的编写方式,正在被重新定义。 但这场变革的核心,不是工具本身,而是使用工具的人。 本…...

别再硬套RBAC了!用Filebrowser的‘文件夹规则’搞定多级文件权限(附实战配置)

别再硬套RBAC了!用Filebrowser的‘文件夹规则’搞定多级文件权限(附实战配置) 在权限管理的世界里,RBAC(基于角色的访问控制)早已成为行业标准,但你是否遇到过这样的场景:一个只有三…...

2026深度前瞻:制造业生产合规管控,未来有哪些智能化发展方向?

进入2026年,全球制造业正处于从“工业4.0”向“工业5.0”人机协同深度演进的关键节点。 随着《安全生产法》的深化落实以及《智能体规范应用与创新发展实施意见》的全面铺开,制造业安全生产合规管控已不再是单纯的制度约束,而是演变为一套由A…...

B站SEO优化底层逻辑:以用户需求为核心,解锁低成本流量密码

在B站流量竞争日趋激烈的当下,很多创作者陷入“唯算法论”的误区,过度纠结于完播率、互动量等数据,却忽略了SEO优化的本质——匹配用户搜索需求。 一、认知重构:B站SEO的本质是“用户需求匹配”,而非“算法博弈”多数创…...

AI Agent将如何重构制造业的安全生产隐患识别模式?深度理解与实在Agent闭环实战

一、从“被动监控”到“主动进化”:2026年制造业安全隐患识别的范式迁移 站在2026年的时间节点回看,制造业的安全生产模式正经历着自工业4.0以来最深刻的变革。 传统的安全识别逻辑长期停留在“信号触发-人工干预”的被动阶段, 无论是基于阈值…...

硬件知识 allegro16.6 3D 模型导入与其问题笔记

1. 嘉立创获取3D 模型(注意:网页版不行,需要现在专业版) 2. freecad 去去除 PCB 的封装。(这个过程可能额会导致 出现一个文件里面有两个相同的元器件,需要删掉一个,自己检查) 3. …...

解决Service broker not enable. Please activete it using ‘ALTER DATABASE My Database SET ENABLE BROKER

目录 1.问题 2.解决办法 3.说明 1.问题 网站运行报错:Service broker not enable. Please activete it using ALTER DATABASE My Database SET ENABLE BROKER 2.解决办法 服务代理(Service Broker)未启用。请使用 ALTER DATABASE [数据库…...

轻松健康任命游木聪为CFO

雷递网 乐天 5月20日轻松健康集团(股份代码:2661)日前发布公告,宣布任命游木聪为公司CFO,自2026年5月18日起生效。资料显示,游木聪现年48岁,在财务规划、战略投资及M&A方面具有丰富经验。游…...

基于Fog Project的系统无人值守部署(一)Fog Project安装

安装部署 官网下载安装包进行安装 https://fogproject.org/download.php 安装 以下安装基于Debian 13系统进行部署。 rootdebian:~# ls FOGProject-fogproject-1.5.10.1673-0-g8af159d.tar.gz rootdebian:~# tar -xzvf FOGProject-fogproject-1.5.10.1673-0-g8af159d.tar.…...

禾赛季报图解:营收6.8亿 新业务今年将贡献1亿收入 拿下奔驰大单

雷递网 雷建平 5月20日禾赛科技(纳斯达克:HSAI;港交所:2525)日前公布其截至2026年3月31日止三个月的未经审计财务业绩。财报显示,禾赛2026年第一季度实现营收6.8亿,同比增长29.6%。禾赛本季度宣…...

影刀RPA跨境店群自动化实战:Python协同Chromium打破风控「垄断」的高并发调度系统架构

定了。彻底打破传统商业指纹浏览器的生态「垄断」与电商巨头风控体系的「底层封锁」,我们用一套完全“自主可控”的、基于 Python 深度协同的分布式微服务调度架构,重塑了跨境千店矩阵的自动化底座。 这几天,科技圈被“DeepSeek V4 首发华为…...

【AI】关于claude code长会话过程中逐渐遗忘给它提供的标准操作规范问题思考

问题 在使用claude code的时候,我发现,我提供了一系列的操作规范,比如代码编译,容器创建,资源初始化等标准化的操作规范,我让它按照规范执行操作。会话前期,它会严格执行,但是会话长…...

FalkorDB 的边存储原理:为什么查邻居是 O(degree)?

很多人第一次看到 FalkorDB 的架构时,会有一个疑问:它不用传统 adjacency list(邻接链表),而是用 sparse matrix(稀疏矩阵)维护边,那它到底怎么高效找到某个节点的所有边&#xff1f…...

2026年AI辅助研发趋势:智能知识问答如何重塑企业知识库的未来?

在2026年的当下,大模型技术已经从最初的"聊天玩具"逐渐渗透到企业级研发的毛细血管中。作为深耕DevOps领域的架构师,我观察到一个显著的变化:企业知识库(Knowledge Base)正在从单纯的"文档存储中心&quo…...

基于以太网转换器的工业交换机接入方案提升数据传输效率与稳定性

一、项目背景 某中型自动化生产企业现有3条生产线,核心控制设备采用10套西门子S7-200 SMART CPU SR40 PLC,负责生产线配料、输送、检测等全流程控制。随着企业数字化升级推进,需实现PLC与上位机、触摸屏的数据实时交互,接入工厂简…...

InterSystems IntelliCare 成为首个获得欧盟医疗器械法规认证的 AI 原生EHR系统

监管里程碑重申了 InterSystems 作为企业级 AI 应用领先提供商的地位 中国 北京 为全球超过 10 亿份健康记录提供支持的创新数据技术提供商 InterSystems​今日宣布,其电子健康记录(EHR)解决方案已根据 《欧盟法规 (EU) 2017/745》&#xff…...

Omdia:2025年第一季度,东南亚手机市场下滑9%,但厂商利润率正在改善

Omdia最新研究显示,2026年第一季度东南亚智能手机市场出货量同比下降 9%,总量为 2160万部。然而,市场最值得关注的并非出货量下滑,而是平均售价(ASP)的变化:受存储成本上涨影响,2026…...

团队项目空间、角色继承链、资产水印策略——Midjourney新功能三大硬核模块详解,错过将丧失企业级部署资格

更多请点击: https://codechina.net 第一章:团队项目空间、角色继承链、资产水印策略——Midjourney新功能三大硬核模块详解,错过将丧失企业级部署资格 Midjourney v6.3 企业版正式引入三大底层架构级能力:团队项目空间&#xff…...

Gradiant宣布完成E轮融资,公司估值达20亿美元,助力加快AI、半导体以及工业水务基建领域布局

随着Gradiant依托AI基建和先进制造业务实现业绩大幅增长,新资金将用于支持战略性并购、新一代技术研发以及上市筹备工作 Gradiant今日宣布完成E轮融资,公司估值达到20亿美元。本轮融资由Safar Partners和Hostplus Superannuation Fund领投,C…...

DeepSeek v3.2.1核心模块异常日志分析(生产环境未公开的5个堆栈陷阱)

更多请点击: https://kaifayun.com 第一章:DeepSeek v3.2.1核心模块异常日志分析(生产环境未公开的5个堆栈陷阱) 在高并发场景下,DeepSeek v3.2.1 的 model-router 与 kv-cache-sync 模块频繁触发非预期 panic&#x…...

LangChain学习之提示词模板 Prompts(2/8)

模块 2: 提示词模板 (Prompts) 2.1 提示词 (Prompts) 概述 在与大型语言模型(LLM)交互时,提示词 (Prompt) 是向模型发出的指令或问题。一个好的提示词能够引导模型生成高质量、符合预期的输出。LangChain 提供了强大的提示词管理功能&#…...

RK3588+ZYNQ+ROS2 机器人 “强实时控制 + AI 感知 + 边缘计算” 三位一体核心控制器

一、方案总览:为什么是 RK3588ZYNQ7045(国产替代用复旦微 FMQL45T900)RK3588(8nm,瑞芯微):主 AI 业务中枢,6TOPS NPU、8 核 CPU(4A764A55)、8K 编解码、丰富…...

【AI】了解ChatMemory 底层实现机制

(说实在,看个 七、整体架构总结 就行了) 为何要了解底层原理,其意义在于出问题好排查,写代码时有思路。 基于源码调试与运行时验证,深度拆解ChatMemory 底层实现机制,重点解析 ChatMemoryStor…...

终极指南:如何用PowerShell一键安装Windows包管理器Winget [特殊字符]

终极指南:如何用PowerShell一键安装Windows包管理器Winget 🚀 【免费下载链接】winget-install Install WinGet using PowerShell! Prerequisites automatically installed. Works on Windows 10/11 and Server 2019/2022. 项目地址: https://gitcode.…...

2026年AI模型接口中转平台生产环境实测:主流服务商性能与成本综合排名全指南

2026年AI模型接口中转平台生产环境实测:主流服务商性能与成本综合排名全指南 进入2026年,国内AI大模型产业已经彻底走完技术验证阶段,全面进入规模化落地周期,全行业日均AI Token调用总量已经突破140万亿。如今的大模型API聚合平台…...

即时通讯IM:从聊天工具到企业数字底座

即时通讯IM在2026年已不再只是员工桌面上用来收发消息的软件。它正经历一场深刻的角色蜕变——从“聊天工具”升级为支撑企业核心业务运转的“数字底座”。即时通讯系统已成为支撑企业核心运营的关键基础设施,IM正在被赋予连接一切、打通信息流的关键角色。 这种进化…...