SpringBoot-EasyPoi

SpringBoot-EasyPoi

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

Easypoi 介绍

在项目中,有时会出现需要将数据库数据导出报表等功能,这时一般会用到poi库。poi是一个专门给Java程序提供格式文档读写功能的API接口,包括各种微软的格式文档入excel、word等。

最常用的还是处理Excel格式导入导出(其他都不咋地)。
Easypoi是在poi接口基础上进行了封装,简化了操作,基于注解的方式。

Maven

SpringBoot的Maven

<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-spring-boot-starter</artifactId>
    <version>4.0.0</version>
</dependency

普通项目的Maven

       <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>

excel实体类(重点)

@Excel的各个参数可介绍

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

下面我们创建2个用例:

package com.easypoi.pojo;

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

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User {

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

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

    /**
     * 年龄
     */
    @Excel(name = "年龄")
    private Integer age;

    /**
     * 性别,数值0表示男,1表示女 自动替换
     */

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

    /**
     * 籍贯
     */
    @Excel(name = "籍贯")
    private String address;
}
package com.easypoi.pojo;

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

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Company {
    @Excel(name = "公司名称",width =20)
    private String name;

    /**
     * type为 2 表示字段类型为图片
     * imageType为 1 表示从file读取
     */
    @Excel(name = "公司logo",width =20,type = 2,imageType = 1)
    private String logo;

    @Excel(name = "公司介绍",width =100)
    private String dec;
}

excel样式

package com.easypoi.utils;

import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.afterturn.easypoi.excel.entity.params.ExcelForEachParams;
import cn.afterturn.easypoi.excel.export.styler.IExcelExportStyler;
import org.apache.poi.ss.usermodel.*;

/**
 * @author 胡安民
 * @date 2019/11/04
 */
public class ExcelStyleUtil implements IExcelExportStyler {
    private static final short STRING_FORMAT = (short) BuiltinFormats.getBuiltinFormat("TEXT");
    private static final short FONT_SIZE_TEN = 9; //字体大小
    private static final short FONT_SIZE_ELEVEN = 12;//列大小
    private static final short FONT_SIZE_TWELVE = 15;//大标题
    /**
     * 大标题样式
     */
    private CellStyle headerStyle;
    /**
     * 每列标题样式
     */
    private CellStyle titleStyle;
    /**
     * 数据行样式
     */
    private CellStyle styles;

    public ExcelStyleUtil(Workbook workbook) {
        this.init(workbook);
    }

    /**
     * 初始化样式
     *
     * @param workbook
     */
    private void init(Workbook workbook) {
        this.headerStyle = initHeaderStyle(workbook);
        this.titleStyle = initTitleStyle(workbook);
        this.styles = initStyles(workbook);
    }

    /**
     * 大标题样式
     *
     * @param color
     * @return
     */
    @Override
    public CellStyle getHeaderStyle(short color) {
        return headerStyle;
    }

    /**
     * 每列标题样式
     *
     * @param color
     * @return
     */
    @Override
    public CellStyle getTitleStyle(short color) {
        return titleStyle;
    }

    /**
     * 数据行样式 (控制全部行的样式)
     * @param parity 表示奇偶行
     * @param entity 数据内容
     * @return 样式
     */
    @Override
    public CellStyle getStyles(boolean parity, ExcelExportEntity entity) {
        return styles;
    }

    /**
     * 获取样式方法
     *
     * @param dataRow 数据行
     * @param obj     对象
     * @param data    数据
     */
    @Override
    public CellStyle getStyles(Cell cell, int dataRow, ExcelExportEntity entity, Object obj, Object data) {
        return getStyles(true, entity);
    }

    /**
     * 模板使用的样式设置
     */
    @Override
    public CellStyle getTemplateStyles(boolean isSingle, ExcelForEachParams excelForEachParams) {
        return null;
    }

    /**
     * 初始化--大标题样式
     *
     * @param workbook
     * @return
     */
    private CellStyle initHeaderStyle(Workbook workbook) {
        CellStyle style = getBaseCellStyle(workbook);
        style.setFont(getFont(workbook, FONT_SIZE_TWELVE, true));
        return style;
    }

    /**
     * 初始化--每列标题样式
     *
     * @param workbook
     * @return
     */
    private CellStyle initTitleStyle(Workbook workbook) {
        CellStyle style = getBaseCellStyle(workbook);
        style.setFont(getFont(workbook, FONT_SIZE_ELEVEN, false));
        //背景色
//        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); //灰色
//        style.setFillForegroundColor(IndexedColors.AQUA.getIndex()); //浅蓝色
        style.setFillForegroundColor(IndexedColors.SEA_GREEN.getIndex()); //海藻绿



        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        return style;
    }

    /**
     * 初始化--数据行样式
     *
     * @param workbook
     * @return
     */
    private CellStyle initStyles(Workbook workbook) {
        CellStyle style = getBaseCellStyle(workbook);
        style.setFont(getFont(workbook, FONT_SIZE_TEN, false));
        style.setDataFormat(STRING_FORMAT);
        return style;
    }

    /**
     * 基础样式
     *
     * @return
     */
    private CellStyle getBaseCellStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        //下边框
        style.setBorderBottom(BorderStyle.THIN);
        //左边框
        style.setBorderLeft(BorderStyle.THIN);
        //上边框
        style.setBorderTop(BorderStyle.THIN);
        //右边框
        style.setBorderRight(BorderStyle.THIN);
        //水平居中
        style.setAlignment(HorizontalAlignment.CENTER);
        //上下居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        //设置自动换行
        style.setWrapText(true);
        return style;
    }

    /**
     * 字体样式
     *
     * @param size   字体大小
     * @param isBold 是否加粗
     * @return
     */
    private Font getFont(Workbook workbook, short size, boolean isBold) {
        Font font = workbook.createFont();
        //字体样式
        font.setFontName("宋体");
        //是否加粗
        font.setBold(isBold);
        //字体大小
        font.setFontHeightInPoints(size);
        return font;
    }
}

excel倒入导出工具类

package com.easypoi.utils;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.hutool.core.util.StrUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

/**
 * Excel导入导出工具类
 */

public class ExcelUtils {

    /** 允许导出的最大条数 */
    private static final Integer EXPORT_EXCEL_MAX_NUM = 10000;


    /**
     * excel 导出
     *
     * @param list     数据列表
     * @param fileName 导出时的excel名称
     * @param response
     */
    public static void exportExcel(List<Map<String, Object>> list, String fileName, HttpServletResponse response) throws IOException {
        defaultExport(list, fileName, response);

    }

    /**
     * 默认的 excel 导出
     *
     * @param list     数据列表
     * @param fileName 导出时的excel名称
     * @param response
     */
    private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response) throws IOException {

        //把数据添加到excel表格中
        Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF);
        downLoadExcel(fileName, response, workbook);
    }

    /**
     * excel 导出
     *
     * @param list         数据列表
     * @param pojoClass    pojo类型
     * @param fileName     导出时的excel名称
     * @param response
     * @param exportParams 导出参数(标题、sheet名称、是否创建表头,表格类型)
     */
    private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams) throws IOException {
        //把数据添加到excel表格中
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
        downLoadExcel(fileName, response, workbook);
    }

    /**
     * excel 导出
     *
     * @param list         数据列表
     * @param pojoClass    pojo类型
     * @param fileName     导出时的excel名称
     * @param exportParams 导出参数(标题、sheet名称、是否创建表头,表格类型)
     * @param response
     */
    public static void exportExcel(List<?> list, Class<?> pojoClass, String fileName, ExportParams exportParams, HttpServletResponse response) throws IOException {
        defaultExport(list, pojoClass, fileName, response, exportParams);
    }

    /**
     * excel 导出
     *
     * @param list      数据列表
     * @param title     表格内数据标题
     * @param sheetName sheet名称
     * @param pojoClass pojo类型
     * @param fileName  导出时的excel名称
     * @param response
     */
    public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response) throws IOException {
        //给文件名拼接上日期
        SimpleDateFormat formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
        String dateString = formatter.format (new Date());
        fileName = fileName +  dateString;
        //判断导出数据是否为空
        if (list == null) {
            list = new ArrayList<>();
        }
        //判断导出数据数量是否超过限定值
        if (list.size() > EXPORT_EXCEL_MAX_NUM) {
            title = "导出数据行数超过:" + EXPORT_EXCEL_MAX_NUM + "条,无法导出、请添加导出条件!";
            list = new ArrayList<>();
        }
        //获取导出参数
        ExportParams exportParams = new ExportParams(title, sheetName, ExcelType.XSSF);
        //设置导出样式
        exportParams.setStyle(ExcelStyleUtil.class);
        //设置行高
        exportParams.setHeight((short) 6);



        defaultExport(list, pojoClass, fileName, response, exportParams);
    }




    /**
     * 根据模板生成excel后导出
     * @param templatePath  模板路径
     * @param map 数据集合
     * @param fileName 文件名
     * @param response
     * @throws IOException
     */
    public static void exportExcel(TemplateExportParams templatePath, Map<String, Object> map, String fileName, HttpServletResponse response) throws IOException {
        Workbook workbook = ExcelExportUtil.exportExcel(templatePath, map);
        downLoadExcel(fileName, response, workbook);
    }



    /**
     * excel下载
     *
     * @param fileName 下载时的文件名称
     * @param response
     * @param workbook excel数据
     */
    private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) throws IOException {
        try {
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName + ".xlsx", "UTF-8"));
            workbook.setForceFormulaRecalculation(true); //强制开启excel公式计算
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }



    /**
     * excel 导入
     *
     * @param file      excel文件
     * @param pojoClass pojo类型
     * @param <T>
     * @return
     */
    public static <T> List<T> importExcel(MultipartFile file, Class<T> pojoClass) throws IOException {
        return importExcel(file, 1, 1, pojoClass);
    }

    /**
     * excel 导入
     *
     * @param filePath   excel文件路径
     * @param titleRows  表格内数据标题行
     * @param headerRows 表头行
     * @param pojoClass  pojo类型
     * @param <T>
     * @return
     */
    public static <T> List<T> importExcel(String filePath, Integer titleRows, Integer headerRows, Class<T> pojoClass) throws IOException {
        if (StringUtils.isBlank(filePath)) {
            return null;
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        params.setNeedSave(true);
        params.setSaveUrl("/excel/");
        try {
            return ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);
        } catch (NoSuchElementException e) {
            throw new IOException("模板不能为空");
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }


    /**
     * excel 导入
     *
     * @param file       上传的文件
     * @param titleRows  表格内数据标题行
     * @param headerRows 表头行
     * @param pojoClass  pojo类型
     * @param <T>
     * @return
     */
    public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, Class<T> pojoClass) throws IOException {
        if (file == null) {
            return null;
        }
        try {
            return importExcel(file.getInputStream(), titleRows, headerRows, pojoClass);
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

    /**
     * excel 导入
     *
     * @param inputStream 文件输入流
     * @param titleRows   表格内数据标题行
     * @param headerRows  表头行
     * @param pojoClass   pojo类型
     * @param <T>
     * @return
     */
    public static <T> List<T> importExcel(InputStream inputStream, Integer titleRows, Integer headerRows, Class<T> pojoClass) throws IOException {
        if (inputStream == null) {
            return null;
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        params.setSaveUrl("/excel/");
        params.setNeedSave(true);
        try {
            return ExcelImportUtil.importExcel(inputStream, pojoClass, params);
        } catch (NoSuchElementException e) {
            throw new IOException("excel文件不能为空");
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

测试接口

package com.easypoi.controller;

import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import com.easypoi.pojo.Company;
import com.easypoi.pojo.User;
import com.easypoi.utils.ExcelUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

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

@RestController
@RequestMapping("/easypoi")
public class EasypoiController {
    /**
     * 导入excel数据
     * @param file
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/import", method = RequestMethod.POST)
    public ResponseEntity<String> importExcel(@RequestParam("file") MultipartFile file) throws IOException {
        List<User> list = ExcelUtils.importExcel(file, User.class);
//        int i = userService.insertByBatch(list); //将数据写入到数据库中
//        if (i != 0) {
//            return ResponseEntity.ok( "导入成功");
//        } else {
//            return ResponseEntity.ok( "导入失败");
//        }

        return ResponseEntity.ok( "导入成功");
    }



    

    /**
     * 导出数据
     *  // http://localhost:1011/easypoi/exportExcel
     * @param response
     * @throws IOException
     */
    @GetMapping("/exportExcel")
    public void exportExcel( HttpServletResponse response) throws IOException {
        List<User> list=new ArrayList<User>(){{
            add(User.builder().username("我是大白鲨").age(12).name("胡安民").sex("0").address("北京市").build());
            add(User.builder().username("我是大白鲨1").age(12).name("胡安民1").sex("1").address("北京市1").build());
            add(User.builder().username("我是大白鲨1").age(12).name("胡安民1").sex("男").address("北京市1").build());

        }};

        ExcelUtils.exportExcel(list, "用户信息统计表Title", "用户表Sheet", User.class, "用户信息统计File", response);

    }


    
    

    /**
     * excel带图片的导出
     * // http://localhost:1011/easypoi/imgexport
     * @param response
     * @throws IOException
     */
    @GetMapping("/imgexport")
    public void imgExport(HttpServletResponse response) throws IOException {
        List<Company> list = new ArrayList<>();
        //图片的路径自定义,但必须要正确
        list.add(new Company("百度", "E:/img/1.jpg", "百度一下你就知道"));
        list.add(new Company("腾讯", "E:/img/3.jpg", "腾讯qq,交流的世界"));
        list.add(new Company("阿里巴巴", "E:/img/2.jpg", "阿里巴巴,马云的骄傲"));

        ExcelUtils.exportExcel(list, "图片excelTile", "图片excelSheet", Company.class, "图片excelFile", response);
    }

    /**
     * excel带图片的导入  只支持在linux服务器上 (可以自行查看源码)
     * // http://localhost:1011/easypoi/imgexport
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping("/imgimport")
    public ResponseEntity imgImport(@RequestParam("file") MultipartFile file) throws IOException {

        List<Company> list = ExcelUtils.importExcel(file, Company.class);
        return  ResponseEntity.ok("导入成功:"+list);
    }





    /**
     * 使用模板excel导出  (专门处理一些复杂情况下的数据导出)
     * //http://localhost:1011/easypoi/excelTemplate
     * @param response
     * @throws Exception
     */
    @GetMapping("/excelTemplate")
    public void makeExcelTemplate(HttpServletResponse response) throws Exception {
        List<User> list=new ArrayList<User>(){{
            add(User.builder().username("我是大白鲨").age(12).name("胡安民").sex("0").address("北京市").build());
            add(User.builder().username("我是大白鲨1").age(12).name("胡安民1").sex("1").address("北京市1").build());
            add(User.builder().username("我是大白鲨1").age(12).name("胡安民1").sex("男").address("北京市1").build());

        }};


        TemplateExportParams templatePath = new TemplateExportParams("E:/test.xlsx");
        Map<String, Object> map = new HashMap<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        map.put("date", sdf.format(new Date()));
        map.put("user", "admin");
        map.put("userList", list);
        ExcelUtils.exportExcel(templatePath, map, "使用模板excel导出File", response);
    }
}

application.yml

server:
  port: 1011


spring:
  main:
    allow-bean-definition-overriding: true  #easypoi启用覆盖
  datasource:
    driverClassName: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/voidme?useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false&serverTimezone=UTC
    username: root
    password: root
    hikari.idle-timeout: 60000
    hikari.maximum-pool-size: 30
    hikari.minimum-idle: 10



#spring集成Mybatis环境
#实体类别名扫描包    如果使用接口的话这个可以省略
# 加载Mybatis映射文件 classpath:mapper/*Mapper.xml 代表是  resources 下mapper包里所有是 ..Mapper.xml结尾的xml配置文件  如果使用接口的话这个可以省略
mybatis:
  type-aliases-package: com.easypoi.pojo
  mapper-locations: classpath:mybaitis/*Mapper.xml
  configuration:
    map-underscore-to-camel-case: true

启动类

package com.easypoi;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync

public class EasypoiAppllication {

    public static void main(String[] args) {
        SpringApplication.run(EasypoiAppllication.class,args);
    }

}

效果图

导出效果图

SpringBoot-EasyPoi

带图片的导出效果图

SpringBoot-EasyPoi

使用模板excel导出效果图

SpringBoot-EasyPoi

使用模板excel导出,@Excel注解(无效) 这个是BUG占时官方没有解决

excel模板导出规则

在上面我们已经提供了接口了, 但是excel的模板格式 和规则是什么呢???

SpringBoot-EasyPoi

在两个大括号里写对应的数据名称。

$fe用来遍历数据 , : list数据源 (变量默认t,不需要写)

{{$fe: maplist   t.id }}

http://doc.wupaas.com/docs/easypoi/easypoi-1c10lfhut694k (官方,一般不建议使用代码操作太复杂的表格了)

点赞 -收藏-关注-便于以后复习和收到最新内容
有其他问题在评论区讨论-或者私信我-收到会在第一时间回复
如有侵权,请私信联系我
感谢,配合,希望我的努力对你有帮助^_^
上一篇:L1-038 新世界 (5 分)


下一篇:easypoi框架导出excel