EasyExcel 操作excel导入导出

目录

1、核心依赖

2、导出

前端:一个小页面

后端 

实体类

controller 

dao.xml

sql

效果

导入

前端

后端

实体类(加校验注解)

controller

util包

dao.xml

效果


1、核心依赖

		<!-- easyExcel -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>easyexcel</artifactId>
			<version>2.2.6</version>
		</dependency>

2、导出

前端:一个小页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>excel导入导出</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

</head>
<body>

<button id="easyExcelBtn" type="button" >
    下载列表数据easyExcel
</button>


<script>
   
    /**
     * easyExce导出
     */
    //给"批量导出"按钮添加单击事件
    $("#easyExcelBtn").click(function () {
        //发送同步请求
        window.location.href="easyExcel/write";
    });

   
</script>

</body>
</html>

后端 

实体类


/**
 * 校验
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class EasySysUser {

    //
    @ExcelProperty("用户账号")
    private String  userName;

    @ExcelProperty("用户昵称")
    private String  nickName;

    @ExcelProperty("用户邮箱")
    private String  email;

    @ExcelProperty("手机号码")
    private String  phonenumber;

    @ExcelProperty("用户性别")
    private Integer sex;

    @ExcelProperty("帐号状态(0正常 1停用)")
    private Integer  status;

   
    /**
     * 忽略这个字段
     * @ExcelIgnore
     */
    @ExcelProperty("删除标志(0代表存在 2代表删除)")
    private Integer  delFlag;

}

controller 

为了方便我就把代码业务都写这了。

 

@Autowired
    ExcelService excelService;

    @GetMapping("easyExcel/write")
    public void easyExcelWrite(HttpServletResponse response){


        //查询到数据库中的数据
        List<EasySysUser> users = excelService.poiExcelWrite();


        OutputStream outputStream = null;
        try {

            String fileName = URLEncoder.encode("用户表", StandardCharsets.UTF_8.name());//文件名

            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setCharacterEncoding("utf-8");
            response.addHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xls");
            outputStream = response.getOutputStream();

            //                  流  , 数据类型                   表               数据
            EasyExcel.write(outputStream, EasySysUser.class).sheet("1").doWrite(users);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.flush();//刷新流:通道中数据全部输出
                    outputStream.close();//关闭流
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

dao.xml

    <select id="poiExcelWrite" resultType="com.zoubin.easyexcel.web.entity.EasySysUser">
        SELECT user_name username,nick_name nickname,email,phonenumber,sex,status,del_flag delflag from sys_user;
    </select>

sql

CREATE TABLE `sys_user` (
  `user_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `dept_id` bigint(20) DEFAULT NULL COMMENT '部门ID',
  `user_name` varchar(30) NOT NULL COMMENT '用户账号',
  `nick_name` varchar(30) NOT NULL COMMENT '用户昵称',
  `user_type` varchar(2) DEFAULT '00' COMMENT '用户类型(00系统用户)',
  `email` varchar(50) DEFAULT '' COMMENT '用户邮箱',
  `phonenumber` varchar(11) DEFAULT '' COMMENT '手机号码',
  `sex` char(1) DEFAULT '0' COMMENT '用户性别(0男 1女 2未知)',
  `avatar` varchar(100) DEFAULT '' COMMENT '头像地址',
  `password` varchar(100) DEFAULT '' COMMENT '密码',
  `status` char(1) DEFAULT '0' COMMENT '帐号状态(0正常 1停用)',
  `del_flag` char(1) DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)',
  `login_ip` varchar(128) DEFAULT '' COMMENT '最后登录IP',
  `login_date` datetime DEFAULT NULL COMMENT '最后登录时间',
  `create_by` varchar(64) DEFAULT '' COMMENT '创建者',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `remark` varchar(500) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=158 DEFAULT CHARSET=utf8 COMMENT='用户信息表'

效果

 

 

导入

前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>excel导入导出</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

</head>
<body>

<button id="easyExcelBtn" type="button" >
    下载列表数据easyExcel
</button>

<hr/>
<!-- 导入市场活动的模态窗口 -->
<div class="modal fade" id="importActivityModal3" role="dialog">
    <div class="modal-dialog" role="document" style="width: 85%;">
        <div class="modal-content">
            <div class="modal-header">
                <h4 class="modal-title" id="myModalLabel3">导入EasyExcel校验测试</h4>
            </div>
            <div class="modal-body" style="height: 350px;">
                <div style="position: relative;top: 20px; left: 50px;">
                    请选择要上传的文件:<small style="color: gray;">[仅支持.xls]</small>
                </div>
                <div style="position: relative;top: 40px; left: 50px;">
                    <input type="file" id="activityFile3">
                </div>
                <div style="position: relative;top: 60px; left: 50px;">
                    <button id="importActivityBtn3" type="button" class="btn btn-primary">导入</button>
                </div>
            </div>

        </div>
    </div>
</div>


<script>

    /**
     * easyExce导出
     */
    //给"批量导出"按钮添加单击事件
    $("#easyExcelBtn").click(function () {
        //发送同步请求
        window.location.href="easyExcel/write";
    });

   
    /**
     * EasyExcel导入 校验
     */
    //给"导入"按钮添加单击事件
    $("#importActivityBtn3").click(function () {
        //收集参数
        //——xls文件获取的是文件名
        var activityFileName=$("#activityFile3").val();
        var suffix=activityFileName.substr(activityFileName.lastIndexOf(".")+1).toLocaleLowerCase();//xls,XLS,Xls,xLs,....截取字符串后缀,toLocaleLowerCase():转小写
        if(suffix!="xls"){
            alert("只支持xls文件");
            return;
        }
        //——获取文件内容
        var activityFile=$("#activityFile3")[0].files[0];
        //if(activityFile.size>5*1024*1024){//activityFile.size:获取文件大小
        //    alert("文件大小不超过5MB");
        //    return;
        //}

        //FormData是ajax提供的接口,可以模拟键值对向后台提交参数;
        //FormData最大的优势是不但能提交文本数据,还能提交二进制数据
        var formData=new FormData();
        formData.append("activityFile",activityFile);

        //发送请求
        $.ajax({
            url:'/EasyExcel/readCheck',
            data:formData,
            processData:false,//设置ajax向后台提交参数之前,是否把参数统一转换成字符串:true--是,false--不是,默认是true
            contentType:false,//设置ajax向后台提交参数之前,是否把所有的参数统一按urlencoded编码:true--是,false--不是,默认是true
            type:'post',
            dataType:'json',
            success:function (data) {
                if(data.code=="1"){
                    //提示成功导入记录条数
                    alert("成功导入"+data.retData+"条记录");
                    //关闭模态窗口
                    $("#importActivityModal3").modal("hide");
                }else{
                    //提示信息
                    alert(data.message);
                    //模态窗口不关闭
                    $("#importActivityModal3").modal("show");
                }
            }
        });
    });


</script>

</body>
</html>

后端

实体类(加校验注解)

package com.zoubin.easyexcel.web.entity;

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;

/**
 * 校验
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class EasySysUser {

    @NotEmpty(message = "用户名称不能为空")
    @ExcelProperty("用户账号")
    private String  userName;

    @NotEmpty(message = "用户昵称不能为空")
    @ExcelProperty("用户昵称")
    private String  nickName;

    //    @Pattern(regexp="[a-za-z0-9._%+-]+@[a-za-z0-9.-]+\\.[a-za-z]{2,4}", message="邮件格式错误")
    @Email(message = "邮箱格式不正确")
    @ExcelProperty("用户邮箱")
    private String  email;

    @NotEmpty(message = "手机号码不能为空")
    @ExcelProperty("手机号码")
    private String  phonenumber;

    @ExcelProperty("用户性别")
    private Integer sex;

    @ExcelProperty("帐号状态(0正常 1停用)")
    private Integer  status;

    @ExcelProperty("删除标志(0代表存在 2代表删除)")
    /**
     * 忽略这个字段
     * @ExcelIgnore
     */
    private Integer  delFlag;

}

controller

 /**
     * 导入
     * 数据校验并返回错误
     * @param activityFile
     * @return
     */
    @PostMapping("/EasyExcel/readCheck")
    @ResponseBody
    public Object easyExcelReadCheck(MultipartFile activityFile) {


        ReturnObject returnObject = new ReturnObject();//响应数据
        InputStream inputStream = null;
        try {
            //获取文件流
            inputStream = activityFile.getInputStream();

            // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
            UserListener userListener = new UserListener();
            //             流           数据类型             导入数据监听器
            EasyExcel.read(inputStream, EasySysUser.class, userListener).sheet().doRead();

            //获取监听收集的数据
            List<EasySysUser> dataList = userListener.getDataList();

            //文件中有数据
            if (!dataList.isEmpty()){

                //进行数据校验
                List<String> valid = ValidationUtil02.valid(dataList);
                if (!valid.isEmpty()){//校验不为空就说明有错误数据
                    for (String s:valid){
                        System.out.println(s);//打印错误
                    }
                    //向前端返回错误信息
                    returnObject.setCode("500");//失败
                    returnObject.setMessage(valid.toString());
                    return returnObject;
                }
            }else {
                return null;
            }

            //没有问题调用service层方法,保存用户
            int ret = excelService.saveUsers(dataList);

            returnObject.setCode("1");//成功
            returnObject.setRetData(ret);
        } catch (IOException e) {
            e.printStackTrace();
            returnObject.setCode("500");//失败
            returnObject.setMessage("系统忙,请稍后重试....");
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();//关闭流
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return returnObject;

    }

util包

ReturnObject :返回响应信息

@Data
public class ReturnObject {

    private String code;//返回的编码
    private String message;//返回的提示信息
    private Integer retData;//返回条数
}

 UserListener :EasyExcel导入监听器,获取导入数据

@Component
public class UserListener extends AnalysisEventListener<EasySysUser> {

    //保存数据
    List<EasySysUser> dataList = new ArrayList<>();;

    //读取表头的内容
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
//        System.out.println("表头->"+headMap);
    }
    //一行一行读取excel中的内容
    @Override
    public void invoke(EasySysUser user, AnalysisContext context) {
        dataList.add(user);
    }
    //读取完成之后执行的方法
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {

    }

    public List<EasySysUser> getDataList() {
        return dataList;
    }
}

 ValidationUtil02 : 数据校验工具类


/**
 * 数据校验工具
 */
public class ValidationUtil02 {

    //校验对象(线程安全)
    static Validator validator;

    //初始化
    static {
        validator = Validation.buildDefaultValidatorFactory().getValidator();
    }


    //校验方法 
    public static List<String>  valid(List<EasySysUser> value){

        //校验错误信息
        List<String>  errorResult = new ArrayList<>();
        //初始行数
        int row = 2;

        for (EasySysUser user : value){

            //如果没有校验通过,就会有校验信息
            Set<ConstraintViolation<Object>> validate = validator.validate(user);// 进行校验

            if (!validate.isEmpty()){
                int finalRow = row;
                List<String> collect = validate.stream().map(v ->
                        "第"+ finalRow +"行--"+
                                "属性:" + v.getPropertyPath() +
                                ",属性的值:" + v.getInvalidValue() +
                                ",校验不通过的提示信息:" + v.getMessage())
                        .collect(Collectors.toList());

                errorResult.add(collect.toString());
            }
            ++row;
        }
        return errorResult;

    }

//    //测试
//    public static void main(String[] args) {
//        EasySysUserCheck user = new EasySysUserCheck();
//        user.setNickName("你好");
//        List<String> valid = ValidationUtil.valid(user);
//        System.out.println(valid);
//
//
//    }

}


dao.xml

    <insert id="saveUsers">
        insert into sys_user(user_name,nick_name,email,phonenumber,sex,status,del_flag)
        values
        <foreach collection="list" item="obj" separator=",">
            (#{obj.userName},#{obj.nickName},#{obj.email},#{obj.phonenumber},#{obj.sex},#{obj.status},#{obj.delFlag})
        </foreach>
    </insert>

效果

错误数据

 

选择文件进行导入

 

 

 

准备正确数据

 

 

 本文还是有许多不足的,欢迎指正。

 可以试着去进行优化,提高拓展和复用性。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白要努力变黑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值