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)){
                //生成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行的身份证籍贯信息不一致! 
 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

javaWeb项目-网吧网咖管理系统功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、JAVA简介 JavaSc…

本地环境通过ssh通道连接服务器数据库,实现本地客户端和代码可以访问数据库

使用方法&#xff1a; ssh -p 搭建隧道的端口 -fNL 本地端口:远程ip:远程端口号 搭建隧道的账号搭建隧道的ip 可以增加参数-v,输出更多的信息 ssh -p 搭建隧道的端口 -fNL 本地端口:远程ip:远程端口号 -v 搭建隧道的账号搭建隧道的ip 有时候&#xff0c;测试环境的数据库不允许…

深度卷积神经网络的整体运行流程(以alexnet为例)

0.基础概念&#xff08;复习一下&#xff09; 1.小批量随机梯度下降 目的&#xff1a; 希望找到最佳的参数&#xff0c;使损失函数最小。 使损失函数对w求导&#xff08;b就是x等于1的w&#xff09;&#xff0c;一个小批次的/eta&#xff08;学习率&#xff09;*小批次的平均…

hexo配置教程、主题使用及涉及的技术学习

一、背景 最近,一直想做一个属于自己的网站.可以从零开始搭建一个网站,顺便可以把日常中学到的技术用于实战,还可以顺便记录自己的所思所感,记录成长的过程. 方案 一开始的方案是从零开始,模仿常见个人博客的设计,基于vueSpringbootMySQL的去实现网站. 新建项目之后,发现vu…

【网络原理】UDP协议的报文结构 及 校验和字段的错误检测机制(CRC算法、MD5算法)

目录 UDP协议 UDP协议的报文结构及注意事项 UDP报文结构中的校验和字段 1. 校验和主要校验的内容 2. UDP校验和的实现方式 3. CRC&#xff08;循环冗余校验&#xff09;算法 4. MD5&#xff08;Message Digest Algorithm 5&#xff09; UDP协议 上一篇文章提过&#xf…

Linux cmake 初窥【1】

1.开发背景 linux 下编译程序需要用到对应的 Makefile&#xff0c;用于编译应用程序&#xff0c;但是 Makefile 的语法过于繁杂&#xff0c;甚至有些反人类&#xff0c;所以这里引用了cmake&#xff0c;cmake 其中一个主要功能就是用于生成 Makefile&#xff0c;cmake 的语法更…

吴恩达深度学习 (week5,6)

文章目录 一、训练开发测试集二、机器学习基础三、 正则化初步介绍四、Dropout 正则化五、其他正则化方法六、归一化输入介绍七、梯度消失与梯度爆炸八、神经网络的权重初始化九、梯度数值逼近和检验十、上述学习总结第一题 划分训练/开发/测试集第二题 开发和测试集分布第三题…

谷粒商城学习笔记

1.系统架构 2.环境准备 21.安装Linux 1.VirtualBox: https://download.virtualbox.org/virtualbox/6.0.10/VirtualBox-6.0.10-132072-Win.exe 2.安装 Vagrant 1).Vagrant 下载地址: https://releases.hashicorp.com/vagrant/2.2.5/vagrant_2.2.5_x86_64.msi https://www…

Obsidian 快速安装

看网上Obsidian 很好用&#xff0c;但自己下载总是中断&#xff0c;烦的要死&#xff0c;一度以为要开魔法…… 直到我找到了这个网站Thoughts (teambition.com) yeah~ 亲测有效&#xff0c;大概不到2min吧. 快速开始~&#xff0c;成功水了一片

海外服务器被恶意攻击怎么办

如果您的海外服务器遭受了恶意攻击&#xff0c;以下是一些应对措施和步骤&#xff0c;立即隔离服务器。如果您察觉到服务器受到恶意攻击&#xff0c;立即隔离服务器&#xff0c;将其与网络隔离&#xff0c;以防止攻机进一步扩散。通知服务器提供商&#xff0c;以便他们能够提供…

大小写不规范引起的LVS问题

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 往期文章链接: LVS常见问题解析 综合网表不规范,大小写混用常导致LVS问题,比如两个端口clk和CLK只有大小写区别,PR工具是可以识别为两个端口的,只不过Calibre LVS默认不区分大小写,会报错。 …

第二部分-Foundation基础-学习导航

专题地址&#xff1a;MacOS一站式程序开发系列专题 第一部分&#xff1a;基础入门-学习导航 ObjectiveC-第一部分-基础入门-学习导航 第二部分&#xff1a;Foundation基础学习导航 Foundation框架-13-数据对象&#xff1a;主要讲述NSRange, NSString, NSValue, NSNull, NSD…

从旺店通·企业奇门到用友BIP通过接口配置打通数据

从旺店通企业奇门到用友BIP通过接口配置打通数据 接入系统&#xff1a;旺店通企业奇门 旺店通是北京掌上先机网络科技有限公司旗下品牌&#xff0c;国内的零售云服务提供商&#xff0c;基于云计算SaaS服务模式&#xff0c;以体系化解决方案&#xff0c;助力零售企业数字化智能化…

CLAHE算法上新

加入我们的FPGA实现CLAHE算法课程&#xff0c;探索图像增强的前沿技术&#xff01; [课程名称]&#xff1a; FPGA实现对比度受限自适应直方图均衡化&#xff08;CLAHE&#xff09;算法 [授课方式]&#xff1a; 录播课程 互动讨论 实践操作 在线答疑 课程简介&#xff1a; 在…

Vue2之组件通信(爆肝)

大家有什么想看的可以在评论区留言&#xff0c;我尽量满足&#xff0c;感谢大家&#xff01; 组件通信是vue中一个非常重要的内容&#xff0c;我们需要掌握好组件通信&#xff0c;那么让我为大家介绍几种组件通信的方式吧&#xff01; 一、props 这是父传子的方式&#xff0…

贪吃蛇代码实现

一.基本信息 实现目标&#xff1a;使用C语言在Windows环境的控制台中实现贪吃蛇游戏 游戏运行&#xff1a; 地图绘制基本玩法提示信息游戏的开始与结束 基本玩法&#xff1a; 通过上下左右键控制蛇的移动蛇可以加速减速吃掉食物可以得分并增加蛇的长度可以自动暂停 游戏结…

Macs Fan Control Pro for Mac:全面优化Mac风扇控制软件

Macs Fan Control Pro for Mac是一款专为苹果电脑用户设计的风扇控制软件&#xff0c;旨在通过精确的风扇速度调节&#xff0c;全面优化Mac的散热性能&#xff0c;确保系统始终运行在最佳状态。 Macs Fan Control Pro for Mac中文版下载 该软件具备实时监控功能&#xff0c;能够…

HarmonyOS ArkUI实战开发-NAPI异步编程

笔者在前 5 小节里讲述了在 OpenHarmony 上通过 NAPI 的方式实现了 JS 调用 C的能力&#xff0c;但是这些实现都是同步的&#xff0c;本节笔者简单介绍一下 NAPI 的异步实现。 约定编程规范 ArkUI 开发框架对外提供的 API 命名是需遵守一定规范的&#xff0c;以 ohos.display…

初学python记录:力扣39. 组合总和

题目&#xff1a; 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些组合。 candidates 中的 同一个 数字可以 无限…

【STM32】嵌入式实验二 GPIO 实验:数码管

实验内容&#xff1a; 编写程序&#xff0c;在数码管上显示自己的学号。 数码管相关电路&#xff1a; PA7对应的应该是段码&#xff0c;上面的图写错了。 注意&#xff1a;选中数码管是低电平选中&#xff1b;并且用74HC595模块驱动输出的段码&#xff0c; 这个模块的学习可以…