springboot项目利用easypoi导入导出(包括一对多导出的动态列选择,以及普通导入)

这篇具有很好参考价值的文章主要介绍了springboot项目利用easypoi导入导出(包括一对多导出的动态列选择,以及普通导入)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

springboot项目利用easypoi导入导出(包括一对多导出的动态列选择,以及有错误数据导入返回错误信息)

因为项目只涉及到一对多的导出,以及普通的导入,所以,本文只会涉及这方面的使用

导入的时候,有校验,如果有错误数据,就会返回错误数据的所在行,以及错误信息(如果需要返回错误信息的所在的那几行数据以及错误信息的excel文件的话,可以看看第三个参考文章,这个项目最开始是做的返回excel文件,最后又取消了)

参考了一下文章(排名不分先后):

  1. easypoi的官方文档
  2. 使用easypoi根据表头信息动态导出
  3. 微服务中EasyPoi上传Excel文件带校验并返回错误信息
  4. easyPOI基本用法
  5. Springboot 导入导出Excel ,一对多关系,复合表格、合并单元格数据
  6. SpringBoot实现Excel导入导出,好用到爆,POI可以扔掉了!

一. 前置准备

1. 在pom.xml中导入依赖

<dependency>
			<groupId>cn.afterturn</groupId>
			<artifactId>easypoi-base</artifactId>
			<version>4.1.0</version>
		</dependency>
		<dependency>
			<groupId>cn.afterturn</groupId>
			<artifactId>easypoi-web</artifactId>
			<version>4.1.0</version>
		</dependency>
		<dependency>
			<groupId>cn.afterturn</groupId>
			<artifactId>easypoi-annotation</artifactId>
			<version>4.1.0</version>
		</dependency>

		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>5.2.4.Final</version>
		</dependency>

2. application.yml配置环境

# mybatis yml文件配置
mybatis:
  mapper-locations: classpath:mapper/*.xml
  configuration:
    #    映射数据库中的下划线命名到 java 中的驼峰命名
    map-underscore-to-camel-case: true

3. 工具包

MyExcelUtils.java
package com.xxx.template.utils.recruitmentManagement;

import java.lang.reflect.*;

import java.util.List;
import java.util.Map;

import com.byd.template.log.Log;

import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelCollection;
import cn.afterturn.easypoi.excel.annotation.ExcelEntity;
import lombok.extern.slf4j.Slf4j;


@Slf4j
public class MyExcelUtils {
    /**
     * 修改fields上@Excel注解的name属性,不需要下载的列,name修改增加_ignore.
     * 保存原来的@Excel注解name属性值,本次生成后用来恢复
     * @Params
     *     headers:用户勾选,由前端传来的列名,列名的key必须和 Model字段对应
     *     clazz:model实体类
     *     excelMap:用来记录原值的map,因为用到了递归,这里返回值作为参数传入
     * @return Map<String, String> 原实体类字段名和 @Excel注解 name属性值的映射关系<字段名,@Excel注解 name 属性值>
     */
    public static Map<String, String> dynamicChangeAndSaveSourceAnnotation(List<String> headers, Class clazz, Map<String, String> excelMap) {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            // @Excel注解
            if (field.isAnnotationPresent(Excel.class)) {
                boolean flag = true;
                if(headers == null || headers.size()==0){
                    flag =true;
                }else{
                    for (int i = 0; i < headers.size(); i++) {
                        String header = headers.get(i);
                        if (field.getName().equals(header)) {
                            flag = false;
                            break;
                        }
                    }
                }
                // 下载列不包括该字段,进行隐藏,并记录原始值
                if (flag) {
                    Excel annotation = field.getAnnotation(Excel.class);
                    // 保存注解
                    excelMap.put(field.getName(), annotation.name());
                    InvocationHandler handler = Proxy.getInvocationHandler(annotation);
                    String value = annotation.name().toString();
                    changeAnnotationValue(handler, field.getName() + "_ignore");
                }
                // @ExcelCollection注解
            } else if (field.isAnnotationPresent(ExcelCollection.class) && field.getType().isAssignableFrom(List.class)) {
                Type type = field.getGenericType();
                if (type instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) type;
                    Class collectionClazz = (Class) pt.getActualTypeArguments()[0];
                    // 解决@ExcelCollection如果没有需要下载列的异常,java.lang.IllegalArgumentException: The 'to' col (15) must not be less than the 'from' col (16)
                    // 如果没有需要下载列,将@ExcelCollection忽略
                    Field[] collectionFields = collectionClazz.getDeclaredFields();
                    boolean flag = false;
                    out:
                    for (Field temp : collectionFields) {
                        if (!temp.isAnnotationPresent(Excel.class)) {
                            continue;
                        }
                        for (int i = 0; i < headers.size(); i++) {
                            String header = headers.get(i);
                            if (temp.getName().equals(header)) {
                                flag = true;
                                break out;
                            }
                        }
                    }
                    if (flag) {
                        dynamicChangeAndSaveSourceAnnotation(headers, collectionClazz, excelMap);
                    } else {
                        ExcelCollection annotation = field.getAnnotation(ExcelCollection.class);
                        excelMap.put(field.getName(), annotation.name());
                        InvocationHandler handler = Proxy.getInvocationHandler(annotation);
                        changeAnnotationValue(handler, field.getName() + "_ignore");
                    }
                }
                // @ExcelEntity注解
            } else if (field.isAnnotationPresent(ExcelEntity.class)) {
                Class entityClazz = field.getType();
                dynamicChangeAndSaveSourceAnnotation(headers, entityClazz, excelMap);
            }
        }
        return excelMap;
    }
    public static Map<String, String> dynamicChangeAndSaveSourceAnnotation(List<String> headers, List<String> otherHeaders,Class clazz, Map<String, String> excelMap) {

        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            // @Excel注解
            if ( field.isAnnotationPresent(Excel.class)) {
                boolean flag = true;
                if(headers == null || headers.size()==0){
                    flag =true;
                }else{
                    for (int i = 0; i < headers.size(); i++) {
                        String header = headers.get(i);
                        if (field.getName().equals(header)) {
                            flag = false;
                            break;
                        }
                    }
                }
                // 下载列不包括该字段,进行隐藏,并记录原始值
                if (flag) {
                    Excel annotation = field.getAnnotation(Excel.class);
                    // 保存注解
                    excelMap.put(field.getName(), annotation.name());
                    InvocationHandler handler = Proxy.getInvocationHandler(annotation);
                    String value = annotation.name().toString();
                    changeAnnotationValue(handler, field.getName() + "_ignore");
                }
                // @ExcelCollection注解
            } else if (field.isAnnotationPresent(ExcelCollection.class) && field.getType().isAssignableFrom(List.class)) {
                Type type = field.getGenericType();
                if (type instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) type;
                    Class collectionClazz = (Class) pt.getActualTypeArguments()[0];
                    // 解决@ExcelCollection如果没有需要下载列的异常,java.lang.IllegalArgumentException: The 'to' col (15) must not be less than the 'from' col (16)
                    // 如果没有需要下载列,将 @ExcelCollection忽略
                    Field[] collectionFields = collectionClazz.getDeclaredFields();
                    boolean flag = false;

                    if(null == otherHeaders || otherHeaders.size() ==0){
                        ExcelCollection annotation = field.getAnnotation(ExcelCollection.class);
                        excelMap.put(field.getName(), annotation.name());
                        InvocationHandler handler = Proxy.getInvocationHandler(annotation);
                        changeAnnotationValue(handler, field.getName() + "_ignore");

                        return excelMap;
                    }
                    out:
                    for (Field temp : collectionFields) {
                        if (!temp.isAnnotationPresent(Excel.class)) {
                            continue;
                        }
                        for (int i = 0; i < otherHeaders.size(); i++) {
                            String header = otherHeaders.get(i);
                            if (temp.getName().equals(header)) {
                                flag = true;
                                break out;

                            }
                        }
                    }
                    if (flag) {
                        dynamicChangeAndSaveSourceAnnotation(otherHeaders,collectionClazz, excelMap);
                    }else {
                        ExcelCollection annotation = field.getAnnotation(ExcelCollection.class);
                        excelMap.put(field.getName(), annotation.name());
                        InvocationHandler handler = Proxy.getInvocationHandler(annotation);
                        changeAnnotationValue(handler, field.getName() + "_ignore");
                    }
                }
                // @ExcelEntity注解
            } else if (field.isAnnotationPresent(ExcelEntity.class)) {
                Class entityClazz = field.getType();
                dynamicChangeAndSaveSourceAnnotation(otherHeaders, entityClazz, excelMap);
            }
        }
        return excelMap;
    }

    // 改变注解属性值,抽取的公共方法
    private static void changeAnnotationValue(InvocationHandler handler, String propertyValue) {
        try {
            Field field = handler.getClass().getDeclaredField("memberValues");
            field.setAccessible(true);
            Map<String, Object> memberValues = (Map<String, Object>) field.get(handler);
            memberValues.put("name", propertyValue);

        } catch (Exception e) {
            Log.error("替换注解属性值出错!", e);
        }
    }


    /**
     * * 递归恢复 @Excel原始的 name属性
     *
     */
    public static void dynamicResetAnnotation(Class clazz, Map<String, String> excelMap) {
        if (excelMap.isEmpty()) {
            return;
        }
        Field[] fields = clazz.getDeclaredFields();
        try {
            for (Field field : fields) {
                if (field.isAnnotationPresent(Excel.class)) {
                    if (excelMap.containsKey(field.getName())) {
                        Excel annotation = field.getAnnotation(Excel.class);
                        InvocationHandler handler = Proxy.getInvocationHandler(annotation);
                        String sourceName = excelMap.get(field.getName());
                        changeAnnotationValue(handler, sourceName);
                    }
                } else if (field.isAnnotationPresent(ExcelCollection.class) && field.getType().isAssignableFrom(List.class)) {
                    // ExcelCollection修改过,才进行复原
                    if (excelMap.containsKey(field.getName())) {
                        ExcelCollection annotation = field.getAnnotation(ExcelCollection.class);
                        InvocationHandler handler = Proxy.getInvocationHandler(annotation);
                        String sourceName = excelMap.get(field.getName());
                        changeAnnotationValue(handler, sourceName);
                        // ExcelCollection未修改过,递归复原泛型字段
                    } else {
                        Type type = field.getGenericType();
                        if (type instanceof ParameterizedType) {
                            ParameterizedType pt = (ParameterizedType) type;
                            Class collectionClazz = (Class) pt.getActualTypeArguments()[0];
                            dynamicResetAnnotation(collectionClazz, excelMap);
                        }
                    }
                } else if (field.isAnnotationPresent(ExcelEntity.class)) {
                    Class entityClazz = field.getType();
                    dynamicResetAnnotation(entityClazz, excelMap);
                }
            }
        } catch (Exception e) {
            Log.error("解析动态表头,恢复注解属性值出错!", e);
        }
    }

}

EasyPoiExcelUtil.java
package com.xxx.template.utils.recruitmentManagement;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;


public class EasyPoiExcelUtil {
    /**
     * excel 导出
     *
     * @param list           数据列表
     * @param title          表格内数据标题
     * @param sheetName      sheet名称
     * @param pojoClass      Excel 实体类
     * @param fileName       导出时的excel文件名称
     * @param isCreateHeader 是否创建表头
     * @param response
     */
    public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass,
                                   String fileName, boolean isCreateHeader, HttpServletResponse response) {
        ExportParams exportParams = new ExportParams(title, sheetName);
        exportParams.setCreateHeadRows(isCreateHeader);
        defaultExport(list, pojoClass, fileName, response, exportParams);
    }

    /**
     * excel 导出
     *
     * @param list      数据列表
     * @param title     表格内数据标题
     * @param sheetName sheet名称
     * @param pojoClass Excel 实体类
     * @param fileName  导出时的excel文件名称
     * @param response
     */
    public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass,
                                   String fileName, HttpServletResponse response) {
        defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName));
    }
    /**
     * excel 导出
     *
     * @param list         数据列表
     * @param pojoClass    Excel 实体类
     * @param fileName     导出时的excel名称
     * @param response
     * @param exportParams 导出参数(标题、sheet名称、是否创建表头,表格类型)
     */
    private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName,
                                      HttpServletResponse response, ExportParams exportParams) {
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
        if (workbook != null) ;
        downLoadExcel(fileName, response, workbook);
    }

    /**
     * 默认的 excel 导出
     *
     * @param list     数据列表
     * @param fileName 导出时的excel名称
     * @param response
     */
    public static void exportExcel(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {
        defaultExport(list, fileName, response);
    }

    /**
     * 默认的 excel 导出
     *
     * @param list     数据列表
     * @param fileName 导出时的excel名称
     * @param response
     */
    private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {
        Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF);
        if (workbook != null) ;
        downLoadExcel(fileName, response, workbook);
    }



    /**
     * excel下载
     *
     * @param fileName 下载时的文件名称
     * @param response
     * @param workbook excel数据
     */
    private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {
        try {
            //content-Type 的作用是让服务器告诉浏览器它发送的数据属于什么文件类型。
            // application/vnd.ms-excel 将查询结果导出到Excel
            response.setHeader("content-Type", "application/vnd.ms-excel;");

            //Content-Disposition 当Content-Type 的类型为要下载的类型时 , 这个信息头会告诉浏览器这个文件的名字和类型。
            /**
             * Content-Disposition 指示如何处理响应内容。
             *
             * 一般有两种方式:
             *          inline:直接在页面显示
             *          attchment:以附件形式下载
             *  replace("+", "%20") 空格转码为   %20(已解决)
             *  replace("%3A", ":") %3A转码为: 但是下载的文件还是下划线 (未解决)
             */
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8").replace("+", "%20"));
            response.setCharacterEncoding("UTF-8");
            workbook.write(response.getOutputStream());
        } catch (IOException e) {
            //throw new NormalException(e.getMessage());
        }
    }


    /**
     * 功能描述:根据接收的Excel文件来导入Excel,并封装成实体类
     *
     * @param file 上传的文件
     * @param titleRows 表标题的行数
     * @param headerRows 表头行数
     * @param pojoClass Excel实体类
     * @return
     */
    public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, Class<T> pojoClass) {
        if (file == null) {
            return null;
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        List<T> list = null;
        try {
            list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass, params);
        } catch (NoSuchElementException e) {
            // throw new NormalException("excel文件不能为空");
        } catch (Exception e) {
            //throw new NormalException(e.getMessage());
            System.out.println(e.getMessage());
        }
        return list;
    }



    /**
     * 功能描述:根据接收的Excel文件来导入Excel,并封装成实体类
     *
     * @param filePath excel文件路径(但是本系统不会用到)
     * @param titleRows 表标题的行数
     * @param headerRows 表头行数
     * @param pojoClass Excel 实体类
     * @return
     */
    public static <T> List<T> importExcel(String filePath, Integer titleRows, Integer headerRows, Class<T> pojoClass) {
        if (StringUtils.isBlank(filePath)) {
            return null;
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        List<T> list = null;
        try {
            list = ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);
        } catch (NoSuchElementException e) {
            //throw new NormalException("模板不能为空");
        } catch (Exception e) {
            e.printStackTrace();
            //throw new NormalException(e.getMessage());
        }
        return list;
    }

    /**
     * excel 导入
     *
     * @param inputStream 文件输入流
     * @param titleRows   表格内数据标题行
     * @param headerRows  表头行
     * @param pojoClass   Excel 实体类
     * @return
     */
    public static <T> List<T> importExcel(InputStream inputStream, Integer titleRows, Integer headerRows, Class<T> pojoClass) throws IOException {
        if (inputStream == null) {
            return null;
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        params.setSaveUrl("/excel/");
        params.setNeedSave(true);
        try {
            return ExcelImportUtil.importExcel(inputStream, pojoClass, params);
        } catch (NoSuchElementException e) {
            throw new IOException("excel文件不能为空");
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

    /**
     *
     * @param file 导入的文件
     * @param pojoClass 实体对象
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> ExcelImportResult<T> importExcelMore(MultipartFile file, Class<T> pojoClass) throws Exception {
        if (file == null) {
            return null;
        }

        ImportParams params = new ImportParams();
        params.setTitleRows(1);//表格内数据标题行
        params.setHeadRows(1);//表头行
        //开启验证,代表导入这里是需要验证的(根据字段上的注解)
        params.setNeedSave(true);
        params.setNeedVerify(true);
        return ExcelImportUtil.importExcelMore(file.getInputStream(), pojoClass, params);
    }

    /**
     * excel 导入
     *
     * @param inputStream 文件输入流
     * @param pojoClass   pojo类型
     * @param <T>
     * @return
     */
    private static <T> ExcelImportResult<T> importExcelMore(InputStream inputStream, Class<T> pojoClass) throws IOException {
        if (inputStream == null) {
            return null;
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(1);//表格内数据标题行
        params.setHeadRows(1);//表头行
        params.setNeedSave(true);
        params.setNeedVerify(true); //是否开启校验
        try {
            return ExcelImportUtil.importExcelMore(inputStream, pojoClass, params);
        } catch (NoSuchElementException e) {
            throw new IOException("excel文件不能为空");
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

}

二. 实体类

有些字段我删除了,因为不导出它

OriginalDemand.java

package com.xxx.template.domain.recruitmentManagement;

import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelCollection;
import cn.afterturn.easypoi.excel.annotation.ExcelIgnore;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;

import java.time.LocalDateTime;
import java.util.List;

@ExcelTarget("OriginalDemand")

public class OriginalDemand {
    /**
     * 主键id
     */
    @ExcelIgnore
    private int id;


    /**
     * 部门名称
     */
    @Excel(name = "部门", needMerge = true, width = 20,height = 8)
    private String orgName;

   
    /**
     * 岗位名称
     */

    @Excel(name = "岗位", needMerge = true, width = 20,height = 8)
    private String postName;

    /**
     * 岗位级别
     */
    @Excel(name = "级别", needMerge = true, width = 20,height = 8)
    private String level;

    /**
     * 招聘人数
     */
    @Excel(name = "人数", needMerge = true, width = 20,height = 8)
    private int recruitmentQuantity;

    /**
     * 工作地点
     */
    @Excel(name = "工作地点", needMerge = true, width = 20,height = 8)
    private String workPlace;

    /**
     * 剩余需求人数
     */
    @Excel(name = "剩余需求人数", needMerge = true, width = 20,height = 8)
    private int remainingDemandNum;


    /**
     * 已提需求
     */
    @ExcelCollection(name = "已提需求",orderNum="6")
    private List<ProposedDemand> proposedDemand;
    
    //set,get方法,toString,构造器我就不写了

proposedDemand.java

package com.xxx.template.domain.recruitmentManagement;

import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelIgnore;

import java.time.LocalDateTime;

/**
 * 原始需求
 */
public class ProposedDemand {
    /**
     * 主键id
     */
    @ExcelIgnore
    private int id;

    /**
     * 原始需求id
     */
    @ExcelIgnore
    private int originalId;

    /**
     * 科室名称
     */
    @Excel(name = "科室", width = 20,height = 8)
    private String orgName;

    /**
     * 班组名称
     */
    @Excel(name = "班组", width = 20,height = 8)
    private String teamName;

    /**
     * 岗位名称
     */
    @Excel(name = "岗位", width = 20,height = 8)
    private String postName;

    /**
     * 招聘编号
     */
    @Excel(name = "招聘编号", width = 20,height = 8)
    private String recruitmentNo;

    /**
     * 招聘人数
     */
    @Excel(name = "人数", width = 20,height = 8)
    private int recruitmentQuantity;

    /**
     * 备注
     */
    @Excel(name = "备注", width = 20,height = 8)
    private String remark;
    
     //set,get方法,toString,构造器我就不写了

TalentPool.java


package com.xxx.template.domain.recruitmentManagement;

import cn.afterturn.easypoi.handler.inter.IExcelDataModel;
import cn.afterturn.easypoi.handler.inter.IExcelModel;


import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelIgnore;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
import java.time.LocalDateTime;


@ExcelTarget("TalentPool")
public class TalentPool  implements Serializable, IExcelModel, IExcelDataModel {
	/**
     * 主键id
     */
	@ExcelIgnore
	private int id;
	/**
     * 人才编号
     */
	@Excel(name = "人才编号", width = 20, orderNum = "2")
	private String talentId;
	/**
     * 姓名
     */
	@Excel(name = "姓名", width = 10, orderNum = "2")
	@NotNull(message = "姓名不能为空")
	@Pattern(regexp = "^([\\u4e00-\\u9fa5]{1,}|[a-zA-Z\\.\\s]{1,})$", message = "姓名必须为中文或者英文")
	private String name;
	/**
     * 性别
     */
	@Excel(name = "性别", width = 10, orderNum = "2")
	@NotNull(message = "性别不能为空")
	@Pattern(regexp = "^[男女]$", message = "性别必须是男或者女")
	private String gender;
	/**
     * 邮箱
     */
	@Excel(name = "邮箱", width = 20, orderNum = "2")
	@Pattern(regexp = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$", message = "邮箱格式必须正确")
	private String email;
	/**
     * 电话
     */
	@Excel(name = "电话", width = 20, orderNum = "2")
	@Pattern(regexp = "^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$", message = "电话必须正确")
	private String phoneNumber;

	/**
     * 届别
     */
	@Excel(name = "届别", width = 10, orderNum = "3")
	@NotNull(message = "届别不能为空")
	@Pattern(regexp = "^\\d{4}$", message = "届别必须是四位数字")
	private String graduationTime;
	/**
     * 学历
     */
	@Excel(name = "学历", width = 15, orderNum = "3")
	@NotNull(message = "学历不能为空")
	private String education;
	/**
     * 学校
     */
	@Excel(name = "学校", width = 20, orderNum = "3")
	@NotNull(message = "学校不能为空")
	private String school;
	/**
     * 专业
     */
	@Excel(name = "专业", width = 20, orderNum = "3")
	@NotNull(message = "专业不能为空")
	private String major;
	/**
     * 简历文件名
     */
	@ExcelIgnore
	private String fileName;
	/**
     * 应聘部门code
     */
	@ExcelIgnore
	private String orgCode;
	/**
     * 应聘部门名称
     */
	@Excel(name = "部门", width = 20, orderNum = "4")
	@NotNull(message = "部门不能为空")
	private String orgName;
	/**
     * 岗位code
     */
	@ExcelIgnore
	private String postCode;
	/**
     * 岗位名称
     */
	@Excel(name = "岗位", width = 20, orderNum = "5")
	@NotNull(message = "岗位不能为空")
	private String postName;
	/**
     * 工作地点
     */
	@Excel(name = "工作地点", width = 20, orderNum = "6")
	@NotNull(message = "工作地点不能为空")
	private String workPlace;
	/**
     * 一面评价
     */
	@Excel(name = "一面评价", width = 20, orderNum = "7")
	private String firstEvaluation;
	/**
     * 一面结果
     */
	@Excel(name = "一面结果", width = 20, orderNum = "8")
	private String interviewResult;
	/**
     * 备注
     */
	@Excel(name = "备注", width = 20, orderNum = "9")
	private String remark;

	private String errorMsg;

	private int rowNum;
	
}

三. mapper层就省略了

四. service层只是调了一下mapper层,也就不写了

五. controller层

1. 一对多动态列表导出

/**
     * excel导出
     *
     * @return
     */
    @PostMapping("/export")
    public void export(@RequestBody JSONObject info , HttpServletResponse response , HttpServletRequest request) throws Exception {
        HttpSession session = request.getSession();

        Map<String, String> excelMap=new HashMap<>();
        Map<String, String> stringStringMap =null;

        //json转map
        Map<String,List> header = JSONObject.toJavaObject(info.getJSONObject("header"), Map.class);
        //原始需求的列名
        List excelHeaders = null;
        if("".equals(header.get("excel"))||(header.get("excel")==null)){
        }else{
            excelHeaders = header.get("excel");
        }
        //已提需求的列名
        List excelCollectionHeaders = null;
        if("".equals(header.get("excelCollection"))||(header.get("excelCollection")==null)){
        }else{
            excelCollectionHeaders = header.get("excelCollection");
        }
        
        //修改注解 @Excel中的 name值,
        stringStringMap= MyExcelUtils.dynamicChangeAndSaveSourceAnnotation(excelHeaders, excelCollectionHeaders, OriginalDemand.class, excelMap);


        Map<String, Integer> parameter = new HashMap<>(2);
         List<OriginalDemand> data = recruitmentDemandService.selectByCondition(parameter,session);

        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss"));

        //导出excel
        EasyPoiExcelUtil.exportExcel(data, "招聘需求", "招聘需求", OriginalDemand.class, "招聘需求_"+time+".xls", response);
        //导出完成恢复注解的原始值
        MyExcelUtils.dynamicResetAnnotation(OriginalDemand.class,stringStringMap);

    }
//请求的数据:
{
    "header": {
        "excel": [
            "orgName",
            "postName",
            "level"
        ],
        "excelCollection": [
            "remainingDemandNum",
            "remark"
        ]
    },
    "userName": "admin"
}

2. 普通导入

/**
	 * 导入人才库信息
	 *
	 * @param file
	 * @param response
	 * @return
	 */
	@PostMapping("/import")
	public ResponseEntity leadIn(@RequestParam(value = "file") MultipartFile file,@RequestParam(value = "userName") String userName, HttpServletResponse response) {
		String data = null;
		try {
			ExcelImportResult<TalentPool> result = EasyPoiExcelUtil.importExcelMore(file, TalentPool.class);

			// 这是校验成功的数据
			List<TalentPool> successList = result.getList();
			//getFailWorkbook()和getFailList()里面的就是所有校验失败的excel数据
			List<TalentPool> failList = result.getFailList();

			for (TalentPool talentPool : successList) {
				talentPool.setCreatedBy(userName);
				talentPool.setUpdatedBy(userName);
				talentPoolService.insert(talentPool);
			}
			//导入校验存在失败则返回失败行 & 错误信息
			if (failList != null && failList.size() > 0) {
				data = "人才库导入的excel中,";
				for (TalentPool faileds : failList) {
					data= data + "第"+(faileds.getRowNum()-1)+"行,"+faileds.getErrorMsg()+";";
				}
				
				return ResponseEntity.failed(data);
			}
			
			return ResponseEntity.success("导入数据成功", null);
		} catch (Exception e) {
			e.printStackTrace();
			return ResponseEntity.failed("信息导入失败");
		}
	}

在导入的时候,也加入了唯一性判断,通过,姓名+性别+学校+专业进行判断,如果是重复的话,进行更新操作,否则进行新增操作
先在数据库给 姓名+性别+学校+专业 加上索引, on duplicate key update 进行操作

<insert id="insert"  parameterType="com.xxx.template.domain.recruitmentManagement.TalentPool">
        insert into talent_pool
            (name, talent_id, gender, email, phone_number, graduation_time, education, school, major, file_name, org_code, org_name,post_code,post_name,work_place,first_evaluation, interview_result, remark, is_delete, created_by,created_time, updated_by, updated_time)
        VALUES (#{name},#{talentId},#{gender},#{email},#{phoneNumber},#{graduationTime},#{education},#{school},#{major},#{fileName},#{orgCode},#{orgName},#{postCode},#{postName},#{workPlace},#{firstEvaluation},#{interviewResult},#{remark},#{isDelete},#{createdBy},#{createdTime},#{updatedBy},#{updatedTime})
        on duplicate key update
            email = values(email),
            phone_number = values(phone_number),
            graduation_time = values(graduation_time),
            education = values(education),
            file_name = values(file_name),
            org_code = values(org_code),
            org_name = values(org_name),
            post_code = values(post_code),
            post_name = values(post_name),
            work_place = values(work_place),
        	first_evaluation = values(first_evaluation),
        	interview_result = values(interview_result),
        	remark = values(remark),
        	is_delete = values(is_delete),
            updated_by = values(updated_by),
            updated_time = values(updated_time)
    </insert>

人才库导入.xls
springboot项目利用easypoi导入导出(包括一对多导出的动态列选择,以及普通导入)文章来源地址https://www.toymoban.com/news/detail-419875.html

到了这里,关于springboot项目利用easypoi导入导出(包括一对多导出的动态列选择,以及普通导入)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【java】EasyPoi导出导入(合并单元格)

    2024年02月14日
    浏览(45)
  • EasyPoi快速入门(Excel导入导出工具)

    简介: easypoi是一款Excel快速导入导出的工具,最近有所使用,结合了网上的一些用法和官方文档的介绍,在在这里总结一下最简单的esaypoi导入Excel的实现,网上很多教程都已经封装了工具类,虽然方便,但第一次接触easypoi可能看的不是清晰,现在总结一下最为直观的SpringBoot集成easypoi快

    2023年04月22日
    浏览(42)
  • easypoi 模板导入、导出合并excel单元格功能

    hutool 导出复杂excel(动态合并行和列) java使用poi读取跨行跨列excel springboot集成easypoi并使用其模板导出功能和遇到的坑 Easypoi Excel模板功能简要说明 easypoi 模板导出兼容合并单元格功能 高校校舍使用情况统计表 单位(盖章): 填表人: 部门负责人: 分管校领导: 填表日期:

    2023年04月22日
    浏览(53)
  • spring boot 整合EasyPoi导入导出,下载模版功能

    name:Excel中的列名; width:指定列的宽度; needMerge:是否需要纵向合并单元格; format:当属性为时间类型时,设置时间的导出导出格式; desensitizationRule:数据脱敏处理,3_4表示只显示字符串的前3位和后4位,其他为*号; replace:对属性进行替换; suffix:对数据添加后缀。

    2024年02月11日
    浏览(40)
  • 【Java Easypoi & Apache poi】 Word导入与导出

            如果这里造成了读取resources下的文件返回前端乱码问题:除了HttpServletResponse响应中设置字体问题,还有可能是因为在编译期文件就已经乱码了,所以需要在pom.xml中增加以下配置。

    2024年02月10日
    浏览(56)
  • 【Easypoi & Apache poi】 Java后端 Word导入与导出

            如果这里造成了读取resources下的文件返回前端乱码问题:除了HttpServletResponse响应中设置字体问题,还有可能是因为在编译期文件就已经乱码了,所以需要在pom.xml中增加以下配置。

    2024年02月11日
    浏览(55)
  • eclipse的安装与配置详细教程(包括UML插件 汉化 JDK 代码补全 导入导出等)

    1.Eclipse安装与环境配置 1.将JDK与Eclipse这两个软件安装包放在一个文件夹下,方便之后安装使用。   2.安装JDK 在D:LeStoreDownloadJava文件夹下另外新建三个文件夹分别命名为java、jdk和eclipse(分别用于Java、jdk、eclipse的安装路径)【上图】   3.双击jdk-8u261-windows-x64.exe运行安装,进

    2024年02月03日
    浏览(51)
  • JAVA环境配置【eclipse的安装与配置详细教程(包括UML插件 汉化 JDK 代码补全 导入导出等)】

    1.Eclipse安装与环境配置 1.将JDK与Eclipse这两个软件安装包放在一个文件夹下,方便之后安装使用。   2.安装JDK 在D:LeStoreDownloadJava文件夹下另外新建三个文件夹分别命名为java、jdk和eclipse(分别用于Java、jdk、eclipse的安装路径)【上图】   3.双击jdk-8u261-windows-x64.exe运行安装,进

    2024年01月16日
    浏览(51)
  • SpringBoot实现Excel导入导出

    话不多说,直接上代码 依赖文档 找到pom文件,如下图所示 引入需要的依赖 导出写法: 导入写法: 已上就是导入导出

    2024年02月09日
    浏览(43)
  • SpringBoot实现Excel导入导出,简单好用

    POI是Java操作MicroOffice(如对Excel的导入导出)的一个插件。POI的全称是(Poor Obfuscation Implementation),POI官网地址是 http://poi.achache.org/index.html 。 EasyPoi对POI进行了优化 ,更加设计精巧,使用简单,接口丰富,扩展简单。EasyPOI的同类产品有Execel4J,Hutools等。EasyPoi官网地址是 h

    2024年02月11日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包