Excel导入导出在软件开发中很是常见,只要你接触过开发,就必定会遇到。相信不少人会跟我同样选择用Apache POI来完成这项工做,在感觉到POI功能强大的同时,个人团队也遇到了如下问题:java
AutoExcel解决了上述问题,它很是简单,只须要少许的代码便可完成复杂的导入导出;使用它时,程序员对导入导出无感,即不须要直接操做POI;与此同时,实施顾问提供的Excel便是导入导出模板,除非新增数据源或字段,不然模板更新不须要动用开发资源。git
AutoExcel并无对POI进行太重的封装,而是充分利用了Excel自己具备的特性——名称管理器,经过一些小技巧,将单元格与数据源产生映射,从而解耦程序员与POI,避免产生硬编码,让导入导出工做变得愉快而再也不是枯燥乏味。程序员
导出前 | 导出后 |
---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
实现以上导出只须要编写如下少许代码(你须要额外的代码来准备数据源,例如从数据库中获取)github
List<TemplateExportPara> paras = new ArrayList<>(); paras.add(new TemplateExportPara("BusinessUnit", DataGenerator.genBusinessUnit())); paras.add(new TemplateExportPara("Contract", DataGenerator.genContracts())); paras.add(new TemplateExportPara("Project", DataGenerator.genProjects())); List<Product> products = DataGenerator.genProducts(); TemplateExportPara para3 = new TemplateExportPara("Product", products); para3.setInserted(true); paras.add(para3); TemplateExportPara para5 = new TemplateExportPara("Product2", products); para5.setDataDirection(DataDirection.Right); paras.add(para5); ExcelSetting excelSetting = new ExcelSetting(); excelSetting.setRemovedSheets(Arrays.asList("will be removed")); AutoExcel.save(this.getClass().getResource("/template/Common.xlsx").getPath(), this.getClass().getResource("/").getPath() + "ExportWithTemplate.xlsx", paras, excelSetting);
要实现以上导出,首先须要完成模板的制做。一些报表制做工具如微软的RDL,你会在RDL中制做好导出模型,而后结合代码将数据导出到Excel。这个过程,RDL仅仅起到中介做用,意味着每次有新的导出任务,都得先制做一个导出模型。在AutoExcel中,Excel即模板,若是你的Excel来源是实施顾问,极可能这个Excel已经设定好数据格式、单元格样式等,就等着你往上填数据,既然如此,何不就将这份Excel做为咱们的导出模板,咱们要作的,仅仅是在其中加入咱们的东西而已。数据库
Excel中的名称管理器,这个被大多数人忽视的功能,却成为AutoExcel中链接数据源与单元格的桥梁。你能够经过点击菜单公式->名称管理器来打开名称管理器,其中每个名称都对应Excel中的某个具体位置,能够是一个区域,也能够是一个单元格,固然,在这里,咱们定义的名称都指向单元格。所以能够这么理解,名称管理器就是用来给单元格命名的。正是由于单元格有了名字,咱们才能实现给单元格自动赋值而无需个性化的代码。ide
为单元格定义了名称以后,当你再次点击该单元格,会发现左上角的位置显示了你刚才定义的名称工具
除了在名称管理器中新增名称,还有一种方式更加直观快捷。点击你想要命名的单元格,而后直接在左上角输入名称,最后按Entry键便可。推荐使用这种方式建立名称。单元测试
因为单元格名称决定了何种数据按什么方式进行填充,所以必须按如下规则进行命名:测试
全部名称均不区分大小写,如下会根据具体场景分别进行介绍ui
如图所示,批注中注明了每一个单元格的名称,按照数据源名称.字段名称
的规则书写
Java代码:
String templatePath = this.getClass().getResource("/template/Common.xlsx").getPath(); String outputPath = this.getClass().getResource("/").getPath() + "ExportWithTemplate.xlsx"; //DataGenerator.genBusinessUnit()用于生成demo数据 TemplateExportPara para = new TemplateExportPara("BusinessUnit", DataGenerator.genBusinessUnit()); AutoExcel.save(templatePath, outputPath, para);
若是你想导出的是一个列表数据,你只须要按照基础对象的书写规则进行命名便可。固然,列表数据导出每每比基础对象复杂,好比,你可能须要一列行号,而又不想在代码中作特殊处理,这时候你可使用数据源名称.RowNo
,将工做交给AutoExcel来处理。注意,RowNo是内置字段,若是数据源中包含此字段,将会被覆盖。
还有一种状况很是常见,你有一个带公式的单元格在表格中,如:=E6+F6
,你但愿下一行的单元格被赋值=E7+F7
,这时你应该使用数据源名称.Formula.xxxx
,你可使用任何你喜欢的公式,AutoExcel最终都会帮你自动填充。xxxx
的部分你能够随便书写,只要保证名称惟一便可。Formula一样是内置字段。
Java代码:
String templatePath = this.getClass().getResource("/template/Common.xlsx").getPath(); String outputPath = this.getClass().getResource("/").getPath() + "ExportWithTemplate.xlsx"; //DataGenerator.genContracts()用于生成demo数据 TemplateExportPara para = new TemplateExportPara("Contract", DataGenerator.genContracts()); AutoExcel.save(templatePath, outputPath, para);
在一个Sheet中导出多个表格,若是你有这样的需求,请在代码中将不是处于最下面的表格的导出参数设置为:setInserted(true)
,如上图,products对应的导出参数para应作以下设置:para.setInserted(true)
。要知道,AutoExcel是不理会数据导出是否有足够空间的,它只会一个劲地输出,因此当你的模板空间不够时,你须要告诉AutoExcel,以后AutoExcel会在导出前腾出足够的空间来容纳你的数据。
这里引入了新的命名规则:数据源名称.字段名称.合计类型
,用于对指定字段进行合计,目前支持两种合计类型:Sum和Avg。
Java代码:
String templatePath = this.getClass().getResource("/template/Common.xlsx").getPath(); String outputPath = this.getClass().getResource("/").getPath() + "ExportWithTemplate.xlsx"; List<TemplateExportPara> paras = new ArrayList<>(); //DataGenerator.genProjects()用于生成demo数据 paras.add(new TemplateExportPara("Project", DataGenerator.genProjects())); //DataGenerator.genProducts()用于生成demo数据 TemplateExportPara para = new TemplateExportPara("Product", DataGenerator.genProducts()); para.setInserted(true); //导出空间不够时需设置 paras.add(para); AutoExcel.save(templatePath, outputPath, paras);
若是你须要将数据向右而不是向下填充,你只须要使用setDataDirection(DataDirection.Right)
便可。
Java代码:
String templatePath = this.getClass().getResource("/template/Common.xlsx").getPath(); String outputPath = this.getClass().getResource("/").getPath() + "ExportWithTemplate.xlsx"; TemplateExportPara para = new TemplateExportPara("Product2", DataGenerator.genProducts()); para.setDataDirection(DataDirection.Right); //向右填充 AutoExcel.save(templatePath, outputPath, para);
直接导出,即导出过程不须要借助模板,适用于集成到后台系统的通用导出功能中,代码很是简单
String outputPath = this.getClass().getResource("/").getPath() + "Export.xlsx"; DirectExportPara para = new DirectExportPara(DataGenerator.genProjects()); AutoExcel.save(outputPath, para);
效果:
固然,你并不会喜欢这样的标题和标题顺序,所以,你须要借助FieldSetting来让你的标题可读且按照你喜欢的顺序来展示。
List<FieldSetting> fieldSettings = new ArrayList<FieldSetting>() {{ add(new FieldSetting("projName", "Project Name")); add(new FieldSetting("basalArea", "Basal Area")); add(new FieldSetting("buildingArea", "Building Area")); add(new FieldSetting("insideArea", "Inside Area")); add(new FieldSetting("availableArea", "Available Area")); add(new FieldSetting("availablePrice", "Available Price")); add(new FieldSetting("availableAmount", "Available Amount")); }}; String outputPath = this.getClass().getResource("/").getPath() + "Export.xlsx"; DirectExportPara para = new DirectExportPara(DataGenerator.genProjects(), "Projects", fieldSettings); AutoExcel.save(outputPath, para);
最终效果:
AutoExcel致力于处理导入导出的通用场景,若是有个性化的需求,你应该取回Workbook
的控制权,根据你的需求进行个性化处理。save方法提供了两个Consumer
,其中actionAhead
会在导出操做开始以前被调用,actionBehind
会在导出完成以后被调用,你彻底能够经过这两个Consumer
来添加你想要的功能。
String templatePath = this.getClass().getResource("/template/Common.xlsx").getPath(); String outputPath = this.getClass().getResource("/").getPath() + "ExportWithTemplate.xlsx"; List<TemplateExportPara> paras = new ArrayList<>(); paras.add(new TemplateExportPara("BusinessUnit", DataGenerator.genBusinessUnit())); Consumer<Workbook> actionAhead = Workbook -> { //作任何你想作的事情 }; Consumer<Workbook> actionBehind = workbook -> { //作任何你想作的事情 }; AutoExcel.save(templatePath, outputPath, paras, actionAhead, actionBehind);
相较于导出,导入具备如下特色:
数据源名称.字段名称
null
,即读取基础对象,如需读取列表,需指明读取方向为Down
,暂不支持Right方向的读取。Java代码:
List<ImportPara> importParas = new ArrayList<ImportPara>() {{ add(new ImportPara("BusinessUnit")); add(new ImportPara("Contract", DataDirection.Down)); add(new ImportPara("Project", DataDirection.Down)); //add(new ImportPara("Product", DataDirection.Down)); 暂不支持 }}; String fileName = this.getClass().getResource("/").getPath() + "ExportWithTemplate.xlsx"; HashMap<String, List<HashMap<String, Object>>> datas = AutoExcel.read(fileName, importParas);
完整的示例代码请前往单元测试查看