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.将现有项目带入工作空间
  3. 单击“ 选择根目录”旁边的“ 浏览” ,然后导航到C:\ Planet Power \ Employees2。
  4. 选择Employees2文件夹,单击“ 确定” ,然后单击“ 完成” ( 图2 )。
    图2.完成将项目导入Eclipse
    excel 读取.xml_读取,回收和重用:使用Excel,XML和Java技术简化报告,第2部分_第1张图片

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的示例文件中的元素的示例。

07:00

黎明及其括号( <> )和斜杠( / )一词称为标签。 内容为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代码的编写者熟悉以下属性:

Hello, Planet!

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

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

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

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

清单4.基于常规工作簿结构的XML结构

   
      
         Thumb
      
      
         Green
      
      
         Growing Plants
      
      
         5:00 AM
      
      
         2:00 PM
      
      
         150,000
      
   

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

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

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

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

清单5.基于描述数据的XML结构

   
      
         Thumb
      
      
         Green
      
      
         Growing Plants
      
      
         5:00 AM
      
      
         2:00 PM
      
      
         150,000
      
   

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

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

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

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

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

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

清单6.将工作簿结构与基于数据的标记混合

   
      
         Thumb
      
      
         Green
      
      
         Growing Plants
      
      
         5:00 AM
      
      
         2:00 PM
      
      
         150,000
      
   

如果每个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

你可能感兴趣的:(python,java,大数据,xml,编程语言)