#yyds干货盘点#海量数据下如何使用多线程的导出 Excel

莫问天涯路几重,轻衫侧帽且从容。这篇文章主要讲述#yyds干货盘点#海量数据下如何使用多线程的导出 Excel相关的知识,希望能为你提供帮助。
前言
公司项目最近有一个需要:报表导出。整个系统下来,起码超过一百张报表需要导出。这个时候如何优雅的实现报表导出,释放生产力就显得很重要了。下面主要给大家分享一下该工具类的使用方法与实现思路。
实现的功能点
对于每个报表都相同的操作,我们很自然的会抽离出来,这个很简单。而最重要的是:如何把那些每个报表不相同的操作进行良好的封装,尽可能的提高复用性;针对以上的原则,主要实现了一下关键功能点:

  • 导出任意类型的数据
  • 自由设置表头
  • 自由设置字段的导出格式
使用实例
上面说到了本工具类实现了三个功能点,自然在使用的时候设置好这三个要点即可:
  • 设置数据列表
  • 设置表头
  • 设置字段格式
下面的export函数可以直接向客户端返回一个excel数据,其中??productInfoPos??为待导出的数据列表,??ExcelHeaderInfo??用来保存表头信息,包括表头名称,表头的首列,尾列,首行,尾行。
因为默认导出的数据格式都是字符串型,所以还需要一个Map参数用来指定某个字段的格式化类型(例如数字类型,小数类型、日期类型)。这里大家知道个大概怎么使用就好了,下面会对这些参数进行详细解释
@Override
public void export(HttpServletResponse response, String fileName)
// 待导出数据
List< TtlProductInfoPo> productInfoPos = this.multiThreadListProduct();
ExcelUtils excelUtils = new ExcelUtils(productInfoPos, getHeaderInfo(), getFormatInfo());
excelUtils.sendHttpResponse(response, fileName, excelUtils.getWorkbook());


// 获取表头信息
private List< ExcelHeaderInfo> getHeaderInfo()
return Arrays.asList(
new ExcelHeaderInfo(1, 1, 0, 0, "id"),
new ExcelHeaderInfo(1, 1, 1, 1, "商品名称"),

new ExcelHeaderInfo(0, 0, 2, 3, "分类"),
new ExcelHeaderInfo(1, 1, 2, 2, "类型ID"),
new ExcelHeaderInfo(1, 1, 3, 3, "分类名称"),

new ExcelHeaderInfo(0, 0, 4, 5, "品牌"),
new ExcelHeaderInfo(1, 1, 4, 4, "品牌ID"),
new ExcelHeaderInfo(1, 1, 5, 5, "品牌名称"),

new ExcelHeaderInfo(0, 0, 6, 7, "商店"),
new ExcelHeaderInfo(1, 1, 6, 6, "商店ID"),
new ExcelHeaderInfo(1, 1, 7, 7, "商店名称"),

new ExcelHeaderInfo(1, 1, 8, 8, "价格"),
new ExcelHeaderInfo(1, 1, 9, 9, "库存"),
new ExcelHeaderInfo(1, 1, 10, 10, "销量"),
new ExcelHeaderInfo(1, 1, 11, 11, "插入时间"),
new ExcelHeaderInfo(1, 1, 12, 12, "更新时间"),
new ExcelHeaderInfo(1, 1, 13, 13, "记录是否已经删除")
);


// 获取格式化信息
private Map< String, ExcelFormat> getFormatInfo()
Map< String, ExcelFormat> format = new HashMap< > ();
format.put("id", ExcelFormat.FORMAT_INTEGER);
format.put("categoryId", ExcelFormat.FORMAT_INTEGER);
format.put("branchId", ExcelFormat.FORMAT_INTEGER);
format.put("shopId", ExcelFormat.FORMAT_INTEGER);
format.put("price", ExcelFormat.FORMAT_DOUBLE);
format.put("stock", ExcelFormat.FORMAT_INTEGER);
format.put("salesNum", ExcelFormat.FORMAT_INTEGER);
format.put("isDel", ExcelFormat.FORMAT_INTEGER);
return format;

实现效果

源码分析
哈哈,自己分析自己的代码,有点意思。由于不方便贴出太多的代码,大家可以先到github上clone源码,再回来阅读文章。
https://github.com/dearKundy/excel-utils
LZ使用的??poi 4.0.1??版本的这个工具,想要实用海量数据的导出自然得使用??SXSSFWorkbook??这个组件。关于poi的具体用法在这里我就不多说了,这里主要是给大家讲解如何对poi进行封装使用。
成员变量我们重点看??ExcelUtils??这个类,这个类是实现导出的核心,先来看一下三个成员变量
private List list;
private List< ExcelHeaderInfo> excelHeaderInfos;
private Map< String, ExcelFormat> formatInfo;

list该成员变量用来保存待导出的数据
ExcelHeaderInfo该成员变量主要用来保存表头信息,因为我们需要定义多个表头信息,所以需要使用一个列表来保存,??ExcelHeaderInfo??构造函数如下??ExcelHeaderInfo(int firstRow, int lastRow, int firstCol, int lastCol, String title)??
  • firstRow:该表头所占位置的首行
  • lastRow:该表头所占位置的尾行
  • firstCol:该表头所占位置的首列
  • lastCol:该表头所占位置的尾行
  • title:该表头的名称
ExcelFormat该参数主要用来格式化字段,我们需要预先约定好转换成那种格式,不能随用户自己定。所以我们定义了一个枚举类型的变量,该枚举类只有一个字符串类型成员变量,用来保存想要转换的格式,例如??FORMAT_INTEGER??就是转换成整型。
因为我们需要接受多个字段的转换格式,所以定义了一个Map类型来接收,该参数可以省略(默认格式为字符串)
public enum ExcelFormat

FORMAT_INTEGER("INTEGER"),
FORMAT_DOUBLE("DOUBLE"),
FORMAT_PERCENT("PERCENT"),
FORMAT_DATE("DATE");

private String value;

ExcelFormat(String value)
this.value = https://www.songbingjia.com/android/value;


public String getValue()
return value;


核心方法1. 创建表头
该方法用来初始化表头,而创建表头最关键的就是poi中Sheet类的??addMergedRegion(CellRangeAddress var1)??方法,该方法用于??单元格融合??。
【#yyds干货盘点#海量数据下如何使用多线程的导出 Excel】我们会遍历ExcelHeaderInfo列表,按照每个ExcelHeaderInfo的坐标信息进行单元格融合,然后在融合之后的每个单元??首行??和??首列??的位置创建单元格,然后为单元格赋值即可,通过上面的步骤就完成了任意类型的表头设置。
// 创建表头
private void createHeader(Sheet sheet, CellStyle style)
for (ExcelHeaderInfo excelHeaderInfo : excelHeaderInfos)
Integer lastRow = excelHeaderInfo.getLastRow();
Integer firstRow = excelHeaderInfo.getFirstRow();
Integer lastCol = excelHeaderInfo.getLastCol();
Integer firstCol

    推荐阅读