java处理xlsx,根据自建注解的方式赋值给实体类,简化了操作

1 篇文章 0 订阅
1 篇文章 0 订阅

java处理上传上来的xlsx,和xls是非常常见的操作,批量导入

需要的maven包

<dependency>
   <groupId>org.apache.poi</groupId>
   <artifactId>poi</artifactId>
   <version>4.0.1</version>
</dependency>
<dependency>
   <groupId>org.apache.poi</groupId>
   <artifactId>poi-ooxml</artifactId>
   <version>4.0.1</version>
</dependency>
<dependency>
   <groupId>org.apache.poi</groupId>
   <artifactId>poi-ooxml-schemas</artifactId>
   <version>4.0.1</version>
</dependency>

比如有一个这样的excel

创建一个注解类


import java.lang.annotation.*;

/**
 * @ms 用于标记导入的excel的字段
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExcelTitleName {

    /**
     * excel表中的标题
     *
     * @return
     */
    public String name();

}

注意:注解上的注解不做过多赘述,可网上找描述会很清楚

创建一个实体类并在字段上加上刚才创建的注解

public class User {

    @ExcelTitleName(name = "姓名")
    private String name;
    @ExcelTitleName(name = "年龄")
    private String age;
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}

工具类

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

public class ImportExcelTest {

    /**
     * 读取excel
     *
     * @param path
     */
    public <T> List<T> readXlsx(String path, Class<T> tClass) {

        List<T> list = new ArrayList<>();

        FileInputStream is = null;
        Workbook xwb = null;
        try {
            // 读取的时候可以使用流,也可以直接使用文件名
            is = new FileInputStream(path);
            xwb = new XSSFWorkbook(is);
            //第一个工作表(可以循环工作表这里就不举例为第一个工作表)
            Sheet sheet = xwb.getSheetAt(0);
            //标题
            Row title = sheet.getRow(0);
            // 循环row,如果第一行是标题,则 numRow = 1
            for (int numRow = 1; numRow <= sheet.getLastRowNum(); numRow++) {
                Row row = sheet.getRow(numRow);
                if (row == null) {
                    continue;
                }

                //创建实体类
                T t = tClass.newInstance();
                // 循环cell
                for (int numCell = 0; numCell < row.getLastCellNum(); numCell++) {
                    //标题
                    Cell titleCell = title.getCell(numCell);
                    // 打印数据
                    System.out.println("xlsx标题" + getValue(titleCell));

                    Cell cell = row.getCell(numCell);
                    if (cell == null) {
                        continue;
                    }
                    System.out.println("xlsx单元格:" + getValue(cell));
                    assignmentSave(getValue(titleCell), getValue(cell), t);
                }
                list.add(t);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (xwb != null) {
                    xwb.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return list;
    }

    /**
     * 解析excel单元格类型
     *
     * @param cell
     * @return
     */
    private String getValue(Cell cell) {
        String val = null;
        if (null != cell) {
            switch (cell.getCellType()) {
                //布尔类型
                case BOOLEAN:
                    val = String.valueOf(cell.getBooleanCellValue());
                    break;
                // 字符串类型
                case STRING:
                    val = cell.getStringCellValue().trim();
                    break;
                // 数值类型
                case NUMERIC:
                    // 日期格式
                    if (DateUtil.isCellDateFormatted(cell)) {
                        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
                        val = f.format(cell.getDateCellValue());
                    } else {
                        // 四舍五入
                        val = new DecimalFormat("#.####").format(cell.getNumericCellValue());
                    }
                    break;
                //其它类型
                default:
                    break;
            }
        }
        return val;
    }

    /**
     * 通过注解赋值给变量
     *
     * @param t
     * @param titleName
     * @param val
     */
    private <T> void assignmentSave(String titleName, String val, T t) {

        try {
            Field[] at = t.getClass().getDeclaredFields();
            for (Field fd : at) {
                // 变量是否包含ExcelTitleName注解
                if (fd.isAnnotationPresent(ExcelTitleName.class)) {
                    // 获取注解属性
                    ExcelTitleName d = fd.getAnnotation(ExcelTitleName.class);
                    //注解匹配成功给变量赋值
                    if (d.name().equals(titleName)) {
                        // 首字母大写
                        String replace = fd.getName().substring(0, 1).toUpperCase() + fd.getName().substring(1);
                        Method method = t.getClass().getMethod("set" + replace, String.class);
                        method.invoke(t, val);
                        break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) throws Exception {

        List<User> users = new ImportExcelTest().readXlsx("C:\\Users\\Desktop\\ImportExcelTest.xlsx", User.class);
        users.forEach(user -> System.out.println(user.toString()));

    }

}

工具类原理:根据反射获取实体类参数,判断参数上的注解比对注解,通过反射赋值。

结果:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值