有趣的地方

有趣的地方

easypoi实现Excel模板导入(包含文档下载的与前端交互回显)

实战使用easypoi完成Excel模板导入,且包含一对多的导入模板文件的下载 下载成功后浏览器页面的回显功能。

目录

1、后端代码

 2、前端代码

3、导入文件的坑

3.1无法读取某列的数据

3.2一对多的导入注意事项


模板文件的样例:

导入成功后的提示:


1、后端代码

依赖:

使用easypoi依赖和hutool包

<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-base</artifactId>
    <version>4.3.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-web</artifactId>
    <version>4.3.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-annotation</artifactId>
    <version>4.3.0</version>
</dependency>
 
 
<!-- hutool工具类 版本:<hutool.version>5.3.8</hutool.version> --> 
 
<dependency>
   <groupId>cn.hutool</groupId>
   <artifactId>hutool-core</artifactId>
   <version>5.3.8</version>
</dependency>
<dependency>
   <groupId>cn.hutool</groupId>
   <artifactId>hutool-crypto</artifactId>
   <version>5.3.8</version>
</dependency>
 
<dependency>
   <groupId>cn.hutool</groupId>
   <artifactId>hutool-extra</artifactId>
   <version>5.3.8</version>
</dependency>
<dependency>
   <groupId>cn.hutool</groupId>
   <artifactId>hutool-http</artifactId>
   <version>5.3.8</version>
</dependency>

接口:

@Autowired
private ImportExpertListExcelUtil importExpertListExcelUtil;


/**
 * 通过excel导入数据
 */
@PostMapping(value = "/importExcel")
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
    return importExpertListExcelUtil.importExcel(request, response, ExpertInformation.class);
}

实体类:

@Data
@TableName("expert_information")
public class ExpertInformation implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * id
     */
    @TableId(type = IdType.ASSIGN_ID)
    private java.lang.String id;
    /**
     * 姓名
     */
    @NotNull(message = "姓名不能为空")
    @Excel(name = "姓名", needMerge = true, width = 15)
    private java.lang.String name;
    /**
     * 国家/地区
     */
    @Excel(name = "国家/地区", needMerge = true, width = 15)
    private java.lang.String country;
    /**
     * 证件类型
     */
    @Excel(name = "证件类型", needMerge = true, width = 15)
    private java.lang.String credentialType;
    /**
     * 证件号码
     */
    @NotNull(message = "证件号码不能为空")
    @Excel(name = "证件号码", needMerge = true, width = 30)
    private java.lang.String credentialNumber;
    /**
     * 毕业学校
     */
    @Excel(name = "毕业学校", needMerge = true, width = 30)
    private java.lang.String graduationSchool;
    /**
     * 学历
     */
    @Excel(name = "学历", needMerge = true, width = 15)
    private java.lang.String degree;
    /**
     * 联系电话
     */
    @NotNull(message = "联系电话不能为空")
    @Excel(name = "联系电话", needMerge = true, width = 15)
    private java.lang.String phone;
    /**
     * 邮箱
     */
    @Excel(name = "邮箱", needMerge = true, width = 15)
    @NotNull(message = "邮箱不能为空")
    private java.lang.String mail;
    /**
     * 开户银行名称
     */
    @Excel(name = "开户银行名称", needMerge = true, width = 30)
    private java.lang.String openedBankName;
    /**
     * 其开户银行名称 
     */
    @Excel(name = "其开户银行名称(选择 其他 时展示)", width = 30)
    @TableField(updateStrategy = FieldStrategy.IGNORED) //更新操作时,无论字段是否为 空字符串,都会进行更新
    private java.lang.String otherOpenedBankName;
    /**
     * 银行账户
     */
    @Excel(name = "银行账户", needMerge = true, width = 30)
    private java.lang.String bankAccount;
    /**
     * 评审范围
     */
    @Excel(name = "评审范围", width = 15)
    @TableField(updateStrategy = FieldStrategy.IGNORED) //更新操作时,无论字段是否为 空字符串,都会进行更新
    private java.lang.String scopeAssessment;

    @TableField(exist = false)
    private List<String> checkedList;

    /**
     * 单位-列表
     */
    @TableField(exist = false)
    @ExcelCollection(name = "工作经历")
    private List<ExpertWorkExperience> unit;

    /**
     * 单位名称
     */
    @TableField(exist = false)
    private String companyName;
}
@Data
@TableName("expert_work_experience")
public class ExpertWorkExperience implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * id
     */
    @TableId(type = IdType.ASSIGN_ID)
    private java.lang.String id;
    /**
     * 专家主键id
     */
    private java.lang.String expertInformationId;
    /**
     * 单位名称
     */
    @Excel(name = "单位名称", width = 30)
    private java.lang.String companyName;
    /**
     * 职位
     */
    @Excel(name = "职位", width = 15)
    private java.lang.String post;
}

工具类方法:

@Slf4j
@Component
public class ImportExpertListExcelUtil {

/**
     * 通过excel导入数据
     */
      public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response, Class<ExpertInformation> clazz) {

        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        //错误集合
        List<String> errorMsg = new ArrayList<>();
        List<ExpertWorkExperience> totalExpertWorkExperienceList = new LinkedList<>();

        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                long start = System.currentTimeMillis();
                //导入Excel格式校验,看匹配的字段文本概率
                Boolean t = ExcelImportCheckUtil.check(file.getInputStream(), ExpertInformation.class, params);
                if (!t) {
                    throw new RuntimeException("导入Excel校验失败 !");
                }

                List<ExpertInformation> expertInformationList = ExcelImportUtil.importExcel(file.getInputStream(), clazz, params);

                log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒");
                return Result.ok(String.format("文件导入成功:%s 行", expertInformationList.size());

            } catch (Exception e) {
                log.error(e.getMessage(), e);

                return Result.error("文件导入失败:" + e.getMessage());
            } finally {
                try {
                    file.getInputStream().close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.error("文件导入失败!");
    }
}
List<ExpertInformation> expertInformationList = ExcelImportUtil.importExcel(file.getInputStream(), clazz, params);

在这行代码导入Excel后,返回的数据可以根据自己的业务做一些校验,我这里当时对它的证件号码和手机号、邮箱这些字段做一些正则校验,这个代码我就省略了,只是demo演示一下导入Excel。

 2、前端代码

导入按钮的功能:

这里有一对多的导入,这个导入按钮的代码就省略了,每个项目的前端使用框架不一样,封装的组件和方法也不一样,根据自身情况去官方开发文档查看即可。

--我这里前端框架使用的是ant-design的vue2版本,如果和我情况一样,可以评论问我,无偿分享这里的前端代码。

模板下载:

这里让用户把模板下载出来,再去填写数据,避免因为导入的Excel字段和实体类使用注解的name不一致。导致无法读取该列的数据。

   @Excel(name = "单位名称", width = 30)
   private String companyName;

 这个代码在这文章中t提供了文件下载,前端下载成功弹窗回显 和 注意事项,需要的可以去这个文章参考代码。

模板下载icon-default.png?t=N7T8https://blog.csdn.net/RYH6817/article/details/136240011

3、导入文件的坑

3.1无法读取某列的数据

        这里一定要注意使用注解中的name值,必须和Excel列的名字要一致,不然无法识别,就默认这列数据为null。

 导入的Excel字段和实体类使用注解的name不一致。导致无法读取该列的数据。

   @Excel(name = "单位名称", width = 30)
   private String companyName;

3.2一对多的导入注意事项

  • 首先就是在父表ExpertInformation中有子表字段,

例如:在ExpertInformation中添加一个子表的list集合。

     /**
     * 单位-列表
     */
    @TableField(exist = false)
    @ExcelCollection(name = "工作经历")
    private List<ExpertWorkExperience> unit;

这里需要使用注解 @ExcelCollection(name = "工作经历") 而且也必须和页面的列名一致。不然也是无法识别子表的数据。

  •  还有就是这个列名 “工作经历” 必须合并单元格,包含其子表需要导入的字段。我这里子表只导入:”单位名称“和”职位“两个字段。
    完整的一对多模板表格如图:

  •  子表 ExpertWorkExperience 的字段,也需要使用注解 @Excel(name = "单位名称", width = 30)

发表评论:

Powered By Z-BlogPHP 1.7.3

© 2018-2020 有趣的地方 粤ICP备18140861号-1 网站地图