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

news2024/11/13 20:35:26

1.使用POI写入
当我们想在Excel文件中写入100w条数据时,使用XSSFWorkbook进行写入时会发现,只有将100w条数据全部加载到内存后才会用write()方法统一写入,效率很低,所以我们引入了SXXFWorkbook进行超大Excel文件读写。

通过设置 SXXFWorkbook 的构造参数,可以设置每次在内存中保持的行数,当达到这个值的时候,那么会把这些数据flush 到磁盘上,这样就不会出现内存不够的情况。

package com.ztt.Demo02;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.UUID;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

public class demo07 {
	public static void main(String[] args) {
		try (SXSSFWorkbook workbook = new SXSSFWorkbook(100);
				FileOutputStream fos = new FileOutputStream("D:\\test\\tt\\temp.xlsx")){
				Sheet sheet1 = workbook.createSheet();
				
				for (int i = 0; i <= 1000000; i++) {
					Row row = sheet1.createRow(i);
					Cell cell0 = row.createCell(0);
					cell0.setCellValue(UUID.randomUUID().toString());
					Cell cell1 = row.createCell(1);
					cell1.setCellValue( new Date());
				}
				
				workbook.write(fos );
			}catch (IOException e) {
					e.printStackTrace();
			}
	}
}

2.使用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;
	}
	@Override
	public String toString() {
		return "Order [orderId=" + orderId + ", payment=" 
                                                + payment + "]";
	}
}

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

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

package com.ztt.demo01;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;

public class Test1 {
	public static void main(String[] args) {
		//将100w条订单数据写入Excel文件
//		EasyExcel.write("D:\\test\\poi\\alibaba\\0421-a.xlsx",Order.class)
//		.sheet("订单数据")
//		.doWrite(createOrderData());
		
		//读取Excel文件中的数据
		//参数1:文件的的路径
		//参数2:文件中每条数据对应的Class类型
		//参数3:如何解析
		EasyExcel.read("D:\\test\\poi\\alibaba\\0421-a.xlsx",Order.class,new AnalysisEventListener<Order>() {
			
			//读取列头
			@Override
			public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
				System.out.println("Excel文件的列头:"+headMap);
			}
			
			//处理每行数据
			@Override
			public void invoke(Order order, AnalysisContext arg1) {
				System.out.println("读取到一条订单数据:"+order);
			}
			
			@Override
			public void doAfterAllAnalysed(AnalysisContext arg0) {
				System.out.println("读取完毕");
				
			}
		}).sheet().doRead();
	}
	
	//生成100w条订单数据
	private static List<Order> createOrderData() {
		List<Order> orderList=new ArrayList<Order>();
		for(int i=0;i<1000;i++) {
			orderList.add(new Order());
		}
		return orderList;
	}
}

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

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;
	}
	@Override
	public String toString() {
		return "Order [orderId=" + orderId + ", payment=" + payment
                                 + ", creatTime=" + creatTime + "]";
	}
}

运行结果: 

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

package com.ztt.demo01;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;

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

	

}

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

package com.ztt.demo01;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.NumberFormat;

public class Order {
		@ExcelProperty("订单编号")
		private String orderId;//订单编号
		
		@ExcelProperty("支付金额")
		@NumberFormat("¥#,###")
		private Double payment;//支付金额

		//设置LocalDateTime对应转换器
		@ExcelProperty(value="创建时间",converter=LocalDateTimeConverter.class)
		private LocalDateTime createionTime;//创建日期
		
		
		public Order() {
			this.orderId=LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHss"))+UUID.randomUUID().toString().substring(0,5);
			this.payment=Math.random()*10000;
			this.createionTime=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 getCreateionTime() {
			return createionTime;
		}

		public void setCreateionTime(LocalDateTime createionTime) {
			this.createionTime = createionTime;
		}

		@Override
		public String toString() {
			return "Order [orderId=" + orderId + ", payment=" + payment + ", createionTime=" + createionTime + "]";
		}
		


}

运行结果:

练习:检查Excel文件 

1.序号是否连续

2.检查性别是否为男或女

3.身份证号

        3.1 身份证号码格式(必须为18位)

        3.2 身份证号码不能重复

        3.3 身份证号码开头两位是否与籍贯符合

                北京 11 天津12 河北 13 山西14 内蒙古 15

                陕西61 甘肃62 青海 63

4.学历只能填写:大专、本科、硕士、其它

5.体重在40-120之间

package com.ztt.Demo02;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class demo05 {
	public static void main(String[] args) {

		List<String> errorMsgList = validateDataExcel("D:\\test\\tt\\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 excelDataFilePath) {
		
		// 1.序号是否连续
		// 2.检查性别是否为男或女
		// 3.身份证号
		// 3.1 身份证号码格式(必须为18位)
		// 3.2 身份证号码不能重复
		// 3.3 身份证号码开头两位是否与籍贯符合
		// 北京 11 天津12 河北 13 山西14 内蒙古 15
		// 陕西61 甘肃62 青海 63
		// 4.学历只能填写:大专、本科、硕士、其它
		// 5.体重在40-120之间
		
		//创建用于保存错误提示信息的集合
		ArrayList<String> errorList=new ArrayList<String>();
		
		//创建用于检查身份证号码是否重复的set集合
		HashSet<String> idCardNoSet = new HashSet<String>();

		//创建用于检查身份证号码前2位与籍贯省份之间的映射关系的Map集合
		//北京11天津12河北13山西14内蒙古15
		//陕西61甘肃62青海63
		HashMap<String,String> provinceMap = new HashMap<String,String>() {
		//构造代码块
		{
			put("11","北京");
			put("12","天津");
			put( "13","河北");
			put("14","山西");
			put("15","内蒙古");
			put("61","陕西");
			put("62","甘肃");
			put("63","青海");
		}
	};
		//创建一个用于检查学历的List集合
		List<String> eduList = Arrays.asList("大专", "本科" , "硕士","其它");

	       
		
		try(Workbook workbook=new XSSFWorkbook(excelDataFilePath)){
			Sheet sheet=workbook.getSheetAt(0);
			
			for(int i=1;i<sheet.getLastRowNum();i++) {
				Row row =sheet.getRow(i);
				
				//1.序号是否连续
				Cell cellId=row.getCell(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(!gender.equals("男") && !gender.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身份证号码不能重复
				if(!idCardNoSet.add(idCardNo)) {
					errorList.add(String.format("%d行的身份证号码重复存在! ",rowNum));
				}
				
				//3.3身份证号码开头两位是否与籍贯符合
				//北京11天津12河北13山西14内蒙古15
				//陕西61甘肃62青海63
				String idCardNoHomeCode = idCardNo.substring(0,2);
				String homeValue = provinceMap.get(idCardNoHomeCode); //根据身份证号码前两位获取正确的籍贯省份名称
				String home = row.getCell(6).getStringCellValue();//获取表格中当前行的籍贯信息
				if(!homeValue.equals( home)) { 
					errorList.add(String.format("%d行的身份证籍贯信息不一致! ",rowNum));
			}


				//4.学历只能填写:大专、本科、硕士、其它
				String eduValue=row.getCell(7).getStringCellValue();
				if(!eduList.contains(eduValue)) {
					errorList.add(String.format("%d行的学历信息不符合规范! ",rowNum));
				}
			}

                
            
		
			
		} catch (IOException e) {
			e.printStackTrace();
		}

		return errorList;
	}

}

运行结果:

1行的学历信息不符合规范! 
3行的身份证籍贯信息不一致! 
4行的编号不连续!
5行的学历信息不符合规范! 
7行的身份证号码长度有误! 
9行的身份证号码长度有误! 
9行的学历信息不符合规范! 
10行的身份证籍贯信息不一致! 
11行的身份证号码长度有误! 
12行的编号不连续!
13行的身份证号码长度有误! 
14行的学历信息不符合规范! 
15行的学历信息不符合规范! 
16行的性别有误!
18行的编号不连续!
22行的身份证籍贯信息不一致! 
24行的身份证号码重复存在! 
25行的性别有误!
33行的身份证号码重复存在! 
36行的身份证号码长度有误! 
39行的身份证籍贯信息不一致! 
41行的身份证籍贯信息不一致! 
43行的身份证籍贯信息不一致! 
44行的身份证籍贯信息不一致! 
46行的身份证籍贯信息不一致! 


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1645768.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IMU在羽球发球力中的应用

在羽毛球运动中&#xff0c;发球不仅是比赛得分的关键&#xff0c;其技术细节更是影响比赛走向的重要因素。近期&#xff0c;来自斯洛伐克和波兰的科研团队利用先进的IMU传感器技术&#xff0c;对顶尖选手的发球技巧进行了深度分析&#xff0c;旨在揭示不同发球方向对上身动作的…

通过线程池开启异步任务 @Async

同步任务&#xff1a; 同步任务是在单线程中按顺序执行&#xff0c;每次只有一个任务在执行&#xff0c;不会引发线程安全和数据一致性等并发问题 同步任务需要等待任务执行完成后才能执行下一个任务&#xff0c;无法同时处理多个任务&#xff0c;响应慢&#xff0c;影响用户体…

《第一行代码》第二版学习笔记(7)——使用通知和摄像头

文章目录 一、使用通知二、调用摄像头 介绍了通知基于8.0的使用方法和如何调用摄像头拍照 一、使用通知 public void onClick(View v) {if (v.getId() R.id.send_notice){Intent intent new Intent(this,NotificationActivity.class);PendingIntent pi PendingIntent.getAct…

如何快速找出文件夹里的全部带有英文纯英文的文件

参考此文章&#xff1a;如何快速找出文件夹里的全部带有中文&纯中文的文件 只需要根据自己的需求&#xff0c;把下面相关的设置调整好即可

KaiwuDB 解析器之语义解析

KaiwuDB 解析器介绍 解析器是数据库系统的重要组成部分之一&#xff0c;主要的功能是将客户端输入的 SQL 语句分解为语法单元&#xff0c;然后将这些语法单元转化成数据库内部可识别的数据结构&#xff0c;最终生成数据库可以执行的计划。 KaiwuDB 的一条 SQL 执行的整个生命…

事件知识图谱 - EventKGE_Event knowledge graph embedding with event causal transfer

EventKGE: Event knowledge graph embedding with event causal transfer 作者&#xff1a;Daiyi Li&#xff08;南航&#xff09; 来源&#xff1a;2023 Knowledge-Based Systems&#xff08;中科院一区&#xff0c;影响因子8.8&#xff09; 论文&#xff1a;[ScienceDirec…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 5月6日,星期一

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年5月6日 星期一 农历三月廿八 1、 五一假期全社会跨区域人员流动量预计约13.6亿人次&#xff0c;日均超2.7亿人次。 2、 祝贺&#xff01;国羽男队第11次夺得汤姆斯杯冠军&#xff0c;国羽女队第16次夺得尤伯杯冠军。 3、…

Windows系统本地部署Net2FTP文件管理网站并实现远程连接上传下载

文章目录 1.前言2. Net2FTP网站搭建2.1. Net2FTP下载和安装2.2. Net2FTP网页测试 3. cpolar内网穿透3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 文件传输可以说是互联网最主要的应用之一&#xff0c;特别是智能设备的大面积使用&#xff0c;无论是个人…

我独自升级崛起加速器推荐 用什么加速器好用 免费加速器推荐

新韩漫公司所发布的这项动作游戏已向玩家们敞开大门&#xff0c;为大家带来了前所未有的游戏体验和乐趣。这个游戏内包含了大量令人着迷的故事、令人印象深刻的战斗场景以及丰富多样的娱乐元素。在这其中最为引人注目的一点就是游戏内容中融入了“虚拟角色”的元素&#xff0c;…

Docker Compose:简化多容器应用部署

序言 在当今的软件开发中&#xff0c;容器化技术的使用已经很普遍了。而 Docker 作为其中最流行的容器化平台之一&#xff0c;为开发者提供了方便、快捷、一致的开发和部署环境。但是&#xff0c;当我们的应用开始变得更加复杂&#xff0c;涉及到多个容器时&#xff0c;手动管…

HTML_CSS学习:定位

一、相对定位 相关代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>相对定位</title><style>.outer{width: 500px;background-color: #999ff0;border: 1px solid #000;p…

vue-cli+vue3+vite+ts 搭建uniapp项目全过程(一)

unapp官方提供了cli 脚手架创建 uni-app 项目的文档 Vue3/Vite版要求 node 版本 18、20使用Vue3/Vite版创建不会提示选择模板&#xff0c;目前只支持创建默认模板 本文以vue3vitets为例 1、初始化项目 npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project 执行完生成…

OpenHarmony实战开发-请求自绘制内容绘制帧率

对于基于XComponent进行Native开发的业务&#xff0c;可以请求独立的绘制帧率进行内容开发&#xff0c;如游戏、自绘制UI框架对接等场景。 接口说明 开发步骤 说明&#xff1a; 本范例是通过Drawing在Native侧实现图形的绘制&#xff0c;并将其呈现在NativeWindow上 1.定义Ark…

与Apollo共创生态:助力自动驾驶迈向新台阶

引言Apollo七周年大会企业协同工具链携手伙伴共创生态未来展望与总结 引言 2024年4月19日&#xff0c;一场智能汽车未来的盛宴正朝我们走来——Apollo开放平台的七周年大会。 此次大会主题为“破晓•拥抱智变时刻”其中“破晓”象征着新时代的曙光&#xff0c;意味着智能汽车技…

电脑问题2【彻底删除CompatTelRunner】

彻底删除CompatTelRunner 电脑偶尔会运行CompatTelRunner造成CPU占用的资源非常大,所以这里要想办法彻底关闭他 本文摘录于&#xff1a;https://mwell.tech/archives/539只是做学习备份之用&#xff0c;绝无抄袭之意&#xff0c;有疑惑请联系本人&#xff01; 解决办法是进入W…

软件测试,软件评测师

如果你想考软件评测师证书&#xff0c;那这篇文章可以帮你少走很多弯路&#xff0c;估计你用别人一半的时间备考就可以通过考试&#xff0c;以下为本人亲身经验哈&#xff0c;你可以先收藏后看哦&#xff0c;提前祝你考试过过过。 如果以后想从事一份软件测试工程师的工作&…

2024.5.6

#include "mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent) {//设置窗口大小this->resize(1000,740);//设置窗口图标this->setWindowIcon(QIcon("C:\\Users\\Administrator\\Desktop\\pictrue\\Plants.png"));//设置窗口标题this-…

柯桥西语培训之在西班牙旅游点菜哪些坑不能踩?

Por muy bien que se coma en Espaa —que es mucho— hay una cosa innegable: lo que pasa en la cocina se queda en la cocina. No todos los alimentos son igualmente seguros o sabrosos cuando se encuentran fuera de la comodidad de nuestra propia casa. Ya sea po…

保持 Hiti 证卡打印机清洁的重要性和推荐的清洁用品

在证卡印刷业务中&#xff0c;保持印刷设备的清洁至关重要。特别是对于 Hiti 证卡打印机来说&#xff0c;它们是生产高质量证卡的关键工具。保持设备清洁不仅可以保证打印质量和效率&#xff0c;还可以延长其使用寿命。本文将探讨保持 Hiti 证卡打印机清洁卡的重要性&#xff0…

StreamingT2V

下面首先是参考的一些博客 https://blog.csdn.net/qq_44681809/article/details/137081515 qustion SDEdit:就是给图片加一点噪声然后再用模型去噪&#xff0c;来获得一个更好的帧&#xff0c;比如去掉伪影和污点 这里的分割为m个24帧的块&#xff0c;块与块之间已经有8帧重叠…