最近在论坛里又看到很多关于DataTable(DataSet)导入Excel的帖子,我也温故知新一下,用VS2010重新整理了一个Sample。这个问题简化一下就是内存数据到文件,也就是遍历赋值,只不过文件是有特殊格式的Excel,因此不能像一般的文本文件处理。另外,还有一种叫CSV的文件(用逗号分隔的文件,扩展名为.csv),因为默认用Excel打开的,网友也往往把这种文件误当做Excel文件。其实一个通过Excel COM对象作成Excel文件,一个通过一般的IO处理,他们的作成过程是完全不一样的。
先来看看Sample的结构: Form_Load的时候读取DB,绑定到DataGridView。按下"Data2Excel"按钮导出Excel文件(*.xls文件), 按下”Data2CSV”按钮导出CSV文件(*.csv文件)
其实CSV文件用文本文件可以直接打开,看下图,就是逗号分隔的文件,直接通过StringBuilder构造每一行字符串,最后通过System.IO.File.WriteAllText就可以了。
而关于Excel的操作,有两种方式,一种通过Cell一个一个单元格赋值,还有一种通过系统剪切板通过粘贴的方式赋值。因为跨托管域赋值,第一种赋值方式效率很低,原因嘛,可以看看这里:《.NET操作Excel COM对象》。所以Sample里选择了第二种方式。
另外,.NET 4.0里C#终于可以用上像VB.NET的可选参数了 T_T 真是省不少事啊,以前C#操作Excel都要写上很多System.Reflection.Missing.Value呢。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.IO; using System.Runtime.InteropServices; using System.Reflection; using Excel = Microsoft.Office.Interop.Excel; namespace DataExportLib { /// <summary> /// 数据导出工具类 /// 前提:Microsoft Office 11.0 Object Library /// .NET Framework 4.0 /// </summary> public class DataExportUtils { public static void Export2Xls(DataTable data, string filename, bool exportHeader = true) { if (System.IO.File.Exists(filename)) System.IO.File.Delete(filename); Excel._Application xlsApp = null; Excel._Workbook xlsBook = null; Excel._Worksheet xstSheet = null; try { xlsApp = new Excel.ApplicationClass(); xlsBook = xlsApp.Workbooks.Add(); xstSheet = (Excel._Worksheet)xlsBook.Worksheets[1]; var buffer = new StringBuilder(); if (exportHeader) { // Excel中列与列之间按照Tab隔开 foreach (DataColumn col in data.Columns) buffer.Append(col.ColumnName + "/t"); buffer.AppendLine(); } foreach (DataRow row in data.Rows) { foreach (DataColumn col in data.Columns) buffer.Append(row[col].ToString() + "/t"); buffer.AppendLine(); } System.Windows.Forms.Clipboard.SetDataObject(""); // 放入剪切板 System.Windows.Forms.Clipboard.SetDataObject(buffer.ToString()); var range = (Excel.Range)xstSheet.Cells[1, 1]; range.Select(); xstSheet.Paste(); // 清空剪切板 System.Windows.Forms.Clipboard.SetDataObject(""); xlsBook.SaveAs(filename); } finally { if (xlsBook != null) xlsBook.Close(); if (xlsApp != null) xlsApp.Quit(); // finally里清空Com对象 Marshal.ReleaseComObject(xlsApp); Marshal.ReleaseComObject(xlsBook); Marshal.ReleaseComObject(xstSheet); xstSheet = null; xlsBook = null; xlsApp = null; } } public static void Export2CSV(DataTable data, string filename, bool exportHeader = true) { if (File.Exists(filename)) File.Delete(filename); var buffer = new StringBuilder(); if (exportHeader) { for (var i = 0; i < data.Columns.Count; i++) { buffer.AppendFormat("/"{0}/"", data.Columns[i].ColumnName); if (i < data.Columns.Count - 1) buffer.Append(","); } buffer.AppendLine(); } for (var i = 0; i < data.Rows.Count; i++) { for (var j = 0; j < data.Columns.Count; j++) { buffer.AppendFormat("/"{0}/"", data.Rows[i][j].ToString()); if (j < data.Columns.Count - 1) buffer.Append(","); } buffer.AppendLine(); } File.WriteAllText(filename, buffer.ToString(), Encoding.Default); } public static void Export2Xls<T>(List<T> data, string filename, bool exportHeader = true) { if (File.Exists(filename)) File.Delete(filename); Excel._Application xlsApp = null; Excel._Workbook xlsBook = null; Excel._Worksheet xstSheet = null; var type = typeof(T); var properties = type.GetProperties(); var buffer = new StringBuilder(); if (exportHeader) { xlsApp = new Excel.ApplicationClass(); xlsBook = xlsApp.Workbooks.Add(); xstSheet = (Excel._Worksheet)xlsBook.Worksheets[1]; if (exportHeader) { foreach (var property in properties) buffer.Append(property.Name + "/t"); buffer.AppendLine(); } foreach (var row in data) { foreach (var property in properties) buffer.Append(property.GetValue(row, null) + "/t"); buffer.AppendLine(); } System.Windows.Forms.Clipboard.SetDataObject(""); // 放入剪切板 System.Windows.Forms.Clipboard.SetDataObject(buffer.ToString()); var range = (Excel.Range)xstSheet.Cells[1, 1]; range.Select(); xstSheet.Paste(); // 清空剪切板 System.Windows.Forms.Clipboard.SetDataObject(""); xlsBook.SaveAs(filename); } } public static void Export2CSV<T>(List<T> data, string filename, bool exportHeader = true) { if (File.Exists(filename)) File.Delete(filename); var type = typeof(T); var properties = type.GetProperties(); var buffer = new StringBuilder(); if (exportHeader) { for (var i = 0; i < properties.Length; i++) { buffer.AppendFormat("/"{0}/"", properties[i].Name); if (i < properties.Length - 1) buffer.Append(","); } buffer.AppendLine(); } for (var i = 0; i < data.Count; i++) { for (var j = 0; j < properties.Length; j++) { buffer.AppendFormat("/"{0}/"", properties[j].GetValue(data[i], null).ToString()); if (j < properties.Length - 1) buffer.Append(","); } buffer.AppendLine(); } File.WriteAllText(filename, buffer.ToString()); } } }