springboot中easyExcel实现导入导出

发布时间 2023-10-18 17:01:39作者: csjoz11

导出
1、引入easyExcel依赖
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.2.7</version>
</dependency>
1
2
3
4
5
2、实体类
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

import java.util.Date;

@Data
@ContentRowHeight(30)//设置导出的excel的内容高度
@HeadRowHeight(40)//设置导出的excel的表头高度
@ColumnWidth(20)//设置导出的excel的列宽
public class UserVo {

    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    @ExcelProperty(value = "用户序号",index = 0)
    private Integer userid;
    /**
     * 用户名
     */
    @ExcelProperty(value = "登录名称",index = 1)
    private String username;
    /**
     * 昵称
     */
    @ExcelProperty(value = "用户名称",index = 2)
    private String nickname;

    /** 用户邮箱 */
    @ExcelProperty(value = "用户邮箱",index = 3)
    private String email;
    /** 手机号码 */
    @ExcelProperty(value = "手机号码",index = 4)
    private String phonenumber;
    /** 用户性别 */
    @ExcelProperty(value = "用户性别",index = 5)
    private String sex;
    /** 用户状态 0正常 1 禁用  -1 删除 */
    @ExcelProperty(value = "用户状态",index = 6)
    private String status;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
3、ExcelUtil工具类
import com.alibaba.excel.EasyExcel;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.util.List;

import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.mh.common.handler.ExcelListener;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

/**
 * excel导出工具类
 */
public class ExcelUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExcelUtil.class);

    /**
     * 私有化构造方法
     */
    private ExcelUtil(){}
    
    /**
     * 导出excel
     * @param response
     * @param list        要导出的数据list
     * @param fileName    文件名
     * @param clazz        要导出的实体类的class
     */
    public static void ExcelWrite(HttpServletResponse response, List list, String fileName,Class clazz) {
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;filename=" + java.net.URLEncoder.encode(fileName+".xls", "UTF-8"));
            response.setHeader("Access-Control-Expose-Headers", "Content-disposition");
            //头的策略  样式调整
            WriteCellStyle headWriteCellStyle = new WriteCellStyle();
            // 头背景 浅绿
            headWriteCellStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex());
            WriteFont headWriteFont = new WriteFont();
            // 头字号
            headWriteFont.setFontHeightInPoints((short)14);
            // 字体样式
            headWriteFont.setFontName("宋体");
            headWriteCellStyle.setWriteFont(headWriteFont);
            //自动换行
            headWriteCellStyle.setWrapped(true);
            //设置细边框
            headWriteCellStyle.setBorderBottom(BorderStyle.THIN);
            headWriteCellStyle.setBorderLeft(BorderStyle.THIN);
            headWriteCellStyle.setBorderRight(BorderStyle.THIN);
            headWriteCellStyle.setBorderTop(BorderStyle.THIN);
            //设置边框颜色 25灰度
            headWriteCellStyle.setBottomBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());
            headWriteCellStyle.setTopBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());
            headWriteCellStyle.setLeftBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());
            headWriteCellStyle.setRightBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());
            // 水平对齐方式
            headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            // 垂直对齐方式
            headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            // 内容的策略 宋体
            WriteCellStyle contentStyle = new WriteCellStyle();
            //设置垂直居中
            contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            //设置 水平居中
            contentStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            WriteFont contentWriteFont = new WriteFont();
            // 内容字号
            contentWriteFont.setFontHeightInPoints((short)12);
            // 字体样式
            contentWriteFont.setFontName("宋体");
            contentStyle.setWriteFont(contentWriteFont);
            // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
            HorizontalCellStyleStrategy strategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentStyle);
            EasyExcel.write(response.getOutputStream(), clazz).registerWriteHandler(strategy).sheet("sheet1").doWrite(list);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 导入
     * @param excel 上传的excel文件
     * @param clazz 要导入的实体类的class
     */
    public static <T> List<T> readerExcel(MultipartFile excel, Class<T> clazz) throws Exception {
        if (excel.isEmpty()) {
            throw new Exception("请选择excel文件");
        }
        String fileName = excel.getOriginalFilename();
        LOGGER.info("Excel文件解析:文件名 = " + fileName);
        if (fileName == null || (!fileName.toLowerCase().endsWith(".xls") && !fileName.toLowerCase().endsWith(".xlsx"))) {
            throw new Exception("文件格式错误");
        }
        try(InputStream fileStream = new BufferedInputStream(excel.getInputStream())) {
            ExcelListener<T> excelListener = new ExcelListener<>();
            EasyExcel.read(fileStream, clazz, excelListener)
                    .autoTrim(true)
                    .sheet()
                    .doRead();
            return excelListener.getList();
        } catch (Exception e) {
            LOGGER.error("导入失败, 请检查导入数据的准确性", e);
            throw new Exception("导入失败, 请检查导入数据的准确性");
        }
    }

}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
4、UserController导出
@GetMapping(value = "/exports")
@ResponseBody
public void exports(HttpServletResponse response,UserVo user) throws IOException {
    //需要导出的数据
    List<UserVo> list = userService.exportsUser(user);
    String fileName = "用户信息表格"+System.currentTimeMillis();
    //调用工具类
    ExcelUtil.ExcelWrite(response,list,fileName,UserVo.class);
}
1
2
3
4
5
6
7
8
9
导入
1、ExcelListener解析excel表数据
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.List;

public class ExcelListener<T> extends AnalysisEventListener{
    private List<T> list = new ArrayList<>();
    @Override
    public void invoke(Object o, AnalysisContext analysisContext) {
        list.add((T)o);
    }
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {}
    
    public List<T> getList() {
        return list;
    }
    public void setList(List<T> list) {
        this.list = list;
    }
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2、UserController导入
导入数据,无非就是将excel表格里面的数据解析出来,得到一个list,然后将这个list中的数据添加到数据库中。添加时可以一次性将list批量添加到数据库,也可以用for循环一条一条将数据添加到数据库中。

/**
  *
  * @param file
  * @param updateSupport 是否更新数据(当list中有数据库中存在的数据时,是否更新,为true 更新,为false 不更新)
  * @return
  * @throws Exception
  */
@PostMapping("/importData")
@ResponseBody
public String importData(@RequestParam MultipartFile file,@RequestParam boolean updateSupport,HttpServletRequest request) throws Exception {
    List<UserVo> userVos = ExcelUtil.readerExcel(file, UserVo.class);
    String message = userService.batchInsertUser(userVos ,updateSupport);
    return message;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
3、UserService添加数据

private UserMapper userMapper;

/**
  * 导入用户
  * @param list
  * @param isUpdateSupport
  * @return
  */
 public String batchInsertUser(List<UserVo> list,Boolean isUpdateSupport) {
     if (StringUtils.isNull(list) || list.size() == 0) {
         throw new CustomException(ResultEnum.IMPORT_ERROR,"导入用户数据不能为空!");
     }
     int successNum = 0;
     int failureNum = 0;
     StringBuilder successMsg = new StringBuilder();
     StringBuilder failureMsg = new StringBuilder();
     for (UserVo user : list) {
         try {
             // 验证是否存在这个用户
             QueryWrapper<UserVo> queryWrapper = new QueryWrapper();
             queryWrapper.eq("user_name",user.getUserName());
             queryWrapper.ne("status","2");
             /**
                 这里因为用的是mybatis-plus,有自带的增删改查分页这些操作,
                 只需要 UserMapper extends BaseMapper<UserVo>,UserService extends ServiceImpl<UserMapper, UserVo>。
                 使用QueryWrapper设置查询条件,直接调用 BaseMapper 中的 selectOne 即可,
                 就不用自己去写sql语句了,下面的 insert(user) 和 updateById(user) 也是同样的。
                 当然如果查询条件比较复杂,用 mybatis-plus 自带的查询可能就处理不了了,这种情况还是得自己写sql语句。
             */
             UserVo u = userMapper.selectOne(queryWrapper);
             if (StringUtils.isNull(u)) {
                 userMapper.insert(user);
                 successNum++;
                 successMsg.append(successNum + "、账号 " + user.getUserName() + " 导入成功。");
             } else if (isUpdateSupport) {
                 userMapper.updateById(user);
                 successNum++;
                 successMsg.append(successNum + "、账号 " + user.getUserName() + " 更新成功。");
             } else {
                 failureNum++;
                 failureMsg.append(failureNum + "、账号 " + user.getUserName() + " 已存在。");
             }
         } catch (Exception e) {
             failureNum++;
             String msg = failureNum + "、账号 " + user.getUserName() + " 导入失败:";
             failureMsg.append(msg + e.getMessage());
             log.error(msg, e);
         }
     }
     if (failureNum > 0) {
         failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
         throw new CustomException(ResultEnum.IMPORT_ERROR,failureMsg.toString());
     } else {
         successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
     }
     return successMsg.toString();
 }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
文章知识点与官方知识档案匹配,可进一步学习相关知识
————————————————
版权声明:本文为CSDN博主「符华-」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43165220/article/details/113562164