资源预览内容
第1页 / 共9页
第2页 / 共9页
第3页 / 共9页
第4页 / 共9页
第5页 / 共9页
第6页 / 共9页
第7页 / 共9页
第8页 / 共9页
第9页 / 共9页
亲,该文档总共9页全部预览完了,如果喜欢就下载吧!
资源描述
POI2 与 POI3 差异及解决 excel2003 和excel2007 兼容性研究报告 第 1 页1 现有问题:近期发现报表系统(使用 EXCEL 作报表) ,在不知情的用户使用了 EXCEL2007 版本之后,出现了一系列兼容性问题:1、用 POI2.x 操作 EXCEL2007 文件,会导致后台错误。org.apache.poi7.poifs.filesystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)2、涉及 EXCEL 导出的部分,若文件内容是 EXCEL2007,却使用.XLS,为后缀名的文件。那么使用 EXCEL2003 打开会导致乱码现象。3、目前新建报表模版,无论客户端安装的是什么版本的 OFFICE,后台都是用EXCEL2003(POI2)文件格式创建的。4、目前兼容性问题影响范围包含但不限于:模板制作、报表导出、模板版本化、批量折合等所有用到 EXCEL 后台操作的功能。2 问题原因:报表平台现有系统在后台处理 Excel 都是使用 apache 的 POI2.x 进行解析处理,但是 poi2.x 是和 jdk1.4 兼容的,且 poi2.x 只能处理 excel2003 及以前的老版本 excel文件,客户机器上安装的往往是较新版的 office2007,要处理 excel2007 就必须使用poi3.5 以上的版本,poi3.5 及以上的版本适用 jdk1.5 版及以上,并支持 excel2007 的处理。3 POI2.x 与 POI3.x 的区别:3.1 什么是 POIApache POI 是 Apache 软件基金会的开放源码函式库,POI 提供 API 给 Java 程式对Microsoft Office 格式档案读和写的功能。现在较新较稳定的 POI 版本是 3.7,即常说的 POI7,最新的 POI3.8 已经出了 beta2 版本,支持 EXCEL2010 的操作。 第 2 页3.2 如何使用 POI完整的 POI3.8 beta2 包含如下类库:poi-3.8-beta2-20110408.jarpoi-examples-3.8-beta2-20110408.jarpoi-excelant-3.8-beta2-20110408.jarpoi-ooxml-3.8-beta2-20110408.jar ( Office Open XML) poi-ooxml-schemas-3.8-beta2-20110408.jarpoi-scratchpad-3.8-beta2-20110408.jar另需要一些配套包的支持dom4j-1.6.1.jarstax-api-1.0.1.jarxmlbeans-2.3.0.jar (必须使用 2.3 或以上的版本)commons-logging-1.1.jarjunit-3.8.1.jarlog4j-1.2.13.jarPOI3.8 的具体 API 及实现方法不在本文详述。3.3 POI 结构及版本区别:1、首先,相对于 POI2.X 及以下版本,POI3.X 支持较高版本的 Office 操作,在本文中关注的是能够对 EXCEL2007 进行操作,并可兼容操作 EXCEL2003。部分类图如下: 第 3 页(图 1)如上图,POI2.x 的结构只有类图中左半部分,POI3.x 新增了以 XSSF 前缀的 EXCEL文件操作对象,用于对 OOM 格式的 EXCEL 操作。POI3 完整具体结构和作用如下:结构: HSSF 提供读写 Microsoft Excel 格式档案的功能。 XSSF 提供读写 Microsoft Excel OOXML 格式档案的功能。 HWPF 提供读写 Microsoft Word 格式档案的功能。 HSLF 提供读写 Microsoft PowerPoint 格式档案的功能。 HDGF 提供读写 Microsoft Visio 格式档案的功能。 2、其次,另一个重要区别就是,excel2007 文件格式与之前版本不同,之前版本采用的是微软自己的存储格式。07 版内容的存储采用 XML 格式(OOM) 。 第 4 页4 现有问题解决方案:4.1 解决方案要求:1、解决目前 EXCEL2003 和 EXCEL2007 兼容性问题。2、提供后续 EXCEL 版本,如 EXCEL2010 的可扩展性。4.2 算法(实现逻辑)1、兼容性:如(图1)所示,我们可以看到,操作EXCEL2003的对象(HSSF为前缀)与操作EXCEL2007的对象(XSSF为前缀)共用一套接口,在遇到未知版本的EXCEL文件时,可以通过POI提供的方法判断文件头来获取版本信息,构造具体版本的Workbook实例。再返回统一的接口达到兼容性要求。创建兼容性Workbook的工厂方法代码如下:public static Workbook createCommonWorkbook(InputStream inp)throws IOException, InvalidFormatException / 首先判断流是否支持mark和reset方法,最后两个if分支中的方法才能支持if (!inp.markSupported() / 还原流信息inp = new PushbackInputStream(inp, 8);/ EXCEL2003使用的是微软的文件系统if (POIFSFileSystem.hasPOIFSHeader(inp) return new HSSFWorkbook(inp);/ EXCEL2007使用的是OOM文件格式if (POIXMLDocument.hasOOXMLHeader(inp) / 可以直接传流参数,但是推荐使用OPCPackage容器打开return new XSSFWorkbook(OPCPackage.open(inp);throw new IOException(不能解析的excel 版本 );通过传入的文件流,获取到通用的Workbook接口,就可以进行一系列不同的业务操作了,实际上到这一步EXCEL2003与EXCEL2007的兼容性问题已经基本解决了,简单吧?具体实例请阅读本文最后的DEMO,此处不详述。当然,HSSFWorkbook(EXCEL2003)会与XSSFWorkbook(EXCEL2007)有很多差异,通用接口只能满足这两者的交集部分。如下图: 第 5 页(图 2)若接口不能完全满足要求,可以通过判断Workbook类型,强制转换成其对应版本的对象,分别作两套或多套方法来处理。这是为满足兼容性值得牺牲,也是必须牺牲的部分。根据实际操作经验,接口能满足绝大部分EXCEL的基本操作,不能满足需要的情况非常少见。具体功能差异未作深究,感兴趣的读者可自行对比API。伪码如下:Workbook wb = createCommonWorkbook(不确定的版本的EXCEL文件流);if (wb instanceof HSSFWorkbook) HSSFWorkbook hwb = (HSSFWorkbook)wb;EXCEL2003的处理部分 else if (wb instanceof XSSFWorkbook) XSSFWorkbook xwb = (XSSFWorkbook)wb;EXCEL2007的处理部分 else throw new IOException(不能解析的excel 版本 );2、扩展性:我们在兼容性部分已经创建了获取兼容Workbook的工厂方法,若遇到其它版本,如EXCEL2010的需求,在工厂方法里添加一个创建EXCEL2010的Workbook条件就行了。修改createCommonWorkbook方法,伪码如下:public static Workbook createCommonWorkbook(InputStream inp)throws IOException, InvalidFormatException . if (输入文件的文件头为EXCEL2010格式) return new EXCEL2010Workbook(inp);. throw new IOException(不能解析的excel 版本 ); 第 6 页既然版本都是固定的,那么再提供一个版本枚举类,不就可以更方便管理不同的EXCEL版本了吗,如果将枚举的VALUE值定义为文件后缀名,也一并解决了不同版本的EXCEL文件后缀名不同的恼人问题,真是一举多得呢。后续即使有更高的Office版本,如EXCEL2010,也只需要添加一个工厂条件,再添加一个枚举项即可实现无缝升级了。枚举类属性如下:/ KEY:版本号/ VALUE:文件后缀名/* EXCEL2003版本 */EXCEL_2003(2003, .xls),/* EXCEL2007版本 */EXCEL_2007(2007, .xlsx);/* 后续添加扩展添加的EXCEL2010版本 */EXCEL_2010(2010, .xlsx);再创建一个根据Workbook取得版本信息的工具方法,如下:public static ExcelVersionTypeEnum checkExcelVersion(Workbook wb)throws IOException if (wb instanceof HSSFWorkbook) return ExcelVersionTypeEnum.EXCEL_2003; else if (wb instanceof XSSFWorkbook) return ExcelVersionTypeEnum.EXCEL_2007; else throw new IOException(不能解析的excel 版本 );以后获取版本信息或后缀名就方便了:ExcelVersionTypeEnum ev =CompatibleExcelUtil.checkExcelVersion(wb);String suffix = ev.getValue();3、DEMO: 源码如下:public class Test public static
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号