1 POI 组件依赖
按需引入对应依赖 (给出官方的指引)
组件 | 作用 | Maven依赖 |
---|---|---|
POIFS | OLE2 Filesystem | poi |
HPSF | OLE2 Property Sets | poi |
HSSF | Excel XLS | poi |
HSLF | PowerPoint PPT | poi-scratchpad |
HWPF | Word DOC | poi-scratchpad |
HDGF | Visio VSD | poi-scratchpad |
HPBF | Publisher PUB | poi-scratchpad |
HSMF | Outlook MSG | poi-scratchpad |
DDF | Escher common drawings | poi |
HWMF | WMF drawings | poi-scratchpad |
OpenXML4J | OOXML | poi-ooxml plus either poi-ooxml-schemas or ooxml-schemas and ooxml-security |
XSSF | Excel XLSX | poi-ooxml |
XSLF | PowerPoint PPTX | poi-ooxml |
XWPF | Word DOCX | poi-ooxml |
XDGF | Visio VSDX | poi-ooxml |
Common SL | PowerPoint PPT 和 PPTX 共用组件 | poi-scratchpad and poi-ooxml |
Common SS | Excel XLS 和 XLSX 共用组件 | poi-ooxml |
XSSF | Excel XLSX | poi-ooxml |
XSLF | PowerPoint PPTX | poi-ooxml |
XWPF | Word DOCX | poi-ooxml |
XDGF | Visio VSDX | poi-ooxml |
Common SL | PowerPoint PPT 和 PPTX 共用组件 | poi-scratchpad and poi-ooxml |
Common SS | Excel XLS 和 XLSX 共用组件 | poi-ooxml |
2 什么是 OLE2 和 OOXML
OLE2 和 OOXML 本质上都是一种文件格式规范或标准,平时看到的 excel 中,有字体、公式、颜色、图片等等,看起来非常复杂,但是在文件结构上都遵循着固定的格式。
OLE2 文件一般包括 xls、doc、ppt 等,是二进制格式的文件。 相关内容可以参考: 复合文档Ole对象二进制储存格式 。
OOXML文件一般包括 xlsx、docx、pptx 等。该类文件以指定格式的 xml 为基础并以 zip 格式压缩,这里我利用解压工具解压本地的一个 xlsx 文件,可以看到以下文件结构,在本文例子中,我们会重点关注 sharedStrings.xml 和 sheet1.xml 的内容,因为使用 SAX API 时必须用到:
包名 | 描述 |
---|---|
org.apache.poi.ss | Excel API,底层解析方式类似 DOM,效率较低,内存占用较大 |
org.apache.poi.hssf | Excel XLS API,采用 SAX API 方式读写 |
org.apache.poi.xssf | Excel XLSX API,采用 SAX API 方式读写 |
POI SAX 方式的 API 非常繁琐,使用时须熟练掌握 OLE2 或 OOXML 的规范
SXSSFWorkbook
SXSSFWorkbook
专门处理大数据,对于大型 Excel 的创建且不会内存溢出,主要原理是借助临时存储空间生成 Excel.
SXSSFWorkbook
是 Streaming 版本的 XSSFWorkbook
, 它只会保存最新的 Excel rows 在内存里供查看, 在此之前的 Excel rows 都会被写入到硬盘里 (e.g. Windows 写入到 C盘 根目录下的 temp 文件夹). 被写入到硬盘里的 rows是 不可见 / 不可访问的. 只有还在内存的才可被访问到
注: HSSFWorkbook
和 XSSFWorkbook
的 Excel Sheet 导出条数上限是 [65535行, 256 列] (<=2003版) , 或 [1048576行, 16384列] (>=2007版) , 如果数据量超过了此上限, 那么可以使用 SXSSFWorkbook
来导出. (实际中上万条数据, 甚至上千条数据就可以考虑使用 SXSSFWorkbook
了)
poi 4.0.0 版本需要 JDK 1.8 以上,如果是 JDK 1.7 就使用 3.9 版本
// 这样表示 SXSSFWorkbook 只会保留 100条 数据在内存中, 其它的数据都会写到磁盘里, 这样的话占用的内存就会很少
sxssfWorkbook = new SXSSFWorkbook(fechXSSFWorkbook(filePath), 100);
SXSSFSheet sheet = sxssfWorkbook.getSheetAt(0); // 获取第一个 Sheet 页
for (int i = 0; i < 50; i++) {
for (int z = 0; z < 10000; z++) {
SXSSFRow row = sheet.createRow(i*10000+z);
for (int j = 0; j < 10; j++) {
row.createCell(j).setCellValue("你好:"+j);
}
}
}
outputStream = new BufferedOutputStream(new FileOutputStream(filePath));
sxssfWorkbook.write(outputStream);
outputStream.flush();
sxssfWorkbook.dispose(); // 释放 workbook 所占用的所有资源
3 EasyExcel
3.1 关于常见类解析
EasyExcel
入口类,用于构建开始各种操作ExcelReaderBuilder
ExcelWriterBuilder
构建出一个ReadWorkbook
WriteWorkbook
,可以理解成一个Excel 对象,一个 Excel 只需构建一个ExcelReaderSheetBuilder
ExcelWriterSheetBuilder
构建出一个ReadSheet
WriteSheet
对象,可以理解成 Excel 里面的一页,每一页都要构建一个ReadListener
在每一行读取完毕后都会调用ReadListener
来处理数据WriteHandler
在每一个操作包括创建单元格、创建表格等都会调用WriteHandler
来处理数据- 所有配置都是继承的,
Workbook
的配置会被Sheet
继承,所以在用EasyExcel
设置参数的时候,在EasyExcel...sheet()
方法之前作用域是整个 Sheet, 之后针对单个 Sheet
3.2 读
3.2.1 注解
ExcelProperty
指定当前字段对应 Excel 中的那一列。可以根据名字或者 index 去匹配。当然也可以不写,默认第一个字段就是 index=0,以此类推。千万注意,要么全部不写,要么全部用 index,要么全部用名字去匹配。千万别三个混着用,除非你非常了解源代码中三个混着用怎么去排序的。ExcelIgnore
默认所有字段都会和 Excel 去匹配,加了这个注解会忽略该字段DateTimeFormat
日期转换,用String
去接收 Excel 日期格式的数据会调用这个注解。里面的value
参照java.text.SimpleDateFormat
NumberFormat
数字转换,用String
去接收 Excel 数字格式的数据会调用这个注解。里面的value
参照java.text.DecimalFormat
ExcelIgnoreUnannotated
默认不加ExcelProperty
的注解的都会参与读写,加了不会参与
3.2.2 参数
3.2.2.1 通用参数
ReadWorkbook
, ReadSheet
都会有的参数,如果为空,默认使用上级。
converter
转换器,默认加载了很多转换器。也可以自定义。readListener
监听器,在读取数据的过程中会不断的调用监听器。headRowNumber
需要读的表格有几行头数据。默认有一行头,也就是认为第二行开始起为数据。head
与clazz
二选一。读取文件头对应的列表,会根据列表匹配数据,建议使用class。clazz
与head
二选一。读取文件的头对应的class,也可以使用注解。如果两个都不指定,则会读取全部数据。autoTrim
字符串、表头等数据自动 trimpassword
读的时候是否需要使用密码
3.2.2.2 ReadWorkbook(理解成Excel对象)参数
excelType
当前excel的类型 默认会自动判断inputStream
与file
二选一。读取文件的流,如果接收到的是流就只用,不用流建议使用file
参数。因为使用了inputStream
EasyExcel会帮忙创建临时文件,最终还是file
file
与inputStream
二选一。读取文件的文件。autoCloseStream
自动关闭流。readCache
默认小于5M用 内存,超过5M会使用EhCache
,这里不建议使用这个参数。
3.2.2.3 ReadSheet(就是Excel的一个Sheet)参数
sheetNo
需要读取Sheet的编码,建议使用这个来指定读取哪个SheetsheetName
根据名字去匹配 Sheet, Excel 2003不支持根据名字去匹配
3.3 写
3.3.1 注解
ExcelProperty
index 指定写到第几列,默认根据成员变量排序。value
指定写入的名称,默认成员变量的名字,多个value
可以参照快速开始中的复杂头ExcelIgnore
默认所有字段都会写入 Excel,这个注解会忽略这个字段DateTimeFormat
日期转换,将Date
写到 Excel 会调用这个注解。里面的value
参照java.text.SimpleDateFormat
NumberFormat
数字转换,用Number
写 Excel 会调用这个注解。里面的value
参照java.text.DecimalFormat
ExcelIgnoreUnannotated
默认不加ExcelProperty
的注解的都会参与读写,加了不会参与
3.3.2 参数
3.3.2.1 通用参数
WriteWorkbook
, WriteSheet
, WriteTable
都会有的参数,如果为空,默认使用上级.
converter
转换器,默认加载了很多转换器。也可以自定义.writeHandler
写的处理器。可以实现WorkbookWriteHandler
,SheetWriteHandler
,RowWriteHandler
,CellWriteHandler
, 在写入 Excel 的不同阶段会调用relativeHeadRowIndex
距离多少行后开始。也就是开头空几行needHead
是否导出头head
与clazz
二选一。写入文件的头列表,建议使用 classclazz
与head
二选一。写入文件的头对应的 class,也可以使用注解autoTrim
字符串、表头等数据自动 trim
3.3.2.2 WriteWorkbook(理解成 Excel 对象)参数
excelType
当前excel的类型 默认xlsx
outputStream
与file
二选一。写入文件的流file
与outputStream
二选一。写入的文件templateInputStream
模板的文件流templateFile
模板文件autoCloseStream
自动关闭流。password
写的时候是否需要使用密码useDefaultStyle
写的时候是否是使用默认头
3.3.2.3 WriteSheet(就是 Excel 的一个 Sheet)参数
sheetNo
需要写入的编码。默认0sheetName
需要些的 Sheet 名称, 默认同sheetNo
3.3.2.4 WriteTable(就把 Excel 的一个 Sheet, 一块区域看一个 table)参数
tableNo
需要写入的编码. 默认 0
POI upgrade to 5.2.3
Apache POI 版本 <= 4.1.0 中, 使用 XSSFExportToXml 转换 Excel 文档时,
可在 xmlMaps.xml 加入恶意代码制作成 excel 文档, 代码解析恶意文档时,
可以允许攻击者通过 XML External Entity (XXE) 处理在服务器读取文件资源或发送外部请求.
漏洞是在使用 XSSFExportToXml 类 xlsx 转 xml 时触发.
poi > 5.2.3
poi_ooxml > 5.2.3
去掉 poi_ooxml_schemas 依赖
EasyExcel upgrading poi to 5.2.3
接口 | 变动 | 栗子 |
---|---|---|
org.apache.poi.ss.usermodel.CellBase | remove | remove method CellType getCachedFormulaResultTypeEnum() |
org.apache.poi.ss.usermodel.CellStyle | remove|change|add | return short change to int |
org.apache.poi.ss.usermodel.Sheet | add | |
org.apache.poi.ss.usermodel.Workbook | remove|change|add | short to int add method #createEvaluationWorkbook add attribute cellReferenceType |