SpringBoot使用Easypoi导出excel示例

        前面博主介绍了如何通过JXLS模板导出excel,如何通过POI直接导出excel;这里再介绍一种导出excel的方式:使用JueYue封装的工具类---Easypoi导出excel。

 

软硬件环境:Windows10、IntelliJ IDEA、SpringBoot 2.1.1.RELEASE

准备工作:在pom.xml中引入相关依赖

<!-- easy-poi -->
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-base</artifactId>
    <version>3.1.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-web</artifactId>
    <version>3.1.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-annotation</artifactId>
    <version>3.1.0</version>
</dependency>

 

先给出本人测试后的项目结构:

 

下面给出四种导出excel的用法示例:

示例一:直接将List<Map<String, Object>>数据导出为excel示例(无需模板):

/**
 * 直接导出(无需模板)
 * 注:此方式存在一些不足之处,在对性能、excel要求比较严格时不推荐使用
 *
 * @author JustryDeng
 * @date 2018/12/5 11:44
 */
@Test
public void directExportExcel() throws IOException {
    // Map作为每一行的数据容器,List作为行的容器
    List<Map<String, Object>> rowDataList = new ArrayList<>();
    // 每个ExcelExportEntity存放Map行数据的key
    List<ExcelExportEntity> keyList = new ArrayList<>();
    Map<String, Object> aRowMap;
    final int COMMON_KEY_INDEX = 10;
    for (int i = 0; i < 5; i++) {
        // 一个Map对应一行数据(如果需要导出多行数据,那么需要多个Map)
        aRowMap = new HashMap<>(16);
        for (int j = 0; j < COMMON_KEY_INDEX; j++) {
            String key = j + "";
            aRowMap.put(key, "坐标为(" + i + "," + j + ")");
        }
        rowDataList.add(aRowMap);
        // 同一列对应的cell,在从Map里面取值时,会共用同一个key
        // 因此ExcelExportEntity的个数要保持和列数做多的行 的map.size()大小一致
        if (i == 0) {
            ExcelExportEntity excelExportEntity;
            for (int j = 0; j < COMMON_KEY_INDEX; j++) {
                excelExportEntity = new ExcelExportEntity();
                excelExportEntity.setKey(j + "");
                // 设置cell宽
                excelExportEntity.setWidth(15D);
                // 设置cell是否自动换行
                excelExportEntity.setWrap(true);
                keyList.add(excelExportEntity);
            }
        }
    }
    // excel总体设置
    ExportParams exportParams = new ExportParams();
    // 不需要标题
    exportParams.setCreateHeadRows(false);
    // 指定sheet名字
    exportParams.setSheetName("直接导出数据测试");
    // 生成workbook 并导出
    Workbook workbook = ExcelExportUtil.exportExcel(exportParams, keyList, rowDataList);
    File savefile = new File("C:/Users/JustryDeng/Desktop/");
    if (!savefile.exists()) {
        boolean result = savefile.mkdirs();
        System.out.println("目录不存在,创建" + result);
    }
    FileOutputStream fos = new FileOutputStream("C:/Users/JustryDeng/Desktop/abc.xls");
    workbook.write(fos);
    fos.close();
}

运行测试函数,成功导出excel:

导出的excel内容为:


示例二:通过注解,直接将Object(集合)数据导出为excel示例(无需模板):

相关的SchoolVO模型为:

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

/**
 * 学校模型
 *
 * @author JustryDeng
 * @date 2018/12/8 17:12
 */
public class SchoolVO {

    /** 学校名称 */
    @Excel(name = "学校名称", orderNum = "6", width = 20)
    private String schoolName;

    /** 学校地址 */
    @Excel(name = "学校地址", orderNum = "8", width = 20)
    private String schoolAddress;

    public String getSchoolName() {
        return schoolName;
    }

    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }

    public String getSchoolAddress() {
        return schoolAddress;
    }

    public void setSchoolAddress(String schoolAddress) {
        this.schoolAddress = schoolAddress;
    }

    @Override
    public String toString() {
        return "SchoolVO{schoolName='" + schoolName + "', schoolAddress='" + schoolAddress + "'}";
    }
}

相关的StudentVO模型为:

import cn.afterturn.easypoi.excel.annotation.Excel;
import java.util.Date;

/**
 * Student数据模型
 *
 * @author JustryDeng
 * @date 2018/12/5 9:35
 */
public class StudentVO extends SchoolVO {

    /**
     * name指定导出excel时生成的列名
     * orderNum可指定导出的该属性对应的所在列的位置
     * width设置单元格宽度
     * type设置导出类型  1是文本, 2是图片, 3是函数,10 数字 默认是文本
     */
    @Excel(name = "学号", orderNum = "1", type = 10, width = 15)
    private String studentID;

    @Excel(name = "姓名", orderNum = "2", width = 15)
    private String name;

    /**
     * 当gender为1时,导出的结果为 男, 当gender为0时,导出的结果为 女
     * mergeVertical设置是否纵向合并列
     */
    @Excel(name = "性别",mergeVertical = true, replace = {"男_1", "女_0"},orderNum = "3", width = 5)
    private Integer gender;

    /**
     * type设置导出类型  1是文本, 2是图片, 3是函数,10 数字 默认是文本
     */
    @Excel(name = "年龄",orderNum = "4", type = 10, width = 5)
    private int age;

    /**
     * 将Data日期导出为yyyy-MM-dd格式
     * mergeVertical设置是否纵向合并列
     * mergeRely设置合并列的前提条件,即:只有当索引为2的列(即:"性别"列)已经
     *          合并了时,那么此时这一列的纵向相同时,才能纵向合并;如果引为2的
     *          列(即:"性别"列)纵向数据不同,那么就算此列的纵向数据相同,那么
     *          也不会合并
     */
    @Excel(name = "入校时间",mergeVertical = true, mergeRely = {2}, format = "yyyy-MM-dd", orderNum = "5", width = 20)
    private Date entranceTime;

    @Excel(name = "班级",orderNum = "7", width = 15)
    private String className;

    /**
     * 无参构造
     */
    public StudentVO() {
    }

    /**
     * 全参构造
     */
    public StudentVO(String studentID, String name, Integer gender,
                     int age, Date entranceTime, String className) {
        this.studentID = studentID;
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.entranceTime = entranceTime;
        this.className = className;
    }

    public String getStudentID() {
        return studentID;
    }

    public void setStudentID(String studentID) {
        this.studentID = studentID;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public Date getEntranceTime() {
        return entranceTime;
    }

    public void setEntranceTime(Date entranceTime) {
        this.entranceTime = entranceTime;
    }

    @Override
    public String toString() {
        return "StudentVO{studentID='" + studentID + "', name='" + name + "', gender='"
                   + gender + "', age=" + age + ", entranceTime=" + entranceTime
                       + ", className='" + className + "'}";
    }
}

导出excel的测试方法为:

/**
 * 对象---直接导出(无需模板)
 *
 * 注:如果模型 的父类的属性也有@Excel注解,那么导出excel时,会连该模型的父类的属性也一会儿导出
 *
 * @author JustryDeng
 * @date 2018/12/5 11:44
 */
@Test
public void directExportExcelByObject() throws IOException {
    List<StudentVO> list = new ArrayList<>(16);
    StudentVO student;
    Random random = new Random();
    for (int i = 0; i < 10; i++) {
        student = new StudentVO(i + "",
                "name" + i,
                random.nextInt(2),
                random.nextInt(100),
                new Date(),
                "className" + i);
        student.setSchoolName("学校名称" + i);
        student.setSchoolAddress("学校地址" +i);
        list.add(student);
    }
    ExportParams exportParams = new ExportParams();
    exportParams.setSheetName("我是sheet名字");
    // 生成workbook 并导出
    Workbook workbook = ExcelExportUtil.exportExcel(exportParams, StudentVO.class, list);
    File savefile = new File("C:/Users/JustryDeng/Desktop/");
    if (!savefile.exists()) {
        boolean result = savefile.mkdirs();
        System.out.println("目录不存在,创建" + result);
    }
    FileOutputStream fos = new FileOutputStream("C:/Users/JustryDeng/Desktop/student.xls");
    workbook.write(fos);
    fos.close();
}

运行测试函数,成功导出excel:

导出的excel内容为:


示例三:使用模板将Map<String, Object>数据导出为excel示例(需要模板):

模板为:

注:本文末尾,会简单介绍一下模板语法

模板位置在:

注:两个模板的内容是一样的,只是一个是xls,一个是xlsx,任选其一即可。

导出excel的测试方法为:

/**
 * 模板导出---Map组装数据
 *
 * 注:.xls的模板可以导出.xls文件,也可以导出xlsx的文件;
 *    同样的, .xlsx的模板可以导出.xls文件,也可以导出xlsx的文件;
 *
 * @author JustryDeng
 * @date 2018/12/5 11:44
 */
@Test
public void templateExportExcelByMap() throws IOException {
    // 加载模板
    TemplateExportParams params = new TemplateExportParams("templates/templateMap.xls");
    Map<String, Object> map = new HashMap<>(16);
    map.put("title", "全亚洲,最帅气人员名单");
    map.put("date", "2018-12-05");
    map.put("interviewer", "JustryDeng");
    List<Map<String, Object>> list = new ArrayList<>(16);
    Map<String, Object> tempMap;
    for (int i = 0; i < 5; i++) {
        tempMap = new HashMap<>();
        tempMap.put("name", "邓沙利文");
        tempMap.put("gender", new Random().nextInt(2) == 0 ? "男" : "女");
        tempMap.put("age", new Random().nextInt(90) + 11);
        tempMap.put("hobby", "活的,女的!!!");
        tempMap.put("handsomeValue", "100分(满分100分)");
        tempMap.put("motto", "只所以只帅到了全亚洲,是因为其他地方审美不同!");
        list.add(tempMap);
    }
    map.put("dataList", list);
    // 生成workbook 并导出
    Workbook workbook = ExcelExportUtil.exportExcel(params, map);
    File savefile = new File("C:/Users/JustryDeng/Desktop/");
    if (!savefile.exists()) {
        boolean result = savefile.mkdirs();
        System.out.println("目录不存在,进行创建,创建" + (result ? "成功!" : "失败!"));
    }
    FileOutputStream fos = new FileOutputStream("C:/Users/JustryDeng/Desktop/templateMapResult.xlsx");
    workbook.write(fos);
    fos.close();
}

运行测试函数,成功导出excel:

导出的excel内容为:


示例四:使用模板将Object数据导出为excel示例(需要模板):

模板为:

:本文末尾,会简单介绍一下模板语法

模板位置在:

注:两个模板的内容是一样的,只是一个是xls,一个是xlsx,任选其一即可。

相关模型有HandsomeBoyPOJO:

/**
 * 具体信息 模型
 *
 * @author JustryDeng
 * @date 2018/12/5 16:57
 */
public class HandsomeBoyPOJO {

    /** 姓名 */
    private String name;

    /** 性别 */
    private String gender;

    /** 年龄 */
    private int age;

    /** 爱好 */
    private String hobby;

    /** 帅气值 */
    private String handsomeValue;

    /** 座右铭 */
    private String motto;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }

    public String getHandsomeValue() {
        return handsomeValue;
    }

    public void setHandsomeValue(String handsomeValue) {
        this.handsomeValue = handsomeValue;
    }

    public String getMotto() {
        return motto;
    }

    public void setMotto(String motto) {
        this.motto = motto;
    }

    @Override
    public String toString() {
        return "HandsomeBoyPOJO{name='" + name + "', gender='" + gender + "', age=" + age
                + ", hobby='" + hobby + "', handsomeValue='" + handsomeValue + "', motto='" + motto + "'}";
    }
}

相关模型有ResultPOJO:

/**
 * 采访结果 模型
 *
 * @author JustryDeng
 * @date 2018/12/5 17:01
 */
public class ResultPOJO {

    /** 标题 */
    private String title;

    /** 日期 */
    private String date;

    /** 采访人 */
    private String interviewer;

    /** 信息集合 */
    private List<HandsomeBoyPOJO> list;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getInterviewer() {
        return interviewer;
    }

    public void setInterviewer(String interviewer) {
        this.interviewer = interviewer;
    }

    public List<HandsomeBoyPOJO> getList() {
        return list;
    }

    public void setList(List<HandsomeBoyPOJO> list) {
        this.list = list;
    }

    @Override
    public String toString() {
        return "ResultPOJO{title='" + title + "', date='" + date + "', interviewer='" + interviewer
                + "', list=" + list + '}';
    }
}

导出excel的测试方法为:

/**
 * 模板导出---对象组装数据
 *
 * 注:实际上仍然是"模板导出---Map组装数据",不过这里借助了工具类,将对象先转换为了Map<String, Object>
 *
 * 注:.xls的模板可以导出.xls文件,也可以导出xlsx的文件;
 *    同样的, .xlsx的模板可以导出.xls文件,也可以导出xlsx的文件;
 *
 * @author JustryDeng
 * @date 2018/12/5 11:44
 */
@Test
public void templateExportExcelByObject() throws IOException, IllegalAccessException {
    // 加载模板
    TemplateExportParams params = new TemplateExportParams("templates/templateObject.xlsx");
    // 组装数据
    ResultPOJO resultPOJO = new ResultPOJO();
    resultPOJO.setTitle("全亚洲最帅人员名单");
    resultPOJO.setInterviewer("邓沙利文");
    resultPOJO.setDate("2018-12-05");
    List<HandsomeBoyPOJO> list = new ArrayList<>(8);
    resultPOJO.setList(list);
    HandsomeBoyPOJO handsomeBoyPOJO;
    for (int i = 0; i < 5; i++) {
        handsomeBoyPOJO = new HandsomeBoyPOJO();
        handsomeBoyPOJO.setAge(20 + i);
        handsomeBoyPOJO.setGender(i % 2 == 0 ? "女" : "男");
        handsomeBoyPOJO.setHandsomeValue(95 + i + "(满分100分)");
        handsomeBoyPOJO.setHobby("女。。。。");
        handsomeBoyPOJO.setMotto("我是一只小小小小鸟~");
        handsomeBoyPOJO.setName("JustryDeng");
        list.add(handsomeBoyPOJO);
    }
    // 生成workbook 并导出
    Workbook workbook = ExcelExportUtil.exportExcel(params, objectToMap(resultPOJO));
    File savefile = new File("C:/Users/JustryDeng/Desktop/");
    if (!savefile.exists()) {
        boolean result = savefile.mkdirs();
        System.out.println("目录不存在,进行创建,创建" + (result ? "成功!" : "失败!"));
    }
    FileOutputStream fos = new FileOutputStream("C:/Users/JustryDeng/Desktop/templateObjectResult.xls");
    workbook.write(fos);
    fos.close();
}

/**
 * 对象转换为Map<String, Object>的工具类
 *
 * @param obj
 *            要转换的对象
 * @return map
 * @throws IllegalAccessException
 */
private static Map<String, Object> objectToMap(Object obj) throws IllegalAccessException {
    Map<String, Object> map = new HashMap<>(16);
    Class<?> clazz = obj.getClass();
    for (Field field : clazz.getDeclaredFields()) {
        field.setAccessible(true);
        String fieldName = field.getName();
        /*
         * Returns the value of the field represented by this {@code Field}, on the
         * specified object. The value is automatically wrapped in an object if it
         * has a primitive type.
         * 注:返回对象该该属性的属性值,如果该属性的基本类型,那么自动转换为包装类
         */
        Object value = field.get(obj);
        map.put(fieldName, value);
    }
    return map;
}

运行测试函数,成功导出excel:

导出的excel内容为:

 

模板标签语法(摘取自http://easypoi.mydoc.io/):

注:上表中的标签语法,本人只亲测了一部分。

 

笔者个人看法:

>  在方便程度方面:Easypoi    >=    JXLS    >    POI

      注:有时,方便程度 Easypoi    ≈    JXLS

>  在性能方面:        POI    >    Easypoi    >=    JXLS

      注:灵活使用即可。

 

微笑如有不当之处,欢迎指正
微笑参考链接:
         
 http://easypoi.mydoc.io/
           https://blog.csdn.net/zbx931197485/article/details/79524073
微笑测试代码托管链接:
           
https://github.com/JustryDeng/CommonRepository
微笑本文已经被收录进《程序员成长笔记(四)》,笔者JustryDeng

猜你喜欢

转载自blog.csdn.net/justry_deng/article/details/84842111