Excel轻松操控:掌握EasyPoi的妙用技巧

1. 前言

官方文档:http://doc.wupaas.com/docs/easypoi/

1.1 简介

Easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板语言(熟悉的表达式语法),完成以前复杂的写法。

1.2 环境搭建

如果使用maven,请使用如下坐标:

<!--导入导出的工具包,可以完成Excel导出,导入,Word的导出,Excel的导出功能-->
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-base</artifactId>
    <version>4.1.0</version>
</dependency>
<!--耦合了spring-mvc 基于AbstractView,极大的简化spring-mvc下的导出功能-->
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-web</artifactId>
    <version>4.1.0</version>
</dependency>
<!--基础注解包,作用与实体对象上,拆分后方便maven多工程的依赖管理-->
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-annotation</artifactId>
    <version>4.1.0</version>
</dependency>

2. 使用EasyPOI

2.1 相关注解

easypoi起因就是Excel的导入导出,最初的模板是实体和Excel的对应,model–row,filed–col 这样利用注解我们可以和容易做到excel到导入导出

经过一段时间发展,现在注解有5个类分别是

  • @ExcelTarget 这个是作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理
  • @Excel 作用到filed上面,是对Excel一列的一个描述
  • @ExcelCollection 表示一个集合,主要针对一对多的导出,比如一个老师对应多个科目,科目就可以用集合表示
  • @ExcelEntity 表示一个继续深入导出的实体,但他没有太多的实际意义,只是告诉系统这个对象里面同样有导出的字段
  • @ExcelIgnore 和名字一样表示这个字段被忽略跳过这个导出

2.1.1 注解@ExcelTarget

作用于实体类上,同时实体类需要实现序列化接口。value需要给定一个唯一的ID,使用类名即可。

@ExcelTarget("user")
public class User implements Serializable {

2.1.2 注解@Excel

作用于实体类的属性上,每一个属性将会对应Excel上的一列。

属性类型默认值功能
nameStringnull列名,支持name_id
needMergebooleanfasle是否需要纵向合并单元格(用于含有list中,单个的单元格,合并list创建的多个row)
orderNumString“0”列的排序,支持name_id
replaceString[]{}值得替换 导出是{a_id,b_id} 导入反过来
savePathString“upload”导入文件保存路径,如果是图片可以填写,默认是upload/className/ IconEntity这个类对应的就是upload/Icon/
typeint1导出类型 1 是文本 2 是图片,3 是函数,10 是数字 默认是文本
widthdouble10列宽
heightdouble10列高,后期打算统一使用@ExcelTarget的height,这个会被废弃,注意
isStatisticsbooleanfasle自动统计数据,在追加一行统计,把所有数据都和输出[这个处理会吞没异常,请注意这一点]
isHyperlinkbooleanfalse超链接,如果是需要实现接口返回对象
isImportFieldbooleantrue校验字段,看看这个字段是不是导入的Excel中有,如果没有说明是错误的Excel,读取失败,支持name_id
exportFormatString“”导出的时间格式,以这个是否为空来判断是否需要格式化日期
importFormatString“”导入的时间格式,以这个是否为空来判断是否需要格式化日期
formatString“”时间格式,相当于同时设置了exportFormat 和 importFormat
databaseFormatString“yyyyMMddHHmmss”导出时间设置,如果字段是Date类型则不需要设置 数据库如果是string 类型,这个需要设置这个数据库格式,用以转换时间格式输出
numFormatString“”数字格式化,参数是Pattern,使用的对象是DecimalFormat
imageTypeint1导出类型 1 从file读取 2 是从数据库中读取 默认是文件 同样导入也是一样的
suffixString“”文字后缀,如% 90 变成90%
isWrapbooleantrue是否换行 即支持\n
mergeRelyint[]{}合并单元格依赖关系,比如第二列合并是基于第一列 则{0}就可以了
mergeVerticalbooleanfasle纵向合并内容相同的单元格
fixedIndexint-1对应excel的列,忽略名字
isColumnHiddenbooleanfalse导出隐藏列

2.1.3 注解@ExcelCollection

一对多的集合注解,用以标记集合是否被数据以及集合的整体排序。

属性类型默认值功能
idStringnull定义ID
nameStringnull定义集合列名,支持nanm_id
orderNumint0排序,支持name_id
typeClass<?>ArrayList.class导入时创建对象使用
@ExcelCollection(name = "订单列表",orderNum = "8")
private List<Order> orders;
@ExcelTarget("orders")
@Data
@AllArgsConstructor
public class Order implements Serializable {

    /**
     * 订单编号
     */
    @Excel(name = "订单编号",orderNum = "8",width = 20.0)
    private String num;

    /**
     * 订单名称
     */
    @Excel(name = "订单名称",orderNum = "9",width = 20.0)
    private String name;
}

2.1.4 注解@ExcelEntity

一对一实体对应,作用在实体类里面的属性又是一个实体类的情况。同时被组合的实体类也需要使用ExcelTarget和Excel进行标识。同时实现序列化接口。

@ExcelEntity
private Department department;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ExcelTarget("department")
public class Department implements Serializable {

    /**
     * 部门ID
     */
    private Integer deptId;

    /**
     * 部门名称
     */
    @Excel(name = "部门")
    private String deptName;

    /**
     * 地址
     */
    private String address;

}

2.1.5 注解@ExcelIgnore

忽略这个属性。

2.2. Maven项目整合EasyPOI

2.2.1 引入依赖

<dependencies>
    <!--引入EasyPOI-->
    <dependency>
        <groupId>cn.afterturn</groupId>
        <artifactId>easypoi-base</artifactId>
        <version>4.1.0</version>
    </dependency>
    <dependency>
        <groupId>cn.afterturn</groupId>
        <artifactId>easypoi-web</artifactId>
        <version>4.1.0</version>
    </dependency>
    <dependency>
        <groupId>cn.afterturn</groupId>
        <artifactId>easypoi-annotation</artifactId>
        <version>4.1.0</version>
    </dependency>
    <!--引入Junit测试-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.1</version>
        <scope>test</scope>
    </dependency>
    <!--引入Lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.16</version>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>RELEASE</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

2.2.2 创建实体类

2.2.2.1 用户实体
/**
 * @ClassName: User
 * @Description: 用户实体类,需要实现对象序列化接口
 * @author: 莫提
 * @date 2020/11/27 8:55
 * @Version: 1.0
 */
@Data
@AllArgsConstructor
@Builder
@ExcelTarget("user")
public class User implements Serializable {

    /**
     * 用户 ID
     */
    @Excel(name = "编号",orderNum = "0",suffix = "号")
    private Integer id;
    /**
     * 姓名
     */
    @Excel(name = "姓名",orderNum = "1")
    private String name;
    /**
     * 性别
     */
    @Excel(name = "性别",orderNum = "2",replace = {"男性_男","女性_女"})
    private String sex;
    /**
     * 生日
     */
    @Excel(name = "生日",width = 35.0,format = "yyyy-MM-dd HH:mm:ss",orderNum = "4")
    private Date birthday;

    /**
     * 用户状态:【1:正常】【0:封禁】
     */
    @Excel(name = "用户状态",replace = {"正常_1","封禁_0"},orderNum = "3")
    private Integer status;

    /**
     * 密码
     */
    @ExcelIgnore
    private String password;

    /**
     * 爱好
     */
     @Excel(name = "爱好",orderNum = "5",width = 40.0)
    private List<String> hobbies;

    /**
     * 爱好字符串
     */
    @Excel(name = "爱好",orderNum = "5",width = 40.0)
    private String hobbyStr;

    /**
     * 身份证【一对一】
     */
    @ExcelEntity
    private Card card;

    /**
     * 订单列表【一对多】
     */
    @ExcelCollection(name = "订单列表",orderNum = "8")
    private List<Order> orders;

    /**
     * 头像信息,type = 2表示图片
     */
    @Excel(name = "头像",width = 20,height = 40,type = 2)
    private String photo;

    public String getHobbyStr(){
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < hobbies.size(); i++) {
            sb.append(hobbies.get(i));
            if (i != hobbies.size() -1){
                sb.append(",");
            }
        }
        return sb.toString();
    }
}
2.2.2.2 身份证实体类
/**
 * @ClassName: Card
 * @Description: 身份证
 * @author: 莫提
 * @date 2020/11/27 8:55
 * @Version: 1.0
 */
@ExcelTarget("card")
@Data
@AllArgsConstructor
public class Card implements Serializable {
    /**
     * 身份证号
     */
    @Excel(name = "身份证号码",width = 20.0,orderNum = "6")
    private String number;
    /**
     * 地址
     */
    @Excel(name = "住址",width = 50.0,orderNum = "7")
    private String address;
}

2.2.2.3 订单实体类
/**
 * @ClassName: Order
 * @Description: 订单
 * @author: 莫提
 * @date 2020/11/27 8:55
 * @Version: 1.0
 */
@ExcelTarget("orders")
@Data
@AllArgsConstructor
public class Order implements Serializable {

    /**
     * 订单编号
     */
    @Excel(name = "订单编号",orderNum = "8",width = 20.0)
    private String num;

    /**
     * 订单名称
     */
    @Excel(name = "订单名称",orderNum = "9",width = 20.0)
    private String name;
}
2.2.2.4 员工实体类
/**
 * @ClassName: Employee
 * @Description: 导入的员工实体
 * @author: 莫提
 * @date 2020/11/27 8:55
 * @Version: 1.0
 */
@ExcelTarget("employee")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {

    /**
     * 用户 ID
     */
    @Excel(name = "编号",suffix = "号")
    private Integer id;
    /**
     * 姓名
     */
    @Excel(name = "姓名")
    private String name;
    /**
     * 性别
     */
    @Excel(name = "性别")
    private String sex;
    /**
     * 生日
     */
    @Excel(name = "生日",format = "yyyy-MM-dd HH:mm:ss")
    private Date birthday;

    /**
     * 用户状态:【1:正常】【0:封禁】
     */
    @Excel(name = "用户状态",replace = {"正常_1","封禁_0"})
    private Integer status;
}

2.2.3 创建测试类

2.2.3.1 导出测试
public class TestExport {

    /**
     * 获取全部用户
     */
    public List<User> getAllUsers(){
        List<User> list = new ArrayList<>();
        // 创建身份证信息
        Card card1 = new Card("11111","江西省南昌市");
        Card card2 = new Card("22222","四川省成都市");
        Card card3 = new Card("33333","河北省唐山市");
        // 创建订单信息
        Order order1 = new Order("1","泡面");
        Order order2 = new Order("2","外套");
        Order order3 = new Order("3","裤子");
        Order order4 = new Order("4","AJ1");
        Order order5 = new Order("5","NICK");
        Order order6 = new Order("6","笔记本");
        Order order7 = new Order("7","键盘");
        Order order8 = new Order("8","鼠标");

        list.add(User.builder()
                .id(1).name("张三").sex("男").status(0).password("123456").birthday(new Date())
                .hobbies(Arrays.asList("唱歌", "跳舞")).card(card1).orders(Arrays.asList(order1,order2))
                .photo("E:\\头像\\avatar.jpg")
                .build());
        list.add(User.builder()
                .id(2).name("李四").sex("男").status(1).password("123456").birthday(new Date())
                .hobbies(Arrays.asList("睡觉", "游戏")).card(card2).orders(Arrays.asList(order3,order4,order5))
                .photo("E:\\头像\\1.jpg")
                .build());
        list.add(User.builder()
                .id(3).name("丽丽").sex("女").status(0).password("123456").birthday(new Date())
                .hobbies(Arrays.asList("技术", "代码")).card(card3).orders(Arrays.asList(order6,order7,order8))
                .photo("E:\\头像\\2.jpg")
                .build());
        return list;
    }

    /**
     * 导出Excel表格
     */
    @Test
    public void testExport() throws IOException {
        // 获取全部用户
        List<User> users = getAllUsers();

        // 导出到文件
        FileOutputStream outputStream = new FileOutputStream("E:\\导出.xls");

        // 配置Excel文件信息
        ExportParams params = new ExportParams();
        params.setTitle("用户信息");
        params.setSheetName("用户信息1表");

        // 导出Excel表格
        Workbook workbook = ExcelExportUtil.exportExcel(params, User.class, users);
        workbook.write(outputStream);

        // 关闭资源
        outputStream.close();
        workbook.close();
    }
}
2.2.3.2 导入测试
public class TestImport {
    /**
     * 导入
     */
    @Test
    public void testImport() throws Exception {
        // 参数1:文件流
        FileInputStream stream = new FileInputStream("E:\\导入.xls");
        // 参数2:导入类型
        ImportParams params = new ImportParams();
        // 标题占用多少行
        params.setTitleRows(1);
        // 头部属性占用多少行
        params.setHeadRows(1);
        // 从指定的sheet的下标开始读取
        // params.setStartSheetIndex(1);
        // 读取sheet的数量,需要和上面的配合
        // params.setSheetNum(1);

        // 对Excle进行合法参数校验
        params.setImportFields(new String[]{"编号"});

        // 参数3:导出的数据结合
        List<Employee> employees = ExcelImportUtil.importExcel(stream, Employee.class, params);
        for (Employee employee : employees) {
            System.out.println("employee = " + employee);
        }
    }
}

2.3 SpringBoot整合EasyPOI

2.3.1 导入依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.20</version>
        </dependency>
        <!--引入Mybatis的ehCache的适配-->
        <dependency>
            <groupId>org.mybatis.caches</groupId>
            <artifactId>mybatis-ehcache</artifactId>
            <version>1.0.3</version>
        </dependency>
        <!--引入分页插件的依赖-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.10</version>
        </dependency>
        <!--引入EasyPOI-->
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-base</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-web</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-annotation</artifactId>
            <version>4.1.0</version>
        </dependency>
    </dependencies>

2.3.2 修改配置文件

# 配置应用相关
server:
  servlet:
    context-path: /
    session:
      timeout: 60m
  tomcat:
    uri-encoding: UTF-8

# 配置MyBatis相关
mybatis:
  config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mybatis/mapper/*.xml

spring:
  # 禁用ThymeLeaf缓存
  thymeleaf:
    cache: false
  # 配置数据源
  datasource:
    username: root
    password: 983934
    url: jdbc:mysql://127.0.0.1:3306/learn?serverTimezone=Hongkong&useAffectedRows=true
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB

2.3.3 创建数据表

1607917749688

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
  `work_age` int(2) DEFAULT NULL COMMENT '工龄',
  `sex` int(1) DEFAULT NULL COMMENT '性别',
  `birthday` date DEFAULT NULL COMMENT '生日',
  `dept_id` int(11) DEFAULT NULL COMMENT '部门ID',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=18433 DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `department`
-- ----------------------------
DROP TABLE IF EXISTS `department`;
CREATE TABLE `department` (
  `dept_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '部门ID',
  `dept_name` varchar(20) DEFAULT NULL,
  `address` varchar(100) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`dept_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

2.3.4 逆向工程生成文件

  • 生成Mapper.Java
  • 生成Mapper.xml
  • 生成Service.java
  • 生成ServiceImpl.java
  • 生成Entity.java

生成基本的增删查改方法

2.3.5 修改实体类

/**
 * (User)实体类
 *
 * @author 莫提
 * @since 2020-12-13 20:39:36
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ExcelTarget("user")
public class User implements Serializable {

    private static final long serialVersionUID = 587947964930607265L;

    /**
     * 用户ID
     */
    @Excel(name = "ID",suffix = "号")
    private Integer userId;

    /**
     * 用户名
     */
    @Excel(name = "姓名")
    private String userName;

    /**
     * 工龄
     */
    @Excel(name = "工龄",suffix = "年")
    private Integer workAge;

    /**
     * 性别
     */
    @Excel(name = "性别",replace = {"男_1","女_0"})
    private Integer sex;

    /**
     * 生日
     */
    @Excel(name = "生日",format = "yyyy年MM月dd日",width = 20)
    private Date birthday;

    /**
     * 部门ID
     */
    @ExcelIgnore
    private Integer deptId;

    /**
     * 所属部门
     */
    @ExcelEntity
    private Department department;

}
package com.moti.entity;

import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * (Department)实体类
 *
 * @author 莫提
 * @since 2020-12-13 20:39:38
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ExcelTarget("department")
public class Department implements Serializable {

    private static final long serialVersionUID = 164895400081727426L;

    /**
     * 部门ID
     */
    private Integer deptId;

    /**
     * 部门名称
     */
    @Excel(name = "部门")
    private String deptName;

    /**
     * 地址
     */
    private String address;

}

2.3.6 编写前端页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
    <!--引入核心css-->
    <link rel="stylesheet" href="boot/css/bootstrap.min.css">
    <!--更好的更好的响应式支持-->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="js/jquery-3.4.1.js"></script>
</head>
<body>
<hr>
<div class="container">
    <div class="row">
        <div class="col-12">
            <h3>选择Excle文件导入</h3>
            <form class="form-inline" method="post" action="importExcel" enctype="multipart/form-data">
                <input type="file" class="form-control" name="file">
                <input type="submit" class="btn btn-danger" value="导入">
            </form>
        </div>
        <br>
        <div class="col-12">
            <table class="table table-bordered">
                <thead>
                <tr>
                    <th>ID</th>
                    <th>姓名</th>
                    <th>部门</th>
                    <th>性别</th>
                    <th>工龄</th>
                    <th>出生日期</th>
                </tr>
                </thead>
                <tbody>
                <tr th:each="user:${users}">
                    <td th:text="${user.userId}"></td>
                    <td th:text="${user.userName}"></td>
                    <td th:text="${user.department.deptName}"></td>
                    <td th:if="${user.sex == 1}"></td>
                    <td th:if="${user.sex == 0}"></td>
                    <td th:text="${user.workAge}"></td>
                    <td th:text="${#dates.format(user.birthday,'yyyy-MM-dd')}"></td>
                </tr>
                </tbody>
            </table>
            <br>
            <a href="exportExcel" class="btn btn-success btn-sm">导出</a>
        </div>
    </div>
</div>
</body>
</html>

2.3.7 编写控制层

/**
 * @ClassName: HelloController
 * @Description:
 * @author: 莫提
 * @date 2020/11/27 8:55
 * @Version: 1.0
 */
@Controller
@Slf4j
public class HelloController {

    @Autowired
    private UserService userService;
    @Autowired
    private DepartmentService departmentService;

    @GetMapping("/")
    public String hello(Map<String,Object> map){
        // 获取全部用户
        List<User> users = userService.listUsers();
        users.forEach(user -> {
            Department department = departmentService.getById(user.getDeptId());
            user.setDepartment(department);
        });
        map.put("users",users);
        return "index";
    }

    /**
     * 导入
     */
    @PostMapping("/importExcel")
    public String importExcel(MultipartFile file) throws Exception {
        if (ObjectUtils.isEmpty(file) || file.getSize() == 0){
            return "redirect:/";
        }
        log.info("接收到文件:{}",file.getOriginalFilename());
        // 参数1:文件流
        InputStream stream = file.getInputStream();

        // 参数2:导入类型
        ImportParams params = new ImportParams();

        // 标题占用多少行
        params.setTitleRows(1);

        // 头部属性占用多少行
        params.setHeadRows(1);

        // 从指定的sheet的下标开始读取
        // params.setStartSheetIndex(1);

        // 读取sheet的数量,需要和上面的配合
        // params.setSheetNum(1);

        // 对Excle进行合法参数校验
        params.setImportFields(new String[]{"姓名","部门"});

        List<User> users  = ExcelImportUtil.importExcel(stream, User.class,params);
        // 遍历结果,插入到数据库
        users.forEach(user -> {
            Department build = Department.builder().deptName(user.getDepartment().getDeptName()).build();
            List<Department> departments = departmentService.listDepartments(build);
            if (departments.size() > 0){
                user.setDeptId(departments.get(0).getDeptId());
            }
            userService.insert(user);
        });
        log.info("导入用户:{}",users);
        return "redirect:/";
    }

    /**
     * 导出Excel
     */
    @GetMapping("/exportExcel")
    public void exportExcel(HttpServletResponse response) throws IOException {
        response.setHeader("content-disposition",
                "attachment;fileName="+ URLEncoder.encode("用户列表.xls","UTF-8"));
        ServletOutputStream outputStream = response.getOutputStream();
        // 查询所有用户
        List<User> users = userService.listUsers();
        users.forEach(user -> {
            Department department = departmentService.getById(user.getDeptId());
            user.setDepartment(department);
        });
        // 生成文件的信息
        ExportParams params = new ExportParams();
        params.setTitle("导出的用户信息");
        params.setSheetName("用户信息");

        Workbook workbook = ExcelExportUtil.exportExcel(params, User.class, users);

        // 输出
        workbook.write(outputStream);

        // 关闭资源
        outputStream.close();
        workbook.close();
    }
}

1607918618707

1607918654589

1607918734929

导入之后

1607918811156

  • 9
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值