用過layui table的都了解,layui的表格自帶導出功能,隻要在屬性toolbar裡配置即可。
如果嫌toolbar裡的導出按鈕不夠美觀,layui也友好的提供了自行定義按鈕後調用導出頁面資料的方法,詳見:官方文檔
遺憾的是:
該方法暫時并不支援對多層表頭的導出。
而多層複雜表頭在很多系統中都有展現,而若不想通過背景代碼去做導出,隻在前端頁面上該如何做呢?
目錄&曆程
- 1 史前
-
- 1.1 直接使用(兩種方式)
- 1.2 上述插件使用場景解析
- 1.3 不可用場景處理
- 1.4 處理後的使用
- 1.5 新的情況相容:固定列
- 2 蛻變
-
- 2.1 table2excel_ext.js的誕生
- 2.2 新的情況相容:合計行
- 2.3 新的情況相容:排除列
1 史前
1.1 直接使用(兩種方式)
1.
下載下傳插件:
位址:github table2excel
下載下傳下來項目後,在項目的
dist
中就有該js,在自己表格html頁面引用即可使用。
連結:百度雲下載下傳js
提取碼:1f52
/**
* 使用方法該js的方法(兩行代碼)
*/
let table2excel = new Table2Excel();
// 傳入你的tableId即可導出
table2excel.export($('#tableId'), "your filename");
-
複制走即可使用一個解析頁面元素方法:
/**
*
* @param id:表格的id
* @param fileName:導出的excel的名字
*/
function exportForExcle(id,fileName){
var table = $(document.getElementById(id)).clone();
table.attr('id','datatab');
table.appendTo('body');
method5('datatab');
datatab.remove();
function method5(tableid) {
var idTmr;
var tableToExcel = (function() {
var uri = 'data:application/vnd.ms-excel;base64,',
template = '<html><head><meta charset="UTF-8"></head><body><table >{table}</table></body></html>',
base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))) },
format = function(s, c) {return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }) }
return function(table, name) {
if (!table.nodeType) table = document.getElementById(table)
var ctx = {worksheet: name || 'Worksheet', table: table.innerHTML}
var aTag = document.createElement('a');
aTag.download = fileName;
aTag.href = uri + base64(format(template, ctx));
document.body.appendChild(aTag);
aTag.onclick = function () {
document.body.removeChild(aTag);
}
aTag.click();
}
})()
if(getExplorer()=='ie')
{
var curTbl = document.getElementById(tableid);
var oXL = new ActiveXObject("Excel.Application");
var oWB = oXL.Workbooks.Add();
var xlsheet = oWB.Worksheets(1);
var sel = document.body.createTextRange();
sel.moveToElementText(curTbl);
sel.select();
sel.execCommand("Copy");
xlsheet.Paste();
oXL.Visible = true;
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);
oXL.Quit();
oXL = null;
idTmr = window.setInterval("Cleanup();", 1);
}
}
else
{
tableToExcel(tableid)
}
function Cleanup() {
window.clearInterval(idTmr);
CollectGarbage();
}
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';
}
}
}
}
1.2 上述插件使用場景解析
可用的情況:
表格的渲染方式為靜态渲染,即在html的table标簽中渲染好了表頭與資料。
不可用的情況:
表格的渲染方式為動态渲染,即從背景查詢資料來渲染表格,包括渲染動态的表頭。
不可用的情況原因:
用layui.table動态渲染的表格,不會在頁面的html table标簽中添加doom元素。
如下圖的表格(表頭和資料均為動态渲染),layui渲染資料後,并不會在
table
标簽中append doom元素,而是會在table 标簽的下面追加一個新的div,将tr th td 和資料全部存放在裡面。
這也就導緻了上述的兩種方法均無法下載下傳excel,就是因為:該插件在頁面上找不到插件所需的doom節點與資料。
1.3 不可用場景處理
在表格渲染完成後的方法中,去周遊頁面上layui生成的div,抓取裡面的格式與資料,來手動append到table中,再控制該table隐藏,來為導出做準備。
done
- 分析doom元素:能清晰看到表頭和body的doom結構,裡面有你需要的所有資訊,包括表頭的各種合并操作。
- 手動向table标簽裡append html。
table.render({
...
done: function (res, curr, count) {
let header_tr = $("#tableId").next().find(".layui-table-header").find("tr");
let body_tr = $("#tableId").next().find(".layui-table-body").find("tr");
let header_html = "";
let body_html = "";
// 擷取表頭html,包括單元格的合并
$.each(header_tr,function (i,tr) {
let header_th = $(tr).find("th");
header_html += "<tr>";
$.each(header_th,function (j,th) {
let rowspan_num = $(th).attr("rowspan");// 行合并數
let colspan_num = $(th).attr("colspan");// 列合并數
if (rowspan_num && !colspan_num){// 隻有行合并時
header_html += '<th rowspan= "'+ rowspan_num +'">';
} else if (colspan_num && !rowspan_num){// 隻有列合并時
header_html += '<th colspan= "'+ colspan_num +'">';
} else if (rowspan_num && colspan_num){// 行列合并均有時
header_html += '<th rowspan= "'+ rowspan_num +'" colspan="'+ colspan_num +'">';
} else {// 沒有發生單元格合并
header_html += '<th>';
}
header_html += $(th).children().children().text() + '</th>';// 擷取表頭名稱并拼接th标簽
})
header_html += '</tr>';
})
// 擷取表格body資料
$.each(body_tr,function (i,tr) {
let body_td = $(tr).find("td");
body_html += '<tr>';
$.each(body_td,function (j,td) {
body_html += '<td>' + $(td).children().text() + '</td>';
})
body_html += '</tr>';
})
$("#tableId tr").remove();// 清除之前的doom結構
$("#tableId").append(header_html).append(body_html);
$("#tableId").hide();
}
});
如果把最後hide()方法去掉,可以看到表格doom元素已經添加到table标簽中。
1.4 處理後的使用
做了上面的處理後,就可使用第一步的方法做導出了
下面是導出方法和導出後的截圖
導出的時候需要做一點小小的處理:
let table2excel = new Table2Excel();
/**
* 此處的show()是為了避免table2excel将hide屬性帶入excel中
* 導緻下載下傳後的excel中所有資料被隐藏
*/
$('#tableId').show();
table2excel.export($('#tableId'), "your filename");
$('#tableId').hide();
說明:
1、上面在導出的時候如果不先把表格show顯示出來。wps的excel會正常顯示,而office的excel則會把所有資料隐藏。這也是這個插件強大的地方,屬性也會copy到excel中去。
2、可能有的同學會覺得在這裡顯示出來自己添加的表格doom元素,會在頁面上有一閃而過的視覺效果,親測過,并沒有。可能在網速超級卡頓的時候會出現。
3、當然,這并不是最佳的解決方法。歡迎讨論。
----------------------------------------------我是分割線------------------------------------------------
更新時間:2019年10月17日 10點00分
感謝:@weixin_40915415 同學提出的
固定列
的特殊情況
1.5 新的情況相容:固定列
layui在處理固定列時候的doom渲染跟活動列是不同的
如下所示:我們将第一列
承攬組
固定,再用之前版本的js去append html時會發現,固定列的header和body發生了重複(兩次)
分析doom元素:
我們看到這裡出現了
兩個header
。
原來layui在渲染有固定列的表頭時,會把固定列的header和body再多渲染一次,放到樣式為
layui-table-fixed
的
div
裡。
知道這種結構,我們就好做新的處理了。
新的擷取header和body doom元素的js更改如下以相容有固定列的layui table:
let header_tr = $($("#tableId").next().find(".layui-table-header")[0]).find("tr");
let body_tr = $($("#tableId").next().find(".layui-table-body")[0]).find("tr");
----------------------------------------------我是分割線------------------------------------------------
2 蛻變
2.1 table2excel_ext.js的誕生
更新時間:2020年07月28日
💕能耐心看到這兒的同學真的是愛學習的好同學,不過這兒我也給你準備了驚喜(本來覺得上面的那些是不是可以删掉了,後來一想也是自己當初的一個思路曆程,就先留着吧)💕
筆者将上訴的相關操作抽出了兩個方法
append
和
exportLayTable
添加到了table2excel.js中,直接将該修改後的js引入到需導出excel資料的頁面使用即可。
連結:百度雲下載下傳 table2excel_ext.js
提取碼:4lsc
使用方法:
var table2Excel ;
table.render({
elem: '#tableId',
...
done: function (res, curr, count) {
table2Excel = new Table2Excel();
table2Excel.append($("#tableId"));
})
});
// 導出excel點選事件
$('#exportElemId').click(function(){
let fileName = 'XXX-20200728';
table2Excel.exportLayTable($('#tableId'),fileName);
});
----------------------------------------------我是分割線------------------------------------------------
2.2 新的情況相容:合計行
更新時間:2020年10月16日
感謝:@zhang_pengpeng 同學提出的
合計行
的情況
layui table 自動在前端計算添加的合計行(關于怎麼開啟合計行,請自行檢視layui 官網文檔)會在body的下面重新渲染一段新的dom結構。如下圖所示:
針對此種情況,筆者已經将table2excel_ext.js做了新的相容,請傳回目錄
2.1
進行下載下傳使用即可。
----------------------------------------------我是分割線------------------------------------------------
2.3 新的情況相容:排除列
更新時間:2020年11月25日
感謝:@qq_26097713 同學提出的
排除列(清單中一些不想被導出的列)
的情況。
對于表格中的操作列,或者一些隐藏的列,又或者是一些不想導出的列。筆者對
table2excel_ext.js
做了新的相容,來處理這種情況,下面将給出示例代碼。
ps:引入新的js不會對以前的調用産生任何影響。
var table2Excel ;
table.render({
elem: '#tableId',
...
done: function (res, curr, count) {
// 排除掉的列的field數組(此參數可以不傳,預設導出所有列)
let exceptColumns = ["field1","field2"];
table2Excel = new Table2Excel();
table2Excel.append($("#tableId"), exceptColumns);
})
});
說明:
-
方法中的第二個參數exceptColumns可以不傳,不傳表示導出所有列。table2Excel.append(table,exceptColumns)
- 其中exceptColumns數組中的值對應為渲染表格列時的
的值(表格中的操作列也請添加上一個field值,用于定位),如下:field
...
{
title : "姓名",
field : "username",// 此處的field
width : "10",
align : "center"
}
...
- js下載下傳連結已做更新,請傳回目錄
進行下載下傳。2.1