Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1851484
  • 博文数量: 909
  • 博客积分: 4000
  • 博客等级: 上校
  • 技术积分: 12260
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-06 20:50
文章分类

全部博文(909)

文章存档

2008年(909)

我的朋友

分类:

2008-05-06 22:42:16

一起学习
利用 .Net XML 解析 Execl XML单元格

作者:caeser2

下载源代码

阅读本文需要有 XML 规范基础 及 .net XML 解析基础

本文示例代码使用 Visual Stdio 2005 、Office Execl 2007

一、首先我们来看看Execl XML的开头

下面这段是文档的开头,其中定义了一些有用的命名空间,本文要用到的是:

ss:"urn:schemas-microsoft-com:office:spreadsheet",

它代表了工作表空间。

    

    

      
  中间一些跳过不管,直接看Worksheet工作表段落。Worksheet字段的Name属性表示工作表名称 Table 字段中的保存了表格的行、列数目等属性 :
      

      

        接下来是关键部分,也是最乱的地方,表的数据区。
      

      

      a

      b

      ......

      9

      10

      

        上面的数据区如下图所示:

  

  数据区在下面是其他Table表格、下一个Worksheet工作区、表格样式等信息,这里不详细讨论了。

二、Execl XML数据区的格式框架

首先了解一下构架,从上面的数据区编码可以看出,有如下规律:

  • 整个表以行为基础,标记是Row,行号最小的数据记录在最前面的Row中(但不一定是第一个!,随后会说到),其Index属性表示绝对行号
  • 列是Row的子结点,标记是Cell(同时也表示具体数据元素),该行中列号最小的数据记录在该行最前面的Cell中,其Index属性表示绝对列号
  • Data标记是Cell的子结点,其属性记录数据的类型等信息,其值就是数据本身
  • XML中行号、列号的Index属性是该数据在表中的绝对位置;但没有此属性的行、列则用相对位置表示,需要自己解析计算出绝对位置
  • 无论是行还是列,如果其绝对位置是1,那么都没有Index属性;如果不是1,则有Index属性
  • 无论是行还是列,如果两行(列)是相邻的,那么都没有Index属性;如果不相邻,则有Index属性
  • 行、列位置的表示方法 同时存在相对和绝对表示,Index属性的存在不可预知,在解析时一定要注意
  • Table使用的命名空间是"urn:schemas-microsoft-com:office:spreadsheet"


  •   需要注意的是,根据存盘情况不同,Row的情况会有变化,目前观察有如下几种:
  • 用Execl第二次保存之前:不会自动出现AutoFitHeight属性;绝对行号是1则没有Index属性且是第一个Row;绝对行号是2(且是行号最小的数据)则Index属性(=2)且是第一个Row
  • 用Execl第二次保存之后:所有Row均自动加上AutoFitHeight属性;绝对行号是1则没有Index属性且是第一个Row;绝对行号是2(且是行号最小的数据)则没有Index属性且是第二个Row

  •   由于Row的框架会变,我们的程序就必须覆盖所有情况。不知道MS为什么要这样设计,但是很明显我们写代码时将会比较痛苦......

    三、部分解析代码

      全部的Execl单元格解析比较复杂,这里只介绍基本的XML解析。
      .net XML 解析模型

      

      1.读入Execl XML文件

          //有时候用户需要打开Execl的同时做解析,所以我们使用流来构造XML
    
          //我们的目的只是读出单元格,所以使用XPathDocument可以提高解析性能
    
          
    
          //用到的命名空间
    
          using namespace System::IO;
    
          using namespace System::Xml;
    
          using namespace System::Xml::XPath;
    
          
    
          //按下面的参数构造流
    
          FileStream^ sr = File::Open("c:\Book1.XML",FileMode::Open,FileAccess::Read,FileShare::ReadWrite);
    
          //用流来构造XPathDocument
    
          XPathDocument^ doc = gcnew XPathDocument(sr);          
      2.构造游标、命名空间
          //用XPathDocument来构造XPathNavigator游标
    
          XPathNavigator^ navigator = doc->CreateNavigator();
    
          //navigator->NameTable是被原子化的XML文档内容
    
          XmlNamespaceManager^ manager = gcnew XmlNamespaceManager(navigator->NameTable);
    
          //添加命名空间,并起个名字叫ss
    
          manager->AddNamespace("ss","urn:schemas-microsoft-com:office:spreadsheet");
    
          
      3.查询节点
          //找到指定WorkSheet中Name属性,Select需要节点的绝对路径
    
          XPathNodeIterator^ node = navigator->Select("/ss:Workbook/ss:Worksheet/@ss:Name",manager);
    
          XPathNavigator^ child = node->Current;
    
          //未知原因SelectChild()查询子结点总是失败
    
          
      4.操作节点游标
          //移动到节点的第一个属性
    
          child->MoveToFirstAttribute();
    
          //移动到该节点的下一个属性
    
          child->MoveToNextAttribute();
    
          //如果在属性中则MoveToParent()回到节点,如果在节点上则回到上一级节点
    
          child->MoveToParent();
    
          //移动到下一个同级结点
    
          child->MoveToNext();
    
          //移动到第一个子结点
    
          child->MoveToFirstChild();
    
          //还有其他很多
    
          .....
    
          //得到当前游标位置上的名称(可能是节点名称(标记),也可能是属性名称)
    
          child->Name;
    
          //得到当前游标位置上的值(可能是节点的值,也可能是属性值)
    
          chile->Value;
    
          
    四、示例代码

      示例代码的功能是取出Execl中指定的一列,并按照这列的值建立同名的文件夹。
      由于Execl XML的特殊结构,程序里面的解析比较复杂,大家下载后有时间可以看看。
      程序现在还有些小问题,需要改进。
      解析思路为:
      1.找到用户要求的Worksheet工作表
      2.游标移动到Table
      3.找到第一个带数据的Row;如果是相对行位置,则计算出其绝对行号(只有可能是1或2)
      4.按照第一个带数据的Row所在的绝对行号,找到用户要求的起始行所在的Row位置;注意其间会混杂相对行位置和绝对行位置
      5.在该Row内找用户要求的列(注意其间会混杂相对列位置和绝对列位置);如果找不到,则下移一行(注意其间会混杂相对行位置和绝对行位置),再找,直到找到该列为止
      6.得到Data的值(取得指定数据项),做操作
      7.如果用户指定的结束行号大于表中的行号,则以表中的末尾行号为准
      
    运行效果:

    数据解析工作非常辛苦、烦闷,同时也需要极大的耐心。希望我的这篇文章能给大家提供一些帮助。
    下载本文示例代码


    利用 .Net XML 解析 Execl XML单元格利用 .Net XML 解析 Execl XML单元格利用 .Net XML 解析 Execl XML单元格利用 .Net XML 解析 Execl XML单元格利用 .Net XML 解析 Execl XML单元格利用 .Net XML 解析 Execl XML单元格利用 .Net XML 解析 Execl XML单元格利用 .Net XML 解析 Execl XML单元格利用 .Net XML 解析 Execl XML单元格利用 .Net XML 解析 Execl XML单元格利用 .Net XML 解析 Execl XML单元格利用 .Net XML 解析 Execl XML单元格

    阅读(305) | 评论(0) | 转发(0) |
    给主人留下些什么吧!~~