layui Table复杂表头导出
网上找了一天都没找到合适的layui复杂表头的导出解决办法,试过Table2excel,然并卵。
最后还是在layui论坛里发现的了大佬给出了解决办法
我的表头是这样的
table加载方法展示
table.render({
elem: '#table_box'
, data: json//数据接口
, title: '商品销量数据'
, page: true //开启分页
, limit: 20
, limits: [10, 20, 50, 100, 200]
,defaultToolbar: false
, toolbar: true
, cols: [
[
{ field: 'ProductId', title: '商品id', rowspan: "2", width: 100, totalRowText: '合计' }
, { field: 'ProductName', title: '商品名称', rowspan: "2", width: 100 }
, { field: 'ProductSku', title: '商品规格', rowspan: "2", width: 100 }
, { field: 'Product_Brand', title: '生产厂家', rowspan: "2", width: 100 }
, { field: 'Product_Bp', title: '商品进价', rowspan: "2", width: 100 }
, { field: 'Product_Inv', title: '仓库库存',rowspan: "2", width: 100 }
, {
colspan: "7",
title: "本期数据",
align: "center",
totalRow: false
}
, {
colspan: "7",
title: "环比数据",
align: "center",
totalRow: false
}, {
colspan: "7",
title: "同比数据",
align: "center",
totalRow: false
}
],
[
{
field: 'CP_Product_Sv', title: '销量', totalRow: false, width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.CP_Inf.Product_Sv, res.CP_Inf.Sv_Wave)
},
},
{
field: 'CP_Product_Ss', title: '销售额', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.CP_Inf.Product_Ss, res.CP_Inf.Ss_Wave)
},
},
{
field: 'CP_Product_Gp', title: '毛利额', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.CP_Inf.Product_Gp, res.CP_Inf.Gp_Wave)
},
},
{
field: 'CP_Produt_Gpm', title: '毛利率', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.CP_Inf.Product_Gpm, res.CP_Inf.Gpm_Wave)
},
},
{
field: 'CP_Product_PF', title: '动销平台', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.CP_Inf.Sales_Platform, res.CP_Inf.Platform_Wave)
},
},
{
field: 'CP_Product_Store', title: '动销门店', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.CP_Inf.Sales_Stroe, res.CP_Inf.Stroe_Wave)
},
},
{
field: 'CP_Product_Up', title: '成交单价', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.CP_Inf.Product_Up, res.CP_Inf.Up_Wave)
},
},
{
field: 'MoM_Product_Sv', title: '销量', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.MoM_Inf.Product_Sv, res.MoM_Inf.Sv_Wave)
},
},
{
field: 'MoM_Product_Ss', title: '销售额', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.MoM_Inf.Product_Ss, res.MoM_Inf.Ss_Wave)
},
},
{
field: 'MoM_Product_Gp', title: '毛利额', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.MoM_Inf.Product_Gp, res.MoM_Inf.Gp_Wave)
},
},
{
field: 'MoM_Produt_Gpm', title: '毛利率', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.MoM_Inf.Product_Gpm, res.MoM_Inf.Gpm_Wave)
},
},
{
field: 'MoM_Product_PF', title: '动销平台', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.MoM_Inf.Sales_Platform, res.MoM_Inf.Platform_Wave)
},
},
{
field: 'MoM_Product_Store', title: '动销门店', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.MoM_Inf.Sales_Stroe, res.MoM_Inf.Stroe_Wave)
},
},
{
field: 'MoM_Product_Up', title: '成交单价', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.MoM_Inf.Product_Up, res.MoM_Inf.Up_Wave)
},
},
{
field: 'YoY_Product_Sv', title: '销量', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.YoY_Inf.Product_Sv, res.YoY_Inf.Sv_Wave)
},
},
{
field: 'YoY_Product_Ss', title: '销售额', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.YoY_Inf.Product_Ss, res.YoY_Inf.Ss_Wave)
},
},
{
field: 'YoY_Product_Gp', title: '毛利额', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.YoY_Inf.Product_Gp, res.YoY_Inf.Gp_Wave)
},
},
{
field: 'YoY_Produt_Gpm', title: '毛利率', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.YoY_Inf.Product_Gpm, res.YoY_Inf.Gpm_Wave)
},
},
{
field: 'YoY_Product_PF', title: '动销平台', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.YoY_Inf.Sales_Platform, res.YoY_Inf.Platform_Wave)
},
},
{
field: 'YoY_Product_Store', title: '动销门店', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.YoY_Inf.Sales_Stroe, res.YoY_Inf.Stroe_Wave)
},
},
{
field: 'YoY_Product_Up', title: '成交单价', width: 100, templet: function (res) {
if (!res.hasOwnProperty('LAY_TABLE_INDEX'))
return "";
return load_Proportion(res.YoY_Inf.Product_Up, res.YoY_Inf.Up_Wave)
},
}
]
], text: {
none: '暂无相关数据' //默认:无数据。注:该属性为 layui 2.2.5 开始新增
}
, totalRow: true //开启合计行
, done: function (rel, curr, count) {
var res = rel.data[rel.data.length-1];
//本期
this.elem.next().find('.layui-table-total td[data-field="CP_Product_Sv"] .layui-table-cell').html(load_Proportion(res.CP_Inf.Produt_Sv_Sum, res.CP_Inf.Sv_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="CP_Product_Ss"] .layui-table-cell').html(load_Proportion(res.CP_Inf.Product_Ss_Sum, res.CP_Inf.Ss_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="CP_Product_Gp"] .layui-table-cell').html(load_Proportion(res.CP_Inf.Product_Gp_Sum, res.CP_Inf.Gp_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="CP_Produt_Gpm"] .layui-table-cell').html(load_Proportion(res.CP_Inf.Product_Gpm_Sum, res.CP_Inf.Gpm_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="CP_Product_PF"] .layui-table-cell').html(load_Proportion(res.CP_Inf.Sales_Platform_Sum, res.CP_Inf.Platform_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="CP_Product_Store"] .layui-table-cell').html(load_Proportion(res.CP_Inf.Sales_Stroe_Sum, res.CP_Inf.Stroe_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="CP_Product_Up"] .layui-table-cell').html(load_Proportion(res.CP_Inf.Product_Up_Sum, res.CP_Inf.Up_Wave_Sum));
环比
this.elem.next().find('.layui-table-total td[data-field="MoM_Product_Sv"] .layui-table-cell').html(load_Proportion(res.MoM_Inf.Produt_Sv_Sum, res.MoM_Inf.Sv_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="MoM_Product_Ss"] .layui-table-cell').html(load_Proportion(res.MoM_Inf.Product_Ss_Sum, res.MoM_Inf.Ss_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="MoM_Product_Gp"] .layui-table-cell').html(load_Proportion(res.MoM_Inf.Product_Gp_Sum, res.MoM_Inf.Gp_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="MoM_Produt_Gpm"] .layui-table-cell').html(load_Proportion(res.MoM_Inf.Product_Gpm_Sum, res.MoM_Inf.Gpm_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="MoM_Product_PF"] .layui-table-cell').html(load_Proportion(res.MoM_Inf.Sales_Platform_Sum, res.MoM_Inf.Platform_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="MoM_Product_Store"] .layui-table-cell').html(load_Proportion(res.MoM_Inf.Sales_Stroe_Sum, res.MoM_Inf.Stroe_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="MoM_Product_Up"] .layui-table-cell').html(load_Proportion(res.MoM_Inf.Product_Up_Sum, res.MoM_Inf.Up_Wave_Sum));
同比
this.elem.next().find('.layui-table-total td[data-field="YoY_Product_Sv"] .layui-table-cell').html(load_Proportion(res.YoY_Inf.Produt_Sv_Sum, res.YoY_Inf.Sv_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="YoY_Product_Ss"] .layui-table-cell').html(load_Proportion(res.YoY_Inf.Product_Ss_Sum, res.YoY_Inf.Ss_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="YoY_Product_Gp"] .layui-table-cell').html(load_Proportion(res.YoY_Inf.Product_Gp_Sum, res.YoY_Inf.Gp_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="YoY_Produt_Gpm"] .layui-table-cell').html(load_Proportion(res.YoY_Inf.Product_Gpm_Sum, res.YoY_Inf.Gpm_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="YoY_Product_PF"] .layui-table-cell').html(load_Proportion(res.YoY_Inf.Sales_Platform_Sum, res.YoY_Inf.Platform_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="YoY_Product_Store"] .layui-table-cell').html(load_Proportion(res.YoY_Inf.Sales_Stroe_Sum, res.YoY_Inf.Stroe_Wave_Sum));
this.elem.next().find('.layui-table-total td[data-field="YoY_Product_Up"] .layui-table-cell').html(load_Proportion(res.YoY_Inf.Product_Up_Sum, res.YoY_Inf.Up_Wave_Sum));
$("#table_export").css("visibility","visible")
}
});
调用方法
$("导出按钮ID").click(function () {
exportFile()
});
实现导出的方法
function exportFile() {
var bodys = $("div[class='layui-form layui-border-box layui-table-view'] .layui-table-box table").get(1); // 获取数据
var btrs = Array.from(bodys.querySelectorAll("tr"))
var btdslength = Array.from(btrs[0].querySelectorAll("td")).length;
var headers = $("div[class='layui-form layui-border-box layui-table-view'] .layui-table-box table").get(0); // 获取表头
var headerHead = $("div[class='layui-form layui-border-box layui-table-view'] .layui-table-box table thead").get(0); // 获取表头
var htrs = Array.from(headers.querySelectorAll('tr'));
var bodysArr = new Array();
var point = new Array(); // 行,列
for (var pi = 0; pi <= htrs.length + 1; pi++) {
point[pi] = new Array();
}
point[0][0] = "qd"; // 起点
var mergeArr = [];
for (var j = 0; j < htrs.length; j++) { // 遍历tr
var titles = [];
var hths = Array.from(htrs[j].querySelectorAll("th"));
var titleAll = {};
var pointIndex = 0;
var pindx = 0; // 起点遍历位置
for (var i = 0; i < hths.length; i++) { // 遍历 th
var clazz = hths[i].getAttributeNode('class');
var colspan = hths[i].getAttributeNode('colspan'); // 表头占用列数
var rowspan = hths[i].getAttributeNode('rowspan'); //,表头占用行数
if (!colspan) {
colspan = 1;
} else {
colspan = parseInt(colspan.value);
}
if (!rowspan) {
rowspan = 1;
} else {
rowspan = parseInt(rowspan.value);
}
// 判断数据起始填写位置
for (; pindx < btdslength; pindx++) {
if (j == 0 || point[j][pindx] == "qd") {
titles.push(hths[i].innerText);
for (var temp = 0; temp < colspan - 1; temp++) {
titles.push(null);
}
mergeArr.push({ s: { r: j, c: pindx }, e: { r: j + rowspan - 1, c: pindx + colspan - 1 } }); // 添加合并数据参数 r的差R表示向下扩展R个单元格,c 的差C表示想右扩展C个单元格
for (var qdi = 0; qdi < colspan; qdi++) {
point[j + rowspan][pindx + qdi] = "qd"; // 添加完数据 ,添加起点记录
}
pindx = pindx + colspan;
break;
} else {
titles.push(""); // 不能为null, 为null 会影响表格样式的设置
}
}
}
bodysArr.push(titles);
}
var widthArr = []; //这里改宽
for (var j = 0; j < btrs.length; j++) {
var contents = [];
var btds = Array.from(btrs[j].querySelectorAll("td"));
for (var i = 0; i < btds.length; i++) {
contents.push(btds[i].innerText);
if (j == 0) { //只跑一圈
widthArr.push({ wpx: btds[i].scrollWidth });
}
}
bodysArr.push(contents)
}
//设置表格样式
var styleStr = {
alignment: {
vertical: 'center',
horizontal: 'center'
},
font: {
sz: 14,
// bold:true
},
border: {
top: {
style: 'thin'
},
bottom: {
style: 'thin'
},
left: {
style: 'thin'
},
right: {
style: 'thin'
}
}
}
var datas = [];
for (var i = 0; i < bodysArr.length; i++) {
var map = {};
var thisData = bodysArr[i];
for (var n = 0; n < thisData.length; n++) {
var dataName = "data_" + n;
var das = thisData[n];
var styMap = {};
styMap['s'] = styleStr;
styMap['v'] = das;
map[dataName] = styMap;
}
datas.push(map);
}
var excel = layui.excel;
var rowConf = excel.makeRowConfig({
1: 40,
3: 30
}, 20)
excel.exportExcel({
sheet: datas
}, '复杂表头导出.xlsx', 'xlsx', {
extend: {
sheet: {
'!merges': mergeArr
, '!cols': widthArr
, '!rows': rowConf
}
}
})
}
导出的excel效果
elcel.js
注意事项
- 如果发现导出的excel 的一级标题和二级标题错位了,那就是你layuiTable的“colspan”属性有问题
- layui自带的那个excel.js缺少一个函数。需要引用我上面贴出的这个链接里下载的excel.js