利用Aspose.Cells完成easyUI中DataGrid數據的Excel導出功能


我准備在項目中實現該功能之前,google發現大部分代碼都是利用一般處理程序HttpHandler實現的服務器端數據的Excel導出,但是這樣存在的問題是ashx讀取的數據一般都是數據庫中視圖的數據,難免會含有方便操作的主鍵ID這列的記錄。現在項目需要在easyUI的DataGrid中顯示的數據能全部導出Excel,包括DataGrid中的中文標題,其他的統統不要。

完成該功能所需的工具和環境:Newtonsoft.Json序列化和反序列化類庫、easyUI前端UI框架、HttpHandler一般處理程序、Aspose.Cells電子表格生成組件;.Net Framework4.0。

前端完成DataGrid中的題頭和數據行信息遍歷訪問,並以JS中二維數組的形式返回后台供ashx程序處理.

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,題頭標題和行記錄。同時它完美解決了在各瀏覽器下文件名中文亂碼問題,最后以彈窗的形式讓用戶選擇直接打開還是下載。

 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:另外請教兩個問題,知道的童鞋回答一下,謝謝

1,通過客戶端導出Excel的方式,當打開文件的時候,提示:文件錯誤,數據可能丟失, 初步認為可能數字以文本形式存到Excel中出現了問題?如果直接服務器端導出卻沒有這個錯誤

2,一對多表中數據更新問題,比如三張表User,Role和對應的關聯表UserRole,其中主鍵都是自動遞增ID。如果我更改了用戶角色,當前的做法是在UserRole中刪掉該用戶的所有舊角色,再新增。感覺這樣麻煩也不合理,請教大家有好的做飯沒?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM