让poi架起java与office之间的桥梁,让POI架起Java与Office之间的桥梁二

1/5/2008

3255

五、通过eventusermodel读取文件

通过eventusermodel读取文件要比使用usermodel复杂得多,但效率也要高不少,因为它要求应用程序一边读取数据,一边处理数据。

eventusermodel实际上模拟了DOM环境下SAX处理XML文档的办法,应用程序首先要注册期望处理的数据,eventusermodel将在碰到匹配的数据结构时回调应用程序注册的方法。使用eventusermodel最大的困难在于你必须熟悉Excel工作簿的内部结构。

在HSSF中,低层次的二进制结构称为记录(Record)。记录有不同的类型,每一种类型由org.apache.poi.hssf.record包中的一个Java类描述。例如,BOFRecord记录表示Workbook或Sheet区域的开始,RowRecord表示有一个行存在并保存其样式信息。

所有具有CellValueRecordInterface接口的记录表示Excel的单元格,包括NumericRecord、LabelSSTRecord和FormulaRecord(还有其他一些,其中部分已被弃置不用,部分用于优化处理,但一般而言,HSSF可以转换它们)。

下面是一个注册事件处理句柄的例子:

private EventRecordFactory factory = new EventRecordFactory();

factory.registerListener(new ERFListener() {

public boolean processRecord(Record rec) {

(got BOF Record);

return true;

}

}, new short[] {BOFRecord.sid});

factory.processRecords(someInputStream);

六、HSSF电子表格结构

如前所述,HSSF建立在POIFS的基础上。具体地说,Excel 97+文件是OLE 2复合文档( OLE 2 Compound Document),底层的OLE 2复合文档保存了一个总是命名为Workbook(Excel 95除外,HSSF不支持Excel 95)的流。

然而,宏和图片并不保存在Workbook流,它们有自己独立的流,有时甚至会放到OLE 2 CDF文件之内的另一个目录。理想情况下,宏也应该被保留,不过目前POI项目中还没有合适的API来处理宏。

每一个流之内是一组记录,一个记录其实就是一个字节数组,可分为记录头、记录体两部分。记录头指明了记录的类型(也即ID)以及后继数据的长度,记录体被分割成多个字段(Field),字段包含数值数据(包括对其他记录的引用)、字符数据或标记。

Excel工作簿的顶级结构:

Bla.xls {

OLE2CDF headers

"Workbook" stream {

Workbook {

Static String Table Record..

Sheet names… and pointers

}

Sheet {

ROW

ROW

NUMBER RECORD (cell)

LABELSST Record (cell)

}

Sheet

}

}

… images, macros, etc.

Document Summary

Summary

七、通过HPSF读取文档属性

在Microsoft Word、Excel、Powerpoint等软件中,用户可以通过“文件”→“属性”菜单给文档添加附加信息,包括文档的标题、主题、摘要、类别、要害词等,同时应用软件本身还会加入最后访问的用户、最后访问和修改/打印的日期时间等信息。

文档的属性和正文是分开保存的。如前所述,OLE 2 CDF文件内部就象是一个容器,里面包含许多类似目录和文件的结构,而POIFS就是用来访问其中的文件的工具。这些文件也称为流,文档的属性就保存在POIFS文件系统中专用的流里面。

以一个Word文档为例:虽然在资源治理器中你只看到一个叫做MyFile.doc的文档,其实在这个文档的内部,又包含了一个WordDocument、一个SummaryInformation和一个DocumentSummaryInformation文档;通常还会有其他的文档,这里暂且不管。

你能够猜出这些文档(流)分别包含什么内容吗?不错,WordDocument包含了你在Word里面编辑的文本,文档的属性保存在SummaryInformation和DocumentSummaryInformation流里面。也许将所有属性保存在单个文档里面看起来太简单了,所以Microsoft决心要使用两个流,为了使事情更复杂一点,这两个流的名字前面还加上了八进制的\005字符??这是一个不可打印的字符,因此前面就把它省略了。

Microsoft定义的标准属性有一个好处,它们并不在乎主文档到底是什么类型??不管是Word文档、Excel工作簿还是PowerPoint幻灯。只要你知道如何读取Excel文档的属性,就知道了如何读取其他文档的属性。

读取文档属性其实并不复杂,因为Java程序可以利用POI项目的HPSF包。HPSF是 Horrible Property Set Format的缩写,译成中文就是“讨厌的属性集格式”。HPSF包是POI项目实现的读取属性工具,目前还不支持属性写入。

对于读取Microsoft定义的标准属性,通过HPSF提供的API可以很方便地办到;但假如要读取任意属性集就要用到更一般化的API,可以想象它要比读取标准属性的API复杂不少。本文只介绍读取标准属性的简单API,因为对大多数应用程序来说这已经完全足够了。

下面就是一个读取OLE 2 CDF文档的标题(title)属性的Java程序:

import java.io.*;

import org.apache.poi.hpsf.*;

import org.apache.poi.poifs.eventfilesystem.*;

/**

* 读取OLE 2文档标题的示例程序,

* 在命令行参数中指定文档的文件名字。

*/

public class ReadTitle

{

public static void main(String[] args) throws IOException

{

final String filename = args[0];

POIFSReader r     = new POIFSReader();

r.registerListener(new MyPOIFSReaderListener(),

"\005SummaryInformation");

r.read(new FileInputStream(filename));

}

static class MyPOIFSReaderListener

implements POIFSReaderListener

{

public void processPOIFSReaderEvent(POIFSReaderEvent event)

{

SummaryInformation si = null;

try

{

si = (SummaryInformation)

PropertySetFactory.create(event.getStream());

}

catch (Exception ex)

{

throw new RuntimeException

("属性集流\"" + event.getPath() +

event.getName() + "\": " + ex);

}

final String title = si.getTitle();

if (title != null)

System.out.println("标题: \"" + title + "\"");

else

System.out.println("该文档没有标题.");

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值