如何借助Java批量操作Excel文件?
最新技术资源(建议收藏)
https://www.grapecity.com.cn/resources/
前言 | 问题背景
在操作Excel的场景中,通常会有一些针对Excel的批量操作,批量的意思一般有两种:
对批量的Excel文件进行操作。如导入多个Excel文件,并处理数据,或导出多个Excel文件。这类场景,往往操作很相似,但是要反复读写Excel文件。对单个或复数个进行批量操作。如对Excel文件,进行批量替换文本,批量添加公式或者批量增加样式。这类场景,一般需要操作的Excel文件不多,但是需要反复执行特定操作,这种时候需要有易用的API来帮忙。
现有的Excel组件中,POI是非常常用的组件,但是针对上述不同的场景,其分别会对组件提出两类要求。
第一类场景会反复读取或者写入文件,需要组件对于内存有足够好的优化,否则很容易出现内存溢出(out of memory)的问题。
第二类场景则需要组件提供易用的API,例如替换字符串,如果没有查找(find)或者替换(replace)的接口API。则需要自己遍历单元格(cell)来查找值。
虽然POI在上面两种要求上可能会有欠缺,但还有其他的组件可以选择,比如EasyExcel,GcExcel等。
下面是以GcExcel为例,对上述两类场景,分别列举的例子。
什么是GcExcel?

场景1 批量导入Excel文件,并读取特定区域的数据
例如有多个Excel文件,名字都是GUID。这些Excel文件来自于填报的数据,需要对其中的内容进行汇总。
如Excel的表单内容如下图:

需要对B3到C6的格子进行取值,可以用下面的代码提取数据。
@Testpublic void testImportFormFile() {String folderPath = "path/testFolder"; //使用你的路径File folder = new File(folderPath);File[] files = folder.listFiles();if (files != null) {for (File file: files){if(file.isFile() && file.getName().endsWith(".xlsx")){Workbook wb = new Workbook();wb.open(file.getAbsolutePath());Object[][] value = (Object[][]) wb.getActiveSheet().getRange("B3:C6").getValue();System.out.println(value[0][1]); //小葡萄System.out.println(value[1][1]); //20.0System.out.println(value[2][1]); //开发部System.out.println(value[3][1]); //610123456789012345//添加处理数据的逻辑}}}}
通过listFiles()方法,获取所有的Excel文件。循环读取每一个文件,通过GcExcel打开Excel文件。使用IRange上的getValue()方法可以把Excel中的格子以二维数组的方式读取出来。
之后就可以通过访问二维数组来处理业务逻辑。
场景2 批量导出Excel文件,导出前把数据写在特定位置
继续以第一个Excel文件为例子,当在数据库中已经存有一些数据,希望把数据写入并导出到复数个Excel文件里或者导出为PDF文件。
真实的场景有,如企业发放工资,每个月需要给每一位员工发放一份电子版的工资单,因为每个员工的工资单信息不相同,这个场景下,则需要把数据批量导出为复数个PDF。
@Testpublic void testExportFormFile() {String outPutPath = "E:/testFolder";//给valueList初始化数据,替换为从数据库,CSV或者JSON等中获取数据。ArrayList<Object[][]> valueList = new ArrayList<Object[][]>();for (Object[][] value : valueList) {Workbook wb = new Workbook();wb.getActiveSheet().getRange("B3:C6").setValue(value);wb.save(outPutPath + UUID.randomUUID().toString() + ".xlsx");}}
GcExcel可以直接把二维数组设置给一个range,从数据库中把数据加载出来以后,可以整理成二维数组。
之后通过GcExcel的SetValue()把二维数组直接设置到sheet上,最后通过工作簿(workbook)上的save方法保存导出。
场景3 打开Excel文件,批量替换关键字
在这个场景中,需要把Excel文件作为模板,把其中的一些自定义关键字,替换成数据。
比如在有一个制式的报表,需要把数据填写进去。例如表头,姓名,报表相关的条目,数据等信息。可能会把报表制作成一个模板,之后把表头,姓名等位置留空,或者用关键字作为占位符。例如“%Name%”可以作为名字的占位符,在填写数据的时候,可以对%Name%进行替换。
@Testpublic void testReplaceTemplateFile() {String templateFilePath = "test.xlsx";Workbook wb = new Workbook();wb.open(templateFilePath);IRange usedRange = wb.getActiveSheet().getUsedRange();//load dataArrayList<Object[]> valueList = new ArrayList<Object[]>();for (Object[] value : valueList) {usedRange.replace(value[0],value[1]);}wb.save("result.xlsx", SaveFileFormat.Xlsx);}
通过工作簿(workbook)打开模板(template)文件,准备好数据以后,直接通过IRange的replace方法替换自定义的关键字。
替换完之后,保存为新的Excel即可。
对于更高级复杂的数据填充,GcExcel也有模板功能,设置好模板后,可以直接绑定数据源,GcExcel会自动填充数据到模板里。
场景4 打开Excel模板文件,批量获取计算结果
例如有一个Excel文件,用于计算保险或者行业数据。需要在固定的位置填入值,使用Excel中的公式计算结果。
@Testpublic void testCalcFormulaByTemplateFile() {String templateFilePath = "E:/testFolder/testFormula.xlsx";Workbook wb = new Workbook();wb.open(templateFilePath);//``获取特定的值,比如以下ArrayList<Object[]> valueList = new ArrayList<Object[]>();for (Object[] value : valueList) {Object A1Value = value[0];Object A2Value = value[1];Object result = null;wb.getActiveSheet().getRange("A1").setValue(A1Value);wb.getActiveSheet().getRange("A2").setValue(A2Value);result = wb.getActiveSheet().getRange("A3").getValue();System.out.println(result);}}
GcExcel的公式计算是在取值的时候计算的,因此不需要显示调用calculate之类的方法,只需要把输入的参数准备好,放在Excel特定的cell中,就可以直接获取公式的计算结果了。
以上就是一些常见的批量处理Excel的方法,仅使用GcExcel Java的代码为例,同样的思路也可以使用其他的组件来实现。
扩展链接:
GrapeCity Documents for Excel(服务端Excel组件)V3.0 正式发布
用它来开发“在线Excel”系统,竟如此简单!
如何使用JavaScript实现前端导入和导出excel文件
相关文章:
如何借助Java批量操作Excel文件?
最新技术资源(建议收藏) https://www.grapecity.com.cn/resources/ 前言 | 问题背景 在操作Excel的场景中,通常会有一些针对Excel的批量操作,批量的意思一般有两种: 对批量的Excel文件进行操作。如导入多个Excel文件…...
JUC并发编程_Lock锁
JUC并发编程_Lock锁 1、Lock锁介绍2、主要方法3、与 synchronized 的区别4、Condition 使用示例 1、Lock锁介绍 Java中的 Lock 锁是 java.util.concurrent.locks 包下的一个接口,它提供了比 synchronized 关键字更灵活的锁定机制。 2、主要方法 lock():…...
Unity中的功能解释(数学位置相关和事件)
向量计算 Vector3.Slerp(起点坐标,终点坐标,t),可是从起点坐标以一个圆形轨迹到终点坐标,有那么多条轨迹,那怎么办 Vector3.Slerp 进行的是沿球面插值,因此并不是沿着严格的“圆形…...
ElementPlus---Timeline 时间线组件使用示例
介绍 使用ElementPlus时间线组件在后台首页实现通知公告列表展示,使用Vue3开发。 实现代码 Vue3代码 <el-timeline><el-timeline-itemstyle"max-width: 600px"v-for"(activity, index) in activities":key"index":times…...
推荐4款2024年大家都在用的高质量翻译器。
翻译器在我们的生活中有着很重要的作用,不管是我们在学习还是工作,生活娱乐,出国旅游等场合都会派上用场,它是我们解决沟通的障碍,提高阅读效率的好帮手。我自己使用的翻译器有很多,可以给大家列举几款特别…...
Mybatis 返回 Map 对象
一、场景介绍 假设有如下一张学生表: CREATE TABLE student (id int NOT NULL AUTO_INCREMENT COMMENT 主键,name varchar(100) NOT NULL COMMENT 姓名,gender varchar(10) NOT NULL COMMENT 性别,grade int NOT NULL COMMENT 年级,PRIMARY KEY (id) ) ENGINEInnoD…...
Vue3(三)路由基本使用、工作模式(history,hash)、query传参和param传参、props配置、编程式路由导航
文章目录 一、路由的基本使用二、路由器的工作模式三、RouterLink中to的两种写法四、嵌套路由五、路由传参1. query传参2. params传参 六、路由的propos配置七、编程式路由导航 一、路由的基本使用 安装:npm i vue-router 在src/pages文件下,创建三个路…...
TypeScript概念讲解
简单来说,TypeScript 是 JavaScript 的一个超集,支持 ECMAScript 6 标准; TypeScript 由微软开发的自由和开源的编程语言; TypeScript 设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的 Jav…...
C++ | Leetcode C++题解之第437题路径总和III
题目: 题解: class Solution { public:unordered_map<long long, int> prefix;int dfs(TreeNode *root, long long curr, int targetSum) {if (!root) {return 0;}int ret 0;curr root->val;if (prefix.count(curr - targetSum)) {ret pref…...
回复《对话损友 2》
回复《对话损友 2》 承蒙贵人挂念,亦感激贵人给予这般交流的契机(对话损友 2 -- 回复-CSDN博客)。我自身也一直期望能留存些岁月的痕迹,然而却常困惑于不知哪些事物值得铭记,哪些又应被永远忘却。 随着时光流转&#x…...
MySQL - 运维篇
一、日志 1. 错误日志 2. 二进制日志 3. 查询日志 记录了所有的增删改查语句以及DDL语句 4. 慢查询日志 二、主从复制 1. 概述 2. 原理 3. 搭建 三、分库分表 1. 介绍 2. Mycat概述 3. Mycat入门 4. Mycat配置 5. Mycat分片 6. Mycat管理及监控 四、读写分离 1. 介绍 2. 一…...
WebGIS开发及市面上各种二三维GIS开发框架对比分析
GIS前端开发是现代WebGIS应用开发中非常重要的一环,通过前端开发框架,可以实现地图展示、交互、分析等功能。本文将介绍当前市面上常用的GIS前端开发框架,并进行对比分析。 Leaflet Leaflet是一款轻量级的开源地图库,它提供了丰…...
[论文精读]TorWard: Discovery, Blocking, and Traceback of Malicious Traffic Over Tor
期刊名称:IEEE Transactions on Information Forensics and Security 发布链接:TorWard: Discovery, Blocking, and Traceback of Malicious Traffic Over Tor | IEEE Journals & Magazine | IEEE Xplore 中文译名:TorWard:…...
pytest - 多线程提速
import timedef test1_test1():time.sleep(1)assert 1 1, "11"def test1_test2():time.sleep(1)assert 1 1, "11" 上面2个函数,执行情况: 正常执行时,花费 2.08s2个进程执行时,花费 1.18s2个线程执行时&a…...
python中logging的用法
logging.error 是 Python logging 模块中的一个方法,专门用于记录错误级别(ERROR)的日志信息。logging 模块是 Python 提供的标准日志工具,用于生成各种级别的日志消息,并支持日志的格式化和存储。 logging.error 的基…...
【YOLO目标检测车牌数据集】共10000张、已标注txt格式、有训练好的yolov5的模型
目录 说明图片示例 说明 数据集格式:YOLO格式 图片数量:10000(2000张绿牌、8000张蓝牌) 标注数量(txt文件个数):10000 标注类别数:1 标注类别名称:licence 数据集下载:车牌数据…...
gdb xterm 调试 openmpi 程序
1,编写编译一个openmpi程序 迭代计算 PI 的源程序: pi_reduce.c #include <stdio.h>#include <math.h> #include <mpi.h>double f(double); double f(double x) {return (4.0/(1.0x*x)); }int main(int argc, char* argv[]) {int d…...
【STM32】江科大STM32笔记汇总(已完结)
STM32江科大笔记汇总 STM32学习笔记课程简介(01)STM32简介(02)软件安装(03)新建工程(04)GPIO输出(05)LED闪烁& LED流水灯& 蜂鸣器(06)GPIO输入(07)按键控制LED 光敏传感器控制蜂鸣器(08)OLED调试工具(09)OLED显示屏(10)EXTI外部中断(11)对射式红外传感器计次 旋转编码器…...
Java基础扫盲(二)
想看Java基础扫盲(一)的可以观看我的上篇文章Java基础扫盲 目录 String为什么设计为不可变的 String有长度限制吗 为什么JDK9将String的char[]改为byte[] 泛型中K,T,V,E,Object,?等都代表什么含义 怎么修改一个类中使用了private修饰的String类型…...
兼容React的刮刮乐完整代码实现
需要兼容React的刮刮乐完整代码实现 在现代Web开发中,React作为一种流行的前端框架,为开发者提供了构建动态界面的强大工具。刮刮乐效果作为一种趣味性的用户交互,能够显著提升用户体验和参与度。本文将详细介绍如何在React项目中实现一个兼…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?
系列回顾: 在上一篇《React核心概念:State是什么?》中,我们学习了如何使用useState让一个组件拥有自己的内部数据(State),并通过一个计数器案例,实现了组件的自我更新。这很棒&#…...
13.10 LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析
LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析 LanguageMentor 对话式训练系统架构与实现 关键词:多轮对话系统设计、场景化提示工程、情感识别优化、LangGraph 状态管理、Ollama 私有化部署 1. 对话训练系统技术架构 采用四层架构实现高扩展性的对话训练…...
深度解析云存储:概念、架构与应用实践
在数据爆炸式增长的时代,传统本地存储因容量限制、管理复杂等问题,已难以满足企业和个人的需求。云存储凭借灵活扩展、便捷访问等特性,成为数据存储领域的主流解决方案。从个人照片备份到企业核心数据管理,云存储正重塑数据存储与…...
