批量導入現在基本已經成為各類系統的標配了,當前,我們訂餐系統也不例外,什么商家呀、商品呀、優惠碼之類的,都少不了。畢竟嘛,對非開發人員來說,看到Excel肯定比看到很多管理系統還是要親切很多的。這里,我就分享下自己如何一步步踩坑、爬坑到最后完成Excel批量導入的歷程。或許,你還有更好的方案,不妨也分享下;當然,也希望能給正在坑中,或者爬坑的同仁們一點幫助。
注:Excel操作用了?org.in2bits.myxls.dll? 這個不知道是否是免費的,沒仔細查過。
?
第一次,遇到Excel批量導入時,很自然的,onclick,INSERT...本地用只有幾條數據的Excel測試正常,select下,呀! 數據正常導入,笑咪咪的生成、發布,ok,搞定。客戶使用時,用了幾百條數據的Excel導入,會出現什么問題相信大家都知道吧,多半是執行超時,于是,再baidu,google...,原來可以設置executionTimeout。【設置這個后,應該還有問題,就是想不起了來,于是才有了下文】
?
當我費盡心思希望通過設置解決超時問題,處處碰壁后才知道,這個通常要用多線程。那會才知道見識有多重要,才知道多看博客有多重要。一翻baidu,google后,有了下面的代碼。


protected void btDo_Click(object sender, EventArgs e){Thread t = new Thread(new ThreadStart(InportUser));t.Start();}public void InportUser(){///讀取excel,循環insert}
? 這樣寫,超時的情況變少了(好像也會,具體什么時候,真是慚愧,沒有好好研究過),但是有一個不能接受的現像就是,我不知道什么時候執行完了,也就不知道什么時候可以關瀏覽器。那會兒,只想到了一個好笨的辦法,一直select看條數還有沒有增加。由于一直沒有找到好的辦法,這個情況一直存在于我們系統中很長時間,也像一個石頭一直壓在我心中,每每看到,心里總是隱隱不快,我都不能接受的東西,還要讓客戶去接受。。。直到前不久,才看到 BackgroundWorker 。那會才知道見識有多重要,才知道多看博客有多重要。
BackgroundWorker 具體內容,這里就不去寫了,baidu,google,msdn有全面、權威的介紹。我只分享下這個過程中自己踩的坑吧:
1.一直沒執行 DoWork,也沒有錯誤日志;您可能頁面中沒有加入 Async="true。
2.HttpContext.Current 為null;當時要在DoWork中為每個記錄生成一個二維碼圖片(在一個類中生成),HttpContext.Current.Server一直為空,瞬間想起之前有個博客是《HttpContext.Curren并非無處不在》,當時一下就知道了多看博客有多重要。
3.執行不超時,數據庫鏈接可能會超時。這個和BackgroundWorker沒什么關系,不過好像一起出現的概率比較大哦。正常情況簡單一句SqlCommand.CommandTimeout = 0; 就ok了。
關于BackgroundWorker的代碼,應該隨便一搜就是一籮筐,我還是帖下自己的吧,愿意搜索的自己搜索吧,愿意將就的就看下下面的吧:
aspx主要代碼,主要就是一個設置和上傳控件的問題


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="importshopcart.aspx.cs" Inherits="importshopcart"Async="true" %><asp:FileUpload runat="server" ID="fuFoodExcel" /><asp:Button ID="btSave" runat="server" CssClass="button_1" OnClick="btSave_Click"Text="導入" OnClientClick=" showload_super();"></asp:Button><a href="demo.xls">下載模版</a>
?
aspx.cs主要代碼,只實現了執行完成方法,這點就是之前一直無法實現的東西,開始執行時彈出加載框,執行完成可以進行提示,詳細的東西,大家可以自己動手搜索下。


protected void btSave_Click(object sender, EventArgs e){bgw = new BackgroundWorker();bgw.WorkerSupportsCancellation = true;bgw.WorkerReportsProgress = true;bgw.DoWork += new DoWorkEventHandler(DoWork);bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);bgw.RunWorkerAsync();}/// <summary>/// 耗時操作/// </summary>/// <param name="sender"></param>/// <param name="e"></param>void DoWork(object sender, DoWorkEventArgs e){string suffix = "";if (this.fuFoodExcel.HasFile){suffix = Path.GetExtension(this.fuFoodExcel.PostedFile.FileName);if (suffix == ".xls" || suffix == ".XLS"){}else{msg = "文件格式不正確,請上傳excel文件";return;}}else{msg = "請上傳excel文件";return;}string filepath = "~/upload/excel/";if (!System.IO.Directory.Exists(Server.MapPath(filepath))){System.IO.Directory.CreateDirectory(Server.MapPath(filepath));}string sFile = filepath + System.DateTime.Now.ToString("yyyyMMddHHmmssffff") + suffix; //上傳后文件的新名//保存文件try{this.fuFoodExcel.PostedFile.SaveAs(Server.MapPath(sFile));}catch (Exception ex){HJlog.toLog(ex.ToString());return;}//必要的判斷以防止excel格式的問題導致程序錯誤try{//解析文件并保存數據到數據庫XlsDocument xls = new XlsDocument(Server.MapPath(sFile));Worksheet sheet = xls.Workbook.Worksheets[0];//excel格式:第一行是說明,第二行是標題,第三行開始是數據for (int i = 3; i < sheet.Rows.Count; i++) // {if (sheet.Rows[ushort.Parse(i.ToString())] != null && sheet.Rows[ushort.Parse(i.ToString())].CellCount >= 1 && sheet.Rows[ushort.Parse(i.ToString())].GetCell(ushort.Parse("1")) != null && sheet.Rows[ushort.Parse(i.ToString())].GetCell(ushort.Parse("1")).Value != null){addressbookInfo mm = new addressbookInfo();mm.Parentid = 0;mm.Status = 0;mm.Isdel = 0;mm.Classname = sheet.Rows[ushort.Parse(i.ToString())].GetCell(ushort.Parse("1")).Value.ToString();mm.Depth = 2;mm.Priority = 0;mm.Pic = sheet.Rows[ushort.Parse(i.ToString())].GetCell(ushort.Parse("2")).Value.ToString();mm.Revevar = sheet.Rows[ushort.Parse(i.ToString())].GetCell(ushort.Parse("3")).Value.ToString();mm.path = ChineseConvert.UtilIndexCode(mm.Classname);dal.Add(mm);count++;}else{break;}}}catch (Exception ex){msg = "導入出錯,請檢查excel";HJlog.toLog(ex.ToString());return;}msg = "操作成功,已經導入" + count + "個地址。";}/// <summary>/// 完成/// </summary>/// <param name="sender"></param>/// <param name="e"></param>void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){string tipmsg = "";if (count == 0){tipmsg = "操作未完成," + msg;}else{tipmsg = msg;}AlertScript.RegScript(this.Page, "alert('" + tipmsg + "');hideload_super();");}
執行過程,和完成提示效果:
?? ??
?
文章到此就結束了,分享還會繼續。說實在的很多細節其實我自己也不是很清楚,有錯誤的地方,請指正,也希望能給部分園子里的同學帶來幫助。
成為一名優秀的程序員!