ExtJs6.0之Grid前端導出Excel

該js文件支持三級表頭的導出。
引入該js文件,調用grid2Excel(grid, fileName)即可。

  1. 新建導出按鈕
new Ext.create('Ext.button.Button',{ 
    xtype:'button', 
    iconCls:'excel', 
    type: 'excel', 
    text:'保存爲Excel', 
    handler:function() { 
        //grid 爲Extjs grid對象 
        //"導出文件名"  爲導出的Excel文件的名稱                     
        grid2Excel(grid,"項目授權列表"); 
    } 
})
  1. 點擊後調用該函數即可。

列出詳細代碼:

/** 
* 
* function grid2Excel(grid,filename) 
* @param grid Extjs grid panel 
* @param filename Excel 文件名稱 
* 
* **/ 
(function(){ 
            function  getExplorer() {
            var explorer = window.navigator.userAgent ;
            //ie 
            if (explorer.indexOf("MSIE") >= 0) {
                return 'ie';
            }
            //firefox 
            else if (explorer.indexOf("Firefox") >= 0) {
                return 'Firefox';
            }
            //Chrome
            else if(explorer.indexOf("Chrome") >= 0){
                return 'Chrome';
            }
            //Opera
            else if(explorer.indexOf("Opera") >= 0){
                return 'Opera';
            }
            //Safari
            else if(explorer.indexOf("Safari") >= 0){
                return 'Safari';
            }         
        }

         function export_excel_ie(tableStr, fileName) {//整個表格拷貝到EXCEL中
            if(getExplorer()=='ie')
            {
                var oXL = new ActiveXObject("Excel.Application");
                /*
                 * 設置邊框, 1表示最細邊框,2表示細邊框,4表示粗線。
                 */
                //oXL.Selection.Borders.Weight = 4;
                /*
                 * 設置邊框線 1 實線, -4115 虛線, 4 點劃相間線, 5 劃線後跟兩個點, -4118 點式線, -4119 雙線。
                 */
                //oXL.Selection.Borders.LineStyle = 1;
                var el4table = document.createElement("div");
                el4table.innerHTML = tableStr;
                //創建AX對象excel 
                var oWB = oXL.Workbooks.Add();
                //獲取workbook對象 
                var xlsheet = oWB.Worksheets(1);
                //激活當前sheet 
                var sel = document.body.createTextRange();
                sel.moveToElementText(el4table);
                //把表格中的內容移到TextRange中 
                sel.select;
                //全選TextRange中內容 
                sel.execCommand("Copy");
                //複製TextRange中內容  
                xlsheet.Paste();
                //粘貼到活動的EXCEL中       
                oXL.Visible = true;
                //設置excel可見屬性

                try {
                    var fname = oXL.Application.GetSaveAsFilename("Excel.xls", "Excel Spreadsheets (*.xls), *.xls");
                } catch (e) {
                    print("Nested catch caught " + e);
                } finally {
                    oWB.SaveAs(fname);

                    oWB.Close(savechanges = false);
                    //xls.visible = false;
                    oXL.Quit();
                    oXL = null;
                    //結束excel進程,退出完成
                    //window.setInterval("Cleanup();",1);
                    idTmr = window.setInterval("Cleanup();", 1);

                }

            }
            else
            {
                tableToExcel(tableStr, fileName);
            }
        }
        function Cleanup() {
            window.clearInterval(idTmr);
            CollectGarbage();
        }
    var Base64 = (function() { 
        // private property 
        var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 

        // private method for UTF-8 encoding 
        function utf8Encode(string) { 
            string = string.replace(/\r\n/g,"\n"); 
            var utftext = ""; 
            for (var n = 0; n < string.length; n++) { 
                var c = string.charCodeAt(n); 
                if (c < 128) { 
                    utftext += String.fromCharCode(c); 
                } 
                else if((c > 127) && (c < 2048)) { 
                    utftext += String.fromCharCode((c >> 6) | 192); 
                    utftext += String.fromCharCode((c & 63) | 128); 
                } 
                else { 
                    utftext += String.fromCharCode((c >> 12) | 224); 
                    utftext += String.fromCharCode(((c >> 6) & 63) | 128); 
                    utftext += String.fromCharCode((c & 63) | 128); 
                } 
            } 
            return utftext; 
        } 

        // public method for encoding 
        return { 
            //encode : (typeof btoa == 'function') ? function(input) { return btoa(input); } : function (input) { 
            encode : function (input) { 
                var output = ""; 
                var chr1, chr2, chr3, enc1, enc2, enc3, enc4; 
                var i = 0; 
                input = utf8Encode(input); 
                while (i < input.length) { 
                    chr1 = input.charCodeAt(i++); 
                    chr2 = input.charCodeAt(i++); 
                    chr3 = input.charCodeAt(i++); 
                    enc1 = chr1 >> 2; 
                    enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); 
                    enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); 
                    enc4 = chr3 & 63; 
                    if (isNaN(chr2)) { 
                        enc3 = enc4 = 64; 
                    } else if (isNaN(chr3)) { 
                        enc4 = 64; 
                    } 
                    output = output + 
                        keyStr.charAt(enc1) + keyStr.charAt(enc2) + 
                        keyStr.charAt(enc3) + keyStr.charAt(enc4); 
                } 
                return output; 
            } 
        }; 
    })(); 
    var  format = function(s, c) { return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }) }; 
    var tableToExcel = function(table, fileName) { 
        var uri = 'data:application/vnd.ms-excel;base64,' 
            ,fileName = fileName || 'excelexport' 
        , template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><meta name="renderer" content="webkit"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>'; 

        var ctx = {worksheet:'Worksheet', table: table}; 
        var a = document.createElement('a'); 
        document.body.appendChild(a); 
        a.hreflang = 'zh'; 
        a.charset = 'utf8'; 
        a.type="application/vnd.ms-excel"; 
        a.href = uri + Base64.encode(format(template,ctx)); 
        a.target = '_blank'; 
        a.download = fileName + '.xls';
        a.tableBorder = 1;
        a.click(); 

    }; 
    window.grid2Excel = function(grid, fileName) { 
//      console.log(grid);
        var columns = grid.initialConfig.columns|| [], 
            store = grid.getStore(), 
            headLevel1 = [],headLevel2 = [], headLevel3 = [], headLevel = 1,isGroup = false, isGroup3 = false,
            dataIndex =[],tableStr = '<table border="1" bordercolor="#000"><thead>{thead}</thead><tbody>{tbody}</tbody></table>'; 

        var blankColumn = 0;
        var blankColumn3 = 0;
        var ifWithCheckOrNumFirst;
        columns.forEach(function(column) {

                //說明第一列是checkbox或者是序號列,是有headerId的,如果不是headerId
            //console.log(!column.headerId);
                if(column.headerId){
//                  console.log("序號列");
                    ifWithCheckOrNumFirst = true;
                } else {
                    //帶合併單元格的時候,那一大列是沒有dataindex的,所以會false
                    if(!column.dataIndex) {

                        blankColumn += 1;
                        isGroup = true; 

                        var items = column.columns ||[];
                        items.forEach(function(column3) {
                            if (!column3.dataIndex) {
                                blankColumn3 += 1;  //分爲了三級表頭的數目
                                isGroup3 = true;    //三級表頭
                                return false;
                            }
                        });                     
                        return false; 
                    } 
                }
        }); 
        if(isGroup) { 
            headLevel = 2;  //只支持二級表頭 
            if (isGroup3) {
                headLevel = 3;
            }
        } 
//        console.log("------------表頭: " + headLevel);
//        console.log("三級表頭: " + blankColumn3);

        var indexen = 0;
     //   console.log("長度1:" + headLevel1.length);
        columns.forEach(function(column) { 
            //    console.log(column.dataIndex);

                //說明不需要橫向合併單元格的時候,
            if(column.dataIndex) { 
          //    console.log(column);
                column.colspan = 1;

                //有橫向合併單元格的話,這個縱向合併就會變多。是2層表頭的話,這個rowspan就是2.其實不管他有沒有橫向合併這個數取過來就對
                if (headLevel == 3) {
                    column.rowspan = headLevel; 
                } else if (headLevel == 2) {
                    column.rowspan = headLevel; 
                } else {
                    column.rowspan = 1;
                }               

                headLevel1.push(column); 
                dataIndex.push(column); 

            }else { 
          //    console.log("長度x333:" + headLevel); 
                //不是橫向合併的單元格,還有可能是第一列是checkbox或者是序號所以需要判斷一下,如果是checkbox或者序號,則不push到數組裏
                if (ifWithCheckOrNumFirst) {

                } else {
                    var items = column.columns ||[]; 
                    headLevel1.push(column);
                    items.forEach(function(item2) {
                    //  console.log("二級 dataindex: " + item2.dataIndex);
                        if (item2.dataIndex) {//二級表頭 
                            column.colspan = items.length;
                            column.rowspan = 1;
                            item2.colspan = 1;
                            if (headLevel == 3) {//三級表頭下  如果二級表頭下面沒有再分,二級表頭佔兩行
                                item2.rowspan = 2;
                            } else {
                                item2.rowspan = 1;
                            }

                            headLevel2.push(item2);
                            dataIndex.push(item2);
                        } else {
                            var items3 = item2.columns ||[];
                            headLevel2.push(item2);
                            items3.forEach(function(item33) {
                                if (item33.dataIndex) {
                                    item2.colspan = items3.length;//二級表頭的長度
                                    column.colspan = items3.length + items.length + blankColumn3; //一級表頭的長度
                                    item2.rowspan = 1;
                                    item33.colspan = 1;
                                    item33.rowspan = 1;
                                    headLevel3.push(item33);
                                    dataIndex.push(item33);
                                }

                            });
                        }

                    });
                }
            } 
        }); 

        var headLevel1Str = '<tr>'; 
        headLevel1.forEach(function(head) { 
       //   console.log(head.header);
            if (head.dataIndex != 'operate') {
                headLevel1Str += '<th colspan = "'+head.colspan+ 
                    '" rowspan="'+head.rowspan+'">'+head.header+'</th>'; 
            }

        }); 
        headLevel1Str += '</tr>'; 

        var headLevel2Str = ''; 
        if(headLevel2.length > 0) { 
            headLevel2Str += '<tr>'; 
            headLevel2.forEach(function(head) { 
                if (head.dataIndex != 'operate') {
                    headLevel2Str += '<th colspan = "'+head.colspan+ 
                        '" rowspan="'+head.rowspan+'">'+head.header+'</th>'; 
                }
            }); 
            headLevel2Str += '</tr>' 
        } 

        var headLevel3Str = ''; 
        if(headLevel3.length > 0) { 
            headLevel3Str += '<tr>'; 
            headLevel3.forEach(function(head) { 
                if (head.dataIndex != 'operate') {
                    headLevel3Str += '<th colspan = "'+head.colspan+ 
                        '" rowspan="'+head.rowspan+'">'+head.header+'</th>'; 
                }
            }); 
            headLevel3Str += '</tr>' 
        } 

        var theadStr = headLevel1Str + headLevel2Str + headLevel3Str, 
            tbodyStr = '',defRenderer = function(value) { 
                return value; 
            }; 

        store.each(function(r) { 
            tbodyStr += '<tr>'; 
            dataIndex.forEach(function(c) { 
                if (c.dataIndex != 'operate') {
                    var renderere = c.renderer || defRenderer; 
                    if (renderere.call(r,r.get(c.dataIndex))) {
                        tbodyStr += '<td>'+renderere.call(r,r.get(c.dataIndex)) + "" +'</td>' ;
                    } else {
                        tbodyStr += '<td>'+ " " + "" +'</td>' ;
                    }
                    tbodyStr += '<td>'+renderere.call(r,r.get(c.dataIndex)) + "" +'</td>' ;
                //  console.log("test: " + renderere.call(r,r.get(c.dataIndex)));
                }

            }); 
            tbodyStr +='</tr>' 
        }); 
        tableStr = format(tableStr,{ 
            thead:theadStr, 
            tbody:tbodyStr 
        }); 

     //   console.log(tableStr);
        export_excel_ie(tableStr,fileName); 

    } 
})()

注意:
二級和三級datagrid的有合併單元格,如果數據列表中有序號的不能導出。
解決辦法:
1. 序號列

有序號列的必須這樣寫

{ header: '', xtype: 'rownumberer',dataIndex:'operate', width: 60, align: 'center', sortable: false },

序號列的dataIndex爲operate,在導出函數中如果包含這個的不會導出(篩選)。

而這樣寫會認爲是有序號的,不能導出有合併單元格的列表。

new Ext.grid.RowNumberer({  header: '序號',   width:50}),
  • 複選框列
checkBox = Ext.create('Ext.selection.CheckboxModel', {
    mode : "SIMPLE",
    checkOnly : true
});
grid = Ext.create('Ext.grid.GridPanel', {
    renderTo : 'gridDiv',
    title : '人員考覈列表',
    sripeRows : true,
    store : store,
    // bodyStyle: 'width:100%',
    viewConfig : {
        forceFit : true
    },
    selModel : checkBox,//設置複選框
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章