还有什么不能做?——细谈在C#中读写Excel系列文

来源:http://www.venoautomotive.com 作者:永利电子游戏网址 人气:156 发布时间:2019-10-29
摘要:在其次篇小说中作者生机勃勃度向大家详细介绍了Excel二〇〇七后头版本的文书的OpenXML结构。所谓的OpenXML结构从本质上来讲其实正是贰个ZIP压缩包,全部基于OpenXML数据结构的文书都相

  在其次篇小说中作者生机勃勃度向大家详细介绍了Excel 二〇〇七后头版本的文书的OpenXML结构。所谓的OpenXML结构从本质上来讲其实正是贰个ZIP压缩包,全部基于OpenXML数据结构的文书都相符。那样文件的组织是开放的,你无需依赖任何第三方的零件就足以读取文件中的数据,也许涂改文件的源委。何况具备资源文件诸如图片和多媒体文件都以被编写翻译成多个永世的格式贮存在调整和裁减包中,实际不是价值观形式上的流。此外,以压缩包的款型积累数据也使得文件所攻下的空间更加小。

还有什么不能做?——细谈在C#中读写Excel系列文章之三。  这一个都是它的亮点。其实,微软在.NET中意气风发度提供了对应的类库来赞助大家操作OpenXML文件,好似小编在第二篇文章中向大家介绍的风度翩翩致,微软把OpenXML压缩包称之为二个Package,在Package中的文件称作Parts,差异的Parts有温馨的Content Type。Content Type能够描述任何内容,如application XML,user XML,images,sounds,videos,恐怕其余二进制内容。各种Part之间通过一个被称之为relationship的part连接起来,这一个part其实也是生机勃勃种独特的XML文件,后缀为".rels",在Package中得以找到它。下图表明了叁个Package中逐个Part之间的涉嫌,

图片 1

  就算.NET中提供的Package类能够支持大家丰富方便地解析Excel包,可是也可以有广大的局限性,临时你必须要动用部分主意来自个儿读取包中的内容,或许尝试去改过包中的数据。

  1. 将Package作为三个标准的zip文件举行解压。

  2. 找到Package中你想要读取的parts。有为数不菲的点子可以帮助你找到这几个parts,你能够深入深入分析relationship,也足以一贯通过path来恒定到某贰个文书,不过不太明确path在后天是还是不是会有变化。恐怕还足以经过part的content type来找到它。

还有什么不能做?——细谈在C#中读写Excel系列文章之三。  3. 读取part中的内容。即使parts是以XML的花样存放的,通过标准的XML类库就足以特别方便地读取到数据。假诺是其余情势,如图片、声音或录制文件则也能够透过相应的格局来获得到剧情。

还有什么不能做?——细谈在C#中读写Excel系列文章之三。还有什么不能做?——细谈在C#中读写Excel系列文章之三。  其他方面,你也得以创立二个依据OpenXML的文件(如选取非COM组件的款型创制多个Excel文件),

还有什么不能做?——细谈在C#中读写Excel系列文章之三。  1. 创设或复制全部必得的parts。通过标准XML类库来成立那么些依据XML数据格式的parts,或许从任何package中复制这个parts,或然使用别的此外你所耳熟能详的章程。

  2. 创立relationships部分。也正是创制一个后缀为".rels"的例外XML文件。

  3. 将整个package压缩成三个zip包,然后将文件的后缀校勘成供给的档案的次序(如docx,xlsx,或许pptx等)。只要package中的结构切合需要,修正现在的文本能够平昔被展开。当然,该进程能够在一丝一毫未有安装office的机器上完结(举例服务器),然后分发给须要之处使用。

  全体那总体富含packages,parts,content types,以致relationships都被称之为OpenXML文书档案,微软将以此称呼Open Packaging Conventions。

  有关Excel OpenXML的内部结构甚至一些比较重大的节点含义在前生龙活虎篇文章中早已做了一些介绍,除了直接使用.NET类库中的Package类之外,我们本来也足以利用任何的第三方类库也许本身编写代码读取包中的内容,这里有三个.NET的开源类库特地用来操作zip压缩文件。

  提供贰个主次集下载吧,源代码我们去地点那几个网站下载。ICSharpCode.ShareZipLib.zip

  借用该类库中的ExtractZip()和CreateZip()方法能够支持我们读取或改动(创立)Excel文件。当然那一个类库中的某个代码是使用较早的.NET版本中的语法和目的来编排的,诸如ArratList、Hashtable等,它可能不适合在Silverlight工程中央银行使(扶持Silverlight的.NET Framework与平日的.NET Framework有不菲界别而且转换比较频仍),接下去的文章中笔者会向大家介绍如何在Silverlight工程中运用它。但未来并不要紧碍大家在别的体系的工程中使用。

  来看生龙活虎看实际的例证。这里有三个类提供了一些方法用来读取和修正Excel文件中的数据:

  1 using System.Collections.Generic;
  2 using System.Data;
  3 using System.Globalization;
  4 using System.IO;
  5 using System.Text;
  6 using System.Xml;
  7 using ICSharpCode.SharpZipLib.Zip;
  8 
  9 namespace XlsxReadWrite
 10 {
 11     internal static class XlsxRW
 12     {
 13         public static void DeleteDirectoryContents(string directory)
 14         {
 15             var info = new DirectoryInfo(directory);
 16 
 17             foreach (var file in info.GetFiles())
 18             {
 19                 file.Delete();
 20             }
 21 
 22             foreach (var dir in info.GetDirectories())
 23             {
 24                 dir.Delete(true);
 25             }
 26         }
 27 
 28         public static void UnzipFile(string zipFileName, string targetDirectory)
 29         {
 30             new FastZip().ExtractZip(zipFileName, targetDirectory, null);
 31         }
 32 
 33         public static void ZipDirectory(string sourceDirectory, string zipFileName)
 34         {
 35             new FastZip().CreateZip(zipFileName, sourceDirectory, true, null);
 36         }
 37 
 38         public static IList<string> ReadStringTable(Stream input)
 39         {
 40             var stringTable = new List<string>();
 41 
 42             using (var reader = XmlReader.Create(input))
 43             {
 44                 for (reader.MoveToContent(); reader.Read(); )
 45                 {
 46                     if (reader.NodeType == XmlNodeType.Element && reader.Name == "t")
 47                     {
 48                         stringTable.Add(reader.ReadElementString());
 49                     }
 50                 }
 51             }
 52 
 53             return stringTable;
 54         }
 55 
 56         public static void ReadWorksheet(Stream input, IList<string> stringTable, DataTable data)
 57         {
 58             using (var reader = XmlReader.Create(input))
 59             {
 60                 DataRow row = null;
 61                 int columnIndex = 0;
 62                 string type;
 63                 int value;
 64 
 65                 for (reader.MoveToContent(); reader.Read(); )
 66                     if (reader.NodeType == XmlNodeType.Element)
 67                         switch (reader.Name)
 68                         {
 69                             case "row":
 70                                 row = data.NewRow();
 71                                 data.Rows.Add(row);
 72 
 73                                 columnIndex = 0;
 74 
 75                                 break;
 76 
 77                             case "c":
 78                                 type = reader.GetAttribute("t");
 79                                 reader.Read();
 80                                 value = int.Parse(reader.ReadElementString(), CultureInfo.InvariantCulture);
 81 
 82                                 if (type == "s")
 83                                     row[columnIndex] = stringTable[value];
 84                                 else
 85                                     row[columnIndex] = value;
 86 
 87                                 columnIndex++;
 88 
 89                                 break;
 90                         }
 91             }
 92         }
 93 
 94         public static IList<string> CreateStringTables(DataTable data, out IDictionary<string, int> lookupTable)
 95         {
 96             var stringTable = new List<string>();
 97             lookupTable = new Dictionary<string, int>();
 98 
 99             foreach (DataRow row in data.Rows)
100                 foreach (DataColumn column in data.Columns)
101                     if (column.DataType == typeof(string))
102                     {
103                         var value = (string)row[column];
104 
105                         if (!lookupTable.ContainsKey(value))
106                         {
107                             lookupTable.Add(value, stringTable.Count);
108                             stringTable.Add(value);
109                         }
110                     }
111 
112             return stringTable;
113         }
114 
115         public static void WriteStringTable(Stream output, IList<string> stringTable)
116         {
117             using (var writer = XmlWriter.Create(output))
118             {
119                 writer.WriteStartDocument(true);
120 
121                 writer.WriteStartElement("sst", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
122                 writer.WriteAttributeString("count", stringTable.Count.ToString(CultureInfo.InvariantCulture));
123                 writer.WriteAttributeString("uniqueCount", stringTable.Count.ToString(CultureInfo.InvariantCulture));
124 
125                 foreach (var str in stringTable)
126                 {
127                     writer.WriteStartElement("si");
128                     writer.WriteElementString("t", str);
129                     writer.WriteEndElement();
130                 }
131 
132                 writer.WriteEndElement();
133             }
134         }
135 
136         public static string RowColumnToPosition(int row, int column)
137         {
138             return ColumnIndexToName(column) + RowIndexToName(row);
139         }
140 
141         public static string ColumnIndexToName(int columnIndex)
142         {
143             var second = (char)(((int)'A') + columnIndex % 26);
144 
145             columnIndex /= 26;
146 
147             if (columnIndex == 0)
148                 return second.ToString();
149             else
150                 return ((char)(((int)'A') - 1 + columnIndex)).ToString() + second.ToString();
151         }
152 
153         public static string RowIndexToName(int rowIndex)
154         {
155             return (rowIndex + 1).ToString(CultureInfo.InvariantCulture);
156         }
157 
158         public static void WriteWorksheet(Stream output, DataTable data, IDictionary<string, int> lookupTable)
159         {
160             using (XmlTextWriter writer = new XmlTextWriter(output, Encoding.UTF8))
161             {
162                 writer.WriteStartDocument(true);
163 
164                 writer.WriteStartElement("worksheet");
165                 writer.WriteAttributeString("xmlns", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
166                 writer.WriteAttributeString("xmlns:r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
167 
168                 writer.WriteStartElement("dimension");
169                 var lastCell = RowColumnToPosition(data.Rows.Count - 1, data.Columns.Count - 1);
170                 writer.WriteAttributeString("ref", "A1:" + lastCell);
171                 writer.WriteEndElement();
172 
173                 writer.WriteStartElement("sheetViews");
174                 writer.WriteStartElement("sheetView");
175                 writer.WriteAttributeString("tabSelected", "1");
176                 writer.WriteAttributeString("workbookViewId", "0");
177                 writer.WriteEndElement();
178                 writer.WriteEndElement();
179 
180                 writer.WriteStartElement("sheetFormatPr");
181                 writer.WriteAttributeString("defaultRowHeight", "15");
182                 writer.WriteEndElement();
183 
184                 writer.WriteStartElement("sheetData");
185                 WriteWorksheetData(writer, data, lookupTable);
186                 writer.WriteEndElement();
187 
188                 writer.WriteStartElement("pageMargins");
189                 writer.WriteAttributeString("left", "0.7");
190                 writer.WriteAttributeString("right", "0.7");
191                 writer.WriteAttributeString("top", "0.75");
192                 writer.WriteAttributeString("bottom", "0.75");
193                 writer.WriteAttributeString("header", "0.3");
194                 writer.WriteAttributeString("footer", "0.3");
195                 writer.WriteEndElement();
196 
197                 writer.WriteEndElement();
198             }
199         }
200 
201         public static void WriteWorksheetData(XmlTextWriter writer, DataTable data, IDictionary<string, int> lookupTable)
202         {
203             var rowsCount = data.Rows.Count;
204             var columnsCount = data.Columns.Count;
205             string relPos;
206 
207             for (int row = 0; row < rowsCount; row++)
208             {
209                 writer.WriteStartElement("row");
210                 relPos = RowIndexToName(row);
211                 writer.WriteAttributeString("r", relPos);
212                 writer.WriteAttributeString("spans", "1:" + columnsCount.ToString(CultureInfo.InvariantCulture));
213 
214                 for (int column = 0; column < columnsCount; column++)
215                 {
216                     object value = data.Rows[row][column];
217 
218                     writer.WriteStartElement("c");
219                     relPos = RowColumnToPosition(row, column);
220                     writer.WriteAttributeString("r", relPos);
221 
222                     var str = value as string;
223                     if (str != null)
224                     {
225                         writer.WriteAttributeString("t", "s");
226                         value = lookupTable[str];
227                     }
228 
229                     writer.WriteElementString("v", value.ToString());
230 
231                     writer.WriteEndElement();
232                 }
233 
234                 writer.WriteEndElement();
235             }
236         }
237     }
238 }

  1. DeleteDirectoryContents()方法用来清空有的时候目录的内容,该有时目录被用来贮存解压Excel之后的公文。

  2. UnzipFile()方法直接动用了开源类库中的ExtractZip()方法,将Excel文件解压到一时目录。

  3. ZipDirectory()方法应用开源类库中的CreateZip()方法将一时目录中的内容重新打包成zip压缩文件。

  4. ReadStringTable()方法用来读取xl/sharedStrings.xml文件中节点t的内容。其实应当是一贯读取si节点的从头到尾的经过,应该为实际不是具备的si节点皆有t子节点。

  思量一个意况:在Excel的单元格中,选中后生可畏部分内容,仍遗闻情节中的某一个数字或某二个单词,然后对它独立设置样式。通过这种艺术你能够将Excel单元格中的某一片段内容设置为粗体、上标,还足以在单元格内进行换行等。如下图:

图片 2

  在Excel单元格内设置的体制被存放到sharedStrings.xml文件中后会造成如下这种格局:

<si>
    <r>
      <t xml:space="preserve">  Short-term investments (including securities loaned 
    of </t>
    </r>
    <r>
      <rPr>
        <b/>
        <sz val="8"/>
        <color rgb="FF404040"/>
        <rFont val="Verdana"/>
        <family val="2"/>
      </rPr>
      <t>$9,999</t>
    </r>
    <r>
      <rPr>
        <sz val="8"/>
        <color rgb="FF404040"/>
        <rFont val="Verdana"/>
        <family val="2"/>
      </rPr>
      <t xml:space="preserve"> and $8,888)</t>
    </r>
  </si>

  这时节点si中的内容就不是不过的子节点t了。由此,如何深入分析XML文件必要依照实情去思考,那根本决议于你在Excel文件中蕴藏的剧情。

  5. ReadWorksheet()方法会根据钦点的办事表XML文件(如"xl/worksheets/sheet1.xml")在sharedStrings.xml文件中搜寻数据,并将结果寄存到贰个DataTable中。

  6. CreateStringTables()和WriteStringsTable()方法用来创制三个sharedStrings.xml文件。

  7. WriteWorksheet()方法用来创设二个做事表XML文件。

  来拜访哪些调用:

 1 private void ReadInput(object sender, RoutedEventArgs e)
 2 {
 3     // Get the input file name from the text box.
 4     var fileName = this.inputTextBox.Text;
 5 
 6     // Delete contents of the temporary directory.
 7     XlsxRW.DeleteDirectoryContents(tempDir);
 8 
 9     // Unzip input XLSX file to the temporary directory.
10     XlsxRW.UnzipFile(fileName, tempDir);
11 
12     IList<string> stringTable;
13     // Open XML file with table of all unique strings used in the workbook..
14     using (var stream = new FileStream(Path.Combine(tempDir, @"xlsharedStrings.xml"),
15         FileMode.Open, FileAccess.Read))
16         // ..and call helper method that parses that XML and returns an array of strings.
17         stringTable = XlsxRW.ReadStringTable(stream);
18 
19     // Open XML file with worksheet data..
20     using (var stream = new FileStream(Path.Combine(tempDir, @"xlworksheetssheet1.xml"),
21         FileMode.Open, FileAccess.Read))
22         // ..and call helper method that parses that XML and fills DataTable with values.
23         XlsxRW.ReadWorksheet(stream, stringTable, this.data);
24 }
25 
26 private void WriteOutput(object sender, RoutedEventArgs e)
27 {
28     // Get the output file name from the text box.
29     string fileName = this.outputTextBox.Text;
30 
31     // Delete contents of the temporary directory.
32     XlsxRW.DeleteDirectoryContents(tempDir);
33 
34     // Unzip template XLSX file to the temporary directory.
35     XlsxRW.UnzipFile(templateFile, tempDir);
36 
37     // We will need two string tables; a lookup IDictionary<string, int> for fast searching 
38     // an ordinary IList<string> where items are sorted by their index.
39     IDictionary<string, int> lookupTable;
40 
41     // Call helper methods which creates both tables from input data.
42     var stringTable = XlsxRW.CreateStringTables(this.data, out lookupTable);
43 
44     // Create XML file..
45     using (var stream = new FileStream(Path.Combine(tempDir, @"xlsharedStrings.xml"),
46         FileMode.Create))
47         // ..and fill it with unique strings used in the workbook
48         XlsxRW.WriteStringTable(stream, stringTable);
49 
50     // Create XML file..
51     using (var stream = new FileStream(Path.Combine(tempDir, @"xlworksheetssheet1.xml"),
52         FileMode.Create))
53         // ..and fill it with rows and columns of the DataTable.
54         XlsxRW.WriteWorksheet(stream, this.data, lookupTable);
55 
56     // ZIP temporary directory to the XLSX file.
57     XlsxRW.ZipDirectory(tempDir, fileName);
58 
59     // If checkbox is checked, show XLSX file in Microsoft Excel.
60     if (this.openFileCheckBox.IsChecked == true)
61         System.Diagnostics.Process.Start(fileName);
62 }

  你所要做的只是对XML进行操作,仅此而以!

  扶植.NET操作zip压缩包的类库应该还应该有为数不菲,任何八个都能够,因为Excel的OpenXML文件本人就是二个专门的职业的zip压缩包。但是地点的措施依然有贰个局限性,那正是急需临时目录来存放解压之后的公文,以至重复包装时所钦赐的源文件。对平日的Windows应用程序或asp.net应用程序来讲那一个并从未什么样困难,只要权力允许,读写有的时候目录未有其他难点,可是在Silverlight中则有所差别,因为在Silverlight中读写客商端文件须要比较高的安全品级和表达,那就招致解压文件会有好多不便,二个简练的法子就是向来在文书的流中开展解压和改换,然后再将流打包成zip文件。下后生可畏篇小说中笔者会向大家介绍怎样在Silverlight中动用,以致怎么着定义二个类来落成Excel文件中或多或少字符串样式的改正。

本文由永利官网误乐域发布于永利电子游戏网址,转载请注明出处:还有什么不能做?——细谈在C#中读写Excel系列文

关键词:

上一篇:没有了

下一篇:没有了

最火资讯