excel 读取.xml_读取,回收和重用:使用Excel,XML和Java技术简化报告,第1部分

2010年3月2日在示例应用程序结论相关主题部分中添加了指向第2部分链接

创意借口编号432:报告对环境不利。

图表和报告消耗树木。 电子版本使用电力和化石燃料。 也许一家公司可以“走向绿色”并停止撰写报告?

为高级人员编写报告可能会使Java程序员感到焦虑,尤其是当程序员更喜欢对开发人员友好的输出(例如XML),而高级管理层只讲GUI辅助电子表格的语言时。

焦虑可能会增加所涉及程序员的温室气体“输出”,尤其是当他们开始过度通风时。 尽管报告需要时间和资源,但对于向高层管理人员提供项目可见性而言,这是必不可少的。 管理层可能只是因为高层看不到他们的团队在做什么,所以他们不信任努力工作的团队。

因此,报告对于工作环境至关重要。

处理电子表格爱好者的报告时,一些Java技巧可以增加程序员的“每加仑英里数”。 在完成了本文的步骤之后,中级Java程序员应该了解在Microsoft®Excel®和XML之间以编程方式转换数据的基本原理。

Excel到Java API

几种Java API可操纵Excel文件。 哪一个是最好的? 这取决于您的个人需求和经验水平。

安迪·汗(Andy Khan)的Java Excel API

安迪·汗创建调用的Java API的Excel,或JExcel API(见的API 相关主题 )。 此开源API可以读写Excel电子表格。 另外,由于它是轻量级的,因此对于初学者Java开发人员也是一个不错的选择。 方便的统一建模语言(UML)图表使它更易于使用,API的支持社区也是如此。

该API也有一些缺点。 尽管它读取Microsoft Excel 95,Excel 97,Excel 2000,Excel 2002和Excel 2003文件格式,但当前不适用于任何较新的Excel格式。 它不能创建图表,图形或宏,并且仅支持图像的PNG文件。

xlSQL Excel JDBC驱动程序

另一个Excel到Java API是xlSQL Excel的Java数据库连接(JDBC)驱动程序(参见相关主题 ),一个开源的API进行查询Excel文件,如果他们的数据库。 有了它,开发人员就可以将Excel工作表视为数据库中的表。 如果您熟悉SQL和JDBC,则这可能是检索数据的最简单方法。 您也可以使用SQL insert命令添加数据。 不幸的是,xlSQL Excel JDBC驱动程序似乎当前不受支持。

OpenXLS

OpenXLS(见相关信息 )是Extentech商业产品的开源版本,称为ExtenXLS。 OpenXLS具有广泛的功能。 它可以以编程方式修改公式并使用多种格式设置选项。 与某些开源产品不同,它可以处理复杂的对象,包括命名范围,数据透视表,拆分框架和图表。 此外,与类似产品相比,OpenXLS具有更全面的有关可用功能的前期文档。 不幸的是,尽管开放源代码版本支持从97到2003的Excel格式,但是只有商业版本支持Excel 2007。

Apache POI

Apache POI是一组Java API,可用于处理旧的和较新的Microsoft标准文档。 除了使用97及更高版本的Excel版本外,Apache POI还可以使用Microsoft Word和PowerPoint®文件。 您可以利用对Excel文件的了解来更快地了解如何使用这些其他类型的文件。 还有一个活跃的API支持社区。 但是,由于Apache POI具有如此众多的功能并且可以与其他文件一起使用,所以它可能不仅仅是开发人员仅尝试使用Excel文件需要学习的知识。

本文使用Apache POI是因为它具有支持社区和丰富的功能。

Java XML API

XML是一种流行的数据格式,在Java技术中有几种使用XML的方法。 您可以选择最适合您的项目的XML API。 但是,本文使用Elliotte Rusty Harold的优雅XML API XOM。 有关XML API的更多信息,请参阅参考资料

样例应用

本文的示例应用程序以虚构的Planet Power公司人力资源部提供的Excel电子表格文件开头。 该电子表格称为Employee_List.xls。

本文演示了如何使用Java技术和Apache POI来读取Employee_List.xls。 演示的Java类文件是ExcelReader.java ,并且包含在Eclipse项目中。 在可下载资源下载包含示例电子表格和Eclipse项目的.zip文件。 Eclipse项目中的Readme.txt文件说明了下载中包含的其他示例代码。

本系列文章的第2部分将演示如何将信息转换为XML并创建一个对原始数据进行一些修改的新电子表格。

配置

要准备您的计算机以运行本文中的示例,请完成以下步骤:

  1. 下载 Excel电子表格和示例代码。
  2. 创建目录C:\ Planet Power,然后将文件提取到其中。
  3. 下载使用Eclipse中的链接相关的话题 。 下载Eclipse之后,将其解压缩到C:\ Program Files \ Eclipse目录。
  4. 从链接相关信息 ,下载XOM使用的XOM现场完整拉链链接。 然后,将文件解压缩到C:\ Program Files \ Eclipse \ lib目录。
  5. 下载使用Apache POI中的链接相关的话题 。 将文件解压缩到C:\ Program Files \ Eclipse \ lib。 (您将需要创建lib目录。)

现在,您准备开始在Eclipse中工作。

启动Eclipse

要开始在Eclipse IDE中工作,请完成以下步骤:

  1. 通过导航到C:\ Program Files \ Eclipse \ eclipse并双击eclipse.exe来启动Eclipse。 如果Windows®显示安全警告,请单击“运行”
  2. Workspace Launcher窗口中,将标记为Workspace的路径替换为C:\Eclipse_Projects ,然后单击OK
  3. 当Eclipse完成加载时,单击窗口右侧的Workbench图标(请参见图1 )。
    图1.工作台图标
    Workbench图标的屏幕截图
  4. 在Package Explorer窗格中右键单击,然后单击Import
  5. 展开“ 常规” ,然后选择“ 现有项目”到“工作区” 。 单击Next (参见图2 )。
    图2.将现有项目带入工作空间
    将现有项目带入工作区,导入对话框的屏幕截图,选择选项
  6. 单击浏览 (位于“ 选择根目录”旁边),然后导航到C:\ Planet Power \ Employees。 选择员工文件夹,然后单击确定
  7. 单击Finish如图3所示
    图3.将项目导入Eclipse
    将项目导入Eclipse,“导入”对话框的屏幕截图,“导入项目”选项

现在,Employees文件夹应该出现在Package Explorer窗格中。

使XOM和Apache POI可用于Eclipse

从技术上讲,本部分中的步骤已经在导入的Employees Eclipse项目中执行。 但是,如果您从头开始创建自己的项目,则需要告诉Eclipse项目使用新的XOM和Apache POI下载。 完成以下步骤:

  1. 右键单击“程序包资源管理器”中的“雇员”文件夹,然后单击“ 属性”
  2. 单击左窗格中的Java构建路径
  3. 单击选项卡。
  4. 单击Add External JARs如图4所示
    图4.将外部JAR文件添加到构建路径
    添加构建路径,雇员属性对话框的屏幕截图
  5. 选择包含将在此示例中使用的Apache POI的Java归档(JAR)文件。 (如果您使用的POI版本与此文章相同,则路径为C:\ Program Files \ Eclipse \ lib \ poi-3.6 \ poi-3.6-20091214.jar)。 点击打开
  6. 再次单击添加外部JAR
  7. 选择包含XOM的JAR文件(如果您使用与本文相同的XOM版本,则路径为C:\ Program Files \ Eclipse \ lib \ XOM \ xom-1.2.1.jar)。 点击打开
  8. 单击确定

使用ExcelReader.java文件

对于本文,请使用文件ExcelReader.java,该文件位于src \(默认程序包)下的Employees项目文件夹中。 图5显示了该文件。

图5.打开Employees项目
在Eclipse SDK中打开的ExcelReader.java文件的屏幕截图

要运行文件,请单击屏幕顶部的Run箭头按钮, 如图6所示

图6.运行一个Java文件
Eclipse SDK工具栏中显示“运行”箭头的屏幕截图

运行ExcelReader.java从Employee_List.xls电子表格中的单元格中读取信息,并使用Eclipse的Console选项卡显示它, 如图7所示

图7. Eclipse控制台中的Java输出
在Eclipse SDK中运行ExcelReader.java时,“控制台”选项卡的屏幕截图

入门

理解Java技术的关键是熟悉使用对象并实例化(即创建)这些对象的想法。 创建要使用的对象的标准格式为:

class objectName = new class();

objectName是新创建的对象的名称。 就像变量一样,它标识并提供了使用该特定对象的方法。 而且,信息(通常采用其他现有对象的形式)可能位于class之后的括号( () )内。 括号内的信息用于创建新对象。

处理文件

每当在Java环境中使用文件时,文件都可能会遇到问题。 例如,它可能会丢失。 因此,尝试读取文件可能会导致错误。 捕获可能由操纵文件引起的任何异常。

要使用Excel文件,本文使用FileInputStream类( java.io.FileInputStream )。 FileInputStream表示一个可能不是由常规文本组成的文件。 由于Excel文件包含二进制数据,请使用FileInputStream而不是FileReader类,该类读取仅包含文本字符的文件。

开始编程

阅读Excel工作簿的第一步是准备使用Apache POI和其他必要的类。 ExcelReader.java中所需的类包括一些Apache POI类,一些异常(错误)类和一些文件处理类。 清单1显示了ExcelReader.java顶部的代码,这些代码导入了这些类以使其可用。

清单1.导入类(ExcelReader.java)
import java.io.FileInputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

导入相关类之后,您可以开始使用Apache POI在main方法的主体内进行编程。

HSSF在Apache POI中是什么意思?

Apache POI API程序员为涉及Excel工作簿的类选择了一种不同寻常的命名约定。 他们使用了前缀HSSF。 根据其JavaDocs,该前缀实际上代表可怕的电子表格格式。 实际上,根据Wikipedia所述,POI最初的意思是“ 拙劣的混淆实现”。 谁说程序员不知道如何玩乐?

HSSF类适用于2007年之前的Excel版本(即.xls文件)。 一组不同的类XSSF适用于Excel 2007及更高版本(即.xlsx文件)。 另一类类(SS类)可同时在两个版本中使用。 为了简单起见,本文使用HSSF类。 在您下载的Eclipse项目的Readme.txt文件中标识了使用其他类的代码示例。

工作簿

代表Apache POI中Excel工作簿的HSSF类是org.apache.poi.hssf.usermodel.HSSFWorkbook 。 向HSSFWorkbook传递一个FileInputStream到其构造函数中,您可以期望它代表FileInputStream所基于的文件。

可是等等! 在Apache POI的JavaDocs中,没有用于HSSFWorkbook构造函数,该构造函数声明它可以使用FileInputStream 。 使用FileInputStream是未记录的功能吗? 否。有一个接受InputStream的构造函数。

由于FileInputStreamInputStream的子类,从技术上讲,它也是InputStream ,因此可以将其传递到构造函数中。 实际上, InputStream是抽象的,因此需要某种子类。 FileInputStream会做得很好。

实例化FileInputStream ,向其传递一个String ,该String描述要读取的Excel文件的路径。 对于Windows®文件,请转义文件路径中的所有特殊字符,尤其是目录分隔符反斜杠( \ )。 使用双反斜杠( \\ )在文件路径字符串中创建一个转义的反斜杠。

清单2中的代码实例化一个新的FileInputStream ,然后基于该FileInputStream实例化一个新的HSSFworkbook

清单2.读取一个Excel文件(ExcelReader.java)
public static void main(String[] args) {
 // Create a FileInputStream to hold the file.
 // Use double back-slashes to create one "escaped" slash.
 // Use error handling (try/catch) around its creation in case
 // the file to read does not exist.
 // Be sure to import java.io.FileNotFoundException and java.io.IOException, or use 
 // the superclass IOException to handle both. 

 try {
    FileInputStream excelFIS = new FileInputStream("C:\\Planet Power\\Employee_List.xls");

    // Create an Excel Workbook Object using the FileInputStream created above
    // (which contains the file).
    // Use error handling around its creation in case of Input/Output Exception

    HSSFWorkbook excelWB = new HSSFWorkbook(excelFIS);

 }
 catch (IOException e) {
    System.out.println("Input/Output Exception!");
 }

//End Main Method
}

现在,停留在try错误处理语句内,继续从Excel工作簿(从其工作表开始)收集信息。

工作表和行

一个工作簿可以有几层称为工作表的页面。 工作表对象由HSSFSheet类( org.apache.poi.hssf.usermodel.HSSFSheet )表示。

一个工作簿有几张纸? 要找出getNumberOfSheets() ,可以在工作簿上使用方法getNumberOfSheets() 。 但是,对于本练习,只有一张纸,因此使用其编号更为简单。 第一张纸的编号为零(计算机喜欢从零开始而不是从一开始计数)。 代码类似于清单3

清单3.获取工作表(ExcelReader.java)
// Start by getting the Spreadsheet (Excel books can have several 
      // sheets). Assuming there is just one sheet, it's the zero sheet.

      HSSFSheet topSheet = excelWB.getSheetAt(0);

获取图纸对象后,在图纸上移动并处理其数据。 此类有用的方法和属性的名称指示其作用:

  • HSSFSheet.getFirstRowNum()getLastRowNum()
  • HSSFSheet.getHeader()getFooter()
  • HSSFSheet.getRow()
  • HSSFSheet.getPhysicalNumberOfRows()

要处理工作表中的数据,请首先获取一个HSSFRoworg.apache.poi.hssf.usermodel.HSSFRow )对象,该对象表示工作表中的一行。 获得行的一种方法是在工作表上使用getRow()并按编号要求行,如清单4所示

清单4.获取行(ExcelReader.java)
// getRow() returns an HSSFRow object, but the numbering
      // system is logical, not physical, and zero based.
      // for example, use getRow(2) to get the third row.

      HSSFRow thirdRow = topSheet.getRow(2);

记住, topSheet清单3前面获得的工作表。

从工作表获取该行之后,使用该行向下钻取到单元格级别。

细胞

要深入了解单个单元格的数据,请使用该行以获取表示该单元格的HSSFCell对象( org.apache.poi.hssf.usermodel.HSSFCell )。 要获取String格式的单元格信息,请在HSSFCell上使用getStringCellValue()方法,如清单5所示

清单5.获取内部的单元格和字符串(ExcelReader.java)
// Get the first two cells in the row
      HSSFCell lastnameCell = thirdRow.getCell(0);
      HSSFCell firstnameCell = thirdRow.getCell(1);

      // Get the string information in the cells
      String firstName = firstnameCell.getStringCellValue();
      String lastName = lastnameCell.getStringCellValue();

      // Print out the value of the cells
      System.out.println(firstName + " " + lastName);

要从工作簿中收集所有信息,请遍历所有工作表,每张工作表中的每一行以及每一行中的每个单元格。 但是有一个陷阱:尝试运行下面的代码,它对某些单元格有效。 但是,它将退出并尝试提取单元格值并将其打印出来时出错(请参见清单6中的注释)。 为什么?

清单6.遍历所有单元格并打印出值。 破碎!
// Traverse the sheets by looping through sheets, rows, and cells.
// Remember, excelWB is the workbook object obtained earlier.
// Outer Loop: Loop through each sheet

for (int sheetNumber = 0; sheetNumber < excelWB.getNumberOfSheets(); sheetNumber++) {
   HSSFSheet oneSheet = excelWB.getSheetAt(sheetNumber);

// Now get the number of rows in the sheet
   int rows = oneSheet.getPhysicalNumberOfRows();

   // Middle Loop: Loop through rows in the sheet

   for (int rowNumber = 0; rowNumber < rows; rowNumber++) {
      HSSFRow oneRow = oneSheet.getRow(rowNumber);

      // Skip empty (null) rows.
      if (oneRow == null) {
         continue;
      }

      // Get the number of cells in the row
      int cells = oneRow.getPhysicalNumberOfCells();

      // Inner Loop: Loop through each cell in the row

      for (int cellNumber = 0; cellNumber < cells; cellNumber++) {
         HSSFCell oneCell = oneRow.getCell(cellNumber);

         // Get the value of the string in the cell.
         // Print out the String value of the Cell 
         // This section will result in an error. Why?

         String cellValue = oneCell.getStringCellValue();
         System.out.println(cellValue + ", ");

      // End Inner Loop
      }
   // End Middle Loop
   }
// End Outer Loop
}

怎么了? get String CellValue()仅适用于Strings 。 故名。

一些单元格包含数值。 为避免错误,请测试单元格的数据类型并使用适当的方法从该单元格中获取该数据类型。 使用getCellType()确定单元格包含的数据类型。 数据类型以代表数据类型的整数形式返回。 以下静态字段(常量)表示数据类型:

  • HSSFCELL.CELL_TYPE_STRING 使用getStringCellValue()
  • HSSFCELL.CELL_TYPE_FORMULA 使用getCellFormula()
  • HSSFCELL.CELL_TYPE_NUMERIC 使用getNumericCellValue()
  • HSSFCELL.CELL_TYPE_BOOLEAN 使用getBooleanCellValue()

该单元格还可能包含Excel错误。 如果是这样,则getCellType()返回整数HSSFCELL.CELL_TYPE_ERROR

在遍历单元格时,测试它们的数据类型,如清单7所示

清单7.测试单元格值类型(ExcelReader.java)
// Inner Loop: Loop through each cell in the row

      for (int cellNumber = 0; cellNumber < cells; cellNumber++) {
         HSSFCell oneCell = oneRow.getCell(cellNumber);

         // Test the value of the cell.
         // Based on the value type, use the proper 
         // method for working with the value.

         // If the cell is blank, the cell object is null, so don't 
         // try to use it. It will cause errors.
         // Use continue to skip it and just keep going.

        if (oneCell == null) {
            continue;
         }

         switch (oneCell.getCellType()) {

         case HSSFCell.CELL_TYPE_STRING:
            System.out.println(oneCell.getStringCellValue());
            break;

         case HSSFCell.CELL_TYPE_FORMULA:
            System.out.println(oneCell.getCellFormula());
            break;

         case HSSFCell.CELL_TYPE_NUMERIC:
            System.out.println(oneCell.getNumericCellValue());
            break;

         case HSSFCell.CELL_TYPE_ERROR:
            System.out.println("Error!");
            break;
         }	

      // End Inner Loop
      }

代码运行时,请注意日期显示为数字,而不是日期。 这是因为日期的格式未存储在其值中。 这是单元格的格式选择。 本系列文章的第2部分将讨论如何保留日期格式。

还有一个重要的注意事项:在清单7的以下代码行(在下面的清单8中进行了细分)中,代码测试每个单元以确保其不为null。

清单8.不要忘记测试null(ExcelReader.java)
// If the cell is blank, the cell object is null, so don't 
// try to use it. It will cause errors.
// Use continue to skip it and just keep going.

if (oneCell == null) {
   continue;
}

在Java环境中,如果对象为null,则尝试对其进行操作将导致错误。 在使用行和单元格之类的对象之前,请确保对其进行测试以确保它们不为null。

结论

具备阅读Excel电子表格的基本知识,您可以开始将Excel数据转换为数组,XML或其他格式,以执行计算或创建新的电子表格。 本系列文章的第2部分将演示如何将电子表格信息转换为XML并创建一个对原始数据进行修改的新电子表格。

完成这些文章中的代码后,请确保将其回收以进行更环保的报告。


翻译自: https://www.ibm.com/developerworks/java/library/x-jxmlexl/index.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值