Java从零开始实现导出excel(一)

新人博主,随笔记录。主要还是通过自己日常工作积累,系统整理一些技术。希望能够节省更多人的时间,走出自己的路。话不多说

java导出excel两种方式

1.使用poi向模板中每行写入excel中的内容(主要是针对表格的复杂样式使用)

2.使用poi通过模板实现excel导出(推荐使用)

官方文档:https://www.yuque.com/easyexcel/doc/easyexcel

使用easyExcel通过模板导出excel

1.快速创建工程

我这直接用springboot工程
之后直接下一步就可以了,创建工程时选择Lombok
在这里插入图片描述
进入工程之后,打开Settings(快捷键:Ctrl+Alt+S),安装Lombok插件
在这里插入图片描述
需要使用到的jar包(这里我都是用maven注入的)

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

工程搭建完成之后。开始实现EasyExcel使用模板导出

  1. 首先要准备导出的模板(注意:excel模板有两种后缀名: xls,xlsx。经过测验发现好像只支持xls的模板)
  2. 创建导出实体
  3. 根据模板导出文件

导出模板:
在这里插入图片描述

创建导出实体:

/**
 * 学生
 */
@Data
public class Student extends BaseRowModel {

    /**
     * 姓名
     */
    @ExcelProperty(value = "姓名",index = 0)
    private String name;

    /**
     * 年龄
     */
    @ExcelProperty(value = "年龄",index = 1)
    private int age;

    /**
     * 性别
     */
    @ExcelProperty(value="性别",index = 2)
    @ExcelIgnore
    private String sex;

    /**
     * 学号
     */
    @ExcelProperty(value="学号",index = 3)
    private long num;

    /**
     * 家庭地址
     */
    @ExcelProperty(value = "家庭地址",index = 4)
    private String address;
}

这个实体首先要继承BaseModel
实体中的注解,我在这简单说明一下,具体上面的官方文档都有。可以自己查找
@Data :Lombok的注解,里面包含了所有参数的set和get方法

@ExcelProperty注解:

  1. value :主要是定义表头用的,多个可以用“,”隔开。我们这是最简单的表头就用了一个
  2. index :定义excel中填充列的位置。例如:0代表第一列

@ExcelIgnore : 默认所有字段都会和excel去匹配,加了这个注解会忽略该字段

下面我就直接贴代码

ExportExcelDemo


package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

/**
 * 使用easyExcel导出excel
 */
@RestController
public class ExportExcelDemo {


    /**
     * 使用EasyExcel模板导出excel
     * @param response
     * @param session
     * @throws Exception
     */
    @GetMapping(value = "/exportExcelByTemplate")
    public void exportExcelByTemplate(HttpServletResponse response, HttpSession session) throws Exception {
        response.setContentType("multipart/form-data");
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/octet-stream;charset=utf-8");
        LocalDate time = LocalDate.now();
        String fileName = URLDecoder.decode("easyExcel导出模板_" + time, "UTF-8");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes("gb2312"), "ISO8859-1") + ".xls" + "\"");
        OutputStream out = response.getOutputStream();
        List<Student> data = getData();

        //根据模板导出数excel
        ExcelUtil.exportTemplate("templates/template.xls", "model.xls", out, Student.class,ExportExcelDemo.class, data, session);
    }


    //封装导出数据
    private List<Student> getData() {
        List<Student> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Student student = new Student();
            student.setName("测试学生姓名-" + i);
            student.setAge(i);
            student.setSex(i % 2 == 1 ? "男" : "女");
            student.setNum(111111L);
            student.setAddress("追晨始梦CSDN博客");
            list.add(student);
        }
        return list;
    }
}

ExcelUtil :工具类

package com.example.demo;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.metadata.BaseRowModel;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.util.List;
import java.util.Map;

/**
 * Description: Excel操作工具类
 */
@Slf4j
public class ExcelUtil {

    /**
     * 根据模板导出excel
     * <p>
     * 支持简易循环填写excel
     *
     * @param templatePath 模板路径
     * @param temporaryName 临时文件名称
     * @param out 文件输出流
     * @param head easyPoi 表头对象class
     * @param list 填充列表
     * @param col 导出类class
     * @param session session
     */
    public static void exportTemplate(String templatePath, String temporaryName, OutputStream out, Class head, Class col, List<? extends BaseRowModel> list, HttpSession session) {
        String path = null;
        try {
            InputStream resourceAsStream = col.getClassLoader().getResourceAsStream(templatePath);
            path = ExcelUtil.getFilePath(temporaryName, resourceAsStream, session);
            EasyExcel.write(out, head).needHead(false).withTemplate(path).sheet().doWrite(list);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {//删除临时文件
            if (path!=null && !"".equals(path)) {
                File tempFile = new File(path);
                tempFile.delete();
                System.err.println("删除临时文件成功=====path:" + path);
            }
        }
    }

    /**
     * 获取临时文件路径
     *
     * @param inputStream
     * @param session
     * @param fileName
     * @return
     * @throws IOException
     */
    public static String getFilePath(String fileName, InputStream inputStream, HttpSession session) throws IOException {
        // 模板临时目录
        String rootPath = session.getServletContext().getRealPath("template/");
        // 临时文件路径名
        String filePath = rootPath + "_" + System.currentTimeMillis() + fileName;
        File tempFile = new File(filePath);
        // 保存到临时文件
        saveTempFile(inputStream, tempFile);
        return filePath;
    }

    // 保存到临时目录
    private static void saveTempFile(InputStream inputStream, File tempFile) throws IOException {
        if (!tempFile.getParentFile().exists()) { //如果文件的目录不存在
            tempFile.getParentFile().mkdirs(); //创建目录
        }
        OutputStream os = new FileOutputStream(tempFile);
        byte[] b = new byte[2048];
        int length;
        while ((length = inputStream.read(b)) > 0) {
            os.write(b, 0, length);
        }
        os.flush();
        os.close();
        inputStream.close();
    }

}

导出结果:
在这里插入图片描述

注意事项:

获取到静态资源中模板文件路径的问题;

因为EasyExcel,不支持流的方式读取模板文件,所以我们必须要用路径的方式去获取路径。在本地运行时,使用相对路径或者绝对路径获取模板路径是可以的。但是当工程打成jar包之后,获取的路径无法支持。

所以我们这里使用的方案:通过流获取模板文件,重新写到本地临时文件中,获取模板,使用完模板之后,再将模板删除。

源码链接

官方文档地址

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值