EasyExcel ----- 实现数据库数据 导出为Excel表和Excel表导入数据功能

一、EasyExcel简介

        Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到KB级别,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便。

       EasyExcel阿里官方文档:https://github.com/alibaba/easyexcel

二、EasyExcel的简单使用

1、搭建EasyExcel项目环境

1.1、添加EasyExcel所需依赖

<properties>
    <poi.version>3.17</poi.version>
    <spring.version>5.1.5.RELEASE</spring.version>
</properties>

<dependencies>
    <!-- ******************** EasyExcel依赖包 开始 ******************** -->
    <!-- xls格式 excel依赖包 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>${poi.version}</version>
    </dependency>
    
    <!--xlsx格式 excel依赖包-->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>${poi.version}</version>
    </dependency>
       
    <!-- EasyExcel依赖包 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>easyexcel</artifactId>
        <version>1.1.2-beta5</version>
     </dependency>
     <!-- ******************** EasyExcel依赖包 结束 ******************** -->
     
     <!-- MySql驱动 -->
     <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
         <version>5.1.47</version>
     </dependency>

     <!-- Druid连接池 -->
     <dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>druid</artifactId>
         <version>1.1.10</version>
     </dependency>
     
     <!-- Mybatis -->
     <dependency>
         <groupId>org.mybatis</groupId>
         <artifactId>mybatis</artifactId>
         <version>3.4.6</version>
     </dependency>
     <dependency>
         <groupId>org.mybatis</groupId>
         <artifactId>mybatis-spring</artifactId>
         <version>1.3.2</version>
     </dependency>

     <!-- Lombok -->
     <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <version>1.16.20</version>
         <scope>provided</scope>
     </dependency>
     
     <!-- javax.servlet-api -->
     <dependency>
         <groupId>javax.servlet</groupId>
         <artifactId>javax.servlet-api</artifactId>
         <version>3.1.0</version>
         <scope>provided</scope>
     </dependency>

     <!-- Spring -->
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context</artifactId>
         <version>${spring.version}</version>
     </dependency>
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-beans</artifactId>
         <version>${spring.version}</version>
     </dependency>
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-webmvc</artifactId>
         <version>${spring.version}</version>
     </dependency>
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-jdbc</artifactId>
         <version>${spring.version}</version>
     </dependency>
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-aspects</artifactId>
         <version>${spring.version}</version>
     </dependency>
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-jms</artifactId>
         <version>${spring.version}</version>
     </dependency>
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context-support</artifactId>
         <version>${spring.version}</version>
     </dependency>
     
     <!-- junit单元测试 -->
     <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.11</version>
         <scope>test</scope>
     </dependency>

</dependencies>

      
     <!-- 打包资源文件 -->
     <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>

1.2、设计并创建对应的user数据库表

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(11) DEFAULT NULL,
  `sex` varchar(3) DEFAULT NULL,
  `age` int(4) DEFAULT NULL,
  `birthday` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

1.3、在resources资源目录下,创建一个properties目录,并创建和编写jdbc.properties配置文件,设置jdbc连接数据库的四个参数

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/easy_excel?rewriteBatchedStatements=true&allowMultiQueries=true&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&useSSL=false
jdbc.username=root
jdbc.password=123456

---------------------------mysql 连接数据库参数设置介绍

//设置JDBC驱动批量执行SQL
rewriteBatchedStatements=true 

//设置允许JDBC连接能够一次执行多条增删改查操作,假如没配这个参数的话,所有批量操作都会报错。
allowMultiQueries=true       

//指定字符的编码、解码格式
useUnicode=true&characterEncoding=utf-8  

//在使用数据库连接池的情况下,最好设置如下两个参数
autoReconnect=true  //当数据库连接异常中断时,自动重新连接
failOverReadOnly=false   //自动重连成功后,连接是否设置为只读

//设置关闭SSL连接
useSSL=false

1.4、在resources资源目录下,创建一个spring目录,并创建和编写applicationContext-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	   http://www.springframework.org/schema/context
	   http://www.springframework.org/schema/context/spring-context-4.2.xsd
	   http://www.springframework.org/schema/tx
	   http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

    <!-- 配置包扫描器,扫描注解的类 -->
    <context:component-scan base-package="com.easyexcel.service"/>

    <!-- 加载配置文件 -->
    <context:property-placeholder location="classpath:properties/jdbc.properties" />
    <!-- 数据库连接池 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="driverClassName" value="${jdbc.driver}" />
        <property name="maxActive" value="10" />
        <property name="minIdle" value="5" />
    </bean>

    <!-- 让spring管理sqlsessionfactory 使用mybatis和spring整合包中的 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 数据库连接池 -->
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- MapperScannerConfigurer 自动扫描将Mapper接口生成代理注入到spring -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--basePackage指定要扫描的包,在此包之下的映射器都会被搜索到。可指定多个包,包与包之间用逗号或分号分隔-->
        <property name="basePackage" value="com.easyexcel.mapper" />
    </bean>

    <!-- 事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 数据源 -->
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 传播行为 -->
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="create*" propagation="REQUIRED" />
            <tx:method name="delete*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="select*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
        </tx:attributes>
    </tx:advice>
    <!-- 切面 -->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.easyexcel.service.*.*(..))" />
    </aop:config>

</beans>

2、使用EasyExcel导入、导出带有表头注解的Java实体类模型的Excel

2.1、编写与数据库表对应的带有表头注解的实体类模型 (需要继承BaseRowModel类)

package com.easyexcel.pojo;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.metadata.BaseRowModel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

import java.io.Serializable;
import java.util.Date;

@Getter
@Setter
@ToString
@NoArgsConstructor
public class User extends BaseRowModel implements Serializable {

    /**
     * @ExcelProperty(value = "表头名称",index = 0,format = "yyyy-MM-dd")
     * value是表头数据,默认会写在excel的表头位置
     * index代表第几列,从0开始
     * format表示时间日期输出到Excel表中的格式
     */
    @ExcelProperty(value="主键id",index=0)
    private Integer id;
    @ExcelProperty(value="姓名",index=1)
    private String name;
    @ExcelProperty(value="性别",index=2)
    private String sex;
    @ExcelProperty(value="年龄",index=3)
    private Integer age;
    @ExcelProperty(value="生日",index=4,format="yyyy-MM-dd")
    private Date birthday;

    private static final long serialVersionUID = 1L;

}

2.2、编写与数据库交互的UserMapper接口

package com.easyexcel.mapper;

import com.easyexcel.pojo.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface UserMapper {

    /**
     * 查询所有用户信息
     * @return List<User>
     */
    List<User> selectAllOfUser();

    /**
     * 批量插入所有用户信息
     * @param users 用户信息集合
     * @return int
     */
    int insertAllOfUser(@Param("users") List<User> users);

}

2.3、编写与UserMapper接口对应的UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.easyexcel.mapper.UserMapper" >
  <resultMap id="BaseResultMap" type="com.easyexcel.pojo.User" >
    <id column="id" property="id" jdbcType="INTEGER" />
    <result column="name" property="name" jdbcType="VARCHAR" />
    <result column="sex" property="sex" jdbcType="VARCHAR" />
    <result column="age" property="age" jdbcType="INTEGER" />
    <result column="birthday" property="birthday" jdbcType="DATE" />
  </resultMap>

  <sql id="Base_Column_List" >
    id, name, sex, age, birthday
  </sql>

  <select id="selectAllOfUser" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from user
  </select>

  <insert id="insertAllOfUser" parameterType="com.easyexcel.pojo.User" >
    insert into user 
    (<include refid="Base_Column_List" />)
    values
    <foreach collection="users" item="user" separator=",">
      (#{user.id},#{user.name},#{user.sex},#{user.age},#{user.birthday})
    </foreach>
  </insert>
  
</mapper>

2.4、编写UserService接口

package com.easyexcel.service;

import com.easyexcel.pojo.User;
import java.util.List;

public interface UserService {

    /**
     * 查询所有用户信息
     *
     * @return List<User> User实体类对象集合
     */
    List<User> selectAllOfUser();

    /**
     * 批量插入所有用户信息
     *
     * @param users 用户信息集合
     * @return int 影响行数
     */
    int insertAllOfUser(List<User> users);

}

2.5、编写UserService接口的实现类UserServiceImpl

package com.easyexcel.service.impl;

import com.easyexcel.mapper.UserMapper;
import com.easyexcel.pojo.User;
import com.easyexcel.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;


@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public List<User> selectAllOfUser() {
        return userMapper.selectAllOfUser();
    }

    @Override
    public int insertAllOfUser(List<User> users) {
        return userMapper.insertAllOfUser(users);
    }
}

2.6、编写ExcelException异常处理器

package com.easyexcel.exception;

public class ExcelException extends RuntimeException{

    public ExcelException(String message){
        super(message);
    }
}

2.7、编写ExcelListener监听类

package com.easyexcel.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;

import java.util.ArrayList;
import java.util.List;


public class ExcelListener extends AnalysisEventListener{

    /**
     *  自定义用于暂时存储data。
     *  可以通过实例获取该值
     */
    private List<Object> datas = new ArrayList<Object>();

    @Override
    public void invoke(Object object, AnalysisContext analysisContext) {

        System.out.println("当前行:"+ analysisContext.getCurrentRowNum());
        System.out.println(object);
        //数据存储到list,供批量处理,或后续自己业务逻辑处理。
        datas.add(object);
        //根据自己业务做处理
        doSomething(object);

    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
         //解析结束销毁不用的资源
        // datas.clear();
    }

    public List<Object> getDatas() {
        return datas;
    }

    public void setDatas(List<Object> datas) {
        this.datas = datas;
    }

    private void doSomething(Object object){
        //入库调用接口
    }
}

2.8、编写ExcelUtils工具类,可以直接调用该工具类的方法完成 Excel 的导入或者导出

package com.easyexcel.utils;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.easyexcel.exception.ExcelException;
import com.easyexcel.listener.ExcelListener;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;


public class ExcelUtils {

    //--------------------------------------------导入Excel--------------------------------------------

    /**
     * 读取带有表头注解的Java实体类模型
     * 读取多个sheet 的Excel
     *
     * @param inputStream 字节输入流
     * @param clazz 类的字节码文件对象
     * @return List<?> 实体对象集合
     */
    public static List<?> readExcel(InputStream inputStream, Class clazz){

        BufferedInputStream bufferedInputStream = null;
        ExcelListener excelListener = null;

        try {
            //包装成缓冲字节输入流
            bufferedInputStream = new BufferedInputStream(inputStream);
            //解析Excel表格的每行数据
            excelListener = new ExcelListener();
            //读取Excel表格数据
            ExcelReader excelReader = EasyExcelFactory.getReader(bufferedInputStream,excelListener);
            //循环读取多个Sheet
            for(Sheet sheet : excelReader.getSheets()){
                  sheet.setClazz(clazz);
                  excelReader.read(sheet);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭缓冲字节输入流,释放资源
            if(bufferedInputStream != null){
                try {
                    bufferedInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return excelListener.getDatas();

    }


    /**
     * 读取带有表头注解的Java实体类模型
     * 读取单个指定sheet 的Excel
     *
     * @param inputStream 字节输入流
     * @param clazz 类的字节码文件对象
     * @param sheetNo sheet的序号 默认从1开始
     * @return List<?> 实体对象集合
     */
    public static List<?> readExcel(InputStream inputStream, Class clazz, int sheetNo){
       return readExcel(inputStream,clazz,sheetNo,1);
    }


    /**
     * 读取带有表头注解的Java实体类模型
     * 读取单个指定sheet和headLineNum 的Excel
     *
     * @param inputStream 字节输入流
     * @param clazz 类的字节码文件对象
     * @param sheetNo sheet的序号 默认从1开始
     * @param headLineNum 实体对象集合 默认从1开始
     * @return List<?> 实体对象集合
     */
    public static List<?> readExcel(InputStream inputStream, Class clazz, int sheetNo, int headLineNum){

        BufferedInputStream bufferedInputStream = null;
        ExcelListener excelListener = null;

        try {
            //包装成缓冲字节输入流
            bufferedInputStream = new BufferedInputStream(inputStream);
            //解析Excel表格的每行数据
            excelListener = new ExcelListener();
            //读取Excel表格数据
            ExcelReader excelReader = EasyExcelFactory.getReader(bufferedInputStream,excelListener);
            excelReader.read(new Sheet(sheetNo,headLineNum,clazz));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭缓冲字节输入流,释放资源
            if(bufferedInputStream != null){
                try {
                    bufferedInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return excelListener.getDatas();
    }


    
    
    
    //--------------------------------------------导出Excel--------------------------------------------

    /**
     * 判断上传的Excel文件是否符合格式要求
     *
     * @param excel 上传的Excel文件
     * @return boolean true表示符合文件格式要求,false表示不符合文件格式要求
     */
    public static boolean  determineExcelIsFormatted(MultipartFile excel){

        //获取文件名
        String fileName = excel.getOriginalFilename();
        //判断文件名是否符合文件格式
        boolean flag = (fileName == null || (!fileName.toLowerCase().endsWith(".xls") && !fileName.toLowerCase().endsWith(".xlsx")));

        if(flag){
            return false;
        }

        return true;
    }
    

    /**
     * 设置文件响应信息,并返回字节输出流
     *
     * @param fileName 文件名
     * @param response HttpServletResponse响应
     * @return OutputStream 字节输出流
     */
    public static OutputStream setResponse(String fileName, HttpServletResponse response){

        try {
            //设置文件名
            fileName = new String((fileName +" "+ new SimpleDateFormat("yyyy-MM-dd").format(new Date()))
                    .getBytes(),"UTF-8");
            //设置文件ContentType类型
            response.setContentType("multipart/form-data");
            //设置服务器响应数据的编码
            response.setCharacterEncoding("utf-8");
            //设置文件头
            response.setHeader("Content-disposition", "attachment;filename="+fileName+".xlsx");
            return response.getOutputStream();
        } catch (IOException e) {
           throw new ExcelException("创建文件失败!");
        }

    }

    /**
     * 导出带有表头注解的Java实体类模型
     * 导出单个sheet 的Excel,带表头
     *
     * @param outputStream 字节输出流
     * @param clazz 类的字节码文件对象
     * @param data 实体对象集合
     */
    public static void writeExcel(OutputStream outputStream, Class clazz, List<? extends BaseRowModel> data){
         writeExcel(outputStream,clazz,"User表格",data);
    }


    /**
     * 导出带有表头注解的Java实体类模型
     * 导出单个sheet 的Excel,带表头,可自定义sheet表格名称
     *
     * @param outputStream 字节输出流
     * @param clazz 类的字节码文件对象
     * @param sheetName sheet表格名称
     * @param data 实体对象集合
     */
    public static void writeExcel(OutputStream outputStream, Class clazz, String sheetName, List<? extends BaseRowModel> data){

        BufferedOutputStream bufferedOutputStream = null;

        try {
            //包装成缓冲字节输入流
            bufferedOutputStream = new BufferedOutputStream(outputStream);
            //包装成缓冲字节输入流
            ExcelWriter writer = EasyExcelFactory.getWriter(outputStream);
            //创建sheet表格,并设置表格名称
            Sheet sheet = new Sheet(1, 0, clazz);
            sheet.setSheetName(sheetName);
            //设置自适应宽度
            sheet.setAutoWidth(Boolean.TRUE);
            //把数据写入表格
            writer.write(data,sheet);
            writer.finish();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭缓冲字节输出流,释放资源
            if(bufferedOutputStream != null){
                try {
                    bufferedOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
}

2.9、准备Excel表格数据 (因为数据库表字段id,我设置为 int自增类型,所以主键id这一列我们不设置值)

主键id 姓名 性别 年龄 生日
  曾华 42 1977-09-01
  匡明 44 1975-10-02
  王丽 43 1976-01-23
  李军 43 1976-02-20
  王芳 44 1975-02-10
  陆君 45 1974-06-03
  李诚 61 1958-12-02
  张旭 50 1969-03-12
  王萍 47 1972-05-05
  刘冰 42 1977-08-14

2.10、编写带有表头注解的Java实体类模型的测试用例

package com.easyexcel.test;

import com.easyexcel.pojo.User;
import com.easyexcel.service.UserService;
import com.easyexcel.utils.ExcelUtils;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.*;
import java.util.List;

public class EasyExcelTest {

    private UserService userService;

    @Before
    public void init() {

        //读取applicationContext-spring.xml配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/applicationContext-spring.xml");
        //获取Spring容器中已初始化的UserServiceImpl实例对象
        userService = (UserService) context.getBean("userServiceImpl");
    }


    /**
     * 读取带有表头注解的Java实体类模型
     * 读取单个指定sheet 的Excel,并导入到数据库中
     */
    @Test
    public void readExcel() {

        InputStream fileInputStream = null;
        try {
            //读取user.xlsx表格,获得文件输入流
            fileInputStream = new FileInputStream("G:/user.xlsx");
            //获得User实体类对象集合
            List<User> users = (List<User>) ExcelUtils.readExcel(fileInputStream, User.class, 1);
            //批量插入到数据库user表中
            userService.insertAllOfUser(users);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            //关闭文件输入流,释放资源
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 导出带有表头注解的Java实体类模型
     * 导出单个sheet 的Excel,带表头
     */
    @Test
    public void writeExcel() {

        FileOutputStream fileOutputStream = null;
        try {
            //获取文件输出流
            fileOutputStream = new FileOutputStream("G:/create_user.xlsx");
            //获得User实体类对象集合
            List<User> users = userService.selectAllOfUser();
            //把数据写入到指定的Excel表格中
            ExcelUtils.writeExcel(fileOutputStream, User.class, users);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {

            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

2.11、测试结果如下图所示

导入结果图:

导出结果图:

2.12、如果想通过Java实体类模型生成如下多层级表头

Java实体类模型写法如下:

public class MultiLineHeadExcelModel extends BaseRowModel {

    @ExcelProperty(value = {"表头1","表头1","表头31"},index = 0)
    private String p1;

    @ExcelProperty(value = {"表头1","表头1","表头32"},index = 1)
    private String p2;

    @ExcelProperty(value = {"表头3","表头3","表头3"},index = 2)
    private int p3;

    @ExcelProperty(value = {"表头4","表头4","表头4"},index = 3)
    private long p4;

    @ExcelProperty(value = {"表头5","表头51","表头52"},index = 4)
    private String p5;

    @ExcelProperty(value = {"表头6","表头61","表头611"},index = 5)
    private String p6;

    @ExcelProperty(value = {"表头6","表头61","表头612"},index = 6)
    private String p7;

    @ExcelProperty(value = {"表头6","表头62","表头621"},index = 7)
    private String p8;

    @ExcelProperty(value = {"表头6","表头62","表头622"},index = 8)
    private String p9;
}

2.13、Controller层 编写Excel文件导入、模板导出 和 数据导出方法

package com.easyexcel.controller;

import com.easyexcel.Exception.ExcelException;
import com.easyexcel.pojo.User;
import com.easyexcel.service.UserService;
import com.easyexcel.utils.ExcelUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

@Controller
public class ExcelController {

    @Autowired
    private UserService userService;

    /**
     * 导入带有表头注解的Java实体类模型
     * 导入单个Excel表
     * 
     * @param excel 上传的Excel文件
     */
    @RequestMapping(value="/uploadExcel")
    public void uploadExcel(@RequestParam(value="file") MultipartFile excel){

        InputStream inputStream = null;

        try {
            //判断文件后缀是否以.xls 或者 .xlsx 结尾
            boolean flag = ExcelUtils.determineExcelIsFormatted(excel);
            if (!flag){
                throw new ExcelException("文件格式有误");
            }

            //获取文件输入流
            inputStream = excel.getInputStream();
            //获得User实体类对象集合
            List<User> users = (List<User>) ExcelUtils.readExcel(inputStream, User.class, 1);
            //批量插入到数据库user表中
            userService.insertAllOfUser(users);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭字节输入流,释放资源
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    
    /**
     * 导出带有表头注解的Java实体类模型
     * 导出模板,用于填写导入数据
     * 
     * @param response HttpServletResponse响应
     */
    @RequestMapping(value="/downLoadExcelTemplate")
    public void downLoadExcelTemplate(HttpServletResponse response){
        //设置Excel表的名称
        String fileName = "User导入模板";
        //设置文件响应信息,并获得字节输出流
        OutputStream outputStream = ExcelUtils.setResponse(fileName, response);
        //把数据写入到Excel表格中
        ExcelUtils.writeExcel(outputStream,User.class,null);

        //关闭字节输入流,释放资源
        if(outputStream != null){
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    
    /**
     * 导出Excel数据表文件
     * 
     * @param response HttpServletResponse响应
     */
    @RequestMapping(value="/downLoadExcel")
    public void downLoadExcel(HttpServletResponse response){

        //设置Excel表的名称
        String fileName = "User信息详情";
        //获得User实体类对象集合
        List<User> users = userService.selectAllOfUser();
        //设置文件响应信息,并获得字节输出流
        OutputStream outputStream = ExcelUtils.setResponse(fileName, response);
        //把数据写入到Excel表格中
        ExcelUtils.writeExcel(outputStream,User.class,users);

        //关闭字节输入流,释放资源
        if(outputStream != null){
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

3、使用EasyExcel导入、导出带有表头的无注解模型映射关系的数据模型的Excel

3.1、在ExcelUtils工具类中添加如下方法 (由于导入可以直接调用带有表头注解的Java实体类模型的导入方法,这里就不在陈述)

    /**
     * 导出带有表头的无注解模型映射关系的数据模型
     * 导出单个sheet 的Excel,带表头
     *
     * @param outputStream 字节输出流
     * @param data         实体对象集合
     * @param head         表头
     */
    public static void writeExcelWithOutJavaModel(OutputStream outputStream, List<List<Object>> data, List<List<String>> head) {
        writeExcelWithOutJavaModel(outputStream, "Data表格", data, head);
    }


    /**
     * 导出带有表头的无注解模型映射关系的数据模型
     * 导出单个sheet 的Excel,带表头,可自定义sheet表格名称
     *
     * @param outputStream 字节输出流
     * @param sheetName    sheet表格名称
     * @param data         实体对象集合
     */
    public static void writeExcelWithOutJavaModel(OutputStream outputStream, String sheetName, List<List<Object>> data, List<List<String>> head) {

        BufferedOutputStream bufferedOutputStream = null;

        try {
            //包装成缓冲字节输入流
            bufferedOutputStream = new BufferedOutputStream(outputStream);
            //包装成缓冲字节输入流
            ExcelWriter writer = EasyExcelFactory.getWriter(outputStream);
            //创建sheet表格,并设置表格名称
            Sheet sheet = new Sheet(1, 0);
            sheet.setSheetName(sheetName);
            //设置自适应宽度
            sheet.setAutoWidth(Boolean.TRUE);

            //无注解模型映射关系的数据模型,动态添加表头
            Table table = new Table(1);
            table.setHead(head);

            //把数据写入表格,如果数据类型是List<List<String>>,请使用writer.write0(data, sheet)进行数据写入
            writer.write1(data, sheet, table);
            writer.finish();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭缓冲字节输出流,释放资源
            if (bufferedOutputStream != null) {
                try {
                    bufferedOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

3.2、编写带有表头的无注解模型映射关系的数据模型的测试用例

package com.easyexcel.test;

import com.easyexcel.utils.ExcelUtils;
import org.junit.Test;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class EasyExcelTest {

    /**
     * 读取带有表头的无注解模型映射关系的数据模型
     * 单个指定sheet 的Excel,并导入到数据库中
     */
    @Test
    public void readExcelWithOutJavaModel() {

        InputStream fileInputStream = null;
        try {
            //读取data.xlsx表格,获得文件输入流
            fileInputStream = new FileInputStream("G:/data.xlsx");
            //获得dataList集合对象,注意:无注解模型映射关系的数据模型在读取Excel时,其Class参数传null就行
            List<List<Object>> dataList = (List<List<Object>>) ExcelUtils.readExcel(fileInputStream, null, 1);
            //循环打印获取到的dataList集合对象
            for (List<Object> list : dataList) {
                System.out.println(list);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            //关闭文件输入流,释放资源
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 导出带有表头的无注解模型映射关系的数据模型
     * 单个sheet 的Excel,带表头
     */
    @Test
    public void writeExcelWithOutJavaModel() {

        FileOutputStream fileOutputStream = null;
        try {
            //获取文件输出流
            fileOutputStream = new FileOutputStream("G:/create_data.xlsx");
            //动态创建数据,注意创建的数据类型是List<List<Object>>
            List<List<Object>> rows = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                List<Object> row = new ArrayList<>();
                row.add("2015435040" + i);
                row.add("李四--" + i);
                row.add(Integer.valueOf(10 + i));
                row.add("男");
                row.add("博客:浅末年华");
                rows.add(row);
            }

            //无注解模型映射关系的数据模型,动态创建表头数据
            List<List<String>> head = createTestListStringHead();

            //把数据写入到指定的Excel表格中
            ExcelUtils.writeExcelWithOutJavaModel(fileOutputStream, rows, head);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {

            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 无注解模型映射关系的数据模型,动态创建表头数据
     *
     * @return List<List<String>> 表头
     */
    public static List<List<String>> createTestListStringHead() {
        //无注解模型映射关系的数据模型,动态创建表头数据
        List<List<String>> head = new ArrayList<List<String>>();
        List<String> headCoulumn1 = new ArrayList<String>();
        List<String> headCoulumn2 = new ArrayList<String>();
        List<String> headCoulumn3 = new ArrayList<String>();
        List<String> headCoulumn4 = new ArrayList<String>();
        List<String> headCoulumn5 = new ArrayList<String>();

        headCoulumn1.add("第一列");headCoulumn1.add("第一列");headCoulumn1.add("第一列");
        headCoulumn2.add("第一列");headCoulumn2.add("第一列");headCoulumn2.add("第一列");
        headCoulumn3.add("第二列");headCoulumn3.add("第二列");headCoulumn3.add("第二列");
        headCoulumn4.add("第三列1");headCoulumn4.add("第三列2");headCoulumn4.add("第三列2");
        headCoulumn5.add("第四列");headCoulumn5.add("第四列1");headCoulumn5.add("第四列2");

        head.add(headCoulumn1);
        head.add(headCoulumn2);
        head.add(headCoulumn3);
        head.add(headCoulumn4);
        head.add(headCoulumn5);
        return head;
    }

}

4、EasyExcel自定义导出带有表头注解的Java实体类模型的表头以及内容样式的Excel

方式一:通过调用Table类中的 setTableStyle(TableStyle tableStyle) 来设置表头以及内容样式

4.1、在ExcelUtils工具类中添加如下方法

    /**
     * 导出带有表头注解的Java实体类模型
     * 导出单个sheet 的Excel,带表头,可自定义sheet表格名称 和 Excel表格样式
     *
     * @param outputStream 字节输出流
     * @param clazz        类的字节码文件对象
     * @param sheetName    sheet表格名称
     * @param data         实体对象集合
     * @param tableStyle   Excel表格样式
     */
    public static void writeExcelWithStyle(OutputStream outputStream, Class clazz, String sheetName, List<? extends BaseRowModel> data, TableStyle tableStyle) {

        BufferedOutputStream bufferedOutputStream = null;

        try {
            //包装成缓冲字节输入流
            bufferedOutputStream = new BufferedOutputStream(outputStream);
            //包装成缓冲字节输入流
            ExcelWriter writer = EasyExcelFactory.getWriter(outputStream);
            //创建sheet表格,并设置表格名称
            Sheet sheet = new Sheet(1, 0, clazz);
            sheet.setSheetName(sheetName);
            //设置自适应宽度
            sheet.setAutoWidth(Boolean.TRUE);

            //设置Excel表格样式
            Table table = new Table(0);
            table.setTableStyle(tableStyle);
            table.setClazz(clazz);

            //把数据写入表格
            writer.write(data, sheet, table);
            writer.finish();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭缓冲字节输出流,释放资源
            if (bufferedOutputStream != null) {
                try {
                    bufferedOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

4.2、编写导出带有表头注解的Java实体类模型的测试用例

package com.easyexcel.test;

import com.alibaba.excel.metadata.Font;
import com.alibaba.excel.metadata.TableStyle;
import com.easyexcel.pojo.User;
import com.easyexcel.service.UserService;
import com.easyexcel.utils.ExcelUtils;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.*;
import java.util.List;

public class EasyExcelTest {

    private UserService userService;

    @Before
    public void init() {

        //读取applicationContext-spring.xml配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/applicationContext-spring.xml");
        //获取Spring容器中已初始化的UserServiceImpl实例对象
        userService = (UserService) context.getBean("userServiceImpl");
    }

    /**
     * 导出带有表头注解的Java实体类模型
     * 导出单个sheet 的Excel,带表头和表格样式
     */
    @Test
    public void writeExcelWithStyle() {

        FileOutputStream fileOutputStream = null;
        try {
            //获取文件输出流
            fileOutputStream = new FileOutputStream("G:/create_user.xlsx");
            //获得User实体类对象集合
            List<User> users = userService.selectAllOfUser();
            //自定义表格样式
            TableStyle tableStyle = createTableStyle();
            //把数据写入到指定的Excel表格中
            ExcelUtils.writeExcelWithStyle(fileOutputStream, User.class, "User表格",users,tableStyle);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {

            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 自定义表格样式
     */
    public static TableStyle createTableStyle() {
        TableStyle tableStyle = new TableStyle();
        // 设置表头样式
        Font headFont = new Font();
        // 字体是否加粗
        headFont.setBold(true);
        // 字体大小
        headFont.setFontHeightInPoints((short)12);
        // 字体
        headFont.setFontName("楷体");
        tableStyle.setTableHeadFont(headFont);
        // 背景色
        tableStyle.setTableHeadBackGroundColor(IndexedColors.BLUE);


        // 设置表格内容样式
        Font contentFont = new Font();
        contentFont.setBold(true);
        contentFont.setFontHeightInPoints((short)12);
        contentFont.setFontName("黑体");
        tableStyle.setTableContentFont(contentFont);
        tableStyle.setTableContentBackGroundColor(IndexedColors.GREEN);
        return tableStyle;
    }
    
}

4.3、测试导出Excel结果如下图所示

方式二:通过实现WriterHandler接口来实现自定义表头以及内容样式,WriterHandler接口中定义了如下三个方法:

void sheet(int sheetNo, Sheet sheet):在创建每个sheet后,自定义业务逻辑处理

void row(int rowNum, Row row):在创建每个row后,自定义业务逻辑处理

void cell(int cellNum, Cell cell):在创建每个cell后,自定义业务逻辑处理

4.1、编写自定义样式处理类ExcelStyleHandler,实现WriterHandler接口

package com.easyexcel.handler;

import com.alibaba.excel.event.WriteHandler;
import org.apache.poi.ss.usermodel.*;

public class ExcelStyleHandler implements WriteHandler {

    @Override
    public void sheet(int sheetNo, Sheet sheet) {

    }

    @Override
    public void row(int rowNum, Row row) {

    }

    @Override
    public void cell(int cellNum, Cell cell) {

        //这里可以获得Workbook是因为Sheet类有这个接口,但是其他地方没有对应的Sheet,所以要获得的话,需要用到反射了
        Workbook workbook = cell.getSheet().getWorkbook();
        CellStyle cellStyle = workbook.createCellStyle();
        Font font = workbook.createFont();
        //设置边框为细边框
        borderStyle(cellStyle,BorderStyle.THIN);
        //设置水平、垂直居中对齐
        alignmentStyle(cellStyle,HorizontalAlignment.CENTER,VerticalAlignment.CENTER);

        //设置标题行(表头)样式
        if(0 == cell.getRowIndex()){
            //设置字体样式
            fontStyle(cellStyle, font,IndexedColors.AQUA,true,14,"黑体");
            //设置设置单元格填充样式 和 颜色
            colorStyle(cellStyle,FillPatternType.SOLID_FOREGROUND,IndexedColors.LEMON_CHIFFON);
        }

        //设置表格内容样式
        if (cell.getRowIndex() > 0) {
            //设置字体样式
            fontStyle(cellStyle, font,IndexedColors.AQUA,true,14,"楷体");
            //设置设置单元格填充样式 和 颜色
            colorStyle(cellStyle,FillPatternType.SOLID_FOREGROUND,IndexedColors.TURQUOISE);
        }

        cell.getRow().getCell(cellNum).setCellStyle(cellStyle);
    }


    /**
     * 设置四周边框
     *
     * @param cellStyle 单元格样式实体对象
     */
    private void borderStyle(CellStyle cellStyle,BorderStyle borderStyle) {

        //设置上、下、左、右边框为细边框
        cellStyle.setBorderTop(borderStyle);
        cellStyle.setBorderBottom(borderStyle);
        cellStyle.setBorderLeft(borderStyle);
        cellStyle.setBorderRight(borderStyle);

    }


    /**
     * 设置水平和垂直对齐格式
     *
     * @param horizontalAlignment
     * @param verticalAlignment
     */
    private void alignmentStyle(CellStyle cellStyle, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment) {

        // 水平居中对齐
        cellStyle.setAlignment(horizontalAlignment);
        // 垂直居中对齐
        cellStyle.setVerticalAlignment(verticalAlignment);
    }


    /**
     * 设置字体样式
     *
     * @param cellStyle 单元格样式实体对象
     * @param font      字体实体对象
     */
    private void fontStyle(CellStyle cellStyle, Font font,IndexedColors indexedColors,boolean isBold,int fontHeight,String fontName) {

        //设置字体颜色
        font.setColor(indexedColors.getIndex());
        //设置字体是否加粗
        font.setBold(isBold);
        //设置字体大小
        font.setFontHeightInPoints((short) fontHeight);
        //设置字体
        font.setFontName(fontName);

        cellStyle.setFont(font);

    }


    /**
     * 设置单元格填充样式 和 颜色
     *
     * @param cellStyle 单元格样式实体对象
     * @param fillPatternType 字体实体对象
     * @param indexedColors 字体实体对象
     */
    private void colorStyle(CellStyle cellStyle, FillPatternType fillPatternType, IndexedColors indexedColors) {

        //设置前景填充样式
        cellStyle.setFillPattern(fillPatternType);
        //前景填充色
        cellStyle.setFillForegroundColor(indexedColors.getIndex());
    }

}

4.2、在ExcelUtils工具类中添加如下方法

    /**
     * 导出带有表头注解的Java实体类模型
     * 导出单个sheet 的Excel,带表头,可自定义sheet表格名称 和 Excel表格样式
     *
     * @param outputStream 字节输出流
     * @param clazz        类的字节码文件对象
     * @param sheetName    sheet表格名称
     * @param data         实体对象集合
     * @param handler      Excel表格样式
     */
    public static void writeExcelWithStyle(OutputStream outputStream, Class clazz, String sheetName, List<? extends BaseRowModel> data, WriteHandler handler) {

        BufferedOutputStream bufferedOutputStream = null;

        try {
            //包装成缓冲字节输入流
            bufferedOutputStream = new BufferedOutputStream(outputStream);
            //包装成缓冲字节输入流
            ExcelWriter writer = EasyExcelFactory.getWriterWithTempAndHandler(null, outputStream, ExcelTypeEnum.XLSX, true, handler);
            //创建sheet表格,并设置表格名称
            Sheet sheet = new Sheet(1, 0, clazz);
            sheet.setSheetName(sheetName);
            //设置自适应宽度
            sheet.setAutoWidth(Boolean.TRUE);
            //把数据写入表格
            writer.write(data, sheet);
            writer.finish();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭缓冲字节输出流,释放资源
            if (bufferedOutputStream != null) {
                try {
                    bufferedOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

4.3、编写导出带有表头注解的Java实体类模型的Excel表格样式的测试用例

package com.easyexcel.test;

import com.easyexcel.handler.ExcelStyleHandler;
import com.easyexcel.pojo.User;
import com.easyexcel.service.UserService;
import com.easyexcel.utils.ExcelUtils;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

public class EasyExcelTest {

    private UserService userService;

    @Before
    public void init() {

        //读取applicationContext-spring.xml配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/applicationContext-spring.xml");
        //获取Spring容器中已初始化的UserServiceImpl实例对象
        userService = (UserService) context.getBean("userServiceImpl");
    }


    /**
     * 导出带有表头注解的Java实体类模型
     * 导出单个sheet 的Excel,带表头和表格样式
     */
    @Test
    public void writeExcelWithStyle() {

        FileOutputStream fileOutputStream = null;
        try {
            //获取文件输出流
            fileOutputStream = new FileOutputStream("G:/create_user.xlsx");
            //获得User实体类对象集合
            List<User> users = userService.selectAllOfUser();
            //自定义表格样式
            ExcelStyleHandler handler = new ExcelStyleHandler();
            //把数据写入到指定的Excel表格中
            ExcelUtils.writeExcelWithStyle(fileOutputStream, User.class, "User表格",users,handler);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {

            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
}

4.4、测试导出Excel结果如下图所示

5、EasyExcel自定义导出带有表头的无注解模型映射关系的数据模型的表头以及内容样式Excel

5.1、在ExcelUtils工具类中添加如下方法

    /**
     * 导出带有表头的无注解模型映射关系的数据模型
     * 导出单个sheet 的Excel,带表头,可自定义sheet表格名称 和 Excel表格样式
     *
     * @param outputStream 字节输出流
     * @param sheetName    sheet表格名称
     * @param data         实体对象集合
     * @param tableStyle   实体对象集合
     */
    public static void writeExcelWithOutJavaModelOfStyle(OutputStream outputStream, String sheetName, List<List<Object>> data, List<List<String>> head, TableStyle tableStyle) {

        BufferedOutputStream bufferedOutputStream = null;

        try {
            //包装成缓冲字节输入流
            bufferedOutputStream = new BufferedOutputStream(outputStream);
            //包装成缓冲字节输入流
            ExcelWriter writer = EasyExcelFactory.getWriter(outputStream);
            //创建sheet表格,并设置表格名称
            Sheet sheet = new Sheet(1, 0);
            sheet.setSheetName(sheetName);
            //设置自适应宽度
            sheet.setAutoWidth(Boolean.TRUE);

            //无注解模型映射关系的数据模型,动态添加表头
            Table table = new Table(1);
            table.setHead(head);
            //设置Excel表格样式
            table.setTableStyle(tableStyle);

            //把数据写入表格,如果数据类型是List<List<String>>,请使用writer.write0(data, sheet)进行数据写入
            writer.write1(data, sheet, table);
            writer.finish();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭缓冲字节输出流,释放资源
            if (bufferedOutputStream != null) {
                try {
                    bufferedOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

5.2、编写带有表头的无注解模型映射关系的数据模型的Excel表格样式的测试用例

package com.easyexcel.test;

import com.alibaba.excel.metadata.TableStyle;
import com.easyexcel.utils.ExcelUtils;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.junit.Test;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class EasyExcelTest {

    /**
     * 导出带有表头的无注解模型映射关系的数据模型
     * 单个sheet 的Excel,带表头
     */
    @Test
    public void writeExcelWithOutJavaModel() {

        FileOutputStream fileOutputStream = null;
        try {
            //获取文件输出流
            fileOutputStream = new FileOutputStream("G:/create_data.xlsx");
            //动态创建数据,注意创建的数据类型是List<List<Object>>
            List<List<Object>> rows = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                List<Object> row = new ArrayList<>();
                row.add("2015435040" + i);
                row.add("李四--" + i);
                row.add(Integer.valueOf(10 + i));
                row.add("男");
                row.add("博客:浅末年华");
                rows.add(row);
            }

            //无注解模型映射关系的数据模型,动态创建表头数据
            List<List<String>> head = createTestListStringHead();
            //自定义表格样式
            TableStyle tableStyle = createTableStyle();

            //把数据写入到指定的Excel表格中
            ExcelUtils.writeExcelWithOutJavaModelOfStyle(fileOutputStream, "Data表格", rows, head, tableStyle);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {

            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 无注解模型映射关系的数据模型,动态创建表头数据
     *
     * @return List<List < String>> 表头
     */
    public static List<List<String>> createTestListStringHead() {
        //无注解模型映射关系的数据模型,动态创建表头数据
        List<List<String>> head = new ArrayList<List<String>>();
        List<String> headCoulumn1 = new ArrayList<String>();
        List<String> headCoulumn2 = new ArrayList<String>();
        List<String> headCoulumn3 = new ArrayList<String>();
        List<String> headCoulumn4 = new ArrayList<String>();
        List<String> headCoulumn5 = new ArrayList<String>();

        headCoulumn1.add("第一列");headCoulumn1.add("第一列");headCoulumn1.add("第一列");
        headCoulumn2.add("第一列");headCoulumn2.add("第一列");headCoulumn2.add("第一列");
        headCoulumn3.add("第二列");headCoulumn3.add("第二列");headCoulumn3.add("第二列");
        headCoulumn4.add("第三列1");headCoulumn4.add("第三列2");headCoulumn4.add("第三列2");
        headCoulumn5.add("第四列");headCoulumn5.add("第四列1");headCoulumn5.add("第四列2");

        head.add(headCoulumn1);
        head.add(headCoulumn2);
        head.add(headCoulumn3);
        head.add(headCoulumn4);
        head.add(headCoulumn5);
        return head;
    }


    /**
     * 自定义表格样式
     */
    public static com.alibaba.excel.metadata.TableStyle createTableStyle() {
        com.alibaba.excel.metadata.TableStyle tableStyle = new com.alibaba.excel.metadata.TableStyle();
        // 设置表头样式
        com.alibaba.excel.metadata.Font headFont = new com.alibaba.excel.metadata.Font();
        // 字体是否加粗
        headFont.setBold(true);
        // 字体大小
        headFont.setFontHeightInPoints((short) 12);
        // 字体
        headFont.setFontName("楷体");
        tableStyle.setTableHeadFont(headFont);
        // 背景色
        tableStyle.setTableHeadBackGroundColor(IndexedColors.BLUE);


        // 设置表格内容样式
        com.alibaba.excel.metadata.Font contentFont = new com.alibaba.excel.metadata.Font();
        contentFont.setBold(true);
        contentFont.setFontHeightInPoints((short) 12);
        contentFont.setFontName("黑体");
        tableStyle.setTableContentFont(contentFont);
        tableStyle.setTableContentBackGroundColor(IndexedColors.GREEN);
        return tableStyle;
    }

}

6、使用EasyExcel合并单元格,通过调用ExcelWriter类中的 merge(int firstRow, int lastRow, int firstCol, int lastCol) 来合并单元格

merge方法的四个参数:

     firstRow:开始合并的行数 、lastRow:结束合并的行数、firstCol:开始合并的列数、astCol:结束合并的列数

需要注意的是:行数 和 列数的下标是从0开始的,同时对应的 last 的值必须大于 first 的值

package com.easyexcel.test;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import org.junit.Test;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class EasyExcelTest {

    /**
     * 导出带有表头的无注解模型映射关系的数据模型
     * 单个sheet 的Excel,带表头并合并单元格
     */
    @Test
    public void writeExcelWithOutJavaModel() {

        FileOutputStream fileOutputStream = null;
        try {
            //获取文件输出流
            fileOutputStream = new FileOutputStream("G:/create_data.xlsx");
            //动态创建数据,注意创建的数据类型是List<List<Object>>
            List<List<Object>> rows = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                List<Object> row = new ArrayList<>();
                row.add("2015435040" + i);
                row.add("李四--" + i);
                row.add(Integer.valueOf(10 + i));
                row.add("男");
                row.add("博客:浅末年华");
                rows.add(row);
            }

            //无注解模型映射关系的数据模型,动态创建表头数据
            List<List<String>> head = createTestListStringHead();
            //包装成缓冲字节输入流
            ExcelWriter writer = EasyExcelFactory.getWriter(fileOutputStream);
            //创建sheet表格,并设置表格名称
            Sheet sheet = new Sheet(1, 0);
            sheet.setSheetName("合并单元格");
            //设置自适应宽度
            sheet.setAutoWidth(Boolean.TRUE);

            //无注解模型映射关系的数据模型,动态添加表头
            Table table = new Table(1);
            table.setHead(head);
            //把数据写入表格,如果数据类型是List<List<String>>,请使用writer.write0(data, sheet)进行数据写入
            writer.write1(rows, sheet, table);
            //合并单元格,表示把第四行到第六行、第一列到第二列进行合并
            writer.merge(3,5,0,1);
            writer.finish();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {

            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 无注解模型映射关系的数据模型,动态创建表头数据
     *
     * @return List<List<String>> 表头
     */
    public static List<List<String>> createTestListStringHead() {
        //无注解模型映射关系的数据模型,动态创建表头数据
        List<List<String>> head = new ArrayList<List<String>>();
        List<String> headCoulumn1 = new ArrayList<String>();
        List<String> headCoulumn2 = new ArrayList<String>();
        List<String> headCoulumn3 = new ArrayList<String>();
        List<String> headCoulumn4 = new ArrayList<String>();
        List<String> headCoulumn5 = new ArrayList<String>();

        headCoulumn1.add("第一列");headCoulumn1.add("第一列");headCoulumn1.add("第一列");
        headCoulumn2.add("第一列");headCoulumn2.add("第一列");headCoulumn2.add("第一列");
        headCoulumn3.add("第二列");headCoulumn3.add("第二列");headCoulumn3.add("第二列");
        headCoulumn4.add("第三列1");headCoulumn4.add("第三列2");headCoulumn4.add("第三列2");
        headCoulumn5.add("第四列");headCoulumn5.add("第四列1");headCoulumn5.add("第四列2");

        head.add(headCoulumn1);
        head.add(headCoulumn2);
        head.add(headCoulumn3);
        head.add(headCoulumn4);
        head.add(headCoulumn5);
        return head;
    }

}

6.1、测试导出Excel结果如下图所示

7、使用EasyExcel实现一个Excel写入多个Sheet表格

package com.easyexcel.test;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Font;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.TableStyle;
import com.easyexcel.pojo.User;
import com.easyexcel.service.UserService;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class EasyExcelTest {

    private UserService userService;

    @Before
    public void init() {

        //读取applicationContext-spring.xml配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/applicationContext-spring.xml");
        //获取Spring容器中已初始化的UserServiceImpl实例对象
        userService = (UserService) context.getBean("userServiceImpl");
    }


    /**
     * 导出带有表头注解的Java实体类模型
     * 导出单个sheet 的Excel,带表头和表格样式
     */
    @Test
    public void writeExcelWithStyle() {

        FileOutputStream fileOutputStream = null;
        try {
            //获取文件输出流
            fileOutputStream = new FileOutputStream("G:/create_data.xlsx");
            ExcelWriter writer = EasyExcelFactory.getWriter(fileOutputStream);
            //动态创建数据
            List<List<Object>> list = createDynamicModelList();
            //获得User实体类对象集合
            List<User> users = userService.selectAllOfUser();

            //写第一个sheet, sheet1 数据是List<List<Object>> 无注解模型映射关系的数据模型,无表头
            Sheet sheet1 = new Sheet(1, 0);
            sheet1.setSheetName("第一个sheet");
            sheet1.setAutoWidth(Boolean.TRUE);
            sheet1.setStartRow(-1);
            writer.write1(list, sheet1);

            //写第二个sheet,sheet2 数据是List<User> 有表头注解的Java实体类模型
            Sheet sheet2 = new Sheet(2, 0, User.class);
            sheet2.setSheetName("第二个sheet");
            sheet2.setAutoWidth(Boolean.TRUE);
            writer.write(users, sheet2);

            //写第三个sheet,sheet3 数据是List<List<Object>> 带有表头以及内容样式
            List<List<String>> head = createTestListStringHead();
            //自定义表格样式
            TableStyle tableStyle = createTableStyle();
            Sheet sheet3 = new Sheet(3, 0, null, "第三个sheet", head);
            sheet3.setAutoWidth(Boolean.TRUE);
            sheet3.setTableStyle(tableStyle);
            writer.write1(list, sheet3);

            writer.finish();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {

            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 动态创建数据
     */
    public List<List<Object>> createDynamicModelList() {
        //动态创建数据,注意创建的数据类型是List<List<Object>>
        List<List<Object>> rows = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            List<Object> row = new ArrayList<>();
            row.add("2015435040" + i);
            row.add("李四--" + i);
            row.add(Integer.valueOf(10 + i));
            row.add("男");
            row.add("博客:浅末年华");
            rows.add(row);
        }
        return rows;
    }


    /**
     * 自定义表格样式
     */
    public static TableStyle createTableStyle() {
        TableStyle tableStyle = new TableStyle();
        // 设置表头样式
        Font headFont = new Font();
        // 字体是否加粗
        headFont.setBold(true);
        // 字体大小
        headFont.setFontHeightInPoints((short) 12);
        // 字体
        headFont.setFontName("楷体");
        tableStyle.setTableHeadFont(headFont);
        // 背景色
        tableStyle.setTableHeadBackGroundColor(IndexedColors.BLUE);


        // 设置表格内容样式
        Font contentFont = new Font();
        contentFont.setBold(true);
        contentFont.setFontHeightInPoints((short) 12);
        contentFont.setFontName("黑体");
        tableStyle.setTableContentFont(contentFont);
        tableStyle.setTableContentBackGroundColor(IndexedColors.GREEN);
        return tableStyle;
    }


    /**
     * 无注解模型映射关系的数据模型,动态创建表头数据
     *
     * @return List<List<String>> 表头
     */
    public static List<List<String>> createTestListStringHead() {
        //无注解模型映射关系的数据模型,动态创建表头数据
        List<List<String>> head = new ArrayList<List<String>>();
        List<String> headCoulumn1 = new ArrayList<String>();
        List<String> headCoulumn2 = new ArrayList<String>();
        List<String> headCoulumn3 = new ArrayList<String>();
        List<String> headCoulumn4 = new ArrayList<String>();
        List<String> headCoulumn5 = new ArrayList<String>();

        headCoulumn1.add("第一列");headCoulumn1.add("第一列");headCoulumn1.add("第一列");
        headCoulumn2.add("第一列");headCoulumn2.add("第一列");headCoulumn2.add("第一列");
        headCoulumn3.add("第二列");headCoulumn3.add("第二列");headCoulumn3.add("第二列");
        headCoulumn4.add("第三列1");headCoulumn4.add("第三列2");headCoulumn4.add("第三列2");
        headCoulumn5.add("第四列");headCoulumn5.add("第四列1");headCoulumn5.add("第四列2");

        head.add(headCoulumn1);
        head.add(headCoulumn2);
        head.add(headCoulumn3);
        head.add(headCoulumn4);
        head.add(headCoulumn5);
        return head;
    }

}

7.1、测试导出Excel结果如下图所示

8、使用EasyExcel实现Excel中一个Sheet表格写入多个Table表格

package com.easyexcel.test;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Font;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.metadata.TableStyle;
import com.easyexcel.pojo.User;
import com.easyexcel.service.UserService;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class EasyExcelTest {

    private UserService userService;

    @Before
    public void init() {

        //读取applicationContext-spring.xml配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/applicationContext-spring.xml");
        //获取Spring容器中已初始化的UserServiceImpl实例对象
        userService = (UserService) context.getBean("userServiceImpl");
    }


    /**
     * 导出带有表头注解的Java实体类模型
     * 导出单个sheet 的Excel,带表头和表格样式
     */
    @Test
    public void writeExcelWithStyle() {

        FileOutputStream fileOutputStream = null;
        try {
            //获取文件输出流
            fileOutputStream = new FileOutputStream("G:/create_data.xlsx");
            ExcelWriter writer = EasyExcelFactory.getWriter(fileOutputStream);
            //动态创建数据
            List<List<Object>> list = createDynamicModelList();
            //获得User实体类对象集合
            List<User> users = userService.selectAllOfUser();

            //创建Sheet
            Sheet sheet = new Sheet(1, 0);
            sheet.setSheetName("第一个sheet");
            sheet.setAutoWidth(Boolean.TRUE);
            sheet.setStartRow(-1);

            //写第一个table, table1 数据是List<List<Object>> 无注解模型映射关系的数据模型,无表头
            Table table1 = new Table(1);
            writer.write1(list,sheet,table1);

            //写第二个table,table2 数据是List<User> 有表头注解的Java实体类模型
            Table table2 = new Table(2);
            table2.setClazz(User.class);
            writer.write(users, sheet,table2);

            //写第三个table,table3 数据是List<List<Object>> 带有表头以及内容样式
            List<List<String>> head = createTestListStringHead();
            //自定义表格样式
            TableStyle tableStyle = createTableStyle();
            Table table3 = new Table(3);
            table3.setHead(head);
            table3.setTableStyle(tableStyle);
            writer.write1(list, sheet, table3);

            writer.finish();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {

            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 动态创建数据
     */
    public List<List<Object>> createDynamicModelList() {
        //动态创建数据,注意创建的数据类型是List<List<Object>>
        List<List<Object>> rows = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            List<Object> row = new ArrayList<>();
            row.add("2015435040" + i);
            row.add("李四--" + i);
            row.add(Integer.valueOf(10 + i));
            row.add("男");
            row.add("博客:浅末年华");
            rows.add(row);
        }
        return rows;
    }


    /**
     * 自定义表格样式
     */
    public static TableStyle createTableStyle() {
        TableStyle tableStyle = new TableStyle();
        // 设置表头样式
        Font headFont = new Font();
        // 字体是否加粗
        headFont.setBold(true);
        // 字体大小
        headFont.setFontHeightInPoints((short) 12);
        // 字体
        headFont.setFontName("楷体");
        tableStyle.setTableHeadFont(headFont);
        // 背景色
        tableStyle.setTableHeadBackGroundColor(IndexedColors.BLUE);


        // 设置表格内容样式
        Font contentFont = new Font();
        contentFont.setBold(true);
        contentFont.setFontHeightInPoints((short) 12);
        contentFont.setFontName("黑体");
        tableStyle.setTableContentFont(contentFont);
        tableStyle.setTableContentBackGroundColor(IndexedColors.GREEN);
        return tableStyle;
    }


    /**
     * 无注解模型映射关系的数据模型,动态创建表头数据
     *
     * @return List<List<String>> 表头
     */
    public static List<List<String>> createTestListStringHead() {
        //无注解模型映射关系的数据模型,动态创建表头数据
        List<List<String>> head = new ArrayList<List<String>>();
        List<String> headCoulumn1 = new ArrayList<String>();
        List<String> headCoulumn2 = new ArrayList<String>();
        List<String> headCoulumn3 = new ArrayList<String>();
        List<String> headCoulumn4 = new ArrayList<String>();
        List<String> headCoulumn5 = new ArrayList<String>();

        headCoulumn1.add("第一列");headCoulumn1.add("第一列");headCoulumn1.add("第一列");
        headCoulumn2.add("第一列");headCoulumn2.add("第一列");headCoulumn2.add("第一列");
        headCoulumn3.add("第二列");headCoulumn3.add("第二列");headCoulumn3.add("第二列");
        headCoulumn4.add("第三列1");headCoulumn4.add("第三列2");headCoulumn4.add("第三列2");
        headCoulumn5.add("第四列");headCoulumn5.add("第四列1");headCoulumn5.add("第四列2");

        head.add(headCoulumn1);
        head.add(headCoulumn2);
        head.add(headCoulumn3);
        head.add(headCoulumn4);
        head.add(headCoulumn5);
        return head;
    }

}

8.1、测试导出Excel结果如下图所示

               如果有遇到不懂或者有问题时,可以扫描下方二维码,欢迎进群交流与分享,希望能够跟大家交流学习!

                                                              

发布了76 篇原创文章 · 获赞 253 · 访问量 43万+

猜你喜欢

转载自blog.csdn.net/qq_39135287/article/details/98348091