【Java--一行代码】工具类基于POI实现根据excel导入

本文介绍了一个Java工具类,用于将Excel文件数据转换为List<StudentEntity>对象,支持图片导出。工具通过Apache POI库实现,不支持行或列合并的情况。调用示例展示在Controller中,通过MultipartFile接收文件并返回转换后的实体列表。实现原理包括定位sheet、数据、字段等,提供pom依赖,并展示了核心及辅助代码。
摘要由CSDN通过智能技术生成

写在前面的话:

        调用本工具,将excel数据转换为List<对象>,用户自行对list做业务处理。

        备注:1、由于本方法为通用方法,故不支持涉及到行or列合并的情况。

-- 你永远不要去低估一颗冠军的心,恭喜龙队


一、前情提要

        Java--一行代码】工具类基于POI实现导出excel(支持图片)

二、结果示例

        1、代码调用示例(Controller)

    @ApiOperation("导出")
    public JsonResult<List<StudentEntity>> importByExcel(MultipartFile file) {
        List<StudentEntity> studentList = ExcelUtils.importByExcel(file, 0, 0, 2, 1, StudentEntity.class);

        // Omitted code
        // ...

        return JsonResult.success(studentList);
    }

        2、结果示例

        

        3、目标excel示例:

 

三、实现原理

        1、定位要导入的sheet页。

        2、定位目标sheet中,有效数据的起始行、起始列。

        3、定位目标sheet中,字段名所在行。

        4、遍历excel中的行数据,通过反射比对,对实体进行赋值。

四、pom依赖引入

        <commons.lang3.version>3.8.1</commons.lang3.version>
        <poi.version>3.17</poi.version>
        <commons.io.version>2.6</commons.io.version>
        
 
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>${commons.lang3.version}</version>
        </dependency>
 
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>${poi.version}</version>
        </dependency>
 
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>${poi.version}</version>
        </dependency>
 
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>${commons.io.version}</version>
        </dependency>

五、工具源码

1、工具核心代码

    /**
     * 导入Excel文件
     * 本方法暂不支持一次性导入 多sheet页 数据。
     * 若需导入多sheet页,请调用方多次调用。
     *
     * @param excelFile      上传的excel文件
     * @param sheetNum       导入excel的sheet页编号。如:导入该excel的sheet1页的数据,则该值为0。通常都为0。【sheet页起始值为0】
     * @param validColumnNum 有效的起始列。如:excel从A列开始即为字段数据,则该值为0。【列的起始值为0】
     * @param validRowNum    有效的起始行。如:excel从3行开始即为需导入数据,则该值为2。【行的起始值为0,一般第一行为中文标题,第二行为字段名】
     * @param fieldsNum      字段所在行。如:excel第2行为字段,则该值为1【行的起始值为0,一般第一行为中文标题,第二行为字段名】
     * @param clazz          T.class
     * @return 组装好的list 调用方执行入库即可
     */
    public static <T> List<T> importByExcel(MultipartFile excelFile, Integer sheetNum, Integer validColumnNum, Integer validRowNum, Integer fieldsNum, Class<T> clazz) {
        if (!(excelFile.getOriginalFilename().endsWith("xls") || excelFile.getOriginalFilename().endsWith("xlsx"))) {
            // 文件格式有误
            log.error("文件格式有误!");
            throw new RuntimeException(Constants4Api.FILE_IS_NOT_EXCEL);
        }

        HSSFWorkbook workbook = null;

        try {
            InputStream inputStream = excelFile.getInputStream();
            workbook = new HSSFWorkbook(inputStream);
        } catch (IOException e) {
            log.error("获取上传文件的输入流失败!请检查后端文件接收变量名与前端变量名是否一致!");
            throw new RuntimeException(Constants4Api.EXCEL_IS_ERROR);
        }

        HSSFSheet sheet = workbook.getSheetAt(sheetNum);

        Integer lastColumnNum = Integer.valueOf(sheet.getRow(0).getLastCellNum());

        // 获取数据类型字段集合
        List<String> fieldsStrList = getFieldsStrList(sheet.getRow(fieldsNum), validColumnNum, lastColumnNum);

        List<T> tList = new ArrayList<>();
        for (Row row : sheet) {
            T t = null;
            try {
                t = clazz.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

            // 过滤掉无效的行
            int rowNum = row.getRowNum();
            if (rowNum < validRowNum) {
                continue;
            }

            for (int colNum = validColumnNum; colNum < lastColumnNum; colNum++) {
                // 判断cell类型
                Object value = getValueThrowDifferentType(row.getCell(colNum));
                loadValue2Entity(t, clazz, value, fieldsStrList.get(colNum - validColumnNum));

            }
            tList.add(t);
        }
        return tList;
    }

2、辅助代码

    /**
     * 获取所有字段名
     * 
     * @param row 字段所在行
     * @param validColumnNum 有效起始列
     * @param lastColumnNum 有效结束列
     * @return 字段名List
     */
    private static List<String> getFieldsStrList(Row row, Integer validColumnNum, Integer lastColumnNum) {
        List<String> fieldsStrList = new ArrayList<>();

        for (int i = validColumnNum; i < lastColumnNum; i++) {
            String fields = row.getCell(i).getStringCellValue();
            fieldsStrList.add(fields);
        }

        return fieldsStrList;
    }
    /**
     * 根据 数据类型 取 单元格的值
     * 
     * 备注: 若后续有其他数据类型,则在此处添加对应的处理方式即可 
     * 
     * @param cell 单元格
     * @return value
     */
    private static Object getValueThrowDifferentType(Cell cell) {
        Object value = null;
        if (!Objects.isNull(cell)) {
            CellType cellType = cell.getCellTypeEnum();

            switch (cellType) {
                case NUMERIC:
                    value = cell.getNumericCellValue();
                    break;
                case STRING:
                    value = cell.getStringCellValue();
                    break;
                case BOOLEAN:
                    value = cell.getBooleanCellValue();
                    break;
                default:
                    break;
            }
        }

        return value;
    }
    /**
     * 以反射的方式 给实体类赋值
     * 
     * @param t 实体
     * @param clazz t.class
     * @param value 值
     * @param objFiled 目标字段名
     * @param <T> 泛型
     */
    private static <T> void loadValue2Entity(T t, Class<T> clazz, Object value, String objFiled) {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (objFiled.equals(field.getName())) {
                try {
                    if (!Objects.isNull(value)) {
                        setValueThrowDifferentType(field, t, value);
                    }
                } catch (Exception e) {
                    log.error("反射赋值失败!当前字段:" + objFiled + ", 当前值:" + value , e);
                    throw new RuntimeException(Constants4Api.EXCEL_BIND_ENTITY_ERROR);
                }
            }
        }
    }
    /**
     * 根据不同的数据类型 对 实体 进行赋值
     * 
     * @param field 字段名
     * @param t 实体
     * @param value 值
     * @param <T> 泛型
     * @throws Exception exception
     */
    private static <T> void setValueThrowDifferentType(Field field, T t, Object value) throws Exception {
        String fieldType = field.getGenericType().toString();
        field.setAccessible(true);

        switch (fieldType) {
            case "class java.lang.Integer":
                field.set(t, Integer.parseInt(value.toString().split("\\.")[0]));
                break;
            case "class java.lang.Double":
                field.set(t, Double.parseDouble(value.toString()));
                break;
            case "class java.lang.Boolean":
                Boolean flag = null;
                if ("是".equals(value.toString())) {
                    flag = true;
                } else if ("否".equals(value.toString())) {
                    flag = false;
                } else {
                    flag = Boolean.parseBoolean(value.toString());
                }
                field.set(t, flag);
                break;
            case "class java.lang.String":
                String[] tempArr = value.toString().split("\\.");
                if (tempArr.length == 2 && tempArr[1].equals("0")) {
                    // 纯数字,会自动加 .0
                    field.set(t, tempArr[0]);
                } else {
                    field.set(t, StringUtils.isEmpty(value.toString()) ? "" : value.toString());
                }

                break;
            case "class java.math.BigDecimal":
                field.set(t, new BigDecimal(value.toString()));
                break;
            case "class java.util.Date":
                field.set(t, HSSFDateUtil.getJavaDate(Double.parseDouble(value.toString())));
                break;
            default:
                log.error("待添加的转换类:" + fieldType);
                break;
        }
    }

3、示例中是student实体类

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_student")
@ApiModel("sys_student表实体类")
public class StudentEntity extends Model<StudentEntity> {

    private static final long serialVersionUID = 1L;


    @TableId(value = "dept_id", type = IdType.UUID)
    @ApiModelProperty(value = "学生编号:主键id")
    private String studentId;

    @ApiModelProperty(value = "姓名")
    private String studentName;

    @ApiModelProperty(value = "性别:str")
    private String gender;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值