前后端分离项目中-EasyExcel导入和导出

前后端分离项目中-EasyExcel导入和导出

添加依赖

创建SpringBoot工程,我这里使用的SpringBoot是2.7.16
添加需要的依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.3.2</version>
        </dependency>

我这里使用的easyexcel版本是3.3.2,是我在写这篇文章的时候的最新版本。

导入操作

流程说明

导入Excel的操作的流程应该是:
①上传Excel文件。
②后端接收到文件之后,解析excel文件中的数据。
③拿到解析得到的数据之后,按需处理。
现在的处理是,文件上传还是传统的文件上传操作。EasyExcel帮我们完成了文件的解析,我们可以直接获取到解析后的数据。

代码示例

看看具体的代码和API说明吧:
第一步: 创建实体类
EasyExcel 可以帮我们将Excel表格中的转换为我们的实体类对象列表,所以我们需要定义一个实体类。
比如:

public class Student {
    @ExcelProperty("编号")
    private Long stuId;
    @ExcelProperty("姓名")
    private String stuName;
    @ExcelProperty("生日")
    private Date stuBirth;
    @ExcelProperty("是否毕业")
    private Boolean graduate;
    @ExcelProperty("年龄")
    private Integer age;

    public Student() {
    }

    public Student(Long stuId, String stuName, Date stuBirth, Boolean graduate, Integer age) {
        this.stuId = stuId;
        this.stuName = stuName;
        this.stuBirth = stuBirth;
        this.graduate = graduate;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "stuId=" + stuId +
                ", stuName='" + stuName + '\'' +
                ", stuBirth=" + stuBirth +
                ", graduate=" + graduate +
                ", age=" + age +
                '}';
    }

说明

实体类成员变量上方的注解说明

  • ExcelProperty 用于匹配excel和实体类的匹配,参数如下:
    • value 默认为空,用于匹配excel中的头,必须全匹配,如果有多行头,会匹配最后一行头
    • order 默认Integer.MAX_VALUE,优先级高于value,会根据order的顺序来匹配实体和excel中数据的顺序
    • index 默认-1,优先级高于value和order,会根据index直接指定到excel中具体的哪一列
  • ExcelIgnore 默认所有字段都会和excel去匹配,加了这个注解会忽略该字段
  • ExcelIgnoreUnannotated 默认不加ExcelProperty 的注解的都会参与读写,加了不会参与读写
  • DateTimeFormat 日期转换,用String去接收excel日期格式的数据会调用这个注解,参数如下:
    • value 默认空,参照java.text.SimpleDateFormat书写即可
    • use1904windowing 默认自动选择,excel中时间是存储1900年起的一个双精度浮点数,但是有时候默认开始日期是1904,所以设置这个值改成默认1904年开始
  • NumberFormat 数字转换,用String去接收excel数字格式的数据会调用这个注解。
    • value 默认空,参照java.text.DecimalFormat书写即可
    • roundingMode 默认RoundingMode.HALF_UP,格式化的时候设置舍入模式

第二步:准备监听器处理解析的数据。
EasyExcel在解析excel文件并不是直接返回解析的数据,而是在解析过程中需要一个监听器来监听解析过程,每解析一条数据出来都会触发监听的对应的方法,并且将我们解析的数据传入到这个方法中,我们只需要在这个方法中处理这条数据即可。
看看我们的处理器:

@Component
@Scope("prototype")
public class StudentListener extends AnalysisEventListener<Student> {
    @Override
    public void invoke(Student student, AnalysisContext analysisContext) {
        System.out.println("在listener中保存一行数据:" + student);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {

    }
}

第三步:准备controller,这个就简单了,直接上货

@RestController
@CrossOrigin
public class DemoController {

    @Autowired
    private StudentListener studentListener;

    @RequestMapping("/upload")
    public String upload(MultipartFile uploadFile){
        try {
        	// 得到excel读取对象
            ExcelReaderBuilder builder = EasyExcel.read(uploadFile.getInputStream(), Student.class,studentListener);
            // 获取表格
            ExcelReaderSheetBuilder sheet = builder.sheet();
            // 读取数据
            sheet.doRead();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return "ok";
    }
}

第四步:前端,额~~这一部分的话按需处理极刻,我这里是ElementPlus,上货

<template>
  <div>
    <el-upload
      v-model:file-list="fileList"
      class="upload-demo"
      action="http://localhost:8888/upload"
      name="uploadFile"
      :on-success="uploadSuccess"
      :show-file-list="false"
    >
      <el-button type="primary">导入信息</el-button>
    </el-upload>
    <el-button @click="doExport" type="success">直接超链接导出</el-button>
    <el-button @click="downloadExcel" type="success">axios导出</el-button>
  </div>
</template>

OK,准备文件:
在这里插入图片描述
上传,搞定。

导出操作

思路说明

导出操作相当简单,我们准备好数据,然后将数据交给EasyExcel,EasyExcel自动将数据列表转换为Excel文件,我们按照传统文件下载的操作设置好相关的响应头内容,获得输出流,然后将输出流交个EasyExcel,就自动完成文件的导出操作了。

代码示例

实体类还是使用上一章节的实体类,这里我们只需要写好controller即可:

    @RequestMapping("/download")
    public void download(HttpServletResponse response) throws IOException {
        // 设置头消息
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        // 文件名
        String fileName = URLEncoder.encode("学员信息","utf-8");
        // 设置响应头
        response.addHeader("Content-Disposition","attachment;filename=" + fileName + ".xlsx");
        response.addHeader("Access-Control-Expose-Headers","Content-Disposition");
        // 得到输出流
        ServletOutputStream out = response.getOutputStream();
        // 得到Writer
        ExcelWriterBuilder writer = EasyExcel.write(out,Student.class);
        // 获得表格数据对象
        ExcelWriterSheetBuilder sheet = writer.sheet();
        // 准备输出的数据
        List<Student> list = new ArrayList<>();
        list.add(new Student(1L,"卡卡西",new Date(),false,31));
        list.add(new Student(3L,"鸣人",new Date(),false,31));
        list.add(new Student(12L,"佐助",new Date(),true,31));
        // 写出数据
        sheet.doWrite(list);
    }

特别说明:
在前后端分离的项目中,默认只有部分的响应头消息可以响应到前端,我们代码中设置的Content-Disposition是无法响应的,如果我们希望这个响应头到达前端,我们就需要做一些设置:response.addHeader("Access-Control-Expose-Headers","Content-Disposition");

前端的处理:

methods: {
    uploadSuccess(res) {
      console.log(res);
    },
    doExport() {
     // 这里直接使用超链接完成下载
      document.location.href = "http://localhost:8888/download";
    },
   // 有时候我们需要一个下载的动画,或者下载的反馈,这时可能就要考虑下面的方案了。
    downloadExcel() {
      axios.get("http://localhost:8888/download").then((res) => {
        if (!res) {
          return;
        }
         // 得到文件流后,前端生成文件,创建出a标签进行点击
        const fileName = res.headers.get("Content-Disposition").split("=")[1];
        const blob = new Blob([res.data], {
          type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8",
        });
        const url = window.URL.createObjectURL(blob);
        const aLink = document.createElement("a");
        aLink.style.display = "none";
        aLink.href = url;
        aLink.setAttribute("download", decodeURI(fileName));
        document.body.appendChild(aLink);
        aLink.click();
        document.body.removeChild(aLink);
        window.URL.revokeObjectURL(url);
      });
    },
  },

完事!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

戴着假发的程序员

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

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

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

打赏作者

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

抵扣说明:

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

余额充值