热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

基于POI的JavaMaven项目中实现Excel数据的高效导入与导出功能

本项目在JavaMaven框架下,利用POI库实现了Excel数据的高效导入与导出功能。通过优化数据处理流程,提升了数据操作的性能和稳定性。项目已发布至GitHub,当前最新版本为0.0.5。该项目不仅适用于小型应用,也可扩展用于大型企业级系统,提供了灵活的数据管理解决方案。GitHub地址:https://github.com/83945105/holygrail,Maven坐标:`com.github.83945105:holygrail:0.0.5`。

个人项目

GitHub地址:https://github.com/83945105/holygrail

Maven坐标: 目前最新版0.0.5

com.github.83945105
holygrail欢迎到官网搜索最新版:

地址一:点击打开链接

地址二:点击打开链接

导入导出目前实现了常用功能,后续我会不断完善,如添加字体设置


开始教程








一、导出








  • 1、废话不多说,先来2个最简单的例子

/*模拟从数据库获取数据开始*/Collection> records = new ArrayList<>();Map record01 = new HashMap<>();Map record02 = new HashMap<>();Map record03 = new HashMap<>();record01.put("username", "张三1");record01.put("password", "666");record02.put("username", "张三2");record02.put("password", "666");record03.put("username", "张三3");record03.put("password", "666");records.add(record01);records.add(record02);records.add(record03);/*模拟从数据库获取数据结束*/Export.buildSXSSFExportExcelWorkBook()//构建查询对象.createSheet()//创建一个Sheet,可以传参设置Sheet名.setColumnFields("username","password")//设置列字段,对应Map集合的key.importData(records)//导入数据,支持多次导入.export("E://测试.xlsx");//导出成Excel

/*模拟从数据库获取数据开始*/Collection records = new ArrayList<>();User user01 = new User();User user02 = new User();User user03 = new User();user01.setUsername("张三1");user01.setPassword("666");user02.setUsername("张三2");user02.setPassword("666");user03.setUsername("张三3");user03.setPassword("666");records.add(user01);records.add(user02);records.add(user03);/*模拟从数据库获取数据结束*/Export.buildSXSSFExportExcelWorkBook()//构建查询对象.createSheet()//创建一个Sheet,可以传参设置Sheet名.setColumnFields("username","password")//设置列字段,对应User对象的属性名.importData(records)//导入数据,支持多次导入.export("E://测试.xlsx");//导出成Excel


  • 2、连续创建Sheet表

/*模拟从数据库获取数据开始*/Collection records = new ArrayList<>();User user01 = new User();User user02 = new User();User user03 = new User();user01.setUsername("张三1");user01.setPassword("666");user01.setMobile("110");user02.setUsername("张三2");user02.setPassword("666");user01.setMobile("120");user03.setUsername("张三3");user03.setPassword("666");user01.setMobile("119");records.add(user01);records.add(user02);records.add(user03);/*模拟从数据库获取数据结束*/Export.buildSXSSFExportExcelWorkBook().createSheet().setColumnFields("username","password").importData(records).getOwnerWorkBook().createSheet("SheetB")//创建第二个Sheet,设置了Sheet名.setColumnFields("mobile").importData(records).export("E://测试.xlsx");

  • 3、自定义标题(这种方式可以动态创建列)

//构建用于描述标题的二维数组,获取数据代码略SXSSFExcelTitle[][] titles = new SXSSFExcelTitle[1][];SXSSFExcelTitle[] title = new SXSSFExcelTitle[3];title[0] = new SXSSFExcelTitle();title[1] = new SXSSFExcelTitle();title[2] = new SXSSFExcelTitle();title[0].setField("username");//设置标题所在列对应数据的字段title[1].setField("password");title[2].setField("mobile");title[0].setTitle("姓名");//设置标题名称title[1].setTitle("密码");title[2].setTitle("手机号");title[0].setWidth(50);//设置列宽,默认10,由于计算原因,实际效果稍有误差title[1].setWidth(60);title[2].setWidth(70);title[0].setHAlign(CellStyle.H_AlignType.LEFT);//设置水平对齐方式为左对齐,标题默认水平居中title[0].setVAlign(CellStyle.V_AlignType.BOTTOM);//设置垂直对齐方式为底部对齐,标题默认垂直居中title[0].setBorderLeft(CellStyle.BorderStyle.DASH_DOT);//设置左边框样式,同样还可以设置其它方向边框titles[0] = title;Export.buildSXSSFExportExcelWorkBook().createSheet().setTitles(titles)//设置标题.importData(records).export("E://测试.xlsx");
 

  • 4、用js文件描述标题(这种方式正常操作不能动态创建列,你要是动态生成这个文件当我没说)

ExcelWorkBookExport.exportTemplateJavascriptFile("E://user.js");//你可以这样导出一个模板文件

[[{title: &#39;姓名&#39;,field: &#39;username&#39;,width: 20,borderLeft: &#39;DASHED&#39;
},{title: &#39;密码&#39;,field: &#39;password&#39;,hAlign: &#39;Left&#39;,vAlign: &#39;top&#39;,width: 30
},{title: &#39;手机号&#39;,field: &#39;mobile&#39;,width: 15
}]]

 基于模板我把表头文件修改成这种,如果你会使用easyui的datagrid的columns属性,

那你就很好理解为什么标题要用二维数组来描述

Export.buildSXSSFExportExcelWorkBook().createSheet()//解析一个标题文件,文件放在你能加载到的位置就可以,这里我使用输入流的方式 .parseTitlesJson(Test.class.getResourceAsStream("/com/xx/xx/xx/xx/user.js")) .importData(records).export("E://测试.xlsx");

  • 5、复杂的标题(合并单元格,以js文件方式为例)
  • [[{title: &#39;姓&#39;
    }, {title: &#39;名&#39;
    }, {title: &#39;密码+手机号&#39;,colSpan: 2
    }, {title: &#39;占用2行&#39;,rowSpan: 2
    }], [{title: &#39;姓名&#39;,field: &#39;username&#39;,width: 20,colSpan: 2}, {title: &#39;密码&#39;,field: &#39;password&#39;,width: 15}, {title: &#39;手机号&#39;,field: &#39;mobile&#39;,width: 15}
    ]]

     修改标题js如上,二维数组第一维表示一行,rowSpan表示占用行数,colSpan表示占用列数
 导出Excel效果如下

  • 6、格式化单元格
  • 除了标题单元格可以自定义,数据单元格同样可以自定义(格式化)
 
 我们将上面的标题js加入一个序号列,占用2行

Export.buildSXSSFExportExcelWorkBook()//构建查询对象.createSheet()//创建一个Sheet,可以传参设置Sheet名.parseTitlesJson(Test.class.getResourceAsStream("/com/xx/xx/xx/xx/user.js"))//使用lambda表达式作为第二个参数格式化单元格,如果你会写Javascript可以理解为JS的回调函数.importData(records, (value, record, cellHandler, field, rowCursor, index) -> {//value => 当前单元格的值//record => 当前行数据//cellHandler => 用于设置和获取单元格属性样式的对象,这个对象可以自己点进去看注释,可以干很多事情//field => 当前单元格对应的title field//rowCursor => 行游标,记录当前写入行的游标号,该号从0开始//index => 当前行数据也就是record在数据集合records中的下标if("num".equals(field)) {//如果是序号列cellHandler.setHAlign("center");//设置单元格为水平居中,支持直接传入字符串cellHandler.setVAlign(CellStyle.V_AlignType.CENTER);//设置单元格为垂直居中cellHandler.setType(CellOption.CellType.COMBOBOX);//设置单元格类型为下拉框cellHandler.setOptions(new String[]{"下拉框值1", "下拉框值2"});//设置下拉框值return index + 1;//使用下标号+1作为单元格值}return value;})//导入数据,支持多次导入.export("E://测试.xlsx");
 再来一个更复杂点的例子

[[{title: &#39;序号&#39;,field: &#39;num&#39;,rowSpan: &#39;2&#39;
}, {title: &#39;姓&#39;
}, {title: &#39;名&#39;
}, {title: &#39;密码+手机号&#39;,colSpan: 2
}, {title: &#39;占用2行&#39;,rowSpan: 2,writeEmpty: false
}], [{title: &#39;姓名&#39;,field: &#39;username&#39;,width: 20,colSpan: 2}, {title: &#39;密码&#39;,field: &#39;password&#39;,width: 15}, {title: &#39;手机号&#39;,field: &#39;mobile&#39;,width: 15}
]]
主要说下writeEmpty属性,这个属性默认是true,表示当该列的单元格值为空的时候,也写入数据,

这里我将"占用2行"这列writeEmpty设为false,因为我接下来会格式化手机号列对应的数据单元格,来占用这个列,如果不将writeEmpty设为false,如果单元格值类型对应不上,将报异常,或者打开Excel会提示存在单元格值被覆盖之类的提示。

Export.buildSXSSFExportExcelWorkBook().createSheet().parseTitlesJson(Test.class.getResourceAsStream("/com/xx/xx/xx/xx/user.js")).importData(records, (value, record, cellHandler, field, rowCursor, index) -> {//设置所有数据单元格为水平垂直居中cellHandler.setHAlign("center");cellHandler.setVAlign("center");if("num".equals(field)) {//如果是序号列,将值改为当前数据下标+1return index + 1;}if("username".equals(field)) {//如果是用户名列,将单元格改为占用3列cellHandler.setColSpan(3);}if("password".equals(field)) {//如果是密码列,将单元格起始行下移一行cellHandler.setStartRowNum(cellHandler.getStartRowNum() + 1);//占用行改为3行cellHandler.setRowSpan(3);}if("mobile".equals(field)) {//如果是手机号列//手机号列占用行改为5行cellHandler.setRowSpan(5);//占用列改为2行cellHandler.setColSpan(2);//将值格式化成数值类型return Integer.parseInt(value == null ? "" : value.toString());}return value;})//导入数据,支持多次导入.export("E://测试.xlsx");//导出成Excel

  • 7、最后再丢几个批量创建Sheet的例子


    Export.buildSXSSFExportExcelWorkBook()//批量创建10个sheet.createSheets(10, (sheet, sheetIndex, index, totalAllSheetDataSize, totalSheetDataSize) -> {//sheet => 当前创建的sheet对象//sheetIndex => 当前创建的sheet在整个工作簿中的下标//index => 当前创建的sheet在这个批次sheet的下标//totalAllSheetDataSize => 整个工作簿已经导入的数据总数//totalSheetDataSize => 这个批次sheet已经导入的数据总数sheet.setColumnFields("").importData(new ArrayList<>());}).export("E://批量Sheet.xlsx");

    Export.buildSXSSFExportExcelWorkBook()//批量创建10个sheet.createSheets(10, (sheetIndex, index) -> "格式化Sheet名", (sheet, sheetIndex, index, totalAllSheetDataSize, totalSheetDataSize) -> {sheet.setColumnFields("").importData(new ArrayList<>());}).export("E://批量Sheet.xlsx");

    Export.buildSXSSFExportExcelWorkBook().createSheets((sheet, sheetIndex, index, totalAllSheetDataSize, totalSheetDataSize) -> {sheet.parseTitlesJson("").importData(new HashSet<>());if(totalSheetDataSize > 1000) {//当导入的数据大于1000条,停止创建Sheetreturn false;}return true;//继续创建Sheet,内部限制最大100个}).export("E://批量Sheet.xlsx");

    此外还有一些方法,我就不贴代码了,如设置行号,设置列号控制导入数据的起始行之类的,方法都有详细的注释,用IDE提示就能看到所有方法,基本什么功能都能猜到。


二、导入




所有例子读取以上模板
1、同样先来几个简单的例子

ArrayList> records = Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx"))//解析一个Excel.getSheet(0)//获取下标为0的Sheet.readRows()//读取数据.getReadData();//获得读取的数据集合

这种方式我会将每行数据塞入一个ArrayList,单元格值按照列顺序排列

Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx"))//解析一个Excel.getSheet(0)//获取下标为0的Sheet.readRows((record, records, rowNum, index) -> {ArrayList _record = (ArrayList) record;//一行行获取数据System.out.println(_record.get(0));//取每条数据的第一列的值});在lambda函数中获取当前读取行的数据
2、指定列值获取数据

ArrayList> records = Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx")).getSheet(0).setColumnFields("username", "password")//设置列值.readRows().getReadData();
指定了列值后,默认会将数据注入HashMap,列值为Key,单元格值为Value,如果此时存在没指定列值的单元格,将会使用坐标作为Key,如A1表示第一行第一列,B4表示第四行第二列。

细心会发现,username对应了序号,这是因为设置列值必须自己控制顺序,默认从第一列开始

Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx")).getSheet(0).setColumnFields(2,"num", "username", "password")//设置列值,2表示标题占用2行,那么接下来读取数据将从第三行开始.readRows((record, records, rowNum, index) -> {HashMap _record = (HashMap) record;System.out.println(_record.get(""));});同样可以一行行获取数据

3、使用标题二维数组或者js文件读取Excel(详情见导出)

Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx")).getSheet(0).parseTitlesJson(Test2.class.getResourceAsStream("/com/xx/xx/xx/xx/user.js")).readRows((record, records, rowNum, index) -> {HashMap _record = (HashMap) record;System.out.println(_record.get(""));});二维数组方式同导出,这里就不写了

4、自定义全局接收数据对象

Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx")).getSheet(0)//解析标题文件,并指定使用LinkedHashMap作为数据容器接收数据.parseTitlesJson(Test2.class.getResourceAsStream("/com/xx/xx/xx/xx/user.js"), LinkedHashMap.class).readRows((record, records, rowNum, index) -> {
LinkedHashMap _record = (LinkedHashMap) record;System.out.println(_record.get(""));});

Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx")).getSheet(0)//解析标题文件,并指定使用User对象作为数据容器接收数据.parseTitlesJson(Test2.class.getResourceAsStream("/com/xx/xx/xx/xx/user.js"), User.class).readRows((record, records, rowNum, index) -> {//这里可以转成User对象获取数据User _record = (User) record;System.out.println(_record.getUsername());});


5、自定义行接收对象

Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx")).getSheet(0).parseTitlesJson(Test2.class.getResourceAsStream("/com/xx/xx/xx/xx/user.js"), HashMap.class).readRows(User.class, (record, records, rowNum, index) -> {//读取行时指定对象,覆盖全局,此时不用强转,可直接推导出类型System.out.println(record.getUsername());});
6、连续读取存在的Sheet

Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx")).readSheets((sheet, index) -> {//读取当前Sheet数据sheet.setColumnFields("").readRows(User.class, (record, records, rowNum, index1) -> {System.out.println(record.getUsername());});});

Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx")).readSheets((sheet, index) -> {//读取当前Sheet数据sheet.setColumnFields("").readRows(User.class, (record, records, rowNum, index1) -> {System.out.println(record.getUsername());});if(sheet.getAllReadData().size() > 1000) {//当读取的数据总数大于1000,停止读取下一个Sheetreturn false;}return true;});读取比较简单,就不详细说了。







推荐阅读
  • Ceph API微服务实现RBD块设备的高效创建与安全删除
    本文旨在实现Ceph块存储中RBD块设备的高效创建与安全删除功能。开发环境为CentOS 7,使用 IntelliJ IDEA 进行开发。首先介绍了 librbd 的基本概念及其在 Ceph 中的作用,随后详细描述了项目 Gradle 配置的优化过程,确保了开发环境的稳定性和兼容性。通过这一系列步骤,我们成功实现了 RBD 块设备的快速创建与安全删除,提升了系统的整体性能和可靠性。 ... [详细]
  • 本文探讨了将PEBuilder转换为DIBooter.sh的方法,重点介绍了如何将DI工具集成到启动层,实现离线镜像引导安装。通过使用DD命令替代传统的grub-install工具,实现了GRUB的离线安装。此外,还详细解析了bootice工具的工作原理及其在该过程中的应用,确保系统在无网络环境下也能顺利引导和安装。 ... [详细]
  • 本文详细介绍了使用响应文件在静默模式下安装和配置Oracle 11g的方法。硬件要求包括:内存至少1GB,具体可通过命令`grep -i memtotal /proc/meminfo`进行检查。此外,还提供了详细的步骤和注意事项,确保安装过程顺利进行。 ... [详细]
  • 本文介绍了如何通过掌握 IScroll 技巧来实现流畅的上拉加载和下拉刷新功能。首先,需要按正确的顺序引入相关文件:1. Zepto;2. iScroll.js;3. scroll-probe.js。此外,还提供了完整的代码示例,可在 GitHub 仓库中查看。通过这些步骤,开发者可以轻松实现高效、流畅的滚动效果,提升用户体验。 ... [详细]
  • 掌握PHP框架开发与应用的核心知识点:构建高效PHP框架所需的技术与能力综述
    掌握PHP框架开发与应用的核心知识点对于构建高效PHP框架至关重要。本文综述了开发PHP框架所需的关键技术和能力,包括但不限于对PHP语言的深入理解、设计模式的应用、数据库操作、安全性措施以及性能优化等方面。对于初学者而言,熟悉主流框架如Laravel、Symfony等的实际应用场景,有助于更好地理解和掌握自定义框架开发的精髓。 ... [详细]
  • 本文介绍了使用 Python 编程语言高效抓取微博文本和动态网页图像数据的方法。通过详细的示例代码,展示了如何利用爬虫技术获取微博内容和动态图片,为数据采集和分析提供了实用的技术支持。对于对网络数据抓取感兴趣的读者,本文具有较高的参考价值。 ... [详细]
  • HBase在金融大数据迁移中的应用与挑战
    随着最后一台设备的下线,标志着超过10PB的HBase数据迁移项目顺利完成。目前,新的集群已在新机房稳定运行超过两个月,监控数据显示,新集群的查询响应时间显著降低,系统稳定性大幅提升。此外,数据消费的波动也变得更加平滑,整体性能得到了显著优化。 ... [详细]
  • Spring框架入门指南:专为新手打造的详细学习笔记
    Spring框架是Java Web开发中广泛应用的轻量级应用框架,以其卓越的功能和出色的性能赢得了广大开发者的青睐。本文为初学者提供了详尽的学习指南,涵盖基础概念、核心组件及实际应用案例,帮助新手快速掌握Spring框架的核心技术与实践技巧。 ... [详细]
  • ylbtech-进销存管理解决方案:进销存管理,即购销链管理,涵盖企业从采购(进)、库存(存)到销售(销)的全流程动态管控。其中,“进”涉及从市场询价、供应商选择、采购执行直至货物入库及支付流程;“销”则包括产品定价、客户报价、订单处理及销售出库等环节。该解决方案旨在通过信息化手段,提升企业运营效率,优化库存结构,增强市场响应速度。 ... [详细]
  • 利用PaddleSharp模块在C#中实现图像文字识别功能测试
    PaddleSharp 是 PaddleInferenceCAPI 的 C# 封装库,适用于 Windows (x64)、NVIDIA GPU 和 Linux (Ubuntu 20.04) 等平台。本文详细介绍了如何使用 PaddleSharp 在 C# 环境中实现图像文字识别功能,并进行了全面的功能测试,验证了其在多种硬件配置下的稳定性和准确性。 ... [详细]
  • 提升工作效率:掌握这些技巧,IDEA 使用效率翻倍 | IDEA 高效操作指南
    提升工作效率:掌握这些技巧,IDEA 使用效率翻倍 | IDEA 高效操作指南 ... [详细]
  • PHP连接MySQL的三种方法及预处理语句防止SQL注入的技术详解
    PHP连接MySQL的三种方法及预处理语句防止SQL注入的技术详解 ... [详细]
  • 在2020年8月19日的深度分析中,我们探讨了HTML标签中同时存在`a`标签的`href`和`onclick`属性时的触发顺序问题。此外,还讨论了如何在一个自适应高度的父级`div`中,使两个子`div`中的一个固定高度为300px,另一个自动填充剩余空间的方法。最后,文章详细介绍了JavaScript异步加载的多种实现方式,包括但不限于`async`、`defer`属性以及动态脚本插入技术,为开发者提供了丰富的技术参考。 ... [详细]
  • 掌握DSP必备的56个核心问题,我已经将其收藏以备不时之需! ... [详细]
  • 本书《.NET Core 2.* 开发者指南》是面向开发者的全面学习与实践手册,涵盖了从基础到高级的各个层面。书中详细解析了 .NET Core 的核心概念,包括如何创建 .NET Core 网站,并通过视频教程直观展示操作过程。此外,还深入探讨了 Startup 类的作用、项目目录结构的组织方式以及如何在应用中使用静态文件等内容。对于希望深入了解 .NET Core 架构和开发技巧的开发者来说,本书提供了丰富的实践案例和详尽的技术指导。 ... [详细]
author-avatar
劳允旭易文忠名
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有