[Asp.net]常见数据导入Excel,Excel数据导入数据库解决方案

引言

项目中常用到将数据导入Excel,将Excel中的数据导入数据库的功能,曾经也查找过相关的内容,将曾经用过的方案总结一下。
方案一

   NPOI  
  NPOI 是 POI 项目的 .NET 版本。POI是一个开源的Java读写Excel、WORD等 微软 OLE2组件文档的项目。 
使用 NPOI 你就可以在没有安装 Office 或者相应环境的机器上对 WORD/EXCEL 文档进行读写。NPOI是构建在POI 3.x版本之上的,它可以在没有安装Office的情况下对Word/Excel文档进行读写操作。 
   优势  
   (一)传统操作Excel遇到的问题:  
1、如果是.NET,需要在服务器端装Office,且及时更新它,以防漏洞,还需要设定权限允许.NET访问COM+,如果在导出过程中出问题可能导致服务器宕机。 
2、Excel会把只包含数字的列进行类型转换,本来是文本型的,Excel会将其转成数值型的,比如编号000123会变成123。 
3、导出时,如果字段内容以“-”或“=”开头,Excel会把它当成公式进行,会报错。 
4、Excel会根据Excel文件前8行分析数据类型,如果正好你前8行某一列只是数字,那它会认为该列为数值型,自动将该列转变成类似1.42702E+17格式,日期列变成包含日期和数字的。 
(二)使用NPOI的优势  
1、您可以完全免费使用该框架 
2、包含了大部分EXCEL的特性(单元格样式、数据格式、公式等等) 
3、专业的技术支持服务(24*7全天候) (非免费) 
4、支持处理的文件格式包括xls, xlsx, docx. 
5、采用面向接口的设计架构( 可以查看 NPOI.SS 的命名空间) 
6、同时支持文件的导入和导出 
7、基于.net 2.0 也支持xlsx 和 docx格式(当然也支持.net 4.0) 
8、来自全世界大量成功且真实的测试Cases 
9、大量的实例代码 
11、你不需要在服务器上安装微软的Office,可以避免版权问题。 
12、使用起来比Office PIA的API更加方便,更人性化。 
13、你不用去花大力气维护NPOI,NPOI Team会不断更新、改善NPOI,绝对省成本。 
NPOI之所以强大,并不是因为它支持导出Excel,而是因为它支持导入Excel,并能“理解”OLE2文档结构,这也是其他一些Excel读写库比较弱的方面。通常,读入并理解结构远比导出来得复杂,因为导入你必须假设一切情况都是可能的,而生成你只要保证满足你自己需求就可以了,如果把导入需求和生成需求比做两个集合,那么生成需求通常都是导入需求的子集,这一规律不仅体现在Excel读写库中,也体现在pdf读写库中,目前市面上大部分的pdf库仅支持生成,不支持导入。 
   构成  
     NPOI 1.2.x  主要由  POIFS、DDF、HPSF、HSSF、SS、Util  六部分组成。 
  NPOI.POIFS 
OLE2/ActiveX文档属性读写库
  NPOI.DDF 
Microsoft Office Drawing读写库
  NPOI.HPSF 
OLE2/ActiveX文档读写库
  NPOI.HSSF 
Microsoft Excel BIFF(Excel 97-2003)格式读写库
  NPOI.SS 
Excel公用接口及Excel公式计算引擎
  NPOI.Util 
基础类库,提供了很多实用功能,可用于其他读写文件格式项目的开发
     NPOI  组成部分 
   NPOI 1.x的最新版为NPOI 1.2.5  ,其中包括了以下功能: 
  1、读写  OLE2  文档 
  2、读写  DocummentSummaryInformation  和  SummaryInformation  
  3、基于  LittleEndian  的字节读写 
  4、读写  Excel BIFF  格式 
  5、识别并读写  Excel BIFF  中的常见  Record,如RowRecord, StyleRecord, ExtendedFormatRecord  
6、支持设置单元格的高、宽、样式等
  7、支持调用部分  Excel  内建函数,比如说  sum, countif  以及计算符号 
  8、支持在生成的  XLS  内嵌入打印设置,比如说横向/纵向打印、缩放、使用的纸张等。 
NPOI 2.0主要由SS, HPSF, DDF, HSSF, XWPF, XSSF, OpenXml4Net, OpenXmlFormats组成,具体列表如下:
Assembly名称 模块/命名空间 说明
NPOI.DLL   NPOI.POIFS 
OLE2/ActiveX文档属性读写库
NPOI.DLL   NPOI.DDF 
微软Office Drawing读写库
NPOI.DLL   NPOI.HPSF 
OLE2/ActiveX文档读写库
NPOI.DLL   NPOI.HSSF 
微软Excel BIFF(Excel 97-2003, doc)格式读写库
NPOI.DLL   NPOI.SS 
Excel公用接口及Excel公式计算引擎
NPOI.DLL   NPOI.Util 
基础类库,提供了很多实用功能,可用于其他读写文件格式项目的开发
NPOI.OOXML.DLL NPOI.XSSF Excel 2007(xlsx)格式读写库
NPOI.OOXML.DLL NPOI.XWPF Word 2007(docx)格式读写库
NPOI.OpenXml4Net.DLL NPOI.OpenXml4Net OpenXml底层zip包读写库
NPOI.OpenXmlFormats.DLL NPOI.OpenXmlFormats 微软Office OpenXml对象关系库
  (以上内容来自百度百科)从上表可知NPOI组件已支持excel2007,记得之前用的时候只支持excel2003。很久没研究过这玩意儿了。 
    案例 
   官网地址: http://npoi.codeplex.com/ ,可以从官网下载NPOI2.X版本的。 
  首先引入
ICSharpCode.SharpZipLib.dll
NPOI.dll
NPOI.OOXML.dll
NPOI.OpenXml4Net.dll
NPOI.OpenXmlFormats.dll
然后引入命名空间:
  1. using NPOI.XSSF.UserModel;
  2. using NPOI.SS.UserModel;
  3. using NPOI.HSSF.UserModel;
复制代码
      辅助类
   
  1. using NPOI.XSSF.UserModel;
  2. using NPOI.SS.UserModel;
  3. using NPOI.HSSF.UserModel;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Data;
  7. using System.IO;
  8. using System.Linq;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. using NPOI.SS.Formula.Eval;
  12. namespace Wolfy.Common
  13. {        ///         /// 使用NPOI组件        /// 需引入ICSharpCode.SharpZipLib.dll/NPOI.dll/NPOI.OOXML.dll/NPOI.OpenXml4Net.dll/NPOI.OpenXmlFormats.dll        /// office2007        ///         public class NPOIExcelHelper        {        ///         /// 将Excel文件中的数据读出到DataTable中        ///         ///         ///         public static DataTable Excel2DataTable(string file, string sheetName, string tableName)        {        DataTable dt = new DataTable();        IWorkbook workbook = null;        using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))        {        //office2003 HSSFWorkbook        workbook = new XSSFWorkbook(fs);        }        ISheet sheet = workbook.GetSheet(sheetName);        dt = Export2DataTable(sheet, 0, true);        return dt;        }        ///         /// 将指定sheet中的数据导入到datatable中        ///         /// 指定需要导出的sheet        /// 列头所在的行号,-1没有列头        ///         ///         private static DataTable Export2DataTable(ISheet sheet, int HeaderRowIndex, bool needHeader)        {        DataTable dt = new DataTable();        XSSFRow headerRow = null;        int cellCount;        try        {        if (HeaderRowIndex < 0 || !needHeader)        {        headerRow = sheet.GetRow(0) as XSSFRow;        cellCount = headerRow.LastCellNum;        for (int i = headerRow.FirstCellNum; i
复制代码
NPOIExcelHelper 
  参考: http://www.cnblogs.com/Joetao/articles/3247909.html 
   测试结果  
导入Excel,student.xlsx
     
导入DataTable,这里只将数据导入DataTable,导入数据库部分,就不再写了。
     
测试数据,向qq群里一朋友要的。大概有5w多条,lz机子是老爷机跑不起,只导出了其中的1k条。
方案二

利用office的com组件
首先添加com引用
     
引入命名空间
  1. using Excel = Microsoft.Office.Interop.Excel;
复制代码
Com操作Excel辅助类
  
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Excel = Microsoft.Office.Interop.Excel;
  7. using System.Web.UI;
  8. using System.Web;
  9. using System.Data;
  10. namespace Wolfy.Common
  11. { ///  /// 使用com组件 操作Excel ///  public class ComExcelHelper {        private Excel.Application appExcel = null;        private Excel.Workbook workbook = null;        private Excel.Worksheet sheet = null;        private DateTime dtBefore;        private DateTime dtAfter;        private string filePath;        public string FilePath        { get { return filePath; } set { filePath = value; }        }        private string timestamp;        ///         /// 以时间字符串作为保存文件的名称        ///         public string Timestamp        { get { return timestamp; } set { timestamp = value; }        }        private object mValue = System.Reflection.Missing.Value;        ///         ///是否打开Excel界面        ///         public bool Visible        { set {        appExcel.Visible = value; }        }        public ComExcelHelper()        { this.dtBefore = DateTime.Now; appExcel = new Excel.Application(); this.dtAfter = DateTime.Now; this.timestamp = DateTime.Now.ToShortDateString().Replace("-", "") + DateTime.Now.ToShortDateString().Replace("-", "") + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString();        }        public ComExcelHelper(string strFilePath)        { this.dtBefore = DateTime.Now; appExcel = new Excel.Application(); this.dtAfter = DateTime.Now; this.workbook = (Excel.Workbook)appExcel.Workbooks.Open(strFilePath, mValue, false, mValue, mValue, mValue, mValue, mValue, mValue, mValue, mValue, mValue, mValue, mValue, mValue); this.timestamp = DateTime.Now.ToShortDateString().Replace("-", "") + DateTime.Now.ToShortDateString().Replace("-", "") + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString();        }        public void Dispose()        { try {        System.Runtime.InteropServices.Marshal.ReleaseComObject(sheet);        sheet = null;        workbook.Close(false, mValue, mValue);        System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);        workbook = null;        appExcel.Quit();        System.Runtime.InteropServices.Marshal.ReleaseComObject(appExcel);        appExcel = null;        GC.Collect();        GC.WaitForPendingFinalizers(); } catch (Exception ex) {        throw ex; } finally {        foreach (System.Diagnostics.Process pro in System.Diagnostics.Process.GetProcessesByName("Excel"))        { if (pro.StartTime > this.dtBefore && pro.StartTime < this.dtAfter) {        pro.Kill(); }        } } System.GC.SuppressFinalize(this);        }        ///         /// 加载Excel        ///         public void Load()        { if (workbook == null && this.filePath != null) {        workbook = appExcel.Workbooks.Open(this.filePath, mValue, false, mValue, mValue, mValue, mValue, mValue, mValue, mValue, mValue, mValue, mValue, mValue, mValue); }        }        ///         /// 加载Excel        ///         public void Load(string strFilePath)        { if (workbook == null) {        workbook = appExcel.Workbooks.Open(strFilePath, mValue, false, mValue, mValue, mValue, mValue, mValue, mValue, mValue, mValue, mValue, mValue, mValue, mValue); }        }        ///         /// 新建工作表        ///         ///         public void NewWorkSheet(string sheetName)        { sheet = workbook.Sheets.Add(workbook.Sheets[1], mValue, mValue, mValue); sheet.Name = sheetName;        }        ///         /// 在指定的单元格插入指定的值        ///         /// 单元格 如"A4"        /// 文本 数字等值        public void WriteCell(string strCell, object objValue)        { sheet.get_Range(strCell, mValue).Value2 = objValue;        }        ///         /// 在指定Range中插入指定的值        ///         /// Range的开始单元格        /// Range的结束单元格        /// 文本、数字等值        public void WriteRange(string strStartCell, string strEndCell, object objValue)        { sheet.get_Range(strStartCell, strEndCell).Value2 = objValue;        }        /**/        ///         /// 合并单元格,并在合并后的单元格中插入指定的值        ///         ///         ///         ///         public void WriteAfterMerge(string strStartCell, string strEndCell, object objValue)        { sheet.get_Range(strStartCell, strEndCell).Merge(mValue); sheet.get_Range(strStartCell, mValue).Value2 = objValue;        }        /**/        ///         /// 在连续单元格中插入一个DataTable中的值        ///         /// 开始的单元格        /// 存储数据的DataTable        public void WriteTable(string strStartCell, System.Data.DataTable dtData)        { object[,] arrData = new object[dtData.Rows.Count, dtData.Columns.Count]; for (int i = 0; i < dtData.Rows.Count; i++)        for (int j = 0; j < dtData.Columns.Count; j++) arrData[i, j] = dtData.Rows[i][j]; sheet.get_Range(strStartCell, this.GetEndCell(strStartCell, dtData.Rows.Count - 1, dtData.Columns.Count - 1)).Value2 = arrData; arrData = null;        }        /**/        ///         /// 在连续单元格中插入一个DataTable并作超级链接        ///         /// 起始单元格标识符        /// 存储数据的DataTable        /// 链接的地址字段        /// 链接的文本字段        public void WriteTableAndLink(string strStartCell, System.Data.DataTable dtData, string strLinkField, string strTextField)        { object[,] arrData = new object[dtData.Rows.Count, dtData.Columns.Count - 1]; for (int i = 0; i < dtData.Rows.Count; i++) {        for (int j = 0; j < dtData.Columns.Count; j++)        { if (j > dtData.Columns.IndexOf(strLinkField))        arrData[i, j - 1] = dtData.Rows[i][j]; else if (j  702)        return String.Empty; if (intNumber == 702)        return "ZZ"; string strRtn = String.Empty; string strLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; if (intNumber > 26)        strRtn = strLetters.Substring(intNumber / 26 - 1, 1); strRtn += strLetters.Substring((intNumber % 26) - 1, 1); return strRtn;        } }
  12. }
复制代码
ComExcelHelper 
  参考: http://www.cnblogs.com/waxdoll/archive/2005/10/28/264071.html 
DataTable导入Excel
     
Excel读入DataTable
  这里未对类型进行处理,datetime类型的数据会转换成数值类型的 
     
方案三

将Excel数据表当作数据源,通过 OleDb来实现。
同样需要引入Microsoft Excel 14.0 Object Library
  分享一个操作类:
  
  1. 1 using System;
  2. 2 using System.Collections;
  3. 3 using System.Collections.Generic;
  4. 4 using System.Data;
  5. 5 using System.Data.OleDb;
  6. 6 using System.IO;
  7. 7 using System.Linq;
  8. 8 using System.Text;
  9. 9 using System.Threading.Tasks;
  10. 10 using System.Web;
  11. 11 using System.Web.UI;
  12. 12 using System.Web.UI.WebControls;
  13. 13
  14. 14 namespace Wolfy.Common
  15. 15 {
  16. 16 class OleDbExcelHelper
  17. 17  {
  18. 18 #region 数据导出至Excel文件
  19. 19 ///
  20. 20 /// 导出Excel文件,自动返回可下载的文件流
  21. 21 ///
  22. 22 public static void DataTable1Excel(System.Data.DataTable dtData)
  23. 23  {
  24. 24 GridView gvExport = null;
  25. 25 HttpContext curContext = HttpContext.Current;
  26. 26 StringWriter strWriter = null;
  27. 27 HtmlTextWriter htmlWriter = null;
  28. 28 if (dtData != null)
  29. 29  {
  30. 30 curContext.Response.ContentType = "application/vnd.ms-excel";
  31. 31 curContext.Response.ContentEncoding = System.Text.Encoding.GetEncoding("gb2312");
  32. 32 curContext.Response.Charset = "utf-8";
  33. 33 strWriter = new StringWriter();
  34. 34 htmlWriter = new HtmlTextWriter(strWriter);
  35. 35 gvExport = new GridView();
  36. 36 gvExport.DataSource = dtData.DefaultView;
  37. 37 gvExport.AllowPaging = false;
  38. 38  gvExport.DataBind();
  39. 39  gvExport.RenderControl(htmlWriter);
  40. 40 curContext.Response.Write("" + strWriter.ToString());
  41. 41  curContext.Response.End();
  42. 42  }
  43. 43  }
  44. 44
  45. 45 ///
  46. 46 /// 导出Excel文件,转换为可读模式
  47. 47 ///
  48. 48 public static void DataTable2Excel(System.Data.DataTable dtData)
  49. 49  {
  50. 50 DataGrid dgExport = null;
  51. 51 HttpContext curContext = HttpContext.Current;
  52. 52 StringWriter strWriter = null;
  53. 53 HtmlTextWriter htmlWriter = null;
  54. 54
  55. 55 if (dtData != null)
  56. 56  {
  57. 57 curContext.Response.ContentType = "application/vnd.ms-excel";
  58. 58 curContext.Response.ContentEncoding = System.Text.Encoding.UTF8;
  59. 59 curContext.Response.Charset = "";
  60. 60 strWriter = new StringWriter();
  61. 61 htmlWriter = new HtmlTextWriter(strWriter);
  62. 62 dgExport = new DataGrid();
  63. 63 dgExport.DataSource = dtData.DefaultView;
  64. 64 dgExport.AllowPaging = false;
  65. 65  dgExport.DataBind();
  66. 66  dgExport.RenderControl(htmlWriter);
  67. 67  curContext.Response.Write(strWriter.ToString());
  68. 68  curContext.Response.End();
  69. 69  }
  70. 70  }
  71. 71
  72. 72 ///
  73. 73 /// 导出Excel文件,并自定义文件名
  74. 74 ///
  75. 75 public static void DataTable3Excel(System.Data.DataTable dtData, String FileName)
  76. 76  {
  77. 77 GridView dgExport = null;
  78. 78 HttpContext curContext = HttpContext.Current;
  79. 79 StringWriter strWriter = null;
  80. 80 HtmlTextWriter htmlWriter = null;
  81. 81
  82. 82 if (dtData != null)
  83. 83  {
  84. 84  HttpUtility.UrlEncode(FileName, System.Text.Encoding.UTF8);
  85. 85 curContext.Response.AddHeader("content-disposition", "attachment;filename=" + HttpUtility.UrlEncode(FileName, System.Text.Encoding.UTF8) + ".xls");
  86. 86 curContext.Response.ContentType = "application nd.ms-excel";
  87. 87 curContext.Response.ContentEncoding = System.Text.Encoding.UTF8;
  88. 88 curContext.Response.Charset = "GB2312";
  89. 89 strWriter = new StringWriter();
  90. 90 htmlWriter = new HtmlTextWriter(strWriter);
  91. 91 dgExport = new GridView();
  92. 92 dgExport.DataSource = dtData.DefaultView;
  93. 93 dgExport.AllowPaging = false;
  94. 94  dgExport.DataBind();
  95. 95  dgExport.RenderControl(htmlWriter);
  96. 96  curContext.Response.Write(strWriter.ToString());
  97. 97  curContext.Response.End();
  98. 98  }
  99. 99  }
  100. 100
  101. 101 ///
  102. 102 /// 将数据导出至Excel文件
  103. 103 ///
  104. 104 /// DataTable对象
  105. 105 /// Excel文件路径
  106. 106 public static bool OutputToExcel(System.Data.DataTable Table, string ExcelFilePath)
  107. 107  {
  108. 108 if (File.Exists(ExcelFilePath))
  109. 109  {
  110. 110 throw new Exception("该文件已经存在!");
  111. 111  }
  112. 112
  113. 113 if ((Table.TableName.Trim().Length == 0) || (Table.TableName.ToLower() == "table"))
  114. 114  {
  115. 115 Table.TableName = "Sheet1";
  116. 116  }
  117. 117
  118. 118 //数据表的列数
  119. 119 int ColCount = Table.Columns.Count;
  120. 120
  121. 121 //用于记数,实例化参数时的序号
  122. 122 int i = 0;
  123. 123
  124. 124 //创建参数
  125. 125 OleDbParameter[] para = new OleDbParameter[ColCount];
  126. 126
  127. 127 //创建表结构的SQL语句
  128. 128 string TableStructStr = @"Create Table " + Table.TableName + "(";
  129. 129
  130. 130 //连接字符串
  131. 131 string connString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + ExcelFilePath + ";Extended Properties=Excel 8.0;";
  132. 132 OleDbConnection objConn = new OleDbConnection(connString);
  133. 133
  134. 134 //创建表结构
  135. 135 OleDbCommand objCmd = new OleDbCommand();
  136. 136
  137. 137 //数据类型集合
  138. 138 ArrayList DataTypeList = new ArrayList();
  139. 139 DataTypeList.Add("System.Decimal");
  140. 140 DataTypeList.Add("System.Double");
  141. 141 DataTypeList.Add("System.Int16");
  142. 142 DataTypeList.Add("System.Int32");
  143. 143 DataTypeList.Add("System.Int64");
  144. 144 DataTypeList.Add("System.Single");
  145. 145
  146. 146 //遍历数据表的所有列,用于创建表结构
  147. 147 foreach (DataColumn col in Table.Columns)
  148. 148  {
  149. 149 //如果列属于数字列,则设置该列的数据类型为double
  150. 150 if (DataTypeList.IndexOf(col.DataType.ToString()) >= 0)
  151. 151  {
  152. 152 para[i] = new OleDbParameter("@" + col.ColumnName, OleDbType.Double);
  153. 153  objCmd.Parameters.Add(para[i]);
  154. 154
  155. 155 //如果是最后一列
  156. 156 if (i + 1 == ColCount)
  157. 157  {
  158. 158 TableStructStr += col.ColumnName + " double)";
  159. 159  }
  160. 160 else
  161. 161  {
  162. 162 TableStructStr += col.ColumnName + " double,";
  163. 163  }
  164. 164  }
  165. 165 else
  166. 166  {
  167. 167 para[i] = new OleDbParameter("@" + col.ColumnName, OleDbType.VarChar);
  168. 168  objCmd.Parameters.Add(para[i]);
  169. 169
  170. 170 //如果是最后一列
  171. 171 if (i + 1 == ColCount)
  172. 172  {
  173. 173 TableStructStr += col.ColumnName + " varchar)";
  174. 174  }
  175. 175 else
  176. 176  {
  177. 177 TableStructStr += col.ColumnName + " varchar,";
  178. 178  }
  179. 179  }
  180. 180 i++;
  181. 181  }
  182. 182
  183. 183 //创建Excel文件及文件结构
  184. 184 try
  185. 185  {
  186. 186 objCmd.Connection = objConn;
  187. 187 objCmd.CommandText = TableStructStr;
  188. 188
  189. 189 if (objConn.State == ConnectionState.Closed)
  190. 190  {
  191. 191  objConn.Open();
  192. 192  }
  193. 193  objCmd.ExecuteNonQuery();
  194. 194  }
  195. 195 catch (Exception exp)
  196. 196  {
  197. 197 throw exp;
  198. 198  }
  199. 199
  200. 200 //插入记录的SQL语句
  201. 201 string InsertSql_1 = "Insert into " + Table.TableName + " (";
  202. 202 string InsertSql_2 = " Values (";
  203. 203 string InsertSql = "";
  204. 204
  205. 205 //遍历所有列,用于插入记录,在此创建插入记录的SQL语句
  206. 206 for (int colID = 0; colID < ColCount; colID++)
  207. 207  {
  208. 208 if (colID + 1 == ColCount) //最后一列
  209. 209  {
  210. 210 InsertSql_1 += Table.Columns[colID].ColumnName + ")";
  211. 211 InsertSql_2 += "@" + Table.Columns[colID].ColumnName + ")";
  212. 212  }
  213. 213 else
  214. 214  {
  215. 215 InsertSql_1 += Table.Columns[colID].ColumnName + ",";
  216. 216 InsertSql_2 += "@" + Table.Columns[colID].ColumnName + ",";
  217. 217  }
  218. 218  }
  219. 219
  220. 220 InsertSql = InsertSql_1 + InsertSql_2;
  221. 221
  222. 222 //遍历数据表的所有数据行
  223. 223 for (int rowID = 0; rowID < Table.Rows.Count; rowID++)
  224. 224  {
  225. 225 for (int colID = 0; colID < ColCount; colID++)
  226. 226  {
  227. 227 if (para[colID].DbType == DbType.Double && Table.Rows[rowID][colID].ToString().Trim() == "")
  228. 228  {
  229. 229 para[colID].Value = 0;
  230. 230  }
  231. 231 else
  232. 232  {
  233. 233 para[colID].Value = Table.Rows[rowID][colID].ToString().Trim();
  234. 234  }
  235. 235  }
  236. 236 try
  237. 237  {
  238. 238 objCmd.CommandText = InsertSql;
  239. 239  objCmd.ExecuteNonQuery();
  240. 240  }
  241. 241 catch (Exception exp)
  242. 242  {
  243. 243 string str = exp.Message;
  244. 244  }
  245. 245  }
  246. 246 try
  247. 247  {
  248. 248 if (objConn.State == ConnectionState.Open)
  249. 249  {
  250. 250  objConn.Close();
  251. 251  }
  252. 252  }
  253. 253 catch (Exception exp)
  254. 254  {
  255. 255 throw exp;
  256. 256  }
  257. 257 return true;
  258. 258  }
  259. 259
  260. 260 ///
  261. 261 /// 将数据导出至Excel文件
  262. 262 ///
  263. 263 /// DataTable对象
  264. 264 /// 要导出的数据列集合
  265. 265 /// Excel文件路径
  266. 266 public static bool OutputToExcel(System.Data.DataTable Table, ArrayList Columns, string ExcelFilePath)
  267. 267  {
  268. 268 if (File.Exists(ExcelFilePath))
  269. 269  {
  270. 270 throw new Exception("该文件已经存在!");
  271. 271  }
  272. 272
  273. 273 //如果数据列数大于表的列数,取数据表的所有列
  274. 274 if (Columns.Count > Table.Columns.Count)
  275. 275  {
  276. 276 for (int s = Table.Columns.Count + 1; s = 0)
  277. 334  {
  278. 335 para[k] = new OleDbParameter("@" + col.Caption.Trim(), OleDbType.Double);
  279. 336  objCmd.Parameters.Add(para[k]);
  280. 337
  281. 338 //如果是最后一列
  282. 339 if (k + 1 == ColCount)
  283. 340  {
  284. 341 TableStructStr += col.Caption.Trim() + " Double)";
  285. 342  }
  286. 343 else
  287. 344  {
  288. 345 TableStructStr += col.Caption.Trim() + " Double,";
  289. 346  }
  290. 347  }
  291. 348 else
  292. 349  {
  293. 350 para[k] = new OleDbParameter("@" + col.Caption.Trim(), OleDbType.VarChar);
  294. 351  objCmd.Parameters.Add(para[k]);
  295. 352
  296. 353 //如果是最后一列
  297. 354 if (k + 1 == ColCount)
  298. 355  {
  299. 356 TableStructStr += col.Caption.Trim() + " VarChar)";
  300. 357  }
  301. 358 else
  302. 359  {
  303. 360 TableStructStr += col.Caption.Trim() + " VarChar,";
  304. 361  }
  305. 362  }
  306. 363  }
  307. 364
  308. 365 //创建Excel文件及文件结构
  309. 366 try
  310. 367  {
  311. 368 objCmd.Connection = objConn;
  312. 369 objCmd.CommandText = TableStructStr;
  313. 370
  314. 371 if (objConn.State == ConnectionState.Closed)
  315. 372  {
  316. 373  objConn.Open();
  317. 374  }
  318. 375  objCmd.ExecuteNonQuery();
  319. 376  }
  320. 377 catch (Exception exp)
  321. 378  {
  322. 379 throw exp;
  323. 380  }
  324. 381
  325. 382 //插入记录的SQL语句
  326. 383 string InsertSql_1 = "Insert into " + Table.TableName + " (";
  327. 384 string InsertSql_2 = " Values (";
  328. 385 string InsertSql = "";
  329. 386
  330. 387 //遍历所有列,用于插入记录,在此创建插入记录的SQL语句
  331. 388 for (int colID = 0; colID < ColCount; colID++)
  332. 389  {
  333. 390 if (colID + 1 == ColCount) //最后一列
  334. 391  {
  335. 392 InsertSql_1 += Columns[colID].ToString().Trim() + ")";
  336. 393 InsertSql_2 += "@" + Columns[colID].ToString().Trim() + ")";
  337. 394  }
  338. 395 else
  339. 396  {
  340. 397 InsertSql_1 += Columns[colID].ToString().Trim() + ",";
  341. 398 InsertSql_2 += "@" + Columns[colID].ToString().Trim() + ",";
  342. 399  }
  343. 400  }
  344. 401
  345. 402 InsertSql = InsertSql_1 + InsertSql_2;
  346. 403
  347. 404 //遍历数据表的所有数据行
  348. 405 DataColumn DataCol = new DataColumn();
  349. 406 for (int rowID = 0; rowID < Table.Rows.Count; rowID++)
  350. 407  {
  351. 408 for (int colID = 0; colID < ColCount; colID++)
  352. 409  {
  353. 410 //因为列不连续,所以在取得单元格时不能用行列编号,列需得用列的名称
  354. 411 DataCol = (DataColumn)Columns[colID];
  355. 412 if (para[colID].DbType == DbType.Double && Table.Rows[rowID][DataCol.Caption].ToString().Trim() == "")
  356. 413  {
  357. 414 para[colID].Value = 0;
  358. 415  }
  359. 416 else
  360. 417  {
  361. 418 para[colID].Value = Table.Rows[rowID][DataCol.Caption].ToString().Trim();
  362. 419  }
  363. 420  }
  364. 421 try
  365. 422  {
  366. 423 objCmd.CommandText = InsertSql;
  367. 424  objCmd.ExecuteNonQuery();
  368. 425  }
  369. 426 catch (Exception exp)
  370. 427  {
  371. 428 string str = exp.Message;
  372. 429  }
  373. 430  }
  374. 431 try
  375. 432  {
  376. 433 if (objConn.State == ConnectionState.Open)
  377. 434  {
  378. 435  objConn.Close();
  379. 436  }
  380. 437  }
  381. 438 catch (Exception exp)
  382. 439  {
  383. 440 throw exp;
  384. 441  }
  385. 442 return true;
  386. 443  }
  387. 444 #endregion
  388. 445
  389. 446 ///
  390. 447 /// 获取Excel文件数据表列表
  391. 448 ///
  392. 449 public static ArrayList GetExcelTables(string ExcelFileName)
  393. 450  {
  394. 451 System.Data.DataTable dt = new System.Data.DataTable();
  395. 452 ArrayList TablesList = new ArrayList();
  396. 453 if (File.Exists(ExcelFileName))
  397. 454  {
  398. 455 using (OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=Excel 8.0;Data Source=" + ExcelFileName))
  399. 456  {
  400. 457 try
  401. 458  {
  402. 459  conn.Open();
  403. 460 dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
  404. 461  }
  405. 462 catch (Exception exp)
  406. 463  {
  407. 464 throw exp;
  408. 465  }
  409. 466
  410. 467 //获取数据表个数
  411. 468 int tablecount = dt.Rows.Count;
  412. 469 for (int i = 0; i < tablecount; i++)
  413. 470  {
  414. 471 string tablename = dt.Rows[i][2].ToString().Trim().TrimEnd('$');
  415. 472 if (TablesList.IndexOf(tablename) < 0)
  416. 473  {
  417. 474  TablesList.Add(tablename);
  418. 475  }
  419. 476  }
  420. 477  }
  421. 478  }
  422. 479 return TablesList;
  423. 480  }
  424. 481
  425. 482 ///
  426. 483 /// 将Excel文件导出至DataTable(第一行作为表头)
  427. 484 ///
  428. 485 /// Excel文件路径
  429. 486 /// 数据表名,如果数据表名错误,默认为第一个数据表名
  430. 487 public static DataTable InputFromExcel(string ExcelFilePath, string TableName)
  431. 488  {
  432. 489 if (!File.Exists(ExcelFilePath))
  433. 490  {
  434. 491 throw new Exception("Excel文件不存在!");
  435. 492  }
  436. 493
  437. 494 //如果数据表名不存在,则数据表名为Excel文件的第一个数据表
  438. 495 ArrayList TableList = new ArrayList();
  439. 496 TableList = GetExcelTables(ExcelFilePath);
  440. 497
  441. 498 if (TableName.IndexOf(TableName) < 0)
  442. 499  {
  443. 500 TableName = TableList[0].ToString().Trim();
  444. 501  }
  445. 502
  446. 503 DataTable table = new DataTable();
  447. 504 OleDbConnection dbcon = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + ExcelFilePath + ";Extended Properties=Excel 8.0");
  448. 505 OleDbCommand cmd = new OleDbCommand("select * from [" + TableName + "$]", dbcon);
  449. 506 OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);
  450. 507
  451. 508 try
  452. 509  {
  453. 510 if (dbcon.State == ConnectionState.Closed)
  454. 511  {
  455. 512  dbcon.Open();
  456. 513  }
  457. 514  adapter.Fill(table);
  458. 515  }
  459. 516 catch (Exception exp)
  460. 517  {
  461. 518 throw exp;
  462. 519  }
  463. 520 finally
  464. 521  {
  465. 522 if (dbcon.State == ConnectionState.Open)
  466. 523  {
  467. 524  dbcon.Close();
  468. 525  }
  469. 526  }
  470. 527 return table;
  471. 528  }
  472. 529
  473. 530 ///
  474. 531 /// 获取Excel文件指定数据表的数据列表
  475. 532 ///
  476. 533 /// Excel文件名
  477. 534 /// 数据表名
  478. 535 public static ArrayList GetExcelTableColumns(string ExcelFileName, string TableName)
  479. 536  {
  480. 537 DataTable dt = new DataTable();
  481. 538 ArrayList ColsList = new ArrayList();
  482. 539 if (File.Exists(ExcelFileName))
  483. 540  {
  484. 541 using (OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=Excel 8.0;Data Source=" + ExcelFileName))
  485. 542  {
  486. 543  conn.Open();
  487. 544 dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Columns, new object[] { null, null, TableName, null });
  488. 545
  489. 546 //获取列个数
  490. 547 int colcount = dt.Rows.Count;
  491. 548 for (int i = 0; i < colcount; i++)
  492. 549  {
  493. 550 string colname = dt.Rows[i]["Column_Name"].ToString().Trim();
  494. 551  ColsList.Add(colname);
  495. 552  }
  496. 553  }
  497. 554  }
  498. 555 return ColsList;
  499. 556  }
  500. 557  }
  501. 558 }
复制代码
OleDbExcelHelper 
网上搜集的常用类,这里不再测试。
方案四

将Excel另存为xml文件,对xml文件进行操作。
  1. 1
  2. 2 998
  3. 3 柳雪巧
  4. 4 f
  5. 5 1971/4/30 0:00:00
  6. 6 2005/1/15 0:00:00
  7. 7 台湾省 屏东县
  8. 8 Dolores19710430@139.com
  9. 9 12616310511
  10. 10 False
  11. 11 2014/3/15 10:13:54
  12. 12 5
  13. 13
复制代码
excel表格中每一行数据,其实是以上格式的xml,有规律,就可以很容易的去解析。
方案五

  js插件
  官网地址: http://datatables.net/extras/tabletools/ 
      
方案六

导出为csv文件
分享一个辅助类
  
  1. 1 using System.Data;
  2. 2 using System.IO;
  3. 3
  4. 4 public static class CsvHelper
  5. 5 {
  6. 6 ///
  7. 7 /// 导出报表为Csv
  8. 8 ///
  9. 9 /// DataTable
  10. 10 /// 物理路径
  11. 11 /// 表头
  12. 12 /// 字段标题,逗号分隔
  13. 13 public static bool dt2csv(DataTable dt, string strFilePath, string tableheader, string columname)
  14. 14  {
  15. 15 try
  16. 16  {
  17. 17 string strBufferLine = "";
  18. 18 StreamWriter strmWriterObj = new StreamWriter(strFilePath,false,System.Text.Encoding.UTF8);
  19. 19  strmWriterObj.WriteLine(tableheader);
  20. 20  strmWriterObj.WriteLine(columname);
  21. 21 for (int i = 0; i < dt.Rows.Count; i++)
  22. 22  {
  23. 23 strBufferLine = "";
  24. 24 for (int j = 0; j < dt.Columns.Count; j++)
  25. 25  {
  26. 26 if (j > 0)
  27. 27 strBufferLine += ",";
  28. 28 strBufferLine += dt.Rows[i][j].ToString();
  29. 29  }
  30. 30  strmWriterObj.WriteLine(strBufferLine);
  31. 31  }
  32. 32  strmWriterObj.Close();
  33. 33 return true;
  34. 34  }
  35. 35 catch
  36. 36  {
  37. 37 return false;
  38. 38  }
  39. 39  }
  40. 40
  41. 41 ///
  42. 42 /// 将Csv读入DataTable
  43. 43 ///
  44. 44 /// csv文件路径
  45. 45 /// 表示第n行是字段title,第n+1行是记录开始
  46. 46 public static DataTable csv2dt(string filePath, int n, DataTable dt)
  47. 47  {
  48. 48 StreamReader reader = new StreamReader(filePath, System.Text.Encoding.UTF8, false);
  49. 49 int i = 0, m = 0;
  50. 50  reader.Peek();
  51. 51 while (reader.Peek() > 0)
  52. 52  {
  53. 53 m = m + 1;
  54. 54 string str = reader.ReadLine();
  55. 55 if (m >= n + 1)
  56. 56  {
  57. 57 string[] split = str.Split(',');
  58. 58
  59. 59 System.Data.DataRow dr = dt.NewRow();
  60. 60 for (i = 0; i < split.Length; i++)
  61. 61  {
  62. 62 dr[i] = split[i];
  63. 63  }
  64. 64  dt.Rows.Add(dr);
  65. 65  }
  66. 66  }
  67. 67 return dt;
  68. 68  }
  69. 69 }
复制代码
View Code 
不再测试。
方案七

使用模版的方式,最简单的模版,就是将表头列出,然后再导入数据。第一行为表头,从第二行开始写入数据。导入过程可参考前面的解决方案。
方案八

使用Aspose.Cells组件,貌似收费。
  可参考: http://www.cnblogs.com/lanyue52011/p/3372452.html 
  http://www.cnblogs.com/hongjiumu/archive/2013/03/15/2962277.html 
  http://www.cnblogs.com/wujy/archive/2012/07/19/2600162.html 
总结

列出常见的几种解决方案,在实际项目中,用哪一种,还是根据项目环境来决定吧。
最近项目中用到了Excel导出,导入的功能,就想着将常见的方式总结一下。也许还有遗漏,请留言,将你知道也分享给大家,谢谢。
如果该文章对你有所帮助,不妨推荐一下,让更多的人知道,毕竟分享是件快乐的事情。
     代码下载:链接: http://pan.baidu.com/s/1dD3lleT 密码:axli
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值