main()方法利用poifs的事件系统从命令行指定的ole 2文档读取名为/005summaryinformation的流,当poifsreader 遇到这个流时,它把控制传递给mypoifsreaderlistener的processpoifsreaderevent()方法。
processpoifsreaderevent()到底有什么用呢?它通过参数获得一个输入流,该输入流包含了文档标题等属性。为了访问文档的属性,我们从输入流创建一个propertyset实例,如下所示:
si = (summaryinformation) propertysetfactory.create(event.getstream());
这个语句其实包含三个步骤的操作:
◆ event.getstream()从poifsreader传入的poifsreaderevent获得输入流。
◆ 以刚才获得的输入流为参数,调用propertysetfactory的静态方法create()。正如其名字所暗示的,propertysetfactory是一个工厂类,它有一台“机器”能够把一个输入流转换成一个propertyset实例,这台机器就是create()方法。
◆ 把create()方法返回的propertyset定型(cast)成为summaryinformation。propertyset提供了按照一般办法读取属性集的各种机制,summaryinformation是propertyset的子类,即summaryinformation类在propertyset类的基础上增加了操作microsoft标准属性的便捷方法。
在这个处理过程中,可能引起错误的因素很多,因此我们把这部分内容放入了一个try块,不过这个示例程序只按照最简单的方式处理了异常,在实际应用中,最好能够对可能出现的不同异常类型分别处理。
除了一般的i/o异常之外,还有可能遇到hpsf特有的异常,例如,如果输入流不包含属性集或属性集非法,就会抛出nopropertysetstreamexception异常。
有一种错误不太常见,但也不是绝无可能/005summaryinformation包含一个合法的属性集,但不是摘要信息属性集。如果出现这种情况,则定型成summaryinformation操作会失败,引发classcastexception异常。
获得summaryinformation实例之后,剩下的事情就很简单了,只要调用gettitle()方法,然后输出结果。
除了gettitle()之外,summaryinformation还包含其他一些便捷方法,例如getapplicationname()、getauthor()、getcharcount()、和getcreatedatetime()等。hpsf的javadoc文档详细说明了所有这些方法。
八、文档摘要信息
遗憾的是,并非所有的属性都保存在摘要信息属性集之中。许多(但不是全部)ole 2文件还有另一个属性集,称为“文档摘要信息”,对应的流是/005documentsummaryinformation。这个属性集保存的属性包括文档的类别、powerpoint幻灯的多媒体剪辑数量,等等。
要访问文档摘要信息属性集,程序的处理过程也和上例相似,只是注册的目标应该改成/005documentsummaryinformation有时,你可能想要同时注册到摘要信息和文档摘要信息这两个流。其余的处理方式和前面的例子差不多,你应该把包含文档摘要信息的流传递给propertysetfactory.create(),但这次工厂方法将返回一个documentsummaryinformation对象(而不是前面例子中的summaryinformation对象)。
如果同时注册到了两个流,注意检查返回值的具体类型,或者使用java的instanceof操作符,或者使用专用的issummaryinformation()和isdocumentsummaryinformation()方法。记住,create()方法返回的总是一个propertyset对象,因此你总是可以对create()返回对象调用issummaryinformation()和isdocumentsummaryinformation()方法,propertyset类之所以要提供这两个方法,是因为属性集可能是自定义的。
如果你想要处理自定义的属性集,或者要从标准的属性集读取用户定义的属性,必须使用一个更一般化的api,前面已经提到,这个api要复杂得多,本文不再讨论,请参见hpsf的how-to文档和poi的文档。
结束语:本文探讨了hssf的应用以及如何输出到excel文件,另外还涉及了hpsf以及如何读取属性集文档摘要信息。poi是一个功能非常强大的项目,许多主题本文尚未涉及,例如如何用hssf serializer将xml文档转换成excel格式等,这一切仍有待您去研究了。
九、附录
实例:利用servlet创建和返回一个工作簿。
package org.apache.poi.hssf.usermodel.examples;
import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.poi.hssf.usermodel.*;
public class hssfcreate extends httpservlet {
public void init(servletconfig config)
throws servletexception {
super.init(config);
}
public void destroy() {
}
/** 处理http get 和post请求
* @param request:请求
* @param response:应答
*/
protected void processrequest(httpservletrequest request,
httpservletresponse response)
throws servletexception, ioexception {
response.setcontenttype("application/vnd.ms-excel");
hssfworkbook wb = new hssfworkbook();
hssfsheet sheet = wb.createsheet("new sheet");
// 创建一个新的行,添加几个单元格。
// 行号从0开始计算
hssfrow row = sheet.createrow((short)0);
// 创建一个单元格,设置单元格的值
hssfcell cell = row.createcell((short)0);
cell.setcellvalue(1);
row.createcell((short)1).setcellvalue(1.2);
row.createcell((short)2).setcellvalue("一个字符串值");
row.createcell((short)3).setcellvalue(true);
// 写入输出结果
outputstream out = response.getoutputstream();
wb.write(out);
out.close();
}
/** 处理http get请求
* @param request:请求
* @param response:应答
*/
protected void doget(httpservletrequest request,
httpservletresponse response)
throws servletexception, ioexception {
processrequest(request, response);
}
/** 处理http post请求
* @param request:请求
* @param response:应答
*/
protected void dopost(httpservletrequest request,
httpservletresponse response)
throws servletexception, ioexception {
processrequest(request, response);
}
/** 返回关于servlet的简单说明
*/
public string getservletinfo() {
return "示例:在servlet中用hssf创建excel工作簿";
}
}
闽公网安备 35060202000074号