共计 3530 个字符,预计需要花费 9 分钟才能阅读完成。
摘要:本文由葡萄城技术团队于思否原创并首发。转载请注明出处:葡萄城官网,葡萄城为开发者提供业余的开发工具、解决方案和服务,赋能开发者。
前言 | 问题背景
在操作 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 的格子进行取值,能够用上面的代码提取数据。
@Test
public 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.0
System.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。
@Test
public 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% 进行替换。
@Test
public void testReplaceTemplateFile() {
String templateFilePath = "test.xlsx";
Workbook wb = new Workbook();
wb.open(templateFilePath);
IRange usedRange = wb.getActiveSheet().getUsedRange();
//load data
ArrayList<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 中的公式计算结果。
@Test
public 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 文件