`

Excel2007格式分析和XML解析

 
阅读更多

 


在物料清单采购中,用到excel上传文件解析功能,不过使用poi来解析,发现如果某个单元格为空,则使用poi的官网示例则会被忽略,导致某些非必填的单元格为空,而解析出来则认为不符合格式。找了半天,也没发现poi正确解析的示例和一些资料,只能自己查查excel的格式,然后再解析了。官网地址示例:http://poi.apache.org/spreadsheet/how-to.html#xssf_sax_api

那么我们就看看excel2007的格式了。

 

1.    excel2007是使用xml格式来存储的,把一个excel文件后缀改为.zip,打开之后就直接可以看到一个excel文件对应的xml格式的文件了。

这里面有几部分



 



 

 

<!--[if !supportLists]-->1.       1 <!--[endif]-->对于docProps目录下  这里core是文件的创建时间和修改时间,标题,主题和作者app是文档的其他属性,文档类型,版本,是否只读,是否共享,安全属性等文档属性信息。

 

 

 


 

 
Core.xml
       <dc:creator></dc:creator>
       <cp:lastModifiedBy></cp:lastModifiedBy>
       <dcterms:created xsi:type="dcterms:W3CDTF">2006-09-13T11:21:51Z</dcterms:created>
       <dcterms:modified xsi:type="dcterms:W3CDTF">2013-06-05T09:28:23Z</dcterms:modified>
 
App.xml
 
       <Application>Microsoft Excel</Application>
       <DocSecurity>0</DocSecurity>
       <ScaleCrop>false</ScaleCrop>
       <Company></Company>
       <LinksUpToDate>false</LinksUpToDate>
       <SharedDoc>false</SharedDoc>
       <HyperlinksChanged>false</HyperlinksChanged>
       <AppVersion>12.0000</AppVersion>
     ……

 

 2.xl目录下是文档的具体内容信息

 

 


 

先看workbook.xml

<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
       xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
       <fileVersion appName="xl" lastEdited="4" lowestEdited="4"
              rupBuild="4507" />
       <workbookPr filterPrivacy="1" defaultThemeVersion="124226" />
       <bookViews>
              <workbookView xWindow="0" yWindow="90" windowWidth="19200"
                     windowHeight="11640" />
       </bookViews>
       <sheets>
              <sheet name="Sheet1" sheetId="1" r:id="rId1" />
              <sheet name="Sheet2" sheetId="2" r:id="rId2" />
              <sheet name="Sheet3" sheetId="3" r:id="rId3" />
       </sheets>
       <calcPr calcId="125725" />
</workbook>

 workbook.xml文件包含一对<sheets>标签,其中的每个<sheet>元素都代表Excel 2007文件中的一个,工作表的名称就是其name属性的值,这里有三个sheet

 

xl/_rels/workbook.xml.rels定义每个sheetid对应的sheet内容文件sheet1.xml,共享的单元格内容文件sharedstring.xml,样式文件style.xml是当前单元格的样式字体,颜色等样式的xml配置。

Theme存放的是当前的设置导航栏的默认样式。这两个看看大概也就能明白。

 

关键我们看看下面每个sheet的内容格式,

 



 

打开一个sheet1.xml看看

       <sheetData>
              <row r="1" spans="1:7" ht="33.75" customHeight="1"> row标签是表示每一行的数据,r表示第几行,其他几个都是这几行的样式
                     <c r="A1" s="9" t="s">c标签表示每个单元格的内容,这里A1 第一行的第一列,r表示位置,s表示这个单元格的样式,
                                                          s=9对应style.xml的的index为9的样式即为这个单元格的样式,t=s表示这个单元格有值,里面的v标签即为值的id,id对应到sharedstring.xm里的id对应的值
                            <v>2</v>
                     </c>
                     <c r="B1" s="10" />  没有t属性,表示这个单元格没有值设置
                     <c r="C1" s="10" />
                     <c r="D1" s="10" />
                     <c r="E1" s="10" />
                     <c r="F1" s="10" />
              </row>
              <row r="2" spans="1:7" ht="27.75" customHeight="1">  第二行
                     <c r="A2" s="3" t="s">  第二行第二列
                            <v>1</v>
                     </c>
                     <c r="B2" s="4" t="s">
                            <v>5</v>
                     </c>
                     <c r="C2" s="3" t="s">
                            <v>0</v>

 

 我们找到对应的第一行第一列的值索引为2对应到sharedStrings.xml里面的index的值,这里si0开始,第三个即为index2的值,刚好跟我们的excelA1值符合

 

 

<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
    count="71" uniqueCount="13">
    <si>
           <t>物料编号</t>
           <phoneticPr fontId="1" type="noConversion" />
    </si>
    <si>
           <t>序号</t>
           <phoneticPr fontId="1" type="noConversion" />
    </si>
    <si>
           <t>注意:请不要修改表中蓝色区域文字;带有*号字段是必填项;每张物料清单最多只能导入20条物料信息</t>
           <phoneticPr fontId="1" type="noConversion" />
    </si>

 A1s=9对应的样式style.xml我们也看看,找到cellXfs里面的第9个,不过这里又引用fontid字体样式,borderid样式,numfmtId格式等

 

  <cellXfs count="11">
       ......
              <xf numFmtId="0" fontId="0" fillId="3" borderId="1" xfId="0"
                     applyFill="1" applyBorder="1">
                     <alignment vertical="center" />
              </xf>
              <xf numFmtId="0" fontId="2" fillId="0" borderId="2" xfId="0"
                     applyFont="1" applyBorder="1" applyAlignment="1">
                     <alignment horizontal="left" vertical="center" />
              </xf>
              <xf numFmtId="0" fontId="0" fillId="0" borderId="3" xfId="0"
                     applyBorder="1" applyAlignment="1">
                     <alignment horizontal="left" vertical="center" />
              </xf>
    </cellXfs>

 最重要的是对于单元格的空值是没有v标签的,那么使用xml解析的时候就需要特别处理下,下面这个是官方示例程序,我做了修改,黄色部分是添加解析空单元格情况下座位默认空值添加到rowlist上,这样rowlist就完整了,不会因为一行空单元格就不往rowlist添加,造成无法判断是哪列为空,也无法验证某些列非必填下的判断。(使用的是POI

 

那么xml怎么解析如下这个空单元格呢

<c r="C1" s="10" />

 

下面private boolean cellNull; 这个就是添加来判断是否为空单元格的

public class Excel2007Reader extends DefaultHandler {

    // 共享字符串表
    private SharedStringsTable sst;
    // 上一次的内容
    private String             lastContents;
    private boolean            nextIsString;
    
    private boolean            cellNull;

    private int                sheetIndex = -1;
    private List<String>       rowlist    = new ArrayList<String>();
    // 当前行
    private int                curRow     = 0;
    // 当前列
    private int                curCol     = 0;

    private IRowReader         rowReader;

    public void setRowReader(IRowReader rowReader) {
        this.rowReader = rowReader;
    }

    /**
     * 只遍历一个电子表格,其中sheetId为要遍历的sheet索引,从1开始,1-3
     * 
     * @param filename
     * @param sheetId
     * @throws Exception
     */
    public void processOneSheet(String filename, int sheetId) throws Exception {
        OPCPackage pkg = OPCPackage.open(filename);
        XSSFReader r = new XSSFReader(pkg);
        SharedStringsTable sst = r.getSharedStringsTable();
        XMLReader parser = fetchSheetParser(sst);

        // 根据 rId# 或 rSheet# 查找sheet
        InputStream sheet2 = r.getSheet("rId" + sheetId);
        sheetIndex++;
        InputSource sheetSource = new InputSource(sheet2);
        parser.parse(sheetSource);
        sheet2.close();
    }

    public void process(InputStream inputStream) throws Exception {
        OPCPackage pkg = OPCPackage.open(inputStream);
        proccessintern(pkg);
    }

    /**
     * 遍历工作簿中所有的电子表格

     * 
     * @param filename
     * @throws Exception
     */
    public void process(String filename) throws Exception {
        OPCPackage pkg = OPCPackage.open(filename);
        proccessintern(pkg);
    }

    private void proccessintern(OPCPackage pkg) throws IOException, OpenXML4JException, InvalidFormatException,
                                               SAXException {
        XSSFReader r = new XSSFReader(pkg);
        SharedStringsTable sst = r.getSharedStringsTable();
        XMLReader parser = fetchSheetParser(sst);
        Iterator<InputStream> sheets = r.getSheetsData();
        while (sheets.hasNext()) {
            curRow = 0;
            sheetIndex++;
            InputStream sheet = sheets.next();
            InputSource sheetSource = new InputSource(sheet);
            parser.parse(sheetSource);
            sheet.close();
        }
    }

    public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
        XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
        this.sst = sst;
        parser.setContentHandler(this);
        return parser;
    }

    public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {

        // c => 单元格
        if ("c".equals(name)) {
            // 如果下一个元素是 SST 的索引,则将nextIsString标记为true
            String cellType = attributes.getValue("t");
            if ("s".equals(cellType)) {
                nextIsString = true;
                cellNull = false;
            } 
            else {
                nextIsString = false;
                cellNull = true;
            }
        }

        // 置空
        lastContents = "";
    }

    public void endElement(String uri, String localName, String name) throws SAXException {

        // 根据SST的索引值的到单元格的真正要存储的字符串
        // 这时characters()方法可能会被调用多次
        if (nextIsString) {
            try {
                int idx = Integer.parseInt(lastContents);
                lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
            } catch (Exception e) {

            }
        }
     
        
        if ("v".equals(name) || "t".equals(name)) {
            String value = lastContents.trim();
            value = value.equals("") ? " " : value;
            rowlist.add(curCol, value);
            curCol++;
            cellNull = false;
        }else if("c".equals(name) && cellNull == true){
            rowlist.add(curCol, "");
            curCol++;
            cellNull = false;
        }
        else {
            // 如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法
            if (name.equals("row")) {
                rowReader.getRows(sheetIndex, curRow, rowlist);
                rowlist.clear();
                curRow++;
                curCol = 0;
            }
        }

    }

    public void characters(char[] ch, int start, int length) throws SAXException {
        // 得到单元格内容的值

        lastContents += new String(ch, start, length);
    }
}

  

 

 另外:poi有几种解析excel的方式,如果把整个文档加载进去解析,那么可能会造成内存溢出(之前以前出过问题),所以可以使用这个xml事件驱动方式解析,内存使用率非常小。而使用buffered streaming只能写excel,读不支持。这是官网的几种方式的说明。

 

 

 

  • 大小: 158.1 KB
  • 大小: 69.1 KB
  • 大小: 7.5 KB
  • 大小: 12.3 KB
  • 大小: 10.5 KB
  • 大小: 17.6 KB
分享到:
评论
1 楼 aki319 2014-04-03  
帮了我大忙了,谢谢哈~

相关推荐

    excel文档解析和生成xml文件

    而XML(eXtensible Markup Language)则是一种通用的数据交换格式,适合在网络环境中传输和存储数据。本主题将详细探讨如何使用Java的Apache POI库读取Excel文件,并利用JDOM库生成XML文件。 首先,Apache POI是一...

    将EXCEL文件全方位解析成生成XML数据

    综上所述,将Excel文件转换为XML数据是一项涉及数据读取、解析、格式转换和数据结构理解的技术任务。通过这种方式,我们可以利用XML的优势来处理和传输数据,提高数据的可用性和互操作性。在实际项目中,应根据具体...

    解析Excel和XML

    Excel是Microsoft Office套件中的电子表格应用程序,常用于数据分析、财务管理和报告制作。XML(eXtensible Markup Language)则是一种标记语言,用于存储和传输结构化数据,尤其在Web服务和企业级应用程序中广泛...

    解析excel和xml的jar

    它可能封装了上述提到的Apache POI和Java的XML解析库,提供了一种方便的方式来处理这两种数据格式,而无需手动管理多个依赖。 总结一下,Java中的Excel解析主要依靠Apache POI库,XML解析则可以使用DOM、SAX或StAX...

    java 解析、生成 Excel XML 四个实例

    在Java编程中,处理Excel和XML文件是常见的需求,特别是在数据导入导出、报表生成以及数据分析等场景。本文将深入探讨四个使用Java解析和生成Excel及XML的实例,旨在帮助开发者掌握相关技能。 实例一:解析Excel...

    excel和xml解析需要引入的jar包

    这些库的引入使得开发者能够轻松地在Java应用程序中实现Excel和XML的读取、写入、分析和转换。例如,使用Apache POI可以创建新的Excel工作簿,添加工作表,插入单元格数据,设置样式等;而DOM4J则可以方便地解析XML...

    xml2excel,java解析xml文件

    Java内置了两个主要的API用于XML解析:DOM(Document Object Model)和SAX(Simple API for XML)。DOM解析器会将整个XML文档加载到内存中,形成一个树形结构,便于遍历和查询,但对大文件可能造成内存压力。SAX解析...

    poi读取大文件Excel,使用xml格式解析,速度实测50mb文件13s,可指定sheet页内容,带工具类和测试类

    这里的主题是利用XML格式解析大文件Excel,以提高读取速度。 标题和描述中的"xml格式解析"指的是XSSFEventUserModel API,它是基于事件驱动的模型,适合处理大文件。这种模式不会一次性加载整个工作簿,而是逐行...

    基于DOM4j和POI实现的XML文件转换为XLS(即标准EXCEL)的JAVA程序

    此外,可能还会涉及到样式设置,如字体、颜色、对齐方式等,以确保转换后的Excel文件符合原始XML数据的布局和格式。 在项目结构中,"xmlwork.iml"是IntelliJ IDEA的项目配置文件,"pom.xml"是Maven的项目配置文件,...

    解析excel写入xml

    在IT领域,Excel和XML是两种非常重要的数据格式,它们各有各的应用场景和优势。Excel通常用于处理表格数据,而XML则是一种结构化数据的存储和交换格式,尤其适合于跨平台的数据传输和复杂数据的组织。本篇将详细探讨...

    java解析excel2007源码

    Java解析Excel 2007源码主要涉及的是对Microsoft Office Open XML (OOXML) 格式的处理,这种格式主要用于xlsx文件。...无论选择哪种方法,理解和掌握XML解析的基本原理以及相关工具库的使用都是至关重要的。

    Excel2xml,excel文档解析

    本篇将深入探讨如何将Excel文件解析并转换为XML格式,主要涉及的技术包括Java中的Apache POI库和DOM4J库。 首先,Apache POI是Java领域用于读写Microsoft Office格式文件的库,其中包括Excel(XLS和XLSX)。通过POI...

    解析XML,并把解析的属性值写入excel

    这些示例代码可以帮助初学者理解XML解析和Excel导出的实现过程。 为了确保程序的健壮性,还需要考虑错误处理。例如,当XML文件不存在或格式不正确时,程序应该能够适当地捕获异常并给出反馈。此外,如果Excel文件...

    神级testlink-导出的xml用例转Excel或Excel转xml上传到testlink

    总的来说,"testlinkconvert"工具提供了一种快速、直观的方法来在TestLink的XML格式和Excel格式之间切换,极大地简化了测试用例的管理和协作。只要按照正确的步骤操作,就能有效地提升测试团队的工作效率。

    解析excel、xml配置文件&&输出java测试文件Demo

    在Java开发中,解析Excel和XML配置文件是常见的任务,特别是在构建可配置系统或处理数据导入导出时。Spring框架的出现,使得这项工作变得更加简便。本Demo将演示如何使用Java来解析Excel和XML配置文件,并基于这些...

    Excel和String.xml 互相转换工具

    XML格式使得这些字符串易于组织,并且支持变量和格式化。例如: ```xml 我的应用 你好,世界! 设置 ``` 在上述例子中,`name`属性是字符串的唯一标识符,而`value`则是显示的文本。开发者可以在代码中通过`R...

    EXCEL文件转XML文件

    在IT行业中,Excel和XML是两种非常常见的数据存储和交换格式。Excel文件(.xls)主要用于数据管理和分析,尤其在企业环境中,它以其直观的表格形式和强大的计算功能深受用户喜爱。而XML(eXtensible Markup Language...

    python文件对比 xml、excel

    在Python编程中,处理XML和Excel文件是常见的任务,尤其在数据处理和分析领域。XML(eXtensible Markup Language)是一种结构化数据格式,常用于存储和交换数据,而Excel则是Microsoft Office套件中的一个应用程序,...

    用VBA将excel格式转换成xml输出

    3. **XML基础知识**:XML(Extensible Markup Language)是一种数据交换格式,它以结构化的方式存储数据,易于解析和理解。在Excel中,数据可以被组织成类似XML的结构,因此转换相对直接。 4. **VBA中的XML导出**:...

Global site tag (gtag.js) - Google Analytics