您好,登錄后才能下訂單哦!
數據的導入導出,在很多系統里面都比較常見,這個導入導出的操作,在Winform里面比較容易實現,我曾經在之前的一篇文章《Winform開發框架之通用數據導入導出操作》介紹了在Winform里面的通用導入導出模塊的設計和開發過程,但在Web上我們應該如何實現呢?本文主要介紹利用MVC4+EasyUI的特點,并結合文件上傳控件Uploadify 的使用,實現文件上傳后馬上進行處理并顯示,然后確認后把數據寫入數據庫的過程。
我們知道,Web上對Excel的處理和Winform的有所差異,如果是在Web上處理,我們需要把Excel文檔上傳到服務器上,然后讀取文件進行顯示,所以第一步是實現文件的上傳操作,關于文件上傳控件,具體可以參考我的文章《基于MVC4+EasyUI的Web開發框架形成之旅--附件上傳組件uploadify的使用》。
在Winform里面,我們處理Excel數據導入的界面如下所示。
在Web上的主界面如下所示。
導入界面如下所示。
為了實現Web上的數據導入導出操作,我們需要增加兩個按鈕,一個是導入按鈕,一個是導出按鈕。
<a href="javascript:void(0)" class="easyui-linkbutton" id="btnImport" iconcls="icon-excel" onclick="ShowImport()">導入</a> <a href="javascript:void(0)" class="easyui-linkbutton" id="btnExport" iconcls="icon-excel" onclick="ShowExport()">導出</a>
導入的JS處理代碼如下所示。
//顯示導入界面 function ShowImport() { $.showWindow({ title: '客戶聯系人-Excel數據導入', useiframe: true, width: 1024, height: 700, content: 'url:/Contact/Import', buttons: [{ text: '取消', iconCls: 'icon-cancel', handler: function (win) { win.close(); } }] }); }
上面主要就是彈出一個窗口(上面的導入數據窗口),用來方便客戶選擇Excel文件并保存數據或者下載導入模板等操作的。
然后在Import.cshtml的視圖代碼里面,我們需要初始化Datagrid和相關的界面元素,初始化DataGrid的代碼如下所示。
//實現對DataGird控件的綁定操作 function InitGrid() { var guid = $("#AttachGUID").val(); $('#grid').datagrid({ //定位到Table標簽,Table標簽的ID是grid url: '/Contact/GetExcelData?guid=' + guid, //指向后臺的Action來獲取當前用戶的信息的Json格式的數據 title: '客戶聯系人-Excel數據導入', iconCls: 'icon-view', height: 400, width: function () { return document.body.clientWidth * 0.9 },//自動寬度 ..................
上面紅色部分的內容,就是我們在文件順利上傳到服務器上的時候,根據一個guid的參數初始化DataGrid的列表數據。
下面是附件上傳控件uploadify的初始化腳本代碼,其中紅色部分注意一下,我們需要上傳的是一個文件,并且不允許多選,限定上傳文件的類型為xls。
文件上傳完成后,首先調用CheckExcelColumns控制器函數來檢查是否匹配導入模板的字段,如果匹配通過,加載Excel并展示數據到Datagrid里面,否則提示用戶按模板格式錄入數據。
$(function () { //添加界面的附件管理 $('#file_upload').uploadify({ 'swf': '/Content/JQueryTools/uploadify/uploadify.swf', //FLash文件路徑 'buttonText': '瀏 覽', //按鈕文本 'uploader': '/FileUpload/Upload', //處理ASHX頁面 'queueID': 'fileQueue', //隊列的ID 'queueSizeLimit': 1, //隊列最多可上傳文件數量,默認為999 'auto': false, //選擇文件后是否自動上傳,默認為true 'multi': false, //是否為多選,默認為true 'removeCompleted': true, //是否完成后移除序列,默認為true 'fileSizeLimit': '10MB', //單個文件大小,0為無限制,可接受KB,MB,GB等單位的字符串值 'fileTypeDesc': 'Excel Files', //文件描述 'fileTypeExts': '*.xls', //上傳的文件后綴過濾器 'onQueueComplete': function (event, data) { //所有隊列完成后事件 var guid = $("#AttachGUID").val(); ViewUpFiles(guid, "div_files"); //提示用戶Excel格式是否正常,如果正常加載數據 $.ajax({ url: '/Contact/CheckExcelColumns?guid=' + guid, type: 'get', dataType:'json', success: function (data) { if (data.Success) { InitGrid(); //重新刷新表格數據 $.messager.alert("提示", "文件已上傳,數據加載完畢!"); } else { $.messager.alert("提示", "上傳的Excel文件檢查不通過。請根據頁面右上角的Excel模板格式進行數據錄入。"); } } }); }, 'onUploadStart': function (file) { InitUpFile();//上傳文件前 ,重置GUID,每次不同 $("#file_upload").uploadify("settings", 'formData', { 'folder': '數據導入文件', 'guid': $("#AttachGUID").val() }); //動態傳參數 }, 'onUploadError': function (event, queueId, fileObj, errorObj) { //alert(errorObj.type + ":" + errorObj.info); } }); });
為了有效處理數據的導入,我們需要嚴格保證導入的數據是和模板的字段是匹配的,否則處理容易出錯,也沒有任何意義。為了實現這個目的,框架里面提供方法對字段進行檢查,主要是確保Excel里面包含了完整的字段即可。
/// <summary> /// 檢查Excel文件的字段是否包含了必須的字段 /// </summary> /// <param name="guid">附件的GUID</param> /// <returns></returns> public ActionResult CheckExcelColumns(string guid) { CommonResult result = new CommonResult(); try { DataTable dt = ConvertExcelFileToTable(guid); if (dt != null) { //檢查列表是否包含必須的字段 result.Success = DataTableHelper.ContainAllColumns(dt, columnString); } } catch (Exception ex) { LogTextHelper.Error(ex); result.ErrorMessage = ex.Message; } return ToJsonContent(result); }
而在InitGrid的初始化中的這個GetExcelData的控制器方法如下所示。主要的邏輯就是獲取到Excel,并把Excel里面的數據轉換為DataTable,最后初始化為實體類列表,并返回給調用頁面就可以了。
/// <summary> /// 獲取服務器上的Excel文件,并把它轉換為實體列表返回給客戶端 /// </summary> /// <param name="guid">附件的GUID</param> /// <returns></returns> public ActionResult GetExcelData(string guid) { if (string.IsNullOrEmpty(guid)) { return null; } List<ContactInfo> list = new List<ContactInfo>(); DataTable table = ConvertExcelFileToTable(guid); if (table != null) { #region 數據轉換 int i = 1; foreach (DataRow dr in table.Rows) { string customerName = dr["客戶名稱"].ToString(); if (string.IsNullOrEmpty(customerName)) { continue;//客戶名稱為空,記錄跳過 } CustomerInfo customerInfo = BLLFactory<Customer>.Instance.FindByName(customerName); if (customerInfo == null) { continue;//客戶名稱不存在,記錄跳過 } ContactInfo info = new ContactInfo(); info.Customer_ID = customerInfo.ID;//客戶ID info.HandNo = dr["編號"].ToString(); info.Name = dr["姓名"].ToString(); ..............................//增加一個特殊字段的轉義 info.Data1 = BLLFactory<Customer>.Instance.GetCustomerName(info.Customer_ID); list.Add(info); } #endregion } var result = new { total = list.Count, rows = list }; return JsonDate(result); }
剛才介紹了數據的導入操作,數據的導出操作相對簡單一些,它的JS函數操作如下所示。
//導出Excel數據 var exportCondition; function ShowExport() { var url = "/Contact/Export"; $.ajax({ type: "POST", url: url, data: exportCondition, success: function (filePath) { var downUrl = '/FileUpload/DownloadFile?file=' + filePath; window.location = downUrl; } }); }
雖然數據的導出比較簡單一點,但是由于我們需要使用POST方式對數據條件進行提交,因此不像普通的方式下載文件Window.Open(url)就可以實現文件下載了。如果POST方式提交了參數,那么返回的數據即使是文件流,也無法進行有效的下載。
從上面的腳本我們可以看到,里面的exportCondition就是我們需要提交到服務器的條件,服務器根據這個條件進行檢索數據,并返回一個Excel文件就可以了。
由于使用ajax這種POST方式無法直接下載文件流,因此,我們需要先根據條件,在服務器上生成文件,返回一個文件路徑,再次通過DownloadFile方法進行文件的下載才可以。
因此這個傳遞的條件也是很重要的,在查詢操作的時候,我們可以把對應的條件傳遞給它。
//綁定搜索按鈕的的點擊事件 function BindSearchEvent() { //按條件進行查詢數據,首先我們得到數據的值 $("#btnSearch").click(function () { //得到用戶輸入的參數 //取值有幾種方式:$("#id").combobox('getValue'), $("#id").datebox('getValue'), $("#id").val(),combotree('getValue') //字段增加WHC_前綴字符,避免傳遞如URL這樣的Request關鍵字沖突 var queryData = { WHC_Name: $("#txtName").val(), WHC_OfficePhone: $("#txtOfficePhone").val(), WHC_Mobile: $("#txtMobile").val(), WHC_Address: $("#txtAddress").val(), WHC_Email: $("#txtEmail").val(), WHC_Note: $("#txtNote").val() } //將值傳遞給DataGrid InitGrid(queryData); //傳遞給導出操作 exportCondition = queryData; return false; }); }
在我們選定某個樹的節點的時候,我們也可以傳遞自定義的條件給它。
//根據消息分組加載指定列表 function loadByGroupTree(node) { //賦值給特殊字段,公司和部門查詢的時候選擇其中一個 var queryParams = $('#grid').datagrid('options').queryParams; var condition = "{ id: \"" + node.id +"\", groupname:\"" + node.text +"\", userid:\"" + @Session["UserId"] + "\" }"; queryParams.CustomedCondition = condition;//提供給datagrid的條件 exportCondition = { CustomedCondition: condition };//提供給導出的條件 $("#grid").datagrid("reload"); $('#grid').datagrid('uncheckAll'); }
后臺的Export控制器方法主要的邏輯如下所示。
最終是返回一個生成好的文件地址。
最后給一個方法直接下載文件就可以了。
/// <summary> /// 根據路徑下載文件,主要用于生成的文件的下載 /// </summary> /// <param name="filePath">文件路徑</param> /// <returns></returns> public ActionResult DownloadFile(string file) { string realPath = Server.MapPath(file); string saveFileName = FileUtil.GetFileName(realPath); Response.WriteFile(realPath); Response.Charset = "GB2312"; Response.ContentEncoding = Encoding.GetEncoding("GB2312"); Response.ContentType = "application/ms-excel/msword"; Response.AppendHeader("Content-Disposition", "p_w_upload;filename=" + HttpUtility.UrlEncode(saveFileName)); Response.Flush(); Response.End(); return new FileStreamResult(Response.OutputStream, "application/ms-excel/msword"); }
導出的Excel界面效果如下所示。
由于篇幅的原因,這個導入導出的操作就介紹到這里,希望有問題大家共同探討。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。