easyui datagrid 導出excel

本片文章是介紹如何用ajax的方式將easyui中的datagrid數據導出到excel中。

聲明:該代碼是在參考前人的代碼寫出來的,並非我原創,我只是新增了些功能微笑

新增部分:

1. 對於列是枚舉列的可以設置枚舉值,導出時會自動替換列中的枚舉值,詳細見用例代碼。

2. 新增導出時不導出首列或末列指定個數的列,詳細接用例代碼。

下面是插件源碼:

/**
Jquery easyui datagrid js導出excel
修改自extgrid導出excel
* allows for downloading of grid data (store) directly into excel
* Method: extracts data of gridPanel store, uses columnModel to construct XML excel document,
* converts to Base64, then loads everything into a data URL link.
*
* @author Guo Jing <iTrucks>
* 2015-01-12
*
*/
$.extend($.fn.datagrid.methods, {
    getExcelXml: function (jq, param) {
        var worksheet = this.createWorksheet(jq, param);
        //alert($(jq).datagrid('getColumnFields'));
        var totalWidth = 0;
        var cfs = $(jq).datagrid('getColumnFields');
        /* **判斷是否刪除第一行以及最後一行************begin****************/
        //console.dir(JSON.stringify(param.enums[0].type));
        if (param.removeFirstCol) {
            if (param.removeLastCol) {
                for (var i = param.removeFirstCol; i < cfs.length - param.removeLastCol; i++) {
                    totalWidth += $(jq).datagrid('getColumnOption', cfs[i]).width;
                }
            }
            else {
                for (var i = param.removeFirstCol; i < cfs.length; i++) {
                    totalWidth += $(jq).datagrid('getColumnOption', cfs[i]).width;
                }
            }
        }
        else {
            if (param.removeLastCol) {
                for (var i = 0; i < cfs.length - param.removeLastCol; i++) {
                    totalWidth += $(jq).datagrid('getColumnOption', cfs[i]).width;
                }
            }
            else {
                for (var i = 0; i < cfs.length; i++) {
                    totalWidth += $(jq).datagrid('getColumnOption', cfs[i]).width;
                }
            }
        }
        /*****************************end*********************************/
        //var totalWidth = this.getColumnModel().getTotalWidth(includeHidden);
        return '<?xml version="1.0" encoding="utf-8"?>' +//xml申明有問題,以修正,注意是utf-8編碼,如果是gb2312,需要修改動態頁文件的寫入編碼
    '<ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:o="urn:schemas-microsoft-com:office:office">' +
    '<o:DocumentProperties><o:Title>' + param.title + '</o:Title></o:DocumentProperties>' +
    '<ss:ExcelWorkbook>' +
    '<ss:WindowHeight>' + worksheet.height + '</ss:WindowHeight>' +
    '<ss:WindowWidth>' + worksheet.width + '</ss:WindowWidth>' +
    '<ss:ProtectStructure>False</ss:ProtectStructure>' +
    '<ss:ProtectWindows>False</ss:ProtectWindows>' +
    '</ss:ExcelWorkbook>' +
    '<ss:Styles>' +
    '<ss:Style ss:ID="Default">' +
    '<ss:Alignment ss:Vertical="Top"  />' +
    '<ss:Font ss:FontName="arial" ss:Size="10" />' +
    '<ss:Borders>' +
    '<ss:Border  ss:Weight="1" ss:LineStyle="Continuous" ss:Position="Top" />' +
    '<ss:Border  ss:Weight="1" ss:LineStyle="Continuous" ss:Position="Bottom" />' +
    '<ss:Border  ss:Weight="1" ss:LineStyle="Continuous" ss:Position="Left" />' +
    '<ss:Border ss:Weight="1" ss:LineStyle="Continuous" ss:Position="Right" />' +
    '</ss:Borders>' +
    '<ss:Interior />' +
    '<ss:NumberFormat />' +
    '<ss:Protection />' +
    '</ss:Style>' +
    '<ss:Style ss:ID="title">' +
    '<ss:Borders />' +
    '<ss:Font />' +
    '<ss:Alignment  ss:Vertical="Center" ss:Horizontal="Center" />' +
    '<ss:NumberFormat ss:Format="@" />' +
    '</ss:Style>' +
    '<ss:Style ss:ID="headercell">' +
    '<ss:Font ss:Bold="1" ss:Size="10" />' +
    '<ss:Alignment  ss:Horizontal="Center" />' +
    '<ss:Interior ss:Pattern="Solid"  />' +
    '</ss:Style>' +
    '<ss:Style ss:ID="even">' +
    '<ss:Interior ss:Pattern="Solid"  />' +
    '</ss:Style>' +
    '<ss:Style ss:Parent="even" ss:ID="evendate">' +
    '<ss:NumberFormat ss:Format="yyyy-mm-dd" />' +
    '</ss:Style>' +
    '<ss:Style ss:Parent="even" ss:ID="evenint">' +
    '<ss:NumberFormat ss:Format="0" />' +
    '</ss:Style>' +
    '<ss:Style ss:Parent="even" ss:ID="evenfloat">' +
    '<ss:NumberFormat ss:Format="0.00" />' +
    '</ss:Style>' +
    '<ss:Style ss:ID="odd">' +
    '<ss:Interior ss:Pattern="Solid"  />' +
    '</ss:Style>' +
    '<ss:Style ss:Parent="odd" ss:ID="odddate">' +
    '<ss:NumberFormat ss:Format="yyyy-mm-dd" />' +
    '</ss:Style>' +
    '<ss:Style ss:Parent="odd" ss:ID="oddint">' +
    '<ss:NumberFormat ss:Format="0" />' +
    '</ss:Style>' +
    '<ss:Style ss:Parent="odd" ss:ID="oddfloat">' +
    '<ss:NumberFormat ss:Format="0.00" />' +
    '</ss:Style>' +
    '</ss:Styles>' +
    worksheet.xml +
    '</ss:Workbook>';
    },
    createWorksheet: function (jq, param) {
        // Calculate cell data types and extra class names which affect formatting
        var cellType = [];
        var cellTypeClass = [];
        //var cm = this.getColumnModel();
        var totalWidthInPixels = 0;
        var colXml = '';
        var headerXml = '';
        var visibleColumnCountReduction = 0;
        var cfs = $(jq).datagrid('getColumnFields');
        var colCount = cfs.length;
        var cstartIndex = 0, cendIndex = colCount;
        var colWidthEnumsIndex = [];//記錄枚舉列的下標和枚舉數組對應的下標。
        //alert(param.removeFirstCol + "," + param.removeLastCol);
        if (param.removeFirstCol) {
            cstartIndex = param.removeFirstCol;
            if (param.removeLastCol) {
                cendIndex = colCount - param.removeLastCol;
            }
            else {
                cendIndex = colCount;
            }
        }
        else {
            cstartIndex = 0;
            if (param.removeLastCol) {

                cendIndex = colCount - param.removeLastCol;
            }
            else {
                cendIndex = colCount;
            }
        }
        for (var i = cstartIndex; i < cendIndex; i++) {
            if (cfs[i] != '') {
                var w = $(jq).datagrid('getColumnOption', cfs[i]).width;
                totalWidthInPixels += w;
                if (cfs[i] === "") {
                    cellType.push("None");
                    cellTypeClass.push("");
                    ++visibleColumnCountReduction;
                }
                else {
                    colXml += '<ss:Column ss:AutoFitWidth="1" ss:Width="130" />';
                    headerXml += '<ss:Cell ss:StyleID="headercell">' +
                '<ss:Data ss:Type="String">' + $(jq).datagrid('getColumnOption', cfs[i]).title.replace("<br>","") + '</ss:Data>' +
                '<ss:NamedCell ss:Name="Print_Titles" /></ss:Cell>';
                    cellType.push("String");
                    cellTypeClass.push("");
                    if (param.enums) {
                        //遍歷枚舉數組,檢測是否有列屬於枚舉類型
                        for (var j = 0; j < param.enums.length; j++) {
                            if ($(jq).datagrid('getColumnOption', cfs[i]).title == param.enums[j].type) {
                                //console.dir($(jq).datagrid('getColumnOption', cfs[i]).title + "," + i);
                                colWidthEnumsIndex.push({ colIndex: i, enumIndex: j });
                            }
                        }
                    }

                }
            }
        }
        //console.dir(JSON.stringify(colWidthEnumsIndex.length));
        var visibleColumnCount = cellType.length - visibleColumnCountReduction;
        var result = {
            height: 9000,
            width: Math.floor(totalWidthInPixels * 30) + 50
        };
        var rows = $(jq).datagrid('getRows');
        // Generate worksheet header details.
        var t = '<ss:Worksheet ss:Name="' + param.title + '">' +
    '<ss:Names>' +
    '<ss:NamedRange ss:Name="Print_Titles" ss:RefersTo="=\'' + param.title + '\'!R1:R2" />' +
    '</ss:Names>' +
    '<ss:Table x:FullRows="1" x:FullColumns="1"' +
    ' ss:ExpandedColumnCount="' + (visibleColumnCount + 2) +
    '" ss:ExpandedRowCount="' + (rows.length + 2) + '">' +
    colXml +
    '<ss:Row ss:AutoFitHeight="1">' +
    headerXml +
    '</ss:Row>';
        // Generate the data rows from the data in the Store
        //for (var i = 0, it = this.store.data.items, l = it.length; i < l; i++) {
        for (var i = 0, it = rows, l = it.length; i < l; i++) {
            t += '<ss:Row>';
            var cellClass = (i & 1) ? 'odd' : 'even';
            r = it[i];
            var k = 0;
            for (var j = cstartIndex; j < cendIndex; j++) {
                //if ((cm.getDataIndex(j) != '')
                if (cfs[j] != '') {
                    //var v = r[cm.getDataIndex(j)];
                    var v = r[cfs[j]];
                    if (cellType[k] !== "None") {
                        t += '<ss:Cell ss:StyleID="' + cellClass + cellTypeClass[k] + '"><ss:Data ss:Type="' + cellType[k] + '">';
                        if (cellType[k] == 'DateTime') {
                            t += v.format('Y-m-d');
                        } else {
                            
                            //判斷該列是否屬於枚舉,如果是,則進行轉換
                            for (var lp = 0; lp < colWidthEnumsIndex.length; lp++) {
                                if (j == colWidthEnumsIndex[lp].colIndex) {//當前列是枚舉列
                                    //console.dir(JSON.stringify(param.enums[l].value));
                                    //遍歷枚舉中的值,對元數據進行替換
                                    for (var mp = 0; mp < param.enums[lp].value.length; mp++) {
                                        if (v == param.enums[lp].value[mp].key) {
                                            v = param.enums[lp].value[mp].text;
                                        }
                                        //switch (v) {
                                        //    case param.enums[l].value[m].key:
                                        //        v = param.enums[l].value[m].text;
                                        //        break;
                                        //}
                                    }
                                }
                            }
                            t += v;
                        }
                        t += '</ss:Data></ss:Cell>';
                    }
                    k++;
                }
            }
            t += '</ss:Row>';
        }
        result.xml = t + '</ss:Table>' +
    '<x:WorksheetOptions>' +
    '<x:PageSetup>' +
    '<x:Layout x:CenterHorizontal="1" x:Orientation="Landscape" />' +
    '<x:Footer x:Data="Page &P of &N" x:Margin="0.5" />' +
    '<x:PageMargins x:Top="0.5" x:Right="0.5" x:Left="0.5" x:Bottom="0.8" />' +
    '</x:PageSetup>' +
    '<x:FitToPage />' +
    '<x:Print>' +
    '<x:PrintErrors>Blank</x:PrintErrors>' +
    '<x:FitWidth>1</x:FitWidth>' +
    '<x:FitHeight>32767</x:FitHeight>' +
    '<x:ValidPrinterInfo />' +
    '<x:VerticalResolution>600</x:VerticalResolution>' +
    '</x:Print>' +
    '<x:Selected />' +
    '<x:DoNotDisplayGridlines />' +
    '<x:ProtectObjects>False</x:ProtectObjects>' +
    '<x:ProtectScenarios>False</x:ProtectScenarios>' +
    '</x:WorksheetOptions>' +
    '</ss:Worksheet>';
        return result;
    }
});

用例
//導出
        function Save_Excel() {//導出Excel文件
            //處理列中有枚舉類型的值,傳入枚舉名值對程序將自動進行替換
            var enumsVal = [{ type: "車輛類型", value: [{ key: 10, text: "普通廂式貨車" }, { key: 20, text: "城市配送標準車" }, { key: 30, text: "冷藏冷凍車" }, { key: 40, text: "其他配送車輛" }] },
                            { type: "通行證類型", value: [{ key: 10, text: "特通" }, { key: 20, text: "甲通" }, { key: 30, text: "乙通" }] },

                            { type: "燃料類型", value: [{ key: 10, text: "汽油" }, { key: 20, text: "CNG" }, { key: 30, text: "柴油" }, { key: 40, text: "LNG" }, { key: 50, text: "電動" }] },
                            { type: "狀態", value: [{ key: true, text: "已啓用" }, { key: false, text: "未啓用" }] }
            ];
            //getExcelXML有一個JSON對象的配置,配置項看了下只有title配置,爲excel文檔的標題
            var data = $('#m_dgvList').datagrid('getExcelXml', { title: 'datagrid import to excel', removeFirstCol: 0, removeLastCol: 1, enums: enumsVal }); //獲取datagrid數據對應的excel需要的xml格式的內容
            //用ajax發動到動態頁動態寫入xls文件中
            var url = '../../datagrid-export-excel.ashx'; //如果爲asp注意修改後綴
            var dlurl = "../../DownloadFile.ashx";
            $.ajax({
                url: url, data: { data: data }, type: 'POST', dataType: 'text',
                success: function (fn) {
                    window.location = dlurl + "?FileName=車輛查詢.xls&FilePath=" + fn; //執行下載操作
                    //window.open(dlurl + "?FileName=車輛查詢.xls&FilePath=" + fn);
                },
                error: function (xhr) {
                    alert('動態頁有問題\nstatus:' + xhr.status + '\nresponseText:' + xhr.responseText)
                }
            });
            return false;
        }
datagrid-export-excel.ashx:
<%@ WebHandler Language="C#" Class="datagrid_export_excel" %>

using System;
using System.Web;

public class datagrid_export_excel : IHttpHandler {

    public void ProcessRequest(HttpContext context)
    {
        string fn = System.Configuration.ConfigurationManager.AppSettings["temFilePath"].ToString() + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".xls";
        string data = context.Request.Form["data"];
        System.IO.File.WriteAllText(context.Server.MapPath(fn), data, System.Text.Encoding.Unicode);//如果是gb2312的xml申明,第三個編碼參數修改爲Encoding.GetEncoding(936)

        context.Response.Write(fn);//返回文件名提供下載
    }
    public bool IsReusable
    {
        get
        {
            return false;
        }
    }

}

DownLoadFile.ashx:

<%@ WebHandler Language="C#" Class="DownLoadFile" %>

using System;
using System.Web;
using System.Linq;
using System.Web.SessionState;
using System.IO;

public class DownLoadFile : IHttpHandler, IReadOnlySessionState
{

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        //獲取文件路徑
        string path = context.Request["FilePath"];

        if (string.IsNullOrEmpty(path)) throw new Exception("非法請求!");

        //獲取文件名
        var fileName = context.Request["FileName"];
        if (string.IsNullOrEmpty(fileName)) fileName = path.Split('/').Last().ToString();

        //獲取虛擬目錄的物理路徑。 
        path = context.Server.MapPath(path);

        fileName = fileName.Replace(" ", "");

        if (System.IO.File.Exists(path))
        {
            //刪除除了本次請求的歷史文件
            DeleteOldFiles(path, context.Server.MapPath(System.Configuration.ConfigurationManager.AppSettings["temFilePath"].ToString()));
            System.IO.FileInfo fileInfo = new System.IO.FileInfo(path);
            context.Response.Clear();
            context.Response.ClearContent();
            context.Response.ClearHeaders();
            //根據不同的瀏覽器對文件名進行不同的編碼方式
            if (context.Request.UserAgent.ToLower().IndexOf("msie", System.StringComparison.Ordinal) > -1)//IE瀏覽器
            {
                context.Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(fileName));
            }

            else //其他瀏覽器
            {
                context.Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlDecode(fileName, System.Text.Encoding.UTF8));
            }

            context.Response.AddHeader("Content-Length", fileInfo.Length.ToString());
            context.Response.AddHeader("Content-Transfer-Encoding", "binary");
            context.Response.ContentType = "application/octet-stream;charset=gbk";
            context.Response.ContentEncoding = System.Text.Encoding.UTF8;
            context.Response.WriteFile(fileInfo.FullName);
            context.Response.Flush();
            context.Response.End();
        }
        else
        {
            context.Response.ContentType = "text/html";
            context.Response.Write("<script type='text/javascript'>alert('對不起,文件已不存在。');window.close();</script>");
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
    /// <summary>
    /// 刪除目錄下指定文件外的所有文件
    /// </summary>
    /// <param name="fileName"></param>
    /// <param name="filePath"></param>
    public void DeleteOldFiles(string fileName, string filePath)
    {
        try
        {
            DirectoryInfo di = new DirectoryInfo(filePath);
            FileInfo[] fi = di.GetFiles();//獲得目錄下文件
            foreach (FileInfo f in fi)
            {
                if (f.FullName != fileName)
                {
                    //判斷指定文件是否存在
                    File.Delete(f.FullName);
                }
            }
        }
        catch (Exception ex)
        {
            HttpContext.Current.Response.Write(ex.Message);
        }
    }
}

代碼中都有註釋,就不具體詳解了,有問題歡迎討論。微笑

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章