新版本的xlsx是使用新的存储格式,貌似是处理过的XML。

传统的excel处理方法,我真的感觉像屎。用Oldeb不方便,用com组件要实际调用excel打开关闭,很容易出现死。

对于OpenXML我网上搜了一下,很多人没有介绍。所以我就这里推荐下,相信会成为信息系统开发的必备。

先写出个例子,会发现如此的简介:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using XFormular.config;
  5. using System.IO;
  6. using com.xtar.amfx;
  7. using System.Runtime.Serialization.Formatters.Binary;
  8. using System.Data;
  9.  
  10. namespace XFormular.test
  11. {
  12. class Class1
  13. {
  14. public void test()
  15. {
  16. DataTable table = new DataTable("");
  17. table.Columns.Add("");
  18. for (int i = ; i < ; i++)
  19. {
  20. DataRow row = table.NewRow();
  21. row[] = i;
  22. table.Rows.Add(row);
  23. }
  24.  
  25. List<DataTable> lsit = new List<DataTable>();
  26. lsit.Add(table);
  27.  
  28. OpenXmlSDKExporter.Export(AppDomain.CurrentDomain.BaseDirectory + "\\excel.xlsx", lsit);
  29. }
  30. }
  31. }

写出代码:

  1. using System;
  2. using System.IO;
  3. using System.Windows.Forms;
  4. using DocumentFormat.OpenXml;
  5. using DocumentFormat.OpenXml.Packaging;
  6. using DocumentFormat.OpenXml.Spreadsheet;
  7. using DocumentFormat.OpenXml.Extensions;
  8. using System.Collections.Generic;
  9. using System.Data;
  10. using System.Text.RegularExpressions;
  11.  
  12. namespace XFormular
  13. {
  14. //http://simpleooxml.codeplex.com/
  15. //http://www.pin5i.com/showtopic-21817.html
  16. //http://blog.csdn.net/lbj147123/article/details/6603942
  17. class OpenXmlSDKExporter
  18. {
  19. private static string[] Level = {"A", "B", "C", "D", "E", "F", "G",
  20. "H", "I", "G", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
  21. "U", "V", "W", "X", "Y", "Z" };
  22.  
  23. public static List<DataTable> Import(string path)
  24. {
  25. List<DataTable> tables = new List<DataTable>();
  26.  
  27. if (path.EndsWith(ExcelHelper.POSTFIX_SVN))
  28. return tables;
  29.  
  30. using (MemoryStream stream = SpreadsheetReader.StreamFromFile(path))
  31. {
  32. using (SpreadsheetDocument doc = SpreadsheetDocument.Open(stream, true))
  33. {
  34. foreach (Sheet sheet in doc.WorkbookPart.Workbook.Descendants<Sheet>())
  35. {
  36. DataTable table = new DataTable(sheet.Name.Value);
  37.  
  38. WorksheetPart worksheet = (WorksheetPart)doc.WorkbookPart.GetPartById(sheet.Id);
  39.  
  40. List<string> columnsNames = new List<string>();
  41.  
  42. foreach (Row row in worksheet.Worksheet.Descendants<Row>())
  43. {
  44. foreach (Cell cell in row)
  45. {
  46. string columnName = Regex.Match(cell.CellReference.Value, "[a-zA-Z]+").Value;
  47.  
  48. if (!columnsNames.Contains(columnName))
  49. {
  50. columnsNames.Add(columnName);
  51. }
  52.  
  53. }
  54. }
  55.  
  56. columnsNames.Sort(CompareColumn);
  57.  
  58. foreach (string columnName in columnsNames)
  59. {
  60. table.Columns.Add(columnName);
  61. }
  62.  
  63. foreach (Row row in worksheet.Worksheet.Descendants<Row>())
  64. {
  65. DataRow tableRow = table.NewRow();
  66. table.Rows.Add(tableRow);
  67.  
  68. foreach (Cell cell in row)
  69. {
  70. string columnName = Regex.Match(cell.CellReference.Value, "[a-zA-Z]+").Value;
  71. tableRow[columnName] = GetValue(cell, doc.WorkbookPart.SharedStringTablePart);
  72. }
  73. }
  74.  
  75. if (table.Rows.Count <= )
  76. continue;
  77. if (table.Columns.Count <= )
  78. continue;
  79.  
  80. tables.Add(table);
  81. }
  82. }
  83. }
  84.  
  85. return tables;
  86. }
  87.  
  88. public static String GetValue(Cell cell, SharedStringTablePart stringTablePart)
  89. {
  90.  
  91. if (cell.ChildElements.Count == )
  92.  
  93. return null;
  94.  
  95. //get cell value
  96.  
  97. String value = cell.CellValue.InnerText;
  98.  
  99. //Look up real value from shared string table
  100.  
  101. if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString))
  102.  
  103. value = stringTablePart.SharedStringTable
  104.  
  105. .ChildElements[Int32.Parse(value)]
  106.  
  107. .InnerText;
  108.  
  109. return value;
  110.  
  111. }
  112.  
  113. public static void Export(string path, List<DataTable> tables)
  114. {
  115. using (MemoryStream stream = SpreadsheetReader.Create())
  116. {
  117. using (SpreadsheetDocument doc = SpreadsheetDocument.Open(stream, true))
  118. {
  119. SpreadsheetWriter.RemoveWorksheet(doc, "Sheet1");
  120. SpreadsheetWriter.RemoveWorksheet(doc, "Sheet2");
  121. SpreadsheetWriter.RemoveWorksheet(doc, "Sheet3");
  122.  
  123. foreach (DataTable table in tables)
  124. {
  125. WorksheetPart sheet = SpreadsheetWriter.InsertWorksheet(doc, table.TableName);
  126. WorksheetWriter writer = new WorksheetWriter(doc, sheet);
  127.  
  128. SpreadsheetStyle style = SpreadsheetStyle.GetDefault(doc);
  129.  
  130. foreach (DataRow row in table.Rows)
  131. {
  132. for (int i = ; i < table.Columns.Count; i++)
  133. {
  134. string columnName = SpreadsheetReader.GetColumnName("A", i);
  135. string location = columnName + (table.Rows.IndexOf(row) + );
  136. writer.PasteText(location, row[i].ToString(), style);
  137. }
  138. }
  139.  
  140. writer.Save();
  141. }
  142. SpreadsheetWriter.StreamToFile(path, stream);//保存到文件中
  143. }
  144. }
  145. }
  146.  
  147. private static int CompareColumn(string x, string y)
  148. {
  149. int xIndex = Letter_to_num(x);
  150. int yIndex = Letter_to_num(y);
  151. return xIndex.CompareTo(yIndex);
  152. }
  153.  
  154. /// <summary>
  155. /// 数字26进制,转换成字母,用递归算法
  156. /// </summary>
  157. /// <param name="value"></param>
  158. /// <returns></returns>
  159. private static string Num_to_letter(int value)
  160. {
  161. //此处判断输入的是否是正确的数字,略(正在表达式判断)
  162. int remainder = value % ;
  163. //remainder = (remainder == 0) ? 26 : remainder;
  164. int front = (value - remainder) / ;
  165. if (front < )
  166. {
  167. return Level[front - ] + Level[remainder];
  168. }
  169. else
  170. {
  171. return Num_to_letter(front) + Level[remainder];
  172. }
  173. //return "";
  174. }
  175.  
  176. /// <summary>
  177. /// 26进制字母转换成数字
  178. /// </summary>
  179. /// <param name="letter"></param>
  180. /// <returns></returns>
  181. private static int Letter_to_num(string str)
  182. {
  183. //此处判断是否是由A-Z字母组成的字符串,略(正在表达式片段)
  184. char[] letter = str.ToCharArray(); //拆分字符串
  185. int reNum = ;
  186. int power = ; //用于次方算值
  187. int times = ; //最高位需要加1
  188. int num = letter.Length;//得到字符串个数
  189. //得到最后一个字母的尾数值
  190. reNum += Char_num(letter[num - ]);
  191. //得到除最后一个字母的所以值,多于两位才执行这个函数
  192. if (num >= )
  193. {
  194. for (int i = num - ; i > ; i--)
  195. {
  196. power = ;//致1,用于下一次循环使用次方计算
  197. for (int j = ; j < i; j++) //幂,j次方,应该有函数
  198. {
  199. power *= ;
  200. }
  201. reNum += (power * (Char_num(letter[num - i - ]) + times)); //最高位需要加1,中间位数不需要加一
  202. times = ;
  203. }
  204. }
  205. //Console.WriteLine(letter.Length);
  206. return reNum;
  207. }
  208.  
  209. /// <summary>
  210. /// 输入字符得到相应的数字,这是最笨的方法,还可用ASIICK编码;
  211. /// </summary>
  212. /// <param name="ch"></param>
  213. /// <returns></returns>
  214. private static int Char_num(char ch)
  215. {
  216. switch (ch)
  217. {
  218. case 'A':
  219. return ;
  220. case 'B':
  221. return ;
  222. case 'C':
  223. return ;
  224. case 'D':
  225. return ;
  226. case 'E':
  227. return ;
  228. case 'F':
  229. return ;
  230. case 'G':
  231. return ;
  232. case 'H':
  233. return ;
  234. case 'I':
  235. return ;
  236. case 'J':
  237. return ;
  238. case 'K':
  239. return ;
  240. case 'L':
  241. return ;
  242. case 'M':
  243. return ;
  244. case 'N':
  245. return ;
  246. case 'O':
  247. return ;
  248. case 'P':
  249. return ;
  250. case 'Q':
  251. return ;
  252. case 'R':
  253. return ;
  254. case 'S':
  255. return ;
  256. case 'T':
  257. return ;
  258. case 'U':
  259. return ;
  260. case 'V':
  261. return ;
  262. case 'W':
  263. return ;
  264. case 'X':
  265. return ;
  266. case 'Y':
  267. return ;
  268. case 'Z':
  269. return ;
  270. }
  271. return -;
  272. }
  273. }
  274. }
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Data;
  5. using System.Data.OleDb;
  6.  
  7. namespace xtar_biz_codegen
  8. {
  9. class ExcelHelper
  10. {
  11. public static string POSTFIX_97 = "XLS";
  12.  
  13. public static string POSTFIX_03 = "XLSX";
  14. }
  15. }

最后附送一个项目文件,可以自己测试:

http://pan.baidu.com/s/1msFuY

一个用微软官方的OpenXml读写Excel 目前网上不太普及的方法。的更多相关文章

  1. #应用openxml读写excel代码

    这个例子比较简单,没有考虑格式之类的问题. using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Spreadshe ...

  2. Python: 读写Excel(openpyxl / win32com.client)

    项目周报汇报的时候要做数据汇总,总是要从不同的excel文件中去获取数据最后汇总到一个excel表里面,所以决定用python直接写个自动化脚本来自动执行. 用python来读写excel,目前找了2 ...

  3. 微软官方的Excel android 移动版的折腾

    微软官方的Excel android 移动版,有重大bug.害我折腾了一天多时间.最终确认是Excel自身的问题. 现象描述:手机上新建或是保存excel后.放到电脑上,不能打开.提示”Excel在B ...

  4. 微软官方 Win 11 “体检工具”太烂了?开发者自己做了一个

    1.Win 10 免费升级到 Win 11 最近微软官方终于宣布了 Windows 11,不仅带来了全新的 UI,而且还有很多新功能:比如支持 Android 应用. 虽然微软官方已说明 Win 10 ...

  5. 【原创】.NET读写Excel工具Spire.Xls使用(1)入门介绍

    在.NET平台,操作Excel文件是一个非常常用的需求,目前比较常规的方法有以下几种: 1.Office Com组件的方式:这个方式非常累人,微软的东西总是这么的复杂,使用起来可能非常不便,需要安装E ...

  6. 【原创】.NET读写Excel工具Spire.Xls使用(3)单元格控制

                  本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html .NET读写Excel工具Spire.Xls使用文章 ...

  7. .NET读写Excel工具Spire.Xls使用(1)入门介绍

    原文:[原创].NET读写Excel工具Spire.Xls使用(1)入门介绍 在.NET平台,操作Excel文件是一个非常常用的需求,目前比较常规的方法有以下几种: 1.Office Com组件的方式 ...

  8. 使用NPOI读写Excel、Word

    NPOI 是 POI 项目的 .NET 版本.POI是一个开源的Java读写Excel.WORD等微软OLE2组件文档的项目. 使用 NPOI 你就可以在没有安装 Office 或者相应环境的机器上对 ...

  9. 【原创】.NET读写Excel工具Spire.Xls使用(4)对数据操作与控制

                  本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html .NET读写Excel工具Spire.Xls使用文章 ...

随机推荐

  1. 【转载】最完美解决Nginx部署ThinkPHP项目的办法

    网上通用解决方法的配置如下: server { ... location / { index index.htm index.html index.php; #访问路径的文件不存在则重写URL转交给T ...

  2. rsync排除文件同步

    排除扩展名为log的文件 rsync -ave ssh --exclude '*.log' root@192.168.168.188:/website/abc.com/* /website/abc.c ...

  3. PowerPoint

    工具/原料 PowerPoint 2007 百度经验:jingyan.baidu.com 一.PowerPoint2007基础知识 1 桌面快捷方式:也可以“开始”菜单→程序→Microsoft Of ...

  4. Spring笔记--0907

    包含ioc和aop两大核心概念 aop----事务管理 spring框架运用的设计模式(查一下) ---------------------------------------Ioc(控制反转)和Di ...

  5. 虚拟机安装Ubuntu到U盘

    这篇经验中特指系统安装到U盘,系统在U盘上,不是双系统,不会改变源系统的设置.只需在启动的时候选择启动路径,就可以从U盘启动你的系统.本文仅仅Ubuntu系统,举一反三可以按照此方法安装各种各样的系统 ...

  6. python 元类

    转载自  http://blog.jobbole.com/21351/ 类也是对象 在理解元类之前,你需要先掌握Python中的类.Python中类的概念借鉴于Smalltalk,这显得有些奇特.在大 ...

  7. java的 new 关键字

    java的new关键字想必大家都知道这是实例化一个对象.没错,也是为新对象分配内存空间. 比如new MyDate(22,7,1964)这样一个案例,他的完成需要四部: 一.为新对象分配内存空间,将M ...

  8. WP7系统托盘和应用程序栏

    (一)系统托盘和应用程序栏系统托盘(1)显示系统级别的状态信息(2)Apps能隐藏和显示系统托盘Micosoft.Phone.Shell.SystemTray.IsVisible=true;应用程序栏 ...

  9. [CSDN转载]致C语言初学者—指针注意项

    在论坛里经常见到一些新人对指针提出一些问题,作为一个经历过许多错误后的新手,我想把自己的经历说出来,避免让后来人继续这样的错误.    在讲解指针之前,需要理解一下内存空间.内存是随机存取器,计算机上 ...

  10. 打印文本中的所有单词,并且打印每个单词出现的行号,非实义单词不考虑(TCPL,练习6-3)

    建立一棵二叉树,每个接单存放单词以及指向一个链表的指针,以及指向左右节点的指针.链表内存放行号以及指向下一个链表节点的指针. 每录入一个单词,先寻找二叉树,再寻找它的链表,分别将单词和行号插入二叉树和 ...