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 OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

Python实现批量CSV转Excel的高性能处理方案

《Python实现批量CSV转Excel的高性能处理方案》在日常办公中,我们经常需要将CSV格式的数据转换为Excel文件,本文将介绍一个基于Python的高性能解决方案,感兴趣的小伙伴可以跟随小编一... 目录一、场景需求二、技术方案三、核心代码四、批量处理方案五、性能优化六、使用示例完整代码七、小结一、

ShardingProxy读写分离之原理、配置与实践过程

《ShardingProxy读写分离之原理、配置与实践过程》ShardingProxy是ApacheShardingSphere的数据库中间件,通过三层架构实现读写分离,解决高并发场景下数据库性能瓶... 目录一、ShardingProxy技术定位与读写分离核心价值1.1 技术定位1.2 读写分离核心价值二

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

Java MCP 的鉴权深度解析

《JavaMCP的鉴权深度解析》文章介绍JavaMCP鉴权的实现方式,指出客户端可通过queryString、header或env传递鉴权信息,服务器端支持工具单独鉴权、过滤器集中鉴权及启动时鉴权... 目录一、MCP Client 侧(负责传递,比较简单)(1)常见的 mcpServers json 配置

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象