Excel 电子表格文件格式剖析

Excel 电子表格文件格式,这种Excel和其他的Excel是不同的。他的本质上是一个Xml文件(用英文版的UtraEdit可以看到),所以他可以保存任何符号的字符,包括&(它在Xml文件中是一种特殊字符。所以用aspose等工具是不能读取这种字符的)。

反过来说,我们从中可以得到一种快速生成带有多个Worksheet的Workbook的Excel,从xml文件处理的个角度入手。

<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"><Author>Gary Lim</Author></DocumentProperties><ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>

<Styles>
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Bottom"/>
<Borders/>
<Font/>
<Interior/>
<NumberFormat/>
<Protection/>
</Style>
<Style ss:ID="s27" ss:Name="Hyperlink">
<Font ss:Color="#0000FF" ss:Underline="Single"/>
</Style>
<Style ss:ID="s24">
<Font x:Family="Swiss" ss:Bold="1"/>
</Style>
<Style ss:ID="s25">
<Font x:Family="Swiss" ss:Italic="1"/>
</Style>
<Style ss:ID="s26">
<Alignment ss:Horizontal="Center" ss:Vertical="Bottom"/>
</Style>
<Style ss:ID="my24">
<Font x:Family="Swiss" ss:Size="12"/>
</Style>
<Style ss:ID="my28">
<Alignment ss:Horizontal="Left" ss:Vertical="Center"/>
<Font x:Family="Swiss" ss:Size="12" ss:Bold="1"/>
</Style>
<Style ss:ID="my32">
<Alignment ss:Vertical="Center"/>
<Font x:Family="Swiss" ss:Size="12"/>
</Style>
</Styles>

<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<Selected/>
</WorksheetOptions>

<Worksheet ss:Name="Info">
<Table>
<Column ss:AutoFitWidth="0" ss:Width="123"/>
<Column ss:AutoFitWidth="0" ss:Width="196.5"/>
<Row ss:AutoFitHeight="0" ss:Height="39.75">
<Cell ss:MergeAcross="1" ss:StyleID="my28"><Data ss:Type="String">Report Information</Data></Cell>
</Row>
<Row ss:Height="15">
<Cell ss:MergeAcross="1" ss:StyleID="my32"/>
</Row>
<Row ss:Height="15">
<Cell ss:StyleID="my24"><Data ss:Type="String">MoAddress</Data></Cell>
<Cell ss:StyleID="my24"><Data ss:Type="String">SN=Eri3G,RNC=BORNC01</Data></Cell>
</Row>
<Row ss:Height="15">
<Cell ss:StyleID="my24"><Data ss:Type="String">Data Date</Data></Cell>
<Cell ss:StyleID="my24"><Data ss:Type="String">6/23/2013 3:25:00 AM</Data></Cell>
</Row>
<Row ss:Height="15">
<Cell ss:StyleID="my24"><Data ss:Type="String">Report Created Date</Data></Cell>
<Cell ss:StyleID="my24"><Data ss:Type="String">6/23/2013 4:04:01 AM</Data></Cell>
</Row>
<Row ss:Height="15">
<Cell ss:StyleID="my24"><Data ss:Type="String">VendorName</Data></Cell>
<Cell ss:StyleID="my24"><Data ss:Type="String">Ericsson</Data></Cell>
</Row>
<Row ss:Height="15">
<Cell ss:StyleID="my24"><Data ss:Type="String">Data Version</Data></Cell>
<Cell ss:StyleID="my24"><Data ss:Type="String">W10.1</Data></Cell>
</Row>
</Table>
</Worksheet>

<Worksheet ss:Name="NodeB_Info">
<Table>
<Column ss:AutoFitWidth="0" ss:Width="300"/>
<Row ss:AutoFitHeight="1" ss:Height="16">
<Cell ss:StyleID="s24"><Data ss:Type="String">MoAddress</Data></Cell>
<Cell ss:StyleID="s24"><Data ss:Type="String">NodeB Label</Data></Cell>
<Cell ss:StyleID="s24"><Data ss:Type="String">NodeB Id</Data></Cell>
<Cell ss:StyleID="s24"><Data ss:Type="String">Last Updated Date</Data></Cell>
</Row>
<Row ss:AutoFitHeight="1" >

<Cell><Data ss:Type="String">SN=Eri3G,RNC=BORNC01,NodeB=BA3036W</Data></Cell>

<Cell><Data ss:Type="String">BA3036W</Data></Cell>

<Cell><Data ss:Type="String">BA3036W</Data></Cell>

<Cell><Data ss:Type="String">6/22/2013 5:01:05 AM</Data></Cell>

</Row>

<Row ss:AutoFitHeight="1" >

<Cell><Data ss:Type="String">SN=Eri3G,RNC=BORNC01,NodeB=BA3039W</Data></Cell>

<Cell><Data ss:Type="String">BA3039W</Data></Cell>

<Cell><Data ss:Type="String">BA3039W</Data></Cell>

<Cell><Data ss:Type="String">6/22/2013 5:01:05 AM</Data></Cell>

</Row>

<Row ss:AutoFitHeight="1" >

<Cell><Data ss:Type="String">SN=Eri3G,RNC=BORNC01,NodeB=BA3040W</Data></Cell>

<Cell><Data ss:Type="String">BA3040W</Data></Cell>

<Cell><Data ss:Type="String">BA3040W</Data></Cell>

<Cell><Data ss:Type="String">6/22/2013 5:01:05 AM</Data></Cell>

</Row>

</Table>
</Worksheet>
</Workbook>

这是一个txt文件,也可以是一个xml文件,当我们把他的后缀名修改成.xls的时候,我们居然可以看到是一个带有两个worksheet的workbook的excel 文件

读取方式:

public class TableReader
    {
        private List<System.Data.DataTable> _vlstDtDestination = new List<System.Data.DataTable>();
        private TableParser _vTableParser = null;
 
        public List<System.Data.DataTable> DataTableList
        {
            get { return _vlstDtDestination; }
        }
 
        public void Read(System.IO.StringReader strReader)
        {
            System.Xml.XmlReaderSettings xmlReaderSettings = CustomXmlReaderSetting.Create();
            using (System.Xml.XmlReader xmlReader = System.Xml.XmlReader.Create(strReader, xmlReaderSettings))
            {
                string currentNode = string.Empty;
                string currentTableName = string.Empty;
                KeyValuePair<string, string> currentPair;
                while(xmlReader.Read())
                {
                    if (xmlReader.NodeType == System.Xml.XmlNodeType.Element && xmlReader.Name == "Worksheet")
                    {
                        currentTableName = xmlReader.GetAttribute("ss:Name");
 
                        #region Test
                        if (currentTableName == "Rnc")
                        {
                            Console.WriteLine();
                        }
                        #endregion
 
                        if (currentTableName == "Info")
                        {
                            continue;
                        }
                        currentNode = xmlReader.ReadOuterXml();
                        currentPair=new KeyValuePair<string, string>(currentTableName,currentNode);
                        Parse(currentPair);
                        currentPair = new KeyValuePair<string, string>(null,null);
                    }
                }
            }
        }
 
        #region Private‘s
        private void Parse(KeyValuePair<string, string> source)
        {
            if (_vTableParser==null)
            {
                _vTableParser = new TableParser(_vlstDtDestination);
            }
            _vTableParser.Parse(source);
        }
        #endregion
 
    }
public class TableParser
    {
        private List<System.Data.DataTable> _vlstDtDestination = null;
 
        public TableParser(List<System.Data.DataTable> dtList)
        {
            _vlstDtDestination = dtList;
        }
 
        public void Parse(KeyValuePair<string,string> source)
        {
            if(source.Key.Trim()=="")
            {
                return;
            }
 
            System.Data.DataTable currentDt = null;
            foreach(System.Data.DataTable dt in _vlstDtDestination)
            {
                if(dt.TableName==source.Key)
                {
                    currentDt = dt;
                }
            }
            if(currentDt==null)
            {
                currentDt = new System.Data.DataTable(source.Key);
                _vlstDtDestination.Add(currentDt);
            }
 
            if(source.Value.Trim()=="")
            {
                return;
            }
            System.IO.StringReader reader = new System.IO.StringReader(source.Value);
            System.Xml.XmlReaderSettings xmlReaderSettings = CustomXmlReaderSetting.Create();
            using(System.Xml.XmlReader xmlReader=System.Xml.XmlReader.Create(reader,xmlReaderSettings))
            {
                System.Data.DataRow currentDr = null;
                bool isValued = false;
                bool isConstructed = false;
                int index = 0;
 
                while (xmlReader.Read())
                {
                    switch (xmlReader.NodeType)
                    {
                        case System.Xml.XmlNodeType.Element:
                            if (xmlReader.Name == "Row")
                            {
                                if (isValued)
                                {
                                    currentDt.Rows.Add(currentDr);
                                }
                                currentDr = currentDt.NewRow();
                                index = 0;
                            }
 
                            if (xmlReader.Name == "Data")
                            {
                                if (!isConstructed)
                                {
                                    currentDt.Columns.Add(xmlReader.ReadString(), typeof(System.String));
                                }
                                else
                                {
                                    currentDr[index++] = xmlReader.ReadString();
                                    if (!isValued)
                                    {
                                        isValued = true;
                                    }
                                }
                            }
 
                            break;
                        case System.Xml.XmlNodeType.EndElement:
                            if (xmlReader.Name == "Row" && !isConstructed)
                            {
                                isConstructed = true;
                            }
                            break;
                    }
                }
                if (isValued)
                {
                    currentDt.Rows.Add(currentDr);
                }
 
                 
            }
        }
 
    }
public class CustomXmlReaderSetting
{
    public static System.Xml.XmlReaderSettings Create()
    {
        System.Xml.XmlReaderSettings xmlReaderSettings = new System.Xml.XmlReaderSettings();
        xmlReaderSettings.ProhibitDtd = false;
        xmlReaderSettings.CheckCharacters = false;
        return xmlReaderSettings;
    }
}
public class StreamFilter
    {
        public static System.IO.StringReader Filter(string path)
        {
            System.IO.FileStream fileStream = new System.IO.FileStream(
                    path,
                    System.IO.FileMode.Open,
                    System.IO.FileAccess.Read,
                    System.IO.FileShare.ReadWrite
                );
            StringBuilder builder = new StringBuilder();
 
            fileStream.Seek(0,System.IO.SeekOrigin.Begin);
            System.IO.StreamReader streamReader = new System.IO.StreamReader(fileStream);
 
            for (string strLine = streamReader.ReadLine(); !streamReader.EndOfStream; strLine = streamReader.ReadLine())
            {
                strLine = strLine.Replace("&", "&amp;");
                builder.AppendFormat("{0}\n",strLine);
            }
 
            System.IO.StringReader strReader = new System.IO.StringReader(builder.ToString());
            return strReader;
        }
 
    }
public class NameHandler
    {
        public static string ConvertName(string name)
        {
            string result = name.Trim();
 
            result = Regex.Replace(result, "[^a-zA-Z\\d]", "_");
 
            result = Regex.Replace(result, "_{2,}", "_");
 
            if (result.StartsWith("_")) result = result.Substring(1, result.Length - 1);
            if (result.EndsWith("_")) result = result.Substring(0, result.Length - 1);
 
            return result;
        }
    }
The xml iteself is broken up into several major section:
Workbook:Root node of the xml,parent to all the other sections.
DocumentProperties:Most of the importation one sees when accessing File->Properties is defined here.
Styles:Formatting information defined here is available to different row,columns and specific cells in the worksheets.
Worksheet(s):As many worksheets as you want are defined here.

Worksheets consist of two major sections:
Table:This is where all visible data in the spreadsheet is stored.
WorksheetOptions:Global options for the worksheet itself.

Finally,the Table section defines two components:
Column
Row / Cell

With this information in hand one can plan out how to create the xml document that will then load into Microsoft Excel and look,feel and operate like a document created by sophisticate,loving user.

原文来自http://www.6excel.com/doc/20035转载请注明出处

时间: 2024-10-22 21:24:28

Excel 电子表格文件格式剖析的相关文章

介绍一款开源的类Excel电子表格软件

Excel一直以霸主的地位,占据了Windows桌面表格软件市场No 1,与此同时,Office套装产品几乎成为了IT行业的标配办公技能.有无类似Excel的桌面程序,绿色版,实现基本的数据编辑功能呢? 假如不安装Office,可否实现表格编辑.公式编辑.打印.导出.导出等操作呢? 可以的,本文介绍的这款开源的SpreadDesginer即可实现这样的需求.      谁适合阅读此文? 软件设计师 产品经理 Excel用户 系统必备: .NET Framework 4.0 在管理平台中嵌入Exc

第三篇 从EXCEL电子表格到数据库

一个靠EXCEL电子表格处理各部门业务数据的公司和一个使用一个统一的数据库存储各个部门用到的业务数据并提供大量权限不同的使用界面给用户的公司两者有什么不同呢? EXCEL电子表格是数据和操纵数据的功能在同一个视界内.销售部门用自己的EXCEL表中的数据,仓储用自己的EXCEL表中的数据,采购用自己的EXCEL表中的数据,财务用自己的EXCEL表中的数据.这些数据分散地存储在各个部门各自使用的EXCEL表中,并没有紧密的关联.也许,不同的部门对于同一种客观实体的编码(coding)用的是不同的规则

网页中模拟Excel电子表格实例分享

原文来自http://www.6excel.com/doc/20049 一.电子表格中用到的快捷键: ← → ↑ ↓  :左,右,上,下 Home :当前行的第一列 End  :当前行的最后一列 Shift+Home :表格的第一列 Shift+End:表格的最后一列 如图: 代码如下: <%@ page language="java" pageEncoding="UTF-8"%><html>  <head>    <tit

《介绍一款开源的类Excel电子表格软件》续:七牛云存储实战(C#)

?? 两个月前的发布的博客<介绍一款开源的类Excel电子表格软件>引起了热议:在博客园有近2000个View.超过20个评论. 同时有热心读者电话咨询如何能够在SpreadDesing中实现存储Excel云文件,既通过云方式读取.加载Excel文件.在本文,我们就大家关心的云存储进行实战操练---基于SpreadDesign源码基础. 系统必备: 本文选用的国内比较流行的七牛云存储. SpreadDesign.exe已经升级为最新的Spread Studio 8.35.20143.0内核 .

处理Excel电子表格

一个Excel电子表格文档称为一个工作薄. 每个工作薄可以包含多个工作表. 用户当前查看的表,称为活动表. python没有自带openpyxl,所以必须安装. c:\python\Scripts>pip3.6 install openpyxl Collecting openpyxl   Downloading openpyxl-2.4.9.tar.gz (157kB)     100% |████████████████████████████████| 163kB 183kB/s Colle

为Excel电子表格添加快速打印功能按钮的方法

对于需要频繁切换打印机来完成打印工作的人来说,切换打印机的重复操作非常繁琐且没有效率.其实微软早就为大家准备了各种解决重复劳动的各种工具,比如“快速访问工具栏”和“宏”.下面笔者就跟大家来讲讲如何利用这两个工具来为Excel电子表格添加快速打印的功能按钮,只要轻轻点击一下这个按钮,内容就会发送至指定的打印机进行打印,而不用管当前默认的打印机是哪一台. 一.添加“快速打印”功能按钮 首先打开Excel电子表格,点开窗口左上角下拉箭头的“自定义快速访问工具栏”,然后选择相应的功能即可.比如我们选择“

开源顺顺表格excel电子表格控件免费下载

顺顺表格开源版是基于Web的类似于微软Excel的网页电子表格控件,是一款Javascript电子表格控件.顺顺表格开源版的源代码开放,可以用于Web报表设计器,Web电子表格编辑器,中国特色的电子表单设计器等. 该Web Excel控件可以和Java/Jsp/Asp.Net集成, 实现更强大的电子表格在线编辑功能. 顺顺表格开源版特色 无限制的行和列(增加删除) 电子表格多单元格操作 单元格不同格式(字体,字号等) 统计函数 无限制undo/redo 下载试用 产品 顺顺表格开源版试用版  (

Office word excel电子表格在线编辑的实现方法

Office xp之后的版本支持通过webdav协议(http的扩展)直接编辑服务器上的文件. IIS(6.0)支持webdav,这在IIS管理器的web服务扩展中可以看到.利用IIS作为webdav的服务器端,可以很容易的实现office word,excel在线编辑. 可以简单的实验一下: 确保IIS的webdav扩展安装并被启用了,建立一个虚拟目录test,在其中放一个word文档a.doc,然后打开word, 文件->打开->输入word文档的访问url(http://localhos

LinqToExcel: LINQ查询Excel电子表格

Linq的强大人所共知,能不能将Linq扩展到读取excel呢? 答案当然是肯定的. LinqToExcel就是一个实现了使用Linq语法查询excel表格的.net开源类库. 在nuget搜索下载安装到项目,添加using LinqToExcel引用,然后参见如下代码使用: rtb_Result.Text = "LinqTOExcel的使用(支持Excel2003及以下版本.)\n"; OpenFileDialog excelOpener = new OpenFileDialog()