以前工作中遇见的问题我总喜欢记的一个本本上,后来公司搬了一次家就再也找不到那个本本了,很多记的东西都没有了,我恍然大悟原来这就是高科技之所以诞生的必然性啊!太TM神奇了! 行了,不扯蛋了,都说了这是篇技术性文章~ 主题是C#中将数据导入到Excel中,其实方法有很多种,但是应用的环境不同. 废话少说,进入主题. 首先说我的目的,工作需要,我需要做一个将DataGrid中的数据导出到Excel中之后在Excel中编辑完再导回去,同时更新数据库的这么一个功能. 最开始的实现方法很简单,在网上找到了一个例子,仿造写了以后处理了一点小问题以后搞定!点击按钮完毕后他可以出现一个下载的提示框,然后用户选择保存路径,OK,成功导出,速度也很理想,下面是主要代码,我只写大概代码,必要的注释我都加了: //记得引用(贯穿全文)using System.Data.OleDb; //记得引用using System.IO; //dg为DataGrid的命名 dg.Attributes.Add("style", "vnd.ms-excel numberformat:@"); //此句功能为让保存的Excel为文本格式,如数据中的001 不会被保存成1,Excel自动给00去掉了~没办法谁让他是0呢! dg.AllowPaging = false; dg.DataSource = dt; //请自己给DataGrid一个数据源 dg.DataBind();
Response.Clear(); Response.Buffer = true; Response.Charset = "GB2312"; Response.AppendHeader("Content-Disposition", "attachment;filename=FileName.xls");//FileName是下载时的名字,当然用户可以自己更改 //设置输出流为简体中文 Response.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312"); //设置输出文件类型为excel文件 Response.ContentType = "application/ms-excel"; this.EnableViewState = false; System.Globalization.CultureInfo myCItrad = new System.Globalization.CultureInfo("ZH-CN", true); System.IO.StringWriter oStringWriter = new System.IO.StringWriter(myCItrad); System.Web.UI.HtmlTextWriter oHtmlTextWriter = new System.Web.UI.HtmlTextWriter(oStringWriter); dg.RenderControl(oHtmlTextWriter); Response.Write(oStringWriter.ToString()); Response.End(); /// OK结束了,就这么简单,使用标准输出流实现~ 如果你只想导出一个Excel,我想告诉你,OK你的功能实现了~ But! 如果你像我一样需要再导回来,我想告诉你~This is not enough~.... 导出的Excel你可以右键编辑看一下,我靠~ NND居然是一个伪Excel,他的源文件居然是Html格式的!kao.干~ 但是如果你保存一下呢?选择标准的Excel格式,他就编程了有个标准的Excel~ 所以对于用户来说你会遇到两种情况,第一个他很无聊,是的他很无聊,导出了,什么都没干又导回来了,我知道,你会问"我kao,这小子不是来找茬的吧?"是的,我也在心中无数次这么骂过....但是谁让人家是用户呢! 这样你面对的就是一个Html格式的Excel~如果他编辑后保存再导回去呢,就是一个标准的Excel文件,当然了,作为程序员这两种情况你都要搞定,OK下面粘一段可以同时兼容这两种格式的代码: /// <summary> /// 连接Excel,将Excel里的数据转换成DataTable /// </summary> /// <param name="filePath">Excel路径</param> /// <returns>转换成DataTable以后的Excel内容</returns> public DataTable ImporExcel(string filePath) { DataTable ds = new DataTable(); //Excel连接字符串 OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";Extended Properties=\"Excel 8.0;\""); //try里为正常数据格式 这是针对标准Excel格式的 try { conn.Open(); string fileName = filePath.Substring(filePath.LastIndexOf("\\") + 1); //取得文件名+扩展名 fileName = fileName.Substring(0, fileName.IndexOf(".")); //去掉扩展名,只剩文件名 OleDbCommand myOleDbCommand = new OleDbCommand("select * from [" + fileName + "$]", conn); //得到表名里的内容 OleDbDataAdapter myData = new OleDbDataAdapter(myOleDbCommand); myData.Fill(ds); conn.Close(); return ds; } //catch里为导入的Excel格式,通过分析文件,得到一个ds 这是针对Html格式的 catch { FileStream yuanfile = new FileStream(filePath, FileMode.Open); //当然了,如果他导入的是个图片...你这里还可以写try,我只写大概思路 //打开文件 StreamReader tmpStream = new StreamReader(yuanfile, System.Text.Encoding.GetEncoding("utf-8")); //读出文件,格式为GB2312 string tmpStr = tmpStream.ReadToEnd(); //整个读出文件 tmpStream.Close(); ds = GetDataTbaleFromString(tmpStr); tmpStr = ""; return ds; }
/// <summary> /// 将指定Html字符串的数据转换成DataTable对象 --根据“<tr><td>”等特殊字符进行处理 /// </summary> /// <param name="tmpHtml">Html字符串</param> /// <returns></returns> public DataTable GetDataTbaleFromString(string tmpHtml) { string tmpStr = tmpHtml; DataTable dt = new DataTable(); //删除第一个<tr>之前合最后一个</tr>之后的部分 int index = tmpStr.IndexOf("<tr"); if (index > -1) { tmpStr = tmpStr.Substring(index); } else { return dt; }
index = tmpStr.LastIndexOf("</tr"); if (index > -1) { tmpStr = tmpStr.Substring(0, index + 5); } else { return dt; }
bool exitsSparator = false; char Separator = Convert.ToChar("^"); //如果原字符串中包含分隔符“^”则先把它替换掉 if (tmpStr.IndexOf(Separator.ToString()) > -1) { exitsSparator = true; tmpStr = tmpStr.Replace("^", "^$&^"); }
//根据</tr>分析 string[] tmpRow = tmpStr.Replace("</tr>", "^").Split(Separator); //使用^将字符串分开
for (int i = 0; i < tmpRow.Length - 1; i++) { DataRow newRow = dt.NewRow();
string tmpStrI = tmpRow[i]; if (tmpStrI.IndexOf("<tr>") > -1) { tmpStrI = tmpStrI.Substring(tmpStrI.IndexOf("<tr>")); if (tmpStrI.IndexOf("display:none") < 0 || tmpStrI.IndexOf("display:none") > tmpStrI.IndexOf(">")) { tmpStrI = tmpStrI.Replace("</td>", "^"); string[] tmpField = tmpStrI.Split(Separator);
for (int j = 0; j < tmpField.Length - 1; j++) { tmpField[j] = RemoveString(tmpField[j], "<font>"); index = tmpField[j].LastIndexOf(">") + 1; if (index > 0) { string field = tmpField[j].Substring(index, tmpField[j].Length - index); if (exitsSparator) field = field.Replace("^$&^", "^"); if (i == 0) { string tmpFieldName = field; int sn = 1; while (dt.Columns.Contains(tmpFieldName)) { tmpFieldName = field + sn.ToString(); sn += 1; } dt.Columns.Add(tmpFieldName); } else { newRow[j] = field; } }//end of if(index>0) }
if (i > 0) { dt.Rows.Add(newRow); //将整理好的DataRow添加到dt里 } } } }
dt.AcceptChanges(); return dt; }
/// <summary> /// 从指定Html字符串中剔除指定的对象 /// </summary> /// <param name="tmpHtml">Html字符串</param> /// <param name="remove">需要剔除的对象--例如输入<font>则剔除<font ???????>"</font></param> /// <returns></returns> public string RemoveString(string tmpHtml, string remove) { tmpHtml = tmpHtml.Replace(remove.Replace("<", "</"), ""); //删除<,</这类字符 tmpHtml = tmpHtml.Replace(" ", ""); //删除空格字符( ) 你的里面你看看什么是多于的,你就删什么,别客气,千万别给我留面子! tmpHtml = RemoveStringHead(tmpHtml, remove); return tmpHtml; }
/// <summary> /// 只供方法RemoveString()使用 /// </summary> /// <param name="tmpHtml"></param> /// <param name="remove"></param> /// <returns>处理好的字符串</returns> private string RemoveStringHead(string tmpHtml, string remove) { //为了方便注释,假设输入参数remove="<font>" if (remove.Length < 1) { return tmpHtml;//参数remove为空:不处理返回 } if ((remove.Substring(0, 1) != "<" || remove.Substring(remove.Length - 1) != ">")) { return tmpHtml;//参数remove不是<?????>:不处理返回 }
int IndexS = tmpHtml.IndexOf(remove.Replace(">", ""));//查找“<font”的位置 int IndexE = -1; if (IndexS > -1) { string tmpRight = tmpHtml.Substring(IndexS, tmpHtml.Length - IndexS); IndexE = tmpRight.IndexOf(">"); if (IndexE > -1) { tmpHtml = tmpHtml.Substring(0, IndexS) + tmpHtml.Substring(IndexS + IndexE + 1); } if (tmpHtml.IndexOf(remove.Replace(">", "")) > -1) { tmpHtml = RemoveStringHead(tmpHtml, remove); } } return tmpHtml; } /// OK,结束,后两个类是针对第一个的实现方法,也就是Html的导入,因为他是Html格式,所以他不能用一个方法直接读取进来,但是他毕竟是有规律的Html文件,找到规律,循环一下,处理一下就出来了!
OK到此,导入导出全部OK了! 我再往下写呢,可能真正仔细看这篇文章的,并且和我一样也遇到了这个问题的而且依然没有解决来寻找答案的朋友可能要给我扔板砖了.... long totalCount = dt.Rows.Count; //dt的行数,一会循环要用 //FileName为路径(注意名字要和表的名字一样,比如在次方法中应为excel,其实这3个参数应该全用变量代替的,呵呵,自己写吧,我不改了) string connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + FileName+ ";Extended roperties=Excel 8.0;"; OleDbConnection objConn = new OleDbConnection(connString); OleDbCommand objCmd = new OleDbCommand(); objCmd.Connection = objConn; objConn.Open(); //创建表的结构 objCmd.CommandText = "CREATE TABLE excel(ID int ,字段 varchar)"; objCmd.ExecuteNonQuery(); //插入表 for (int i = 0; i < dt.Rows.Count; i++) { objCmd.CommandText = "INSERT INTO excel(ID,字段) values" + "('" + dt.Rows[i][0].ToString() + "','" + dt.Rows[i][1].ToString() + "')"; objCmd.ExecuteNonQuery(); } objConn.Close(); / 请看上段代码....创建一个标准Excel,代码你也可以继续扩展,比如说让用户自己选择路径啊什么的,等等一系列吧,强调一下,这个方法貌似解决了Excel进程没有关闭的问题!无需引用Excel组件,无需繁琐的代码,谢谢! 啊?导入?就用刚才上面那段标准Excel的就OK了~ 还有就是web呢,这个导出是在服务器上的,你再给个超链接让用户下载就OK了. 再次强调!部分代码来源于网络,本人做了一下整理和处理,目的是为了适应自己的程序,在此我只写了一个大概思路,千万别粘进去就用啊~ 保证你死翘翘~ 如有疑问可以M我,欢迎交流!
转载于:https://www.cnblogs.com/ioricool/archive/2008/08/13/1266498.html
相关资源:C#快速导出Excel文件(3秒可导10万行数据)