在做报表开发时,免不了要导出数据。除了简单的循环列表数据导出外,还有基于模板的数据导出。比如生成运营周报或者月报之类的,甚是符合使用模板导出方式。今天总结一些常用的Execl导出JAR包。
0x01:jxl
支持Excel 95-2000的所有版本;生成Excel 2000标准格式;支持字体、数字、日期操作;能够修饰单元格属性;支持图像和图表。
jxl是纯Java的,不依赖Windows系统,即使运行在Linux下,它同样能够正确的处理Excel文件。另外需要说明的是,jxl对图形和图表的支持很有限,而且仅仅识别PNG格式。
官网
http://jexcelapi.sourceforge.net/
仓库地址
https://mvnrepository.com/artifact/net.sourceforge.jexcelapi/jxl
备注,jxl已经有点过期了。已经很久没有更新了,可以说已经没有维护了。
0x02:Apache POI
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。最主要功能如下:
- HSSF - 提供读写Microsoft Excel格式档案的功能
- XSSF - 提供读写Microsoft Excel OOXML格式档案的功能
- HWPF - 提供读写Microsoft Word格式档案的功能
- HSLF - 提供读写Microsoft PowerPoint格式档案的功能
- HDGF - 提供读写Microsoft Visio格式档案的功能
Apache POI功能非常强大,可以解决几乎所有日常开发中遇到需要使用Execl的问题。但是在解决一些问题是需要开发人员编写大量的代码。
官网:
https://poi.apache.org/
0x03:easypoi
easypoi的功能如同名字easy,主打的功能就是容易,让一个没接触过poi的开发人员,就可以方便的写出Excel导出、Excel模板导出、Excel导、,Word模板导出等功能。通过简单的注解和模板语言(熟悉的表达式语法),完成以前复杂的写法。
API文档:
http://doc.wupaas.com/docs/easypoi/easypoi-1c0u4mo8p4ro8
仓库:
https://gitee.com/lemur/easypoi
https://gitee.com/lemur/easypoi-test
备注,easypoi对Apache POI进行了二次封装,屏蔽了Apache POI那些复制的API。
0x04:easyexcel
Java解析、生成Excel比较有名的框架有Apache POI、jxl。但都存在一个严重的问题就是非常耗内存,POI有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让开发人员更加简单方便。阿里巴巴出品必属精品。
API文档
https://www.yuque.com/easyexcel/doc/easyexcel
官网:
https://github.com/alibaba/easyexcel
下面是我在使用easyexcel时遇到的一个问题,应该说使用不当导致的问题。今天给大家讲一下免得,大家在使用中因为使用不当导致这个问题。先在github下载easyexcel,如果下载慢的话可以使用国内镜像:
https://gitee.com/mirrors/easyexcel
下载完后导入到开发工具eclipse或者idea,可以看到如下目录很多Execl模板
就看如下这个特别复杂的模板,不过演示的这个问题跟模板的复杂程度无关。
找到操作该模板的代码所在
把相关代码拷贝出来,新建一个TestTemplate.java类
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.easyexcel.test.demo.fill.FillData;
import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.WriteDirectionEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
public class TestTemplate {
public static void main(String[] args) {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// {} 代表普通变量 {.} 代表是list的变量 {前缀.} 前缀可以区分不同的list
String templateFileName =
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "composite.xlsx";
//保存的目录
String fileName = "d:/" + System.currentTimeMillis() + ".xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
// 如果有多个list 模板上必须有{前缀.} 这里的前缀就是 data1,然后多个list必须用 FillWrapper包裹
excelWriter.fill(new FillWrapper("data1", data()), fillConfig, writeSheet);
excelWriter.fill(new FillWrapper("data1", data()), fillConfig, writeSheet);
excelWriter.fill(new FillWrapper("data2", data()), writeSheet);
excelWriter.fill(new FillWrapper("data2", data()), writeSheet);
excelWriter.fill(new FillWrapper("data3", data()), writeSheet);
excelWriter.fill(new FillWrapper("data3", data()), writeSheet);
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2019年10月9日13:28:28");
excelWriter.fill(map, writeSheet);
// 别忘记关闭流
excelWriter.finish();
}
private static List<FillData> data() {
List<FillData> list = new ArrayList<FillData>();
for (int i = 0; i < 10; i++) {
FillData fillData = new FillData();
list.add(fillData);
fillData.setName("张三");
fillData.setNumber(5.2);
}
return list;
}
}
直接运行在d:/产生相关根据模板生成的文件。现在来改一下模板文件,把Sheet的名字由sheet1改成月报,并对代码做如下修改
WriteSheet writeSheet = EasyExcel.writerSheet().build();
改成
WriteSheet writeSheet = EasyExcel.writerSheet("sheet1").build();
出现以下异常
2020-11-29 19:49:17.120 DEBUG [main] com.alibaba.excel.context.WriteContextImpl:199 - Can not find sheet:null ,now create it
2020-11-29 19:49:17.198 DEBUG [main] com.alibaba.excel.context.WriteContextImpl:381 - Finished write.
Exception in thread "main" java.lang.NullPointerException
at com.alibaba.excel.write.executor.ExcelWriteFillExecutor.doFill(ExcelWriteFillExecutor.java:191)
at com.alibaba.excel.write.executor.ExcelWriteFillExecutor.fill(ExcelWriteFillExecutor.java:118)
at com.alibaba.excel.write.ExcelBuilderImpl.fill(ExcelBuilderImpl.java:78)
at com.alibaba.excel.ExcelWriter.fill(ExcelWriter.java:185)
at TestTemplate.main(TestTemplate.java:29)
所以在使用模板时注意一下他们之间的关系。