Excel文件解析--超大Excel文件读写

2024-04-23 01:52
文章标签 excel 解析 读写 超大

本文主要是介绍Excel文件解析--超大Excel文件读写,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

使用POI写入

        当我们想在Excel文件中写入100w条数据时,我们用普通的XSSFWorkbook对象写入时会发现,只有在将100w条数据全部加载入内存后才会用write()方法统一写入,这样效率很低,所以我们引入了SXSSFWorkbook进行超大Excel文件的读写。

        SXSSFWorkbook可以通过构造参数来控制:当数据写入内存量达到参数值时,就把这些数据flush到Excel文件中

public class Demo02_SXSSFWorkbook {public static void main(String[] args) {String Path="D://IO流//0421.xlsx";try (Workbook workbook = new SXSSFWorkbook(1000);FileOutputStream out=new FileOutputStream(Path)){//生成SheetSheet sheet=workbook.createSheet();for(int i=0;i<1000000;i++) {Row row =sheet.createRow(i);Cell cell0=row.createCell(0);cell0.setCellValue(UUID.randomUUID().toString());Cell cell1=row.createCell(1);cell1.setCellValue(new Date());}//写入输出流workbook.write(out);}catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}

使用EasyExcel写入

        使用EasyExcel,我们首先要导入相关jar包

         这是一个普通的Order类:

public class Order {private String orderId;private Double payment;public Order() {this.orderId=LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))+UUID.randomUUID().toString().substring(0,5);this.payment=Math.random()*1000;}public String getOrderId() {return orderId;}public void setOrderId(String orderId) {this.orderId = orderId;}public Double getPayment() {return payment;}public void setPayment(Double payment) {this.payment = payment;}@Overridepublic String toString() {return "Order [orderId=" + orderId + ", payment=" + payment + "]";}
}

        然后我们来通过EasyExcel来将100w条数据写入excel文件:

public class Text_order {public static void main(String[] args) {EasyExcel.write("D://IO流//422.xlsx",Order.class).sheet("订单数据").dowrite(creatOrderData());}//生成100w条数据private static List<Order> creatOrderData(){List<Order> orderList=new ArrayList<Order>();for(int i=0;i<1000000;i++) {orderList.add(new Order());}return orderList;}
}

运行结果: 

        我们发现,Order类中的成员变量名就是我们生成的Excel文件中的列头。那么如果我们想自定义列头时,我们可以用:@ExcelProperty("列头名")

public class Order {@ExcelProperty("订单编号")private String orderId;@ExcelProperty("支付金额")private Double payment;public Order() {...}
}

运行结果:

        那么,当我们想加入一列日期数据时:

public class Order {@ExcelProperty("订单编号")private String orderId;@ExcelProperty("支付金额")private Double payment;@ExcelProperty("创建时间")private LocalDateTime  creatTime;public Order() {this.orderId=LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))+UUID.randomUUID().toString().substring(0,5);this.payment=Math.random()*1000;this.creatTime=LocalDateTime.now();}public String getOrderId() {return orderId;}public void setOrderId(String orderId) {this.orderId = orderId;}public Double getPayment() {return payment;}public void setPayment(Double payment) {this.payment = payment;}public LocalDateTime getCreatTime() {return creatTime;}public void setCreatTime(LocalDateTime creatTime) {this.creatTime = creatTime;}@Overridepublic String toString() {return "Order [orderId=" + orderId + ", payment=" + payment+ ", creatTime=" + creatTime + "]";}
}

运行结果:

通过阅读报错提示(Can not find 'Converter' support class LocalDateTime.) ,我们大概可以知道,是因为找不到一个支持LocalDateTime类的转换器,所以为了解决这个问题,我们可以自己写一个比较器类:

public class LocalDateTimeConverter implements Converter<LocalDateTime> {//Excel文件中的类型@Overridepublic CellDataTypeEnum supportExcelTypeKey() {// TODO Auto-generated method stubreturn CellDataTypeEnum.STRING;}//程序中的类型@Overridepublic Class supportJavaTypeKey() {// TODO Auto-generated method stubreturn LocalDateTime.class;}//将LocalDateTime类型的数据转换成String//并封装到一个Excel文件中的CellData@Overridepublic CellData convertToExcelData(LocalDateTime value,         ExcelContentProperty arg1,GlobalConfiguration arg2)throws Exception {// TODO Auto-generated method stubreturn new CellData<>(value.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss")));}//从CellData中获取一个String类型的数据//并转换成LocalDateTime@Overridepublic LocalDateTime convertToJavaData(CellData cellData,             ExcelContentProperty arg1,GlobalConfiguration arg2)throws Exception {// TODO Auto-generated method stubreturn LocalDateTime.parse(				            cellData.getStringValue(),DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"));}
}

        当我们写好这个比较器后,就需要给成员变量creatTime显示的设置好比较器:

public class Order {@ExcelProperty("订单编号")private String orderId;@ExcelProperty("支付金额")private Double payment;//设置LocalDateTime对应转换器@ExcelProperty(value="创建时间",converter=LocalDateTimeConverter.class)private LocalDateTime  creatTime;public Order() {...}
}

运行结果:

Excel文件解析的应用

案例一:检查Excel文件

//检查demo-data.xlsx文件中的人员信息格式是否正确,具体要求如下:

// 1.序号是否连续
// 2.检查性别是否为男或女
// 3.身份证号
// 3.1 身份证号码格式(必须为18位)
// 3.2 身份证号码不能重复
// 3.3 身份证号码开头两位是否与籍贯符合
// 北京 11 天津12 河北 13 山西14 内蒙古 15
// 陕西61 甘肃62 青海 63
// 4.学历只能填写:大专、本科、硕士、其它
// 5.体重在40-180之间

public class Work01 {public static void main(String[] args) {List<String> errorMsgList=validateDataExcel("D:\\IO流\\demo-    data.xlsx");if(errorMsgList.size()==0){System.out.println("文件检查无误");}else {//显示错误信息for(String err:errorMsgList) {System.out.println(err);}}}public static List<String> validateDataExcel(String path){//创建一个list用于保存错误提示信息ArrayList<String> errorList=new ArrayList<String>();//创建一个set用于检查身份证账号是否重复的集合HashSet<String> idcardNoSet=new HashSet<String>();//创建一个HashMap用于检查身份证号码开头两位是否与籍贯符合HashMap<String,String> provinceMap=new HashMap<String,String>(){//匿名构造代码块{put("11","北京");put("12","天津");put("13","河北");put("14","山西");put("15","内蒙古");put("61","陕西");put("62","甘肃");put("63","青海");}};//创建一个用于检查学历的listList<String> eduList=Arrays.asList("大专","硕士","本科","其他");try(Workbook workbook=new XSSFWorkbook(path)){Sheet sheet=workbook.getSheetAt(0);//获取每个Cell中的数据for(int i =1;i<sheet.getLastRowNum();i++){//1.序号是否连续Cell cellId=row.getRow(0);//通过当前行数获取正确的序号int rowNum=row.getRowNum();//获取文件中的序号int id=(int)cellId.getNumericCellValue();if(rowNum!=id) {errorList.add(String.format("%d行的数据不连续",rowNum));		}//2.检查性别是否为男或女String gender =row.getCell(2).getStringCellValue();if(!ender.equals("男")&&!ender.equals("女")){errorList.add(String.format("%d行的性别有误",rowNum));}// 3.身份证号String idCardNo=row.getCell(3).getStringCellValue();// 3.1 身份证号码格式(必须为18位)if(idCardNo.length()!=18) {errorList.add(String.format("%d行的身份证号码长度有误",rowNum));}// 3.2 身份证号码不能重复//如果成功添加进idcardNoSet集合,说明该身份证号没有重复//如果添加不成功,代表有重复if(!idcardNoSet.add(idCardNo)){errorList.add(String.format("%d行的身份证号码重复",rowNum));}// 3.3 身份证号码开头两位是否与籍贯符合// 北京 11 天津12 河北 13 山西14 内蒙古 15// 陕西61 甘肃62 青海 63String idCardNoHomeCode=idCardNo.substring(0,2);//根据身份证号码前两位,在provinceMap中获取正确的籍贯省份名称String homeValue=provinceMap.get(idCardNoHomeCode);// 获取表格中当前行的籍贯省份String home=row.getCell(6).getStringCellValue();if(homeValue!=home) {errorList. add(String. format("%d行的身份证籍贯信息不一致! ", rowNum));}// 4.学历只能填写:大专、本科、硕士、其它//通过在eduList列表中查找来判断学历信息是否符合规范String eduValue = row.getCell(7). getStringCellValue();if(!eduList.contains(eduValue)) {errorList. add(String. format("%d行的学历信息不符合规范! ", rowNum));}}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return errorList;}}

运行结果:

1行的身份证籍贯信息不一致! 
1行的学历信息不符合规范! 
2行的身份证籍贯信息不一致! 
3行的身份证籍贯信息不一致! 
4行的数据不连续
4行的身份证籍贯信息不一致! 
5行的身份证籍贯信息不一致! 
5行的学历信息不符合规范! 
6行的身份证籍贯信息不一致! 
7行的身份证号码长度有误
7行的身份证籍贯信息不一致! 
8行的身份证籍贯信息不一致! 
9行的身份证号码长度有误
9行的身份证籍贯信息不一致! 
9行的学历信息不符合规范! 
10行的身份证籍贯信息不一致! 
11行的身份证号码长度有误
11行的身份证籍贯信息不一致! 
12行的数据不连续
12行的身份证籍贯信息不一致! 
13行的身份证号码长度有误
13行的身份证籍贯信息不一致! 
14行的身份证籍贯信息不一致! 
14行的学历信息不符合规范! 
15行的身份证籍贯信息不一致! 
15行的学历信息不符合规范! 
16行的性别有误
16行的身份证籍贯信息不一致! 
17行的身份证籍贯信息不一致! 
18行的数据不连续
18行的身份证籍贯信息不一致! 
19行的身份证籍贯信息不一致! 
20行的身份证籍贯信息不一致! 
21行的身份证籍贯信息不一致! 
22行的身份证籍贯信息不一致! 
23行的身份证籍贯信息不一致! 
24行的身份证号码重复
24行的身份证籍贯信息不一致! 
25行的性别有误
25行的身份证籍贯信息不一致! 
26行的身份证籍贯信息不一致! 
27行的身份证籍贯信息不一致! 
28行的身份证籍贯信息不一致! 
29行的身份证籍贯信息不一致! 
30行的身份证籍贯信息不一致! 
31行的身份证籍贯信息不一致! 
32行的身份证籍贯信息不一致! 
33行的身份证号码重复
33行的身份证籍贯信息不一致! 
34行的身份证籍贯信息不一致! 
35行的身份证籍贯信息不一致! 
36行的身份证号码长度有误
36行的身份证籍贯信息不一致! 
37行的身份证籍贯信息不一致! 
38行的身份证籍贯信息不一致! 
39行的身份证籍贯信息不一致! 
40行的身份证籍贯信息不一致! 
41行的身份证籍贯信息不一致! 
42行的身份证籍贯信息不一致! 
43行的身份证籍贯信息不一致! 
44行的身份证籍贯信息不一致! 
45行的身份证籍贯信息不一致! 
46行的身份证籍贯信息不一致! 
47行的身份证籍贯信息不一致! 
 

这篇关于Excel文件解析--超大Excel文件读写的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/927468

相关文章

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

Java easyExcel实现导入多sheet的Excel

《JavaeasyExcel实现导入多sheet的Excel》这篇文章主要为大家详细介绍了如何使用JavaeasyExcel实现导入多sheet的Excel,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录1.官网2.Excel样式3.代码1.官网easyExcel官网2.Excel样式3.代码

使用Python绘制3D堆叠条形图全解析

《使用Python绘制3D堆叠条形图全解析》在数据可视化的工具箱里,3D图表总能带来眼前一亮的效果,本文就来和大家聊聊如何使用Python实现绘制3D堆叠条形图,感兴趣的小伙伴可以了解下... 目录为什么选择 3D 堆叠条形图代码实现:从数据到 3D 世界的搭建核心代码逐行解析细节优化应用场景:3D 堆叠图

深度解析Python装饰器常见用法与进阶技巧

《深度解析Python装饰器常见用法与进阶技巧》Python装饰器(Decorator)是提升代码可读性与复用性的强大工具,本文将深入解析Python装饰器的原理,常见用法,进阶技巧与最佳实践,希望可... 目录装饰器的基本原理函数装饰器的常见用法带参数的装饰器类装饰器与方法装饰器装饰器的嵌套与组合进阶技巧

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

深度解析Spring Boot拦截器Interceptor与过滤器Filter的区别与实战指南

《深度解析SpringBoot拦截器Interceptor与过滤器Filter的区别与实战指南》本文深度解析SpringBoot中拦截器与过滤器的区别,涵盖执行顺序、依赖关系、异常处理等核心差异,并... 目录Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现

深度解析Spring AOP @Aspect 原理、实战与最佳实践教程

《深度解析SpringAOP@Aspect原理、实战与最佳实践教程》文章系统讲解了SpringAOP核心概念、实现方式及原理,涵盖横切关注点分离、代理机制(JDK/CGLIB)、切入点类型、性能... 目录1. @ASPect 核心概念1.1 AOP 编程范式1.2 @Aspect 关键特性2. 完整代码实