您现在的位置是:首页 > 文章详情

POI事件模式指北(一)-Excel2003

日期:2019-02-15点击:428

POI事件模式指北(一)-Excel2003

1、简介

Excel2003(.xls)是Microsoft Excel2003之前版本要求的格式,POI提供两种方式读取这种类型的文件

1、用户模式(User API):将xls文件全部读进内存,然后以dom结构处理;

2、事件模式(event API):用流的形式读取文件,占用内存较少,适用于愿意学习低级API结构的开发人员,需要对Excel文件的各个部分有基本的了解。

2、XLS文件介绍

XLS后缀的文件包括Worksheet文档和Workbook文档两种。是Excel 4.0及以前版本为Worksheet文档;以后的版本为Workbook文档。

2.1、Worksheet Document

Worksheet文档只包括一个sheet,默认的文件后缀是“XLS”。

1550305595932

2.2、Workbook Document

Workbook文档可以包含多个sheet,每个Workbook文档都包含一个全局设置,叫做(workbook globals)。

1550306121698

3、OLE 2复合文档系统 - POIFS

就像上面展示的,xls实际上实际上以复合文档的形式组织在一起;然后POI以流的形式读取。

3.1、Workbook文件流 (Workbook Streams)

Workbook文件流会先读取workbook globals Substream,然后再依次读取每个Sheet Substream。

1550307124052

这里展示的是Workbook文档的文件流结构。鉴于我们基本不会遇到Worksheet Document,下面将只针对Workbook Document来讨论。更多相关信息请参见文末参考链接。

3.2、Workbook Records

文件中的各种流会以Record的形式被解析,每个Record都包含特定的数据和格式等相关信息。

例如BOFRecord记录了Workbook或Sheet的开始、EOFRecord记录了Workbook或Sheet的结束等等。。。

org.apache.poi.hssf.record包下面包括了各种Record类,我们需要的数据和文档结构就包含在各个Record类中。

我们常用的Record差不多有下面这些:

// 记录了sheetName BoundSheetRecord // Workbook、Sheet的开始 BOFRecord // 存在单元格样式的空单元格 BlankRecord // 布尔或错误单元格 BoolErrRecord // 公式单元格 FormulaRecord // 公式的计算结果单元格 StringRecord // 文本单元格 LabelRecord // 共用的文本单元格 LabelSSTRecord // 数值单元格:数字单元格和日期单元格 NumberRecord // Workbook、Sheet的结束 EOFRecord

4、解析文件

想要利用事件模式的API,需要将文件用FileSystem将文件读取进来

​ 1、继承HSSFListener接口,创建自己的监听器listener;

利用recordsid,recordsid是org.apache.poi.hssf.record中的类中包含的静态引用号(例如BOFRecord.sid)

​ 2、使用HSSFRequest.addListener(yourlistener,recordsid)注册监听器,也可以用HSSFRequest.addListenerForAllRecords(mylistener)添加全部监听器;

​ 3、构造org.apache.poi.poifs.filesystem.FileSystem的实例并将其传递给XLS文件输入流;

​ 4、将输入流DocumentInputStream解析成record;

​ 5、根据注册的监听类型分别处理各种类型的record;

4.1、org.apache.poi.hssf.eventusermodel.HSSFEventFactory

事件模式常用的方法一般是下面两个:

/** * 将一个文件处理为基本的Record事件 * @param req 一个HSSFRequest实例,记录了Record的所有监听器 * @param fs 包含WorkBook的POIFS文件系统 */ HSSFEventFactory.processWorkbookEvents(HSSFRequest req, POIFSFileSystem fs) /** * 将一个文件处理为基本的Record事件 * @param req 一个HSSFRequest实例,记录了Record的所有监听器 * @param in 包含WorkBook的DirectoryNode的输入流 */ HSSFEventFactory.processEvents(HSSFRequest req, InputStream in)

5、事件模式实例

这个例子是参照POI官网提供的代码,针对的是POI最新的版本POI 4.0.1;但我们常用的3.x也基本都可以正常运行

EventExample.class

/** * 此示例显示如何使用事件API读取文件 */ public class EventExample implements HSSFListener { private SSTRecord sstrec; /** * 此方法监听传入记录并根据需要处理它们 * @param record读取时找到的记录 */ public void processRecord(Record record) { switch (record.getSid()) { //BOFRecord可以表示工作表或工作簿的开头 case BOFRecord.sid: BOFRecord bof = (BOFRecord) record; if (bof.getType() == bof.TYPE_WORKBOOK) { System.out.println("监听到工作表"); } else if (bof.getType() == bof.TYPE_WORKSHEET) { System.out.println("监听到工作簿"); } break; case BoundSheetRecord.sid: BoundSheetRecord bsr = (BoundSheetRecord) record; System.out.println("工作簿名称: " + bsr.getSheetname()); break; case RowRecord.sid: RowRecord rowrec = (RowRecord) record; System.out.println("监听到行, 第一行位于 " + rowrec.getFirstCol() + " 最后一行位于 " + rowrec.getLastCol()); break; case NumberRecord.sid: NumberRecord numrec = (NumberRecord) record; System.out.println("发现单元格: " + numrec.getValue() + " 位于 " + numrec.getRow() + " 行, " + numrec.getColumn() + " 列" ); break; case LabelSSTRecord.sid: LabelSSTRecord lrec = (LabelSSTRecord) record; System.out.println("找到文本值: " + sstrec.getString(lrec.getSSTIndex())); break; } } / ** * 读取Excel文件,并打印出文件内容 * @param args 要读取的文件 * @throws IOException * / public static void main(String[] args) throws IOException { // 使用输入的文件创建一个新的文件输入流 FileInputStream fin = new FileInputStream(args[0]); // 创建一个新的org.apache.poi.poifs.filesystem.Filesystem POIFSFileSystem poifs = new POIFSFileSystem(fin); // 在InputStream中获取Workbook流 InputStream din = poifs.createDocumentInputStream("Workbook"); // 构造出HSSFRequest对象 HSSFRequest req = new HSSFRequest(); // 注册全部的监听器 req.addListenerForAllRecords(new EventExample()); // 创建事件工厂 HSSFEventFactory factory = new HSSFEventFactory(); // 根据文档输入流处理我们监听的事件 factory.processEvents(req, din); // 关闭文件输入流 fin.close(); // 关闭文档输入流 din.close(); System.out.println("读取结束"); } }

6、后记

本文主要介绍了利用POI读取xls文件,xls文件因为是Excel2003以前的版本都使用的格式,其实不同版本之间还是有一些不同的,如果遇到了奇怪的问题不妨考虑一下版本的问题。这篇文章没有涉及d的实用部分,会在之后的文章中写出来。


参考链接
Apache POI官网: https://poi.apache.org
XLS规范[PDF]: http://www.openoffice.org/sc/excelfileformat.pdf

原文链接:https://yq.aliyun.com/articles/690473
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章