Java自动化Excel导入及校验数据代码

Java自动化Excel导入及校验数据代码

主要技术点

1.java反射技术原理 用法:灵活调用参数,自动实例化
2.java自定义注解 用法:定义pojo规则,强制规定每一种属性的范畴

技术点讲解

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
反射就是把java类中的各种成分映射成一个个的Java对象

在这里插入图片描述
而在这张表的基础上 我参照资料整理出这张图
在这里插入图片描述

当将字节码文件加载进内存中后 jvm 会将字节码中的 成员变量 构造 方法 成员方法 存放到 相对应的数组中,而直接通过 Class对象便可以调出这些数组对象的内容

代码部分

注意 自定义的Pojo属性顺序需与Excel的列对应
测试类pojo

/**
 * @program: AdminTrainingCenterController.java
 * @功能:
 * @description: 全自动专属封装类
 * @author: Mr.Han
 * @create: 2021-03-12 10:42
 **/
@Data
public class Person {
	//通过调取自定义注解 来给每一列加入 规则限制

	/** 注意 如果 自定义注解定义好的规则 使用规则的属性 必须全部使用
	value = true,name = "测试名称A",whetherBeAnInteger=true,maxlength = "30",allowedToRepeat=true
	value = true,name = "测试名称A",whetherBeAnInteger=true,maxlength = "30"
	不能出现该状况
	value = true 开启空字段限制 ,
	name 中文名称 ,
	whetherBeAnInteger=true 是否必须为数字 ,
	maxlength="30" 最大长度,
	allowedToRepeat=true,是否开启重复校验
	**/
    @PersionBulid(value = true,name = "测试名称A",whetherBeAnInteger=true,maxlength = "30",allowedToRepeat=true)
    public String testNameA;
    @PersionBulid(value = false,name = "测试名称B",whetherBeAnInteger=false,maxlength = "",allowedToRepeat=true)
    public String testNameB;
    @PersionBulid(value = true,name = "测试名称C",whetherBeAnInteger=false,maxlength = "",allowedToRepeat=false)
    public String testNameC;
    @PersionBulid(value = true,name = "测试名称D",whetherBeAnInteger=false,maxlength = "",allowedToRepeat=false)
    public String testNameD;
}

自定义注解部分

@Retention(RetentionPolicy.RUNTIME)//保持时长 @Target(ElementType.FIELD)
public @interface PersionBulid {
boolean value() default false;//名称是否允许为空
String name() default “”;//属性中文值
boolean allowedToRepeat() default false;//是否允许重复数据
boolean whetherBeAnInteger() default false;//是否要求必须是数值
String maxlength() ;//最大长度 }

读取Excel头部,尾部的公共代码

public List<Object> pk() throws Exception {
    File file=new File("C:\\Users\\Administrator\\Desktop\\test.xls");//定位文件地址
    InputStream inputStream = new FileInputStream(file);//转换为InputStream对象
    Workbook workbook=null;
    List<Object> auxiliary =new ArrayList<>();//存入返回数据
    try {
        workbook= WorkbookFactory.create(inputStream);//解析资源
        inputStream.close();//关闭资源
        Sheet sheet=workbook.getSheetAt(0);//获取第一篇章
        int rowlength = sheet.getLastRowNum();//获取最后一列的长度
        Row row = sheet.getRow(0);//获得行
        Cell cell=row.getCell(0);//获取列
        auxiliary=test.Auxiliary(rowlength, row, sheet, cell, Person.class);
        //传入参数依次为 总列行数,行,第一个工作薄, 列  以及参与映射的Class对象
       
        // List<Person> personList= (List<Person>)auxiliary;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return auxiliary;
}

public static boolean isInteger(String str) {//判断是否全部为数值类型
Pattern pattern = Pattern.compile("1?[\d]*$");
return pattern.matcher(str).matches();
}

/**

  • 解析excel数据内容的核心代码
  • 功能点包括导入 与校验数据 重复检测
  • **/

public static List Auxiliary(int rowlength, Row row, Sheet sheet, Cell cell,Class clazz) throws Exception {
Field[] fields = clazz.getFields();//get模板pojo中全部的public字段数值,
List list=new ArrayList<>();//最终list数据
List goodlist=new ArrayList<>();//存入好数据的list
List bardlist=new ArrayList<>();//存入错误提示的list
Set<Map<String,String>> duplicateData=new HashSet<>();//定义重复数据校验
for (int i = 1; i <= rowlength; i++) {//rowlength 循环一共有多少列 不从标题列下开始循环
row = sheet.getRow(i);//获取列
Object trueObj= clazz.newInstance();//正确的实例化数据
Object fasleObj= clazz.newInstance();//错误的实例化数据
//class方法中 可以调用 newInstance()方法来实例化类对象
if(null!=row){
Integer number=0;//用于取出当前索引位置
for (Field field1 : fields) {//循环模板pojo的属性
cell =null==row.getCell(number)?null: row.getCell(number);//得到当前列的行 避免出现空指针异常
try {

                         PersionBulid filedAno = field1.getAnnotation(PersionBulid.class);//通过自定义注解的Class对象调取自定义注解中的的信息
                    		//属性 方法 构造方法  等 都间接继承了AnnotatedElement中的 getAnnotation 所以可以调用注解属性
                         boolean value = filedAno.value();//获取自定义注解的value属性
                         if(null==cell){
                             if(value){//value定义了数值是否允许为空 true不允许 false允许
                                 field1.set( fasleObj,"第"+(i+1)+"行列名称为:"+filedAno.name()+" 存在空值");
                             }
                         }else{
                             cell.setCellType(CellType.STRING);//接受String 类型
                             String data = cell.getStringCellValue();
                             data = data.trim();//去除空格
                             data=data.replace("'","");
                             if(data.length()>0){
                                 if(!"".equals(filedAno.maxlength())&&Integer.valueOf(filedAno.maxlength())<data.length()){
                                 //先判断长度是否超纲 取出之前定义好的 长度限制 maxlength()
                                     field1.set( fasleObj,"第"+(i+1)+"行列名称为:"+filedAno.name()+"字符串超长规定长度为:"+filedAno.maxlength());//错误信息提示
                                 }else{//如果不超长则继续走
                                     if(filedAno.whetherBeAnInteger()){
                                     //判断是否为数值类型 规则注解中定义好的数值类型whetherBeAnInteger()
                                         if(isInteger(data)){//判断是否都为数值类型
                                             if(filedAno.allowedToRepeat()){//判断数值型是否允许重复
                                                 Map<String,String> map=new HashMap<>();//定义map数值 为什么定义Map呢 Map的键值对非常适合用作这块的功能
                                                 map.put(filedAno.name(),data);//塞入 name值 与相对应的 数据
                                                 int size = duplicateData.size();//取出之前set的长度
                                                 duplicateData.add(map);//添加到set集合中
                                                 if(duplicateData.size()==size){//证明没有可被添加的数据 数据出现重复
                                                     field1.set( fasleObj,"第"+(i+1)+"行列名称为:"+filedAno.name()+"  存在重复数据为:"+data);
                                                 }else{//不重复 放过
                                                     field1.set(trueObj,data);
                                                 }
                                             }else{//允许重复放过
                                                 field1.set(trueObj,data);
                                             }
                                         }else{//反之则证明是字符串
                                             field1.set( fasleObj,"第"+(i+1)+"行列名称为:"+filedAno.name()+" 数据:"+data+" 不为数值");
                                         }
                                     }else{
                                         if(filedAno.allowedToRepeat()){//判断其他字符串型数据是否允许重复
                                             Map<String,String> map=new HashMap<>();
                                             map.put(filedAno.name(),data);
                                             int size = duplicateData.size();
                                             duplicateData.add(map);
                                             if(duplicateData.size()==size){//证明没有可被添加的数据
                                                 field1.set( fasleObj,"第"+(i+1)+"行列名称为:"+filedAno.name()+" 存在重复数据为:"+data);
                                             }else{
                                                 field1.set(trueObj,data);
                                             }
                                         }else{
                                             field1.set(trueObj,data);
                                         }
                                     }
                                 }
                             }else{
                                 field1.set( fasleObj,"第"+(i+1)+"行列名称为:"+filedAno.name()+" 存在空值");
                             }
                         }
                         number++;//每次循环完毕内循环后+1
                     }
                     catch (Exception e) {
                         System.out.println(e);
                     }
                 }
                 if(fasleObj.toString().indexOf("行列名称为")!=-1){//如果错误数据不为空
                     bardlist.add(fasleObj);//保存错误数据
                 }else{
                     goodlist.add(trueObj);//反之正确数据
                 }
             }
         }
 list=bardlist.size()>0?bardlist:goodlist;
 return list;

}

结果

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210316160521647.png#pic_center)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
[Person(a=第2行列名称为:a 数据:李四 不为数值, b=null, c=null, d=null),

Person(a=第3行列名称为:a 数据:李四1 不为数值, b=null, c=null, d=null),

Person(a=第6行列名称为:a字符串超长规定长度为:30, b=第6行列名称为:b 存在重复数据为:狼狗, c=null, d=null),

Person(a=null, b=第7行列名称为:b 存在重复数据为:狼狗, c=null, d=null)]

正确数据展示内容
在这里插入图片描述


  1. -\+ ↩︎

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值