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 = ; 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 = ;
} 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(,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("&", "&");
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(, result.Length - );
if (result.EndsWith("_")) result = result.Substring(, result.Length - ); 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://en.wikipedia.org/wiki/Microsoft_Office_XML_formats
Excel 电子表格文件格式剖析的更多相关文章
- 介绍一款开源的类Excel电子表格软件
Excel一直以霸主的地位,占领了Windows桌面表格软件市场No 1,与此同一时候,Office套装产品差点儿成为了IT行业的标配办公技能.有无相似Excel的桌面程序,绿色版,实现主要的数 ...
- 网页中模拟Excel电子表格实例分享
原文来自http://www.6excel.com/doc/20049 一.电子表格中用到的快捷键: ← → ↑ ↓ :左,右,上,下 Home :当前行的第一列 End :当前行的最后一列 Sh ...
- 《介绍一款开源的类Excel电子表格软件》续:七牛云存储实战(C#)
两个月前的发布的博客<介绍一款开源的类Excel电子表格软件>引起了热议:在博客园有近2000个View.超过20个评论. 同时有热心读者电话咨询如何能够在SpreadDesing中实现存 ...
- 第三篇 从EXCEL电子表格到数据库
一个靠EXCEL电子表格处理各部门业务数据的公司和一个使用一个统一的数据库存储各个部门用到的业务数据并提供大量权限不同的使用界面给用户的公司两者有什么不同呢? EXCEL电子表格是数据和操纵数据的 ...
- C#定时备份正在播放的幻灯片、word文档、excel电子表格,mht格式文档
控制台应用, 代码如下: using System; using System.Collections.Generic; using System.IO; using System.Linq; usi ...
- 从服务端生成Excel电子表格(Node.js+SpreadJS)
Node.js是一个基于Chrome V8引擎的JavaScript运行环境,通常用于创建网络应用程序.它可以同时处理多个连接,并且不像其他大多数模型那样依赖线程. 对于 Web 开发者来说,从数据库 ...
- 从服务端生成Excel电子表格(GcExcel + SpreadJS)
在服务端生成Excel电子表格,除了使用 Node.js + SpreadJS 外,葡萄城官方推荐使用 SpreadJS + GcExcel.该方案不仅能够解决批量绑定数据源并导出Excel.批量修改 ...
- 关闭Excel提示文件格式和扩展名不匹配的警告框
打开某些excel表时,Excel会提示: "a.xls"的文件格式和扩展名不匹配.文件可能已损坏或不安全.除非您信任其来源,否则请勿打开.是否仍要打开它? 在编辑大量的xls ...
- Office word excel电子表格在线编辑的实现方法
Office xp之后的版本支持通过webdav协议(http的扩展)直接编辑服务器上的文件. IIS(6.0)支持webdav,这在IIS管理器的web服务扩展中可以看到.利用IIS作为webdav ...
随机推荐
- Jmeter===Jmeter中使用CSV Data Set Config参数化不重复数据执行N遍(转)
Jmeter中使用CSV Data Set Config参数化不重复数据执行N遍 要求: 今天要测试上千条数据,且每条数据要求执行多次,(模拟多用户多次抽奖) 1.用户id有175个,且没有任何排序规 ...
- 利用eclipse调试ofbiz之debug使用
1.项目右键-配置debug 2.new一个debug调试 3.配置运行类org.ofbiz.base.start.Start 4.设置内存大小:arguments-VM arguments -Xms ...
- 【LabVIEW技巧】LabVIEW中的错误1
前言 前几日,小黑充电学习意外的看到了下面的这个东东. 编程许久竟然没有见过这样子的错误枚举,甚为好奇,问刘大后才知道是Error Ring,为此恶补一下LabVIEW中与错误处理相关的内容. 错误的 ...
- jquery获取元素索引值index()的例子
如果参数是一组DOM元素或者jQuery对象,那么返回值就是传递的元素相对于原先集合的位置. 如果参数是一个选择器,那么返回值就是原先元素相对于选择器匹配元素中的位置.如果找不到匹配的元素,则返回-1 ...
- JavaScript 正则表达式的入门与使用
知道正则表达式已经很久了,粗略会看懂一些,不过以前没有系统的学习,最近在看<JS权威指南>,刚好看到了看到正则表达式部分,就比较系统的学习了正则表达式. 先说一下正则表达式的一些基本知识 ...
- 18:django 日志系统
django使用python内建的logging模块去建造自己的系统日志的,如果你想详细了解这个模块的话,请自己去看python的说明文档,这里仅仅介绍django中的日志系统 日志配置包括四个部分: ...
- HDU-1671
Phone List Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- redis之(三)redis的数据类型
[一]字符串类型(基本数据类型) --->字符串类型是redis的最基本的数据类型 --->能存储任何形式的字符串,(用户邮箱,json化的对象,一张图片) --->一个字符串类型的 ...
- 理解JWT(Json Web Token)
这篇文章写得不错: 理解JWT(JSON Web Token)认证及python实践,这里不做转载,仅摘要如下,有删改,仅做个人学习,感谢原作者. 常用认证机制: 1)HTTP basic Auth: ...
- 【JBPM4】判断节点decision 方法2 condition
运用condition计算并判断. JPDL <?xml version="1.0" encoding="UTF-8"?> <process ...