我準備在項目中實現該功能以前,google發現大部分代碼都是利用通常處理程序HttpHandler實現的服務器端數據的Excel導出,可是這樣存在的問題是ashx讀取的數據通常都是數據庫中視圖的數據,不免會含有方便操做的主鍵ID這列的記錄。如今項目須要在easyUI的DataGrid中顯示的數據能所有導出Excel,包括DataGrid中的中文標題,其餘的通通不要。javascript
完成該功能所需的工具和環境:Newtonsoft.Json序列化和反序列化類庫、easyUI前端UI框架、HttpHandler通常處理程序、Aspose.Cells電子表格生成組件;.Net Framework4.0。前端
前端完成DataGrid中的題頭和數據行信息遍歷訪問,並以JS中二維數組的形式返回後臺供ashx程序處理.java
function ExportExcel() {
// 返回grid的全部可見行給後端供導出Excel用
var rows = $('#userlist').datagrid("getRows");
if (rows.length == 0) {
msgShow("沒有數據可供導出");
return;
}
//返回grid的全部列的選項title、列寬等
// var columns = $('#userlist').datagrid("options").columns;
//定製DataGrid的columns信息,只返回{field:,title:}
var columns = new Array();
var fields = $('#userlist').datagrid('getColumnFields');
for (var i = 0; i < fields.length; i++) {
var opts = $('#userlist').datagrid('getColumnOption', fields[i]);
var column = new Object();
column.field = opts.field;
column.title = opts.title;
columns.push(column);
}
var excelWorkSheet = new Object();
excelWorkSheet.rows = rows;
excelWorkSheet.columns = columns;
excelWorkSheet.sheetName = "設置導出的Excel工做表名";
var filename = "/HttpHandlers/FileHandler.ashx?action=exportexcel&excelWorkSheet=" + JSON.stringify(excelWorkSheet);
location.href = filename;
}
其中FileHandler.ashx是公共的文件處理程序,根據action=Exportexcel來實現Excel導出功能.數據庫
public void ProcessRequest(HttpContext context)
{
var action = context.Request["action"];
switch (action.ToLower())
{
case "exportexcel":
EasyUIGrid2Excel(context);
break;
}
}
EasyUIGrid2Excel完成前臺傳遞的關於Excel報表導出的參數,好比工做表名sheetName,題頭標題和行記錄。同時它完美解決了在各瀏覽器下文件名中文亂碼問題,最後以彈窗的形式讓用戶選擇直接打開仍是下載。json
private void EasyUIGrid2Excel(HttpContext context) { var jsonString = context.Request["excelWorkSheet"]; //使用Newtonsoft.Json.Linq.JObject將json字符串轉化成結構不固定的Class類 dynamic jsonObject = JObject.Parse(jsonString); string fileName = String.Concat(jsonObject.sheetName, DateTime.Now.ToString("yyyyMMdd-HHmmss"), ".xls") ; //解決中文文件名亂碼只在IE中有效 // filename = HttpUtility.UrlEncode(filename, System.Text.Encoding.UTF8); if (context.Request.UserAgent.ToLower().IndexOf("msie") > -1) { //當客戶端使用IE時,對其進行編碼; //使用 ToHexString 代替傳統的 UrlEncode(); fileName = CommonHelper.ToHexString(fileName); } if (context.Request.UserAgent.ToLower().IndexOf("firefox") > -1) { //爲了向客戶端輸出空格,須要在當客戶端使用 Firefox 時特殊處理 context.Response.AddHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\""); } else context.Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName); string extension = Path.GetExtension(fileName); context.Response.ContentType = CommonHelper.GetMimeType(extension); context.Response.ContentEncoding = Encoding.UTF8; Workbook workbook = Object2Workbook(jsonObject, context); context.Response.Clear(); context.Response.Buffer = true; context.Response.BinaryWrite(workbook.SaveToStream().ToArray()); context.Response.End(); }
上面代碼中的紅色標註部分詳見下載中的公共類庫,其中Object2Workbook主要實現Aspose.cells中的Excel格式化輸出定製,沒有太多技巧,Aspose.cells還帶有受權文件的哦,你懂的!後端
private Workbook Object2Workbook(dynamic jsonObject, HttpContext context) { #region Aspose.Cell引用 Aspose.Cells.License licExcel = new License(); //Aspose.Cells申明 if (File.Exists(context.Server.MapPath("~/Bin/cellLic.lic"))) licExcel.SetLicense(context.Server.MapPath("~/Bin/cellLic.lic")); #endregion Workbook workbook = new Workbook(); Worksheet sheet = workbook.Worksheets[0]; Styles styles = workbook.Styles; int styleIndex = styles.Add(); Aspose.Cells.Style borderStyle = styles[styleIndex]; borderStyle.Borders.DiagonalStyle = CellBorderType.None; borderStyle.HorizontalAlignment = TextAlignmentType.Center;//文字居中 Cells cells = sheet.Cells; sheet.FreezePanes(1, 1, 1, 0);//凍結第一行 sheet.Name = jsonObject.sheetName;//接受前臺的Excel工做表名 //爲標題設置樣式 Style styleTitle = workbook.Styles[workbook.Styles.Add()];//新增樣式 styleTitle.HorizontalAlignment = TextAlignmentType.Center;//文字居中 styleTitle.Font.Name = "宋體";//文字字體 styleTitle.Font.Size = 18;//文字大小 styleTitle.Font.IsBold = true;//粗體 //題頭樣式 Style styleHeader = workbook.Styles[workbook.Styles.Add()];//新增樣式 styleHeader.HorizontalAlignment = TextAlignmentType.Center;//文字居中 styleHeader.Font.Name = "宋體";//文字字體 styleHeader.Font.Size = 14;//文字大小 styleHeader.Font.IsBold = true;//粗體 styleHeader.IsTextWrapped = true;//單元格內容自動換行 styleHeader.Borders[BorderType.LeftBorder].LineStyle = CellBorderType.Thin; styleHeader.Borders[BorderType.RightBorder].LineStyle = CellBorderType.Thin; styleHeader.Borders[BorderType.TopBorder].LineStyle = CellBorderType.Thin; styleHeader.Borders[BorderType.BottomBorder].LineStyle = CellBorderType.Thin; //內容樣式 Style styleContent = workbook.Styles[workbook.Styles.Add()];//新增樣式 styleContent.HorizontalAlignment = TextAlignmentType.Center;//文字居中 styleContent.Font.Name = "宋體";//文字字體 styleContent.Font.Size = 12;//文字大小 styleContent.Borders[BorderType.LeftBorder].LineStyle = CellBorderType.Thin; styleContent.Borders[BorderType.RightBorder].LineStyle = CellBorderType.Thin; styleContent.Borders[BorderType.TopBorder].LineStyle = CellBorderType.Thin; styleContent.Borders[BorderType.BottomBorder].LineStyle = CellBorderType.Thin; var rowCount = jsonObject.rows.Count;//表格行數 var columnCount = jsonObject.columns.Count;//表格列數 //生成行1 標題行 cells.Merge(0, 0, 1, columnCount);//合併單元格 cells[0, 0].PutValue(jsonObject.sheetName);//填寫內容 cells[0, 0].Style = styleTitle; cells.SetRowHeight(0, 25); //生成題頭列行 for (int i = 0; i < columnCount; i++) { cells[1, i].PutValue(jsonObject.columns[i]["title"]); cells[1, i].Style = styleHeader; cells.SetRowHeight(1, 23); } //生成內容行,第三行起始 //生成數據行 for (int i = 0; i < rowCount; i++) { for (int k = 0; k < columnCount; k++) { var currentColumnName = jsonObject.columns[k]["field"]; cells[2 + i, k].PutValue(jsonObject.rows[i][currentColumnName.Value]); cells[2 + i, k].Style = styleContent; } cells.SetRowHeight(2 + i, 22); } //添加製表日期 cells[2 + rowCount, columnCount-1].PutValue("製表日期:" + DateTime.Now.ToShortDateString()); sheet.AutoFitColumns();//讓各列自適應寬度 sheet.AutoFitRows();//讓各行自適應寬度 return workbook; }
該code snippet也能很好的移植,在須要實現Excel導出的js文件中調用ExportExcel函數,傳遞sheetName值便可數組
國際慣例,無圖無真相瀏覽器
文件下載服務器
btw:另外請教兩個問題,知道的童鞋回答一下,謝謝app
1,經過客戶端導出Excel的方式,當打開文件的時候,提示:文件錯誤,數據可能丟失, 初步認爲可能數字以文本形式存到Excel中出現了問題?若是直接服務器端導出卻沒有這個錯誤
2,一對多表中數據更新問題,好比三張表User,Role和對應的關聯表UserRole,其中主鍵都是自動遞增ID。若是我更改了用戶角色,當前的作法是在UserRole中刪掉該用戶的全部舊角色,再新增。感受這樣麻煩也不合理,請教你們有好的作飯沒?