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

news2024/9/25 21:28:42

使用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)){
                //生成Sheet
                Sheet 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 block
			e.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;
	}
	@Override
	public 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;
	}
	@Override
	public 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文件中的类型
	@Override
	public CellDataTypeEnum supportExcelTypeKey() {
		// TODO Auto-generated method stub
		return CellDataTypeEnum.STRING;
	}
	//程序中的类型
	@Override
	public Class supportJavaTypeKey() {
		// TODO Auto-generated method stub
		return LocalDateTime.class;
	}

    //将LocalDateTime类型的数据转换成String
	//并封装到一个Excel文件中的CellData
    @Override
	public CellData convertToExcelData(LocalDateTime value,         
                          ExcelContentProperty arg1,
                          GlobalConfiguration arg2)throws Exception {
		// TODO Auto-generated method stub
		return new CellData<>(
				          value.format(DateTimeFormatter.ofPattern
                          ("yyyy年MM月dd日 HH:mm:ss")));
	}

    //从CellData中获取一个String类型的数据
	//并转换成LocalDateTime
	@Override
	public LocalDateTime convertToJavaData(CellData cellData,             
                         ExcelContentProperty arg1,
                         GlobalConfiguration arg2)throws Exception {
		// TODO Auto-generated method stub
		return 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","青海");
			}
        };

        //创建一个用于检查学历的list
        List<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 青海 63
            String 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 block
		e.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行的身份证籍贯信息不一致! 
 

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

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

相关文章

《ElementUI 基础知识》png 图片扩展 icon用法

前言 UI 设计给的切图是 .png 格式。但想与 Element UI icon 用法类似&#xff0c;方案如下。 实现 步骤一 准备图片 步骤二 新建文件&#xff0c;可使用 CSS 预处理语言 styl 或 scss。 stylus 方式 文件 icon.styl /* 定义一个混合 */ cfgIcon(w, h) {display: inlin…

二叉搜索树中的搜索(力扣700)

解题思路&#xff1a;因为二叉搜索树的左小右大特点&#xff0c;中只是寻找比较目标&#xff0c;怎么序遍历都可以&#xff0c;终止条件就是遍历完毕和找到了&#xff0c;然后就遍历左右子树开始寻找就好了 具体代码如下: class Solution { public: TreeNode* searchBST(Tre…

Java入门四步走

1. 简单的入门语法&#xff1a; 1.1 数据类型&#xff1a; 基本数据类型&#xff1a; 整数类型 —— byte、short、int、long, 浮点类型 —— float、double 字符类型 —— char 布尔类型 —— boolean 引用数据类型&#xff1a; 接口&#xff08;interface&#xff09;、数…

上市公司-企业数据要素利用水平数据集及参考文献(2010-2022年)

01、数据介绍 企业数据要素利用水平是指企业在其生产经营活动中&#xff0c;对数据的收集、处理、分析和应用的能力及效果。这种利用水平的高低直接反映了企业在数字化时代中的竞争力和创新能力。 本数据参考《中央财经大学学报》史青春&#xff08;2023&#xff09;老师的研…

芒果超媒的“乘风破浪”,差了一点市场海浪的反馈

4月21日晚间&#xff0c;芒果超媒发布了2023年度&2024一季度报告。 芒果超媒2023年实现营业收入146.28亿元&#xff0c;同比增长4.66%&#xff1b;净利润35.56亿元&#xff0c;同比增长90.73%&#xff1b;基本每股收益1.90元。公司拟每10股派发现金红利1.8元。2024年第一季…

使用gdal均匀筛选点矢量

使用gdal均匀筛选点矢量 作用&#xff1a; 通过计算各点之间的欧式距离&#xff0c;筛选出符合目标的、均匀发布在空间中的N个数据点。 效果示意图 运行环境 python 3.10 安装&#xff1a;tqdm、numpy和tqdm这三个库 完整代码 import numpy as np from osgeo import ogr,…

291个地级市资源错配指数、劳动和资本相对扭曲指数(2006-2021年)

01、数据介绍 资源错配指数&#xff08;Misallocation Index&#xff09;是一个用于衡量资源配置效率的指标&#xff0c;它衡量的是生产要素的配置是否合理&#xff0c;是否达到了最优的状态。资源错配指数越高&#xff0c;资源的利用效率越低。资源错配指数主要用于衡量各种生…

没想到打脸这么快,AI程序员已经出发了!

大家好啊&#xff0c;我是豆小匠。 先介绍一下本期的主角&#xff1a;Devin&#xff0c;世界上第一位AI程序员&#xff0c;由2023年11月成立的10人初创公司Cognition AI开发。 1. AI程序员已经能做到什么程度 3月13日&#xff0c;Cognition AI公司在X平台&#xff08;原推特&…

监控员工上网记录软件 三款超好用监控员工上网的软件

监控员工上网记录软件 三款超好用监控员工上网的软件 监控员工上网聊天、打游戏、看小说等特定行为的软件通常属于员工监控或上网行为管理软件类别。这类软件旨在帮助企业或组织管理者监督员工在工作时间内对计算机及互联网资源的使用情况&#xff0c;确保工作效率&#xff0c;…

进阶C语言-文件操作

文件操作 &#x1f388;1.为什么使用文件&#x1f388;2.什么是文件&#x1f52d;2.1程序文件&#x1f52d;2.2数据文件&#x1f52d;2.3文件名 &#x1f388;3.文件的打开和关闭&#x1f52d;3.1文件指针&#x1f52d;3.2文件的打开和关闭 &#x1f388;1.为什么使用文件 ✅ 我…

vue的学习之用vue写一个hello,vue

根据以下步骤下载vue.js 介绍 — Vue.js 创建一个damo.html &#xff0c;引入vue.js即可 <body><div id"app">{{ message }}</div><!-- Vue --><!-- 开发环境版本&#xff0c;包含了有帮助的命令行警告 --><script src"js/vu…

Mysql基础(二)数据类型和约束

一 数据类型 讲解主要的数据类型,不面面俱到,后续遇到具体问题再查询补充扩展&#xff1a; 知识点的深度和广度以工作为导向 ① int float M : 表示显示宽度&#xff0c;M的取值范围是(0, 255)例如: int(5),当数据宽度小于5位的时候在数字前面需要用字符填满宽度说明&…

2元4mm2高精度温度湿度传感器GXHTC3

温湿度传感器芯片GXHTC3 前言&#xff1a; 该温湿度传感器为国产&#xff0c;批量价格约2元&#xff0c;精度较高&#xff0c;DHT11该被淘汰了&#xff0c;这个才是传感器。 特点 超低功耗 宽工作电压范围(1.62 – 5.5 V) 小型 DFN 封装: 2 2 0.75 mm3 典型精度: 湿度 2 %R…

量子城域网系列(五):几种典型的量子密钥分发网络组网结构

在上之前文章中&#xff0c;我们介绍了最基本的点对点量子保密通信网络形式以及组网方案&#xff0c;但是显然在实际的应用中&#xff0c;点对点的通信是比较少的&#xff0c;大多还是需要多个终端进行互联才能构成网络。本文我们就讨论一下几种基础的量子密钥分发网络组网结构…

基于云计算技术的HIS系统,一体化云HIS、云病历、云LIS系统源码,扩展后能够应用于医联体/医共体

医院信息管理系统云HIS系统源码&#xff0c;云计算技术的HIS系统源码 开发技术&#xff1a; 前端&#xff1a;AngularNginx&#xff1b; 后台&#xff1a;JavaSpring&#xff0c;SpringBoot&#xff0c;SpringMVC&#xff0c;SpringSecurity&#xff0c;MyBatisPlus 等&…

使用【node】创建本地接口

在前端开发的过程中&#xff0c;接口相关的信息一般是由后端处理好返回给前端&#xff0c;但是有时候后端不在的时候想自己写个接口进行测试是非常麻烦的。 node是前端一个不错的写接口工具 一 初始化文件 1 在新建一个空的文件夹node 进入空文件夹在&#xff0c;文件夹的地…

《庆余年》开发衍生短剧,阅文迈向短剧市场的一大步

《庆余年》竟然也要拍短剧了。 据悉&#xff0c;《庆余年》衍生短剧《庆余年之少年风流》预计将于5月1日开机&#xff0c;等了五年都没等到《庆余年2》&#xff0c;没想到先等到了衍生短剧。 由组讯消息可知&#xff0c;《庆余年之少年风流》讲述的是少年庆帝李云潜“扮猪吃老…

一道有意思的面试题

面试过程中没有想到合适的数据结构&#xff0c;想了半天&#xff0c;构思没有实践落地。 也是听错了&#xff0c;以为三道题都要做&#xff0c;做出来了两道&#xff0c;这道死活没落地成功。 结果&#xff0c;三道题里面任选一道就行。。。。 好吧 题目&#xff1a;给定一个…

Qt分享一个壁纸页面布局的方式

分享一个壁纸软件的设计思路 在QScrollArea中添加一个总体的垂直布局&#xff0c;创建若干个水平布局&#xff0c;使用垂直布局组合&#xff0c;具体如图。在添加QAbstractButton时设置button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)属性&#xff0c;它会…

自动化测试的7个步骤

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…