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

您本周是否在老板身上尝试过创造性的借口#432? 你被诱惑了吗?

希望您不必这样做。 本系列的第1部分帮助您了解如何使用Java™技术的Microsoft®Excel®电子表格(请参见“阅读,回收和重用:使用Excel,XML和Java技术简化报告的链接,第1部分”中的链接)。 相关主题 )。 只需下载Apache POI并进行设置即可使用,很快,遍历Excel电子表格几乎和遍历公园一样容易。 几乎和绿色一样。

但是读取Excel文件只是一个开始。 本系列向您展示如何使用Apache POI和XML对象模型(XOM)在XML对象中存储Excel文件。 然后,您可以回收这些对象以编写全新的Excel电子表格和XML文件。

样例应用

该示例应用程序包含一个来自虚构的Planet Power公司的Excel电子表格,名为Employee_List.xls 。 大老板说服了Planet Power的最高员工将其薪水的1%捐赠给他最喜欢的事业:基因工程巨大的野生仓鼠行星际保护区(GEE WHIS)。 该示例应用程序将计算数量并创建一个XML报告以赶往避难所。 同时,该应用程序为Big Boss编写了一个Excel电子表格。

要遵循本文中的示例,请下载示例并将文件提取到C:\ Planet Power。 然后,启动Eclipse。

Employees2 Eclipse项目

要导入包含示例应用程序的Employees2 Eclipse项目,请执行以下步骤:

  1. 在Eclipse中,右键单击Package Explorer,然后单击Import
  2. 展开常规,然后选择现有项目到工作区 。 单击Next图1 )。
    图1.将现有项目带入工作空间
    Eclipse Import对话框的屏幕截图,其中选择了一个现有项目并带入工作区
  3. 单击“ 选择根目录”旁边的“ 浏览” ,然后导航到C:\ Planet Power \ Employees2。
  4. 选择Employees2文件夹,单击“ 确定” ,然后单击“ 完成”图2 )。
    图2.完成将项目导入Eclipse
    Eclipse Import对话框的屏幕截图,其中包含将项目导入Eclipse的完成

Employees2文件夹应出现在“程序包资源管理器”窗格中。

注意:对于此项目,请在Employees2项目中的src \ default_package下使用文件ExcelXML.java。

入门

在本系列的第1部分中,第一步是导入Apache POI以及异常和文件处理类(请参阅参考资料中的第1部分链接)。 另外,您需要添加一些XML API类以及用于处理数字的类,如清单1所示

清单1.导入类(ExcelXML.java)
// File and exception handling imports
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;

// Apache POI imports
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFHyperlink;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;

// XOM imports
import nu.xom.Document;
import nu.xom.Elements;
import nu.xom.Element;
import nu.xom.Attribute;
import nu.xom.Serializer;

// Imports for later calculations
import java.text.NumberFormat;

导入这些类之后,您就可以开始在main()进行编程了。

处理文件

清单2中的代码表示文件( IOException )和数字转换( ParseException )错误的异常处理结构。

清单2.设置异常处理(ExcelXML.java)
public class ExcelXML {

   public static void main(String[] args) {

      try {

      // Put file and number handling code here.

   // End try
   }
   catch (IOException e) {
      System.out.println("File Input/Output Exception!");
   }
   catch (ParseException e) {
      System.out.println("Number Parse Exception!");
   }

   // End main method
   }

// End class block
}

现在,您可以开始使用XOM。

XOM,文档和XML对象

XOM通过将XML解析成代表XML文档碎片的对象,简化了XML的使用。 表示整个XML文档的类是nu.xom.Document 。 在Document ,您可以添加或访问其他作品。 一些使用XML的类包括:

  • nu.xom.Builder
  • nu.xom.Document
  • nu.xom.Elements
  • nu.xom.Element
  • nu.xom.Serializer

XML的主要部分称为元素。 一个元素由一对标签及其之间的内容组成。 这是一个来自名为weather_service.xml的示例文件中的元素的示例。

<dawn>07:00</dawn>

黎明及其括号( <> )和斜杠( / )一词称为标签。 内容为07:00 。

元素可以包含其他元素,文本内容或两者。 包含元素称为父元素,而内部元素称为子元素或children 。

在XOM中,元素由nu.xom.Element对象表示。 一组元素是nu.xom.Elements对象。

一切美好的根源

要查找元素,请确保每个格式正确的XML文档都使用一个元素: 根元素。 根充当其他所有元素的容器。 如果文档没有根,则它不是正确的XML。

要找到根,请在Document对象上使用getRootElement() 。 仅获取一个元素就可以打开探索文档的策略。 想和根的孩子一起工作吗? 使用Element.getChildElements()变体获取所有子元素或具有特定名称的子元素的列表。 想要一个元素? 从Element.getFirstChildElement()仅获取具有特定名称的第一个子元素。

这看起来很熟悉吗? 遍历XML文档以查找孩子的孩子类似于遍历Excel工作表。

在上一篇文章中,您了解了Apache POI的getStringCellValue()方法如何从Excel HSSFCell检索字符串值。 同样,XOM使用Element.getValue()从XML元素获取字符串内容。 但是,与使用单元不同,使用XOM Elements不需要测试数据类型。 XML是所有文本。

Excel-XML混搭和XML标记

遍历电子表格并提取数据时,可以将数据存储在任意数量的对象中:字符串。 数组。 松鼠 本文使用XML元素。 (这样,在松鼠上更容易。)它还提供了一些在两种格式之间转换的见解。

清单3准备了一个新的HSSFWorkbook和XML Document来存储工作簿的信息。

清单3.准备工作簿和XML文档(ExcelXML.java)
// First, create a new XML Document object to load the Excel sheet into XML.
// To create an XML Document, first create an element to be its root.
Element reportRoot = new Element("sheet");

// Create a new XML Document object using the root element
Document XMLReport = new Document(reportRoot);

// Set up a FileInputStream to represent the Excel spreadsheet
FileInputStream excelFIS = new FileInputStream("C:\\Planet Power\\Employee_List.xls");

// Create an Excel Workbook object using the FileInputStream created above 
HSSFWorkbook excelWB = new HSSFWorkbook(excelFIS);

清单3看起来有些落后吗? 该代码在创建Document之前先创建一个新Element 。 为什么?

全新的Document需要做一件事:将Element作为其根元素。 请记住,没有根元素, Document就无法表示格式良好的XML文档。 因此,在创建它时必须将其传递给根元素。

相反,您可以创建不属于根的元素。 您可以将它们保留为自由浮动元素,也可以将它们附加到文档根目录或其他元素中。 但是,在开始之前,您应该计划XML的结构。

XML结构

XML主要通过元素和属性来描述和格式化数据。 属性是名称-值对。 属性的名称部分描述了该属性保存的数据。 属性的值是其数据。 HTML代码的编写者熟悉以下属性:

<font size="12">Hello, Planet!</font>

整个清单是一个元素。 标签是<font> 。 该属性为size="12" 。 该属性的名称为size 。 它的值是12 。 等号( = )将两者结合在一起。 通常,数据存储在元素中,而元数据存储在属性中。

那么,Employee_List.xls工作簿应如何转换为XML?

标记方法1:模仿工作簿结构

构造XML的一种方法是模仿Excel工作簿的物理结构。 考虑清单4

清单4.基于常规工作簿结构的XML结构
<sheet>
   <row>
      <cell>
         Thumb
      </cell>
      <cell>
         Green
      </cell>
      <cell>
         Growing Plants
      </cell>
      <cell>
         5:00 AM
      </cell>
      <cell>
         2:00 PM
      </cell>
      <cell>
         150,000
      </cell>
   </row>
</sheet>

使用这种格式,行和单元格都清晰可见。 但是每个单元格保存哪些数据? 员工的开始时间或结束时间是5:00 AM吗? 使用列名称作为单元格的属性怎么办?

如果维护Excel电子表格结构很重要,则可能有效。 但是,在XOM中,没有学习如何编写XPath查询,就没有一种简单的方法可以根据元素的属性值提取元素的集合。 将列名存储为属性,需要额外的代码才能找到特定列中所有元素的集合。 由于XOM包含一种按其名称查找元素的方法,因此请考虑将Excel列用作元素名称而不是属性。

标记方法2:模仿数据结构

不要将XML基于数据的表示形式,而应考虑描述数据的结构。 如清单5所示,这就是XML最好的。

清单5.基于描述数据的XML结构
<EmployeeData>
   <Employee>
      <EmployeeLastName>
         Thumb
      </EmployeeLastName>
      <EmployeeFirstName>
         Green
      </EmployeeFirstName>
      <MainSuperPower>
         Growing Plants
      </MainSuperPower>
      <DailyStartTime>
         5:00 AM
      </DailyStartTime>
      <DailyEndTime>
         2:00 PM
      </DailyEndTime>
      <Salary>
         150,000
      </Salary>
   </Employee>
</EmployeeData>

这种方法允许您对每个Employee元素使用getChildElements("Salary")方法来快速查找员工的薪水。

但是,将Excel列名称用作元素名称是有风险的。 Excel列可以使用在XML元素名称中无效的字符,例如空格。 因此,请确保从潜在的元素名称中清除这些字符。

要以这种方式构造数据,您必须熟悉数据。 以编程方式很难计算出Excel电子表格中的一行应被称为XML中的Employee 。 计算根元素的名称(在上面的示例中为EmployeeData )也将很困难。

另外,如果结构发生变化或老板希望回收其他电子表格的代码,会发生什么? 电子表格行可以列出仓鼠的类型,而不是雇员。 然后,您必须调整程序调用的行。

标记方法3:Excel XML混搭混合

考虑将Excel结构的XML与数据结构的标记混合在一起,如清单6所示

清单6.将工作簿结构与基于数据的标记混合
<sheet>
   <row>
      <EmployeeLastName>
         Thumb
      </EmployeeLastName>
      <EmployeeFirstName>
         Green
      </EmployeeFirstName>
      <MainSuperPower>
         Growing Plants
      </MainSuperPower>
      <DailyStartTime>
         5:00 AM
      </DailyStartTime>
      <DailyEndTime>
         2:00 PM
      </DailyEndTime>
      <Salary>
         150,000
      </Salary>
   </row>
</sheet>

如果每个Excel电子表格中的第一行包含列名,则此混合可能足够灵活以使用多个Excel工作簿。 由于电子表格之间文档和行中的数据可能不一致,因此可以将通用工作sheetrow用作元素名称,并且它们对于程序员阅读代码仍然有意义。

注意:与以数据为中心的纯标记一样,提防将非法字符渗入XML元素名称中。

本文使用XML-Excel混合格式来存储单元格值。 但是如何跟踪其他单元格信息,例如数据类型和格式呢?

数据类型和格式是元数据。 根据必须保留哪些元数据,可以使用诸如dataFormatdataType类的dataFormat

编码转换

确定XML外观后,开始将Excel数据存储在XML元素中。 使用与本系列第1部分中相同的循环遍历Excel电子表格(请参阅参考资料中的链接)。 然后,添加XML。 清单7回收了上一篇文章中的Excel读取代码。

清单7.开始遍历Excel电子表格(ExcelXML.java)
// Traverse the workbook's rows and cells.			
// Remember, excelWB is the workbook object obtained earlier.

// Just use the first sheet in the book to keep the example simple.
// Pretend this is an outer loop (looping through sheets).

HSSFSheet oneSheet = excelWB.getSheetAt(0);

      // 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;
            }

遍历电子表格的行时,请创建XML元素来表示行,如清单8所示

清单8.创建一个行元素(ExcelXML.java)
// Create an XML element to represent the row.
            Element rowElement = new Element("row");

如果您有空行或空行,请不要将行附加到Document 。 如果添加单元格后行不为空,则可以将其附加到行循环底部的根元素。

接下来,启动内部循环以读取单元格,如清单9所示

清单9.继续遍历Excel单元格(ExcelXML.java)
// 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);

               // 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;
               }

进入内部循环后,使用适当的列名称作为元素名称,创建一个XML元素来表示单元格。 在清单10中 ,因为元素名称不能为空,所以每个名称默认为header. 在第一行之后,根据存储在第一行元素中的数据计算一个新名称,其中包含Excel电子表格列名称。

清单10.使用列名称作为元素名称为单元格创建元素(ExcelXML.java)
// Set up a string to use just "header" as the element name
// to store the column header cells themselves.

String elementName="header";

// Figure out the column position of the Excel cell.
int cellColumnNumber = oneCell.getColumnIndex();

// If on the first Excel row, don't change the element name from "header,"  
// because the first row is headers. Before changing the element name,
// test to make sure you're past the first row, which is the zero row.

if (rowNumber > 0)

 // Set the elementName variable equal to the column name
 elementName=reportRoot.getFirstChildElement("row").getChild(cellColumnNumber).getValue();

// Remove weird characters and spaces from elementName,
// as they're not allowed in element names.
elementName = elementName.replaceAll("[\\P{ASCII}]","");
elementName = elementName.replaceAll(" ", "");

// Create an XML element to represent the cell, using 
// the calculated elementName

Element cellElement = new Element(elementName);

清单10中发生了很多事情。 在注释下方中间的长行中, // Set the elementName variable equal to the column name ,将elementName设置为等于某个值。 阅读该行的结尾,您可以看到使用getValue()将其设置为元素内的文本值。 它使用哪个元素的值?

reportRoot内部,在第一行元素( reportRoot.get First ChildElement("row") )内,代码使用getChild(cellColumnNumber)通过其索引号找到子元素。 您已经将电子表格的第一行存储在第一行元素中,因此该行的子元素的值就是电子表格中的列名。 索引号与电子表格中当前单元格的列号相同。 因此,为elementName设置的值是标题元素第一行中的对应列名称。

接下来,代码清除了电子表格中可能存在的非法字符的elementName字符串。 首先, StringreplaceAll()方法将所有非ASCII字符替换为空字符串。 然后,它将替换所有空格。 这两行都使用正则表达式。 有关正则表达式的信息,请参阅“ 相关主题”

最后, 清单10的最后一行使用适当的列名创建该元素。

追加属性和元素

就像元素一样,您可以独立创建属性,并且它们可以保持自由浮动,直到您使用其addAttribute()方法将它们附加到元素上为止。 创建一个属性,然后使用getter方法(例如来自Apache POI的HSSFCell对象的getDataFormatString()将其与单元格元数据一起填充,如清单11所示

清单11.添加属性(ExcelXML.java)
// Create an attribute to hold the cell's format.
// May be repeated for any other formatting item of interest.
String attributeValue = oneCell.getCellStyle().getDataFormatString();
Attribute dataFormatAttribute = new Attribute("dataFormat", attributeValue);

// Add the attribute to the cell element
cellElement.addAttribute(dataFormatAttribute);

现在,该元素存在并具有属性。

要获取该元素的数据,请记住测试每个HSSFCell的数据类型,以便知道使用哪种getter方法。 因为无论如何都在测试数据类型,所以您还可以创建一个存储单元格数据类型信息的属性。

在使用字符串值时,将数据添加到元素并将元素作为行的子元素追加很简单,如清单12所示

清单12.添加属性,将单元格文本附加到元素,然后将元素附加到行(ExcelXML.java)
switch (oneCell.getCellType()) {

   case HSSFCell.CELL_TYPE_STRING:

      // If the cell value is string, create an attribute
      // for the cellElement to state the data type is a string

      Attribute strTypeAttribute = new Attribute("dataType", "String");
      cellElement.addAttribute(strTypeAttribute);

      // Append the cell text into the element
      cellElement.appendChild(oneCell.getStringCellValue());

      // Append the cell element into the row
      rowElement.appendChild(cellElement);

      break;

对每种数据类型重复case部分。 但是数字数据可能很棘手。 本系列文章的第1部分指出,提取的Excel数据是不一样的电子表格数据(见链接到第1部分相关主题 )。 它是原始数据。 某些数字(例如日期)作为原始数据看起来非常可笑,如果不进行格式化就无法存储正确的值。 您需要在将数字数据放入元素之前对其进行正确格式化。 您可以使用Apache POI类HSSFDataFormatter及其方法formatCellValue()来完成此操作。 参见清单13

清单13.添加属性,格式化数字数据,并附加单元格元素(ExcelXML.java)
case HSSFCell.CELL_TYPE_NUMERIC:
      // If the cell value is a number, create an attribute
      // for the cellElement to state the data type is numeric
      Attribute cellAttribute = new Attribute("dataType", "Numeric");

      // Add the attribute to the cell
      cellElement.addAttribute(cellAttribute);

      // Apply the formatting from the cells to the raw data
      // to get the right format in the XML. First, create an
      // HSSFDataFormatter object.

      HSSFDataFormatter dataFormatter = new HSSFDataFormatter();

      // Then use the HSSFDataFormatter to return a formatted string
      // from the cell rather than a raw numeric value:
      String cellFormatted = dataFormatter.formatCellValue(oneCell);

      //Append the formatted data into the element
      cellElement.appendChild(cellFormatted);

      // Append the cell element into the row
      rowElement.appendChild(cellElement);

      break;

对每种可能的单元格类型重复case部分。 在ExcelXML.java中查看完整的示例。

存储单元格数据后,关闭内部循环。 在关闭表示行的中间循环之前,请测试row元素是否为空。 如果不是,请将其附加到根元素。 然后,关闭中间循环,如清单14所示

清单14.将row元素附加到根元素(ExcelXML.java)
// End inner loop
      }

   // Append the row element into the root 
   // if the row isn't empty.  
   if (rowElement.getChildCount() > 0) {
      reportRoot.appendChild(rowElement);
   }

   // End middle loop	
   }

现在,您的Excel文件是一个完整的XML文档。

在XML内部

使用XML进行计算时(例如计算薪水的1%),必须在字符串和数字之间进行转换。 清单15提供了一个示例。

清单15.计算工资的1%并将其存储在捐赠元素中(ExcelXML.java)
// To get employees' salaries, iterate through row elements and get a collection of rows

Elements rowElements = reportRoot.getChildElements("row");

// For each row element

for (int i = 0; i < rowElements.size(); i++) {

   // Get the salary element, 
   // Calculate 1% of it and store it in a donation element.
      // Unless it's the first row (0), which needs a header element.
   if (i==0) {
      Element donationElement = new Element("header");
      donationElement.appendChild("Donation");

      Attribute dataType = new Attribute("dataType","String");
      donationElement.addAttribute(dataType);

      Attribute dataFormat = new Attribute("dataFormat","General");
      donationElement.addAttribute(dataFormat);

      // Append the donation element to the row element.
      rowElements.get(i).appendChild(donationElement);
   }

   // If the row is not the first row, put the donation in the element.
   else {
      Element donationElement = new Element("Donation");

      Attribute dataType = new Attribute("dataType","Numeric");
      donationElement.addAttribute(dataType);

      // The dataFormat of the donation should be the same 
      // number format as salary, which looking at the XML file tells
      // us is "#,##0".
      Attribute dataFormat = new Attribute("dataFormat","#,##0");
      donationElement.addAttribute(dataFormat);

      // Get the salary element and its value
      Element salaryElement = rowElements.get(i).getFirstChildElement("Salary");
      String salaryString = salaryElement.getValue();

      // Calculate 1% of the salary. Salary is a string
      // with commas, so it 
      // must be converted for the calculation.

      // Get a java.text.NumberFormat object for converting string to a double
      NumberFormat numberFormat = NumberFormat.getInstance(); 

      // Use numberFormat.parse() to convert string to double.
      // Throws ParseException
      Number salaryNumber = numberFormat.parse(salaryString);

      // Use Number.doubleValue() method on salaryNumber to 
      // return a double to use in the calculation.
      // Perform the calculation to figure out 1%.
      double donationAmount = salaryNumber.doubleValue()*.01;

      // Append the value of the donation into the donationElement.
      // donationAmount is a double and must be converted to a string.
      donationElement.appendChild(Double.toString(donationAmount));

      // Append the donation element to the row element
      rowElements.get(i).appendChild(donationElement);

      //End else
      }

// End for loop 
}

现在,您已经为每行存储了一个额外的Donation元素。 您已经完成了XML文档对象的构建。

XOM使您可以轻松地将Document对象写入XML文件。 使用nu.xom.Serailizer.write() ,如清单16所示

清单16.将XML写入Excel(ExcelXML.java)
// Print out the XML version of the spreadsheet to see it in the console
   System.out.println(XMLReport.toXML());

   // To save the XML into a file for GEE WHIS, start with a FileOutputStream
   // to represent the file to write, C:\Planet Power\GEE_WHIS.xml.
   FileOutputStream hamsterFile = new FileOutputStream("C:\\Planet Power\\GEE_WHIS.xml");

   // Create a serializer to handle writing the XML
   Serializer saveTheHamsters = new Serializer(hamsterFile);

   // Set child element indent level to 5 spaces to make it pretty
   saveTheHamsters.setIndent(5);

   // Write the XML to the file C:\Planet Power\GEE_WHIS.xml
   saveTheHamsters.write(XMLReport);

仓鼠会喜欢他们的新捐赠报告。 XML是他们的母语。

写回Excel

要将XML写入Excel电子表格,请遍历XML并设置单元格值和格式。 清单17设置并开始遍历行。

清单17.设置将XML写入Excel(ExcelXML.java)
// Create a new Excel workbook and iterate through the XML 
// to fill the cells.
// Create an Excel workbook object 
HSSFWorkbook donationWorkbook = new HSSFWorkbook();

// Next, create a sheet for the workbook.	
HSSFSheet donationSheet = donationWorkbook.createSheet(); 

// Iterate through the row elements and then cell elements

// Outer loop: There was already an elements collection of all row elements
// created earlier. It's called rowElements. 
// For each row element in rowElements:

for (int j = 0; j < rowElements.size(); j++) {

   // Create a row in the workbook for each row element (j)
   HSSFRow createdRow = donationSheet.createRow(j);

   // Get the cell elements from that row element and add them to the workbook.
   Elements cellElements = rowElements.get(j).getChildElements();

就像遍历行一样,遍历单元格创建也很简单。 最难的部分是格式化单元格。

HSSFCellStyle对象表示单元格的样式选项,例如字体,边框和数字格式(包括日期和时间格式)。 但是,样式是每个工作簿的,而不是每个单元格的。 HSSFCellStyle对象表示工作簿中现有的命名样式,可以将其应用于单元格。 这些样式是样式选项的分组,例如Microsoft Office Word中的命名样式。 同样,为每个工作簿创建一个HSSFDataFormat但仅表示数字格式,例如日期和时间格式。

要设置单元格的样式, HSSFCellStyle为工作簿创建一个新的HSSFCellStyle ,或使用现有的HSSFCellStyle 。 然后,使用HSSFCell.setCellStyle()将其应用于单元格。 要设置单元格的数字格式,请设置HSSFCellStyle而不是单元格的数字格式。 然后,将HSSFCellStyle应用于该单元格。

HSSFDataFormat对象在工作簿中按数字索引。 要告诉HSSFCellStyle使用哪个HSSFDataFormat ,您需要HSSFDataFormat的索引号。 这是数字短HSSFDataFormat ,不是HSSFDataFormat对象。

幸运的是, HSSFDataFormat对象具有一个名为getFormat()的方法。 当传递表示所需格式的字符串时,它返回与该字符串匹配的HSSFDataFormat的索引号。 索引以数字短返回。 如果不匹配,它将创建一个新的HSSFDataFormat并返回其索引。 您可以使用该索引将格式应用于单元格样式,并将单元格样式应用于单元格,如清单18所示

清单18.遍历单元格元素并设置正确的数字格式,然后再插入数据
// Middle loop: Loop through the cell elements.
   for (int k = 0; k < cellElements.size(); k++) {	

      // Create cells and cell styles. Use the row's
      // createCell (int column) method.
      // The column index is the same as the cell element index, which is k.
      HSSFCell createdCell = createdRow.createCell(k);	

      // To set the cell data format, retrieve it from the attribute 
      // where it was stored: the dataFormat attribute. Store it in a string.
      String dataFormatString = cellElements.get(k).getAttributeValue("dataFormat");

      // Create an HSSFCellStyle using the createCellStyle() method of the workbook.
      HSSFCellStyle currentCellStyle = donationWorkbook.createCellStyle();

      // Create an HSSFDataFormat object from the workbook's method
      HSSFDataFormat currentDataFormat = donationWorkbook.createDataFormat();

      // Get the index of the HSSFDataFormat to use. The index of the numeric format
      // matching the dataFormatString is returned by getFormat(dataFormatString).
      short dataFormatIndex = currentDataFormat.getFormat(dataFormatString);

      // Next, use the retrieved index to set the HSSFCellStyle object's DataFormat.
      currentCellStyle.setDataFormat(dataFormatIndex);

      // Then apply the HSSFCellStyle to the created cell.
      createdCell.setCellStyle(currentCellStyle);

设置单元格的样式后,使用setCellValue()将大多数数据类型放入单元格中。

但是,数字数据需要特殊处理。 要将数字存储为数字而不是文本,请先将其转换为双精度。 请勿将日期转换为双精度,否则将不正确。 测试数字数据的数据格式,以确定它是否是日期(请参见清单19 )。

清单19.插入单元格数据,将某些数字数据转换为双精度
// Set cell value and types depending on the dataType attribute

      if (cellElements.get(k).getAttributeValue("dataType")=="String") {
         createdCell.setCellType(HSSFCell.CELL_TYPE_STRING);
         createdCell.setCellValue(cellElements.get(k).getValue());
      }

      if (cellElements.get(k).getAttributeValue("dataType")=="Numeric") {
         createdCell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);

         // In this spreadsheet, number styles are times, dates,
         // or salaries. To store as a number and not as text,
         // salaries should be converted to doubles first.
         // Dates and times should not be converted to doubles first,
         // or you'll be inputting the wrong date or time value.
         // Dates and times can be entered as Java Date objects.

         if (cellElements.get(k).getAttributeValue("dataFormat").contains("#")) {

            // If formatting contains a pound sign, it's not a date.
            // Use a Java NumberFormat to format the numeric type cell as a double,
            // because like before, the element has commas in it.
            NumberFormat numberFormat = NumberFormat.getInstance(); 
            Number cellValueNumber = numberFormat.parse(cellElements.get(k).getValue());
            createdCell.setCellValue(cellValueNumber.doubleValue());

            // Add a hyperlink to the fictional GEE WHIS Web site just
            // to demonstrate that you can.
            HSSFHyperlink hyperlink = new HSSFHyperlink(HSSFHyperlink.LINK_URL);
            hyperlink.setAddress("http://www.ibm.com/developerworks/");
            createdCell.setHyperlink(hyperlink);
         }

         else {
            // if it's a date, don't convert to double
            createdCell.setCellValue(cellElements.get(k).getValue());
         }

      }

//  Handle formula and error type cells. See ExcelXML.java for the full example.

      //End middle (cell) for loop
      }
   // End outer (row) for loop	
   }

对于创建日期的Excel函数TODAY()例如TODAY()NOW() TODAY() ,格式也是必需的。 参见清单20

清单20.以正确的格式使用Excel函数
// Demonstrate functions:
// Add the TODAY() and NOW() functions at bottom of the Excel report
// to say when the workbook was opened.

// Find the last row and increment by two to skip a row
int lastRowIndex = donationSheet.getLastRowNum()+2;

// Create a row and three cells to hold the information.
HSSFRow lastRow = donationSheet.createRow(lastRowIndex);
HSSFCell notationCell = lastRow.createCell(0);
HSSFCell reportDateCell = lastRow.createCell(1);
HSSFCell reportTimeCell = lastRow.createCell(2);

// Set a regular string value in one cell
notationCell.setCellValue("Time:");

// Setting formula values uses setCellFormula()
reportDateCell.setCellFormula("TODAY()");
reportTimeCell.setCellFormula("NOW()");	

// Create HSSFCellStyle objects for the date and time cells.
// Use the createCellStyle() method of the workbook.

HSSFCellStyle dateCellStyle = donationWorkbook.createCellStyle();
HSSFCellStyle timeCellStyle = donationWorkbook.createCellStyle();

// Get a HSSFDataFormat object to set the time and date formats for the cell styles
HSSFDataFormat dataFormat = donationWorkbook.createDataFormat();

// Set the cell styles to the right format by using the index numbers of
// the desired formats retrieved from the getFormat() function of the HSSFDataFormat.
dateCellStyle.setDataFormat(dataFormat.getFormat("m/dd/yy"));
timeCellStyle.setDataFormat(dataFormat.getFormat("h:mm AM/PM"));

// Set the date and time cells to the appropriate HSSFCellStyles.
reportDateCell.setCellStyle(dateCellStyle);
reportTimeCell.setCellStyle(timeCellStyle);

最后,在完成所需的工作簿对象之后,使用工作簿的write()方法将其 write()文件中( 清单21 )。

清单21.将Excel工作簿写入文件
// Write out the workbook to a file. First,
// you need some sort of OutputStream to represent the file.
	
	String filePathString = "C:\\Planet Power\\Employee_Donations.xls";
	FileOutputStream donationStream = new FileOutputStream(filePathString);
	
	donationWorkbook.write(donationStream);

您现在已经编写了一个Excel电子表格,用于计算对GEE WHIS的捐款。

结论

报告完成。 除了阅读Excel和创建XML,Java程序员现在可以将XML写回到Excel文件中。 了解了两种格式之间进行转换的基本知识之后,您可能会觉得自己对报告的整体想法感到全球变暖。

大老板很高兴,您已尽自己的一份力量来帮助Planet Power的环境超级英雄拯救转基因的野生仓鼠。 大家都开心 报告确实对环境有益。


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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值