excel 读取.xml

    技术2024-05-25  84

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

    本系列的其他文章
    第1部分:读取Excel文件并使用Java和XML将它们写入新文件

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

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

    常用缩略语
    API:应用程序编程接口 ASCII:美国信息交换标准代码 HSSF:糟糕的电子表格格式 HTML:超文本标记语言 XML:可扩展标记语言 XSSF:XML SpreadSheet格式

    样例应用

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

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

    Employees2 Eclipse项目

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

    在Eclipse中,右键单击Package Explorer,然后单击Import 。 展开常规,然后选择现有项目到工作区 。 单击Next ( 图1 )。
    图1.将现有项目带入工作空间
    单击“ 选择根目录”旁边的“ 浏览” ,然后导航到C:\ Planet Power \ Employees2。 选择Employees2文件夹,单击“ 确定” ,然后单击“ 完成” ( 图2 )。
    图2.完成将项目导入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()进行编程了。

    处理文件

    读取XML文件

    本文介绍了编写XML而不是阅读XML文件。 有关读取XML的信息,请参阅链接中提供的XOM网站相关信息或下载的Eclipse项目中的代码示例XMLReader.java。

    清单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工作簿。 由于电子表格之间文档和行中的数据可能不一致,因此可以将通用工作sheet和row用作元素名称,并且它们对于程序员阅读代码仍然有意义。

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

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

    数据类型和格式是元数据。 根据必须保留哪些元数据,可以使用诸如dataFormat和dataType类的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字符串。 首先, String的replaceAll()方法将所有非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的捐款。

    结论

    本系列的其他文章
    第1部分:读取Excel文件并使用Java和XML将它们写入新文件

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

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


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

    相关资源:excel读取生成xml文件
    Processed: 0.026, SQL: 9