张强
(徐州市广播电视大学,江苏徐州221006)
摘要:Microsoft 的办公软件Office 下的电子报表Excel 使用十分普遍,但是多数的大型Web 服务器是以Unix 或Linux 为操作系统的,因此需要跨平台操作,该文对利用Java 和POI ,对Office 的Excel 操作进行了探讨。
关键词:跨平台;POI ;Excel ;HSSF
中图分类号:TP311文献标识码:A 文章编号:1009-3044(2010)24-65-03
当前基于网络的Web 应用,已经大大的提高了工作效率和生活方式。Java 作用一种开放式的平台,及动态语言在网络方面可谓是大显神威。与此同时由于Windows 对操作系统的普及,带动Microsoft 的办公软件Office 得到了十分普遍的安装和使用,所以其电子表格应用程序Excel 也得到了广泛应用,用于简单的数据存储和操作。但是,一个十分令人沮丧的事实就是Web 程序难以与Microsoft 专有的文件格式进行交互操作。Apache Software Foundation ①通过称作POI ②的项目,解决了该问题。本文探讨的就是利用POI 操作Excel 。
1介绍POI 项目
POI 是Apache 的一个子项目,其目的是提供对基于OOXML ③和OLE2④的各种文档的操作的Java APIs 包。该项目分为几个组件,其中包括一个叫作HSSF 的组件,它能操作Excel 文件。这就是我们将要使用的组件。HSSF 组件的全称是Horrible Spread sheet Format ,翻译成中文是“可怕的电子表格格式”,也有的翻译成“讨厌的电子表格格式”。我想它针对的是谁大家一定都知道了。HSSF 的名字虽然显得比较具有感情色彩甚至滑稽,但就其组件来说,它是个非常正规和严谨的API 。利用HSSF ,你可以用纯Java 代码来读取、写入、修改Excel 文件。
2介绍Excel 2003
介绍Excel 之前,先来讨论一下何为电子表格?简单说,能够提供输入数值、文字、公式等资料,迅速产生计算结果,并且产生各种统计、分析报表或者统计图形等的计算操作软件,就可以称为电子表格。在Windows 下的电子表格有多种,其中Microsoft 推出的就是Excel ,并不断推出新版本,包Excel 6.0、Excel 7.0、Excel 2000、Excel XP 、Excel 2003、Excel 2007、以及最新的Excel 2010。但是在Windows XP 下使用最多的还是Excel 2003这个版本,所以本文也是以这个版本展开讨论的。
Excel 用来存储、处理数据文件,称之为工作簿,其扩展名为.xls ,通常一张工作簿包含多个工作表,最多为255个工作表。每一个工作表可视为是一个二维矩阵,分为行和列。
3基本读写操作Excel 2003
对Excel 的基本操作分为读、写,其中读写又包括创建、克隆、插入行列等。而读取Excel 文件,POI 提供了两种API 方式,User Model 和Event User Model ,即“用户模型”和“事件-用户模型”。前者很好理解,后者比较抽象,但操作效率要高得多,适合读取大容量的Excel 文件。但是由于Event User Model 并不支持除了读取以外的其它操作,为了操作的连贯性,本文选取了User Model 。
User Model 包把Excel 文件映射成诸如Workbook 、Sheet 、Row 、Cell 等熟悉的结构,以一组对象的形式保存在内存之中。其中Workbook 代表工作簿,Sheet 代表工作簿中的工作表,而Row 、Cell 分别是工作表中的行和单元⑤。
3.1通过User Model 读取文件
a)创建根据文件路径和文件名创建FileInputStream ,和POIFSFileSystem 对象。
POI FSFileSystem fs=new POI FSFileSystem(new FileInputStream("c:\est.xls"));⑥
b)利用上面的POI FSFileSystem 实例,创建一个工作簿对象,并实例化。
HSSFWorkbook wb =new HSSFWorkbook(fs);
c)获取工作表
HSSFSheet sheet =wb.getSheetAt(0);
方法HSSFWorkbook.getSheetAt(int index)获取此工作簿中以index 为索引的HSSFSheet 对象。需要说明的在POI 中关于索引序号是从0开始的。所以此处获取的是第一个工作表。
d)获取行
HSSFRow row =sheet.getRow(2);
方法HSSFSheet.getRow(int rowIndex)获取此工作簿中以index 为索引的HSSFRow 对象,此处获得第三行。索引序号也是从0开收稿日期:2010-07-15
作者简介:张强(1980-),男,助教,江苏徐州广播电视大学机电工程系教师。
ISSN 1009-3044Computer Knowledge and Technology
电脑知识与技术Vol.6,No.24,August 2010,pp.65-67E-mail:kfyj@cccc.net.cn http://www.dnzs.net.cn Tel:+86-551-56909635690965
Computer Knowledge and Technology 电脑知识与技术计算机工程应用技术本栏目责任编辑:梁书
第6卷第24期(2010年8月)始的。
e)获取单元
HSSFCell cell =row.getCell(3)
方法HSSFRow.getCell(int cellnum)获取索引所指的单元格对象,如果索引的单元格没有定义,那么将返回一个null 。注意此法返回的仅仅是单元格的对象,并不是单元格的值。POI 提供了获取值的方法,但在获取值以前必须要确认单元格所存放的这值是什么类型。HSSFCell.getCellStyle()提供了此方法,例如:
if (cell.getCellType()==HSSFCell.CELL_TYPE_STRING){
("单元格是字符串,值是:"+cell.getStringCellValue());
}else if (cell.getCellType()==HSSFCell.CELL_TYPE_NUMERIC){
("单元格是数字,值是:"+cell.getCellValue());
}else (){
("单元格的值不是字符串或数值。");
}
从上面的例子得出:对单元格对象的取值是根据数据类型来调用方法的。如果调用的方法和数据类型不对应,程序会抛出异常。需要指出:用HSSF 处理日期数据要小心。因为Excel 内部本身以数值的形式保存日期数,所以用cell.getCellType()取日期单元格值类型时,将返回HSSFCell.CELL_TYPE_NUMERIC 。怎样解决这个问题呢?可以先利用静态工具函数HSSFDateUtil.isCellDateFor -matted(cell)来判断单元格的值是否为日期。
3.2写入文件
a)创建一个HSSFWorkbook 实例
HSSFWorkbook wb =new HSSFWorkbook();
在创建HSSFWorkbook 实例wb 后,把下面需要对Excel 的操作都围绕着个实例wb 展开,可以把它想象成为在内存中虚拟的Excel 文件。直到最后所有的操作都完成,再把它写入一个空白的.xls 文件。
b)把HSSFWorkbook 实例写文件流
FileOutputStream fileOut =new FileOutputStream(”workbook.xls ”);
wb.write(fileOut);
fileOut.close();
当对HSSFWorkbook 实例操作全部结束后,将其写入数据流实例fileOut 并且关闭。
以上介绍了利用POI 对Excel 的基本读写操作,接下来对于Excel 的数据处理如:创建、克隆工作表,游历整个工作表,插入图像、行,以及对单元格属性设计进行探讨。
4Excel 的数据处理
4.1创建工作表及其内容
HSSFSheet sheet =wb.createSheet();
HSSFRow row =sheet.createRow(0);
HSSFCell cell =row.createCell(0);
cell.setCellValue(1);
row.createCell(1).setCellValue(1.2);
row.createCell(2).setCellValue("一个字符串");
row.createCell(3).setCellValue(true);
创建的顺序必须从相应的父对象出发展开,先是工作表Sheet 、再是行Row 、最后是单元格Cell 。除了创建一个新的工作表Sheet 以外,还可以用类HSSFWorkbook 中的cloneSheet(int sheetIndex)的方法来复制一个表格并把它当成模板来创建一个新的工作表使用。例如HSSFSheet sheet =wb.cloneSheet(0);
4.2游历整个工作表
前面提到了在POI 中视Excel 工作表为一个二维数组,既然如此对于工作表的游历就可以用两个for 循环语句来实现:
for (int i =sheet.getFirstRowNum();i if (row !=null){ for(int j=0;j }}} 如果把工作簿看成整体,视工作表也是其中一维,那么正Excel 文件可以想象成一个三维空间,同时可在上述的两个for 循环的外再加入一个for 循环体,这样就可以游历整个Excel 文件中的每一个单元格了。 4.3插入行 POI 提供了一个移动工作表中行的函数: shiftRows(int startRow, 66 Computer Knowledge and Technology 电脑知识与技术计算机工程应用技术本栏目责任编辑:梁书第6卷第24期(2010年8月)(上接第61页) 从以上的分析中可以看出,只要能够符合80/20法则,那么就可以采用MAID 技术。不过有时候为了发挥MAID 的最大优势,还往往需要跟其他的一些技术结合使用,如存储策略等等。根据笔者的实际工作经验,相信采用MAID 技术应用在存储上,至少可以帮助企业降低30%的成本。 4结束语 综上所述,HSM 、Thin Provisioning 和MAID 技术分别从使用耗能合理的存储介质、减少数据占用的介质空间以及在应用访问数据频率降低时相应的降低硬盘转速等三个角度,有效的降低了数据所占用的存储设备的耗能,从而避免了存储介质的耗能随着数据量的几何级增长而相应的增长,切实有效的做到了绿色节能。 参考文献: [1]黄昆.存储新势力[J].中国计算机用户,2007(38). [2]倪兰.以安全架构奠基,IBM 存储实现新价值[J].通信世界,2008(19). int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) 参数startRow 、endRow 确定了需要移动的行的范围,参数n 需要移动的行数,参数copyRowHeight 是个布尔量,用来确定是否在移动的时候保持行高,参数resetOriginalRowHeight 也是个布尔量,用来确定是否把移过的行的原区域的行高改成默认行高。利用这个函数就可以插入一行或者若干行,但是若是只利用这个函数来实现行的插入,会出现一个问题。例如,希望在一个原本存在边框的表格中插入若干行,或者是希望插入的行继承原先的单元格的属性。这个问题的解决就需要加入新的代码了。下面提出解决的方法,设计一个新函数: void insertRow(HSSFSheet sheet,int startRow,int rows)在其内部使用shiftRows 方法后,加入类似游历工作表的循环: for (int i =0;i 5结束语 Apache 的POI 是一个极佳的用于操作Microsoft Office 文档的工具。本文中,我们构建了从Microsoft Excel 电子表格中读取数据,并且对其进行基本操作,另外一些在Excel 文件使用中经常使用的如设置单元格属性,合并单元格,公式等操作在POI 中都有直接对应的方法来操作,由于篇幅的缘故本文就不一一介绍了,可参照其官方API 说明。由于大量的大型服务器使用的操作系统还是Unix 或者Linux 为主,而桌面系统绝大多数是Windows ,利用POI 这个项目极大的方便了对于类似于基于Web 对Office 访问这样的跨平台操作。 注释: ①The Apache Software Foundation 是一个开源社区,提供一些开源的项目。 ②POI 代表Poor Obfuscation Implementation ,即不良模糊化实现。 ③OOXML 全称是Microsoft Office Open XML ,OOXML 是由微软公司为Office 2007产品开发的技术规范。 ④OLE 全称Object Linking and Embedding,对象连接与嵌入,简称OLE 技术。 ⑤User Model 映射的结构当中并没有“列”这种形式,而是单元。 ⑥笔者假设被操作的文件是在C 盘,当然也可以取其他盘的文件。 参考文献: [1] 陈刚.Eclipse 从入门到精通[M].北京:清华大学出版社,2006.[2] 李伟.Excel 数据转存数据库的应用框架[R].IBM developerWorks,2009.[3] 孙卫琴.Java 面向对象编程[M].北京:电子工业出版社,2006.[4]张古月,汪雄杰.结合JXLS 和POI 技术开发Web 报表[J].电脑知识与技术,2009(22). 67下载本文