摘要:本文由葡萄城技术团队于思否原创并首发。转载请注明出处:葡萄城官网,葡萄城为开发者提供业余的开发工具、解决方案和服务,赋能开发者。

前言 | 问题背景

在操作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文件