本段是菜狗子的碎碎念,解决办法请直接从第二段开始看。layui多级表头的导出,弄了两天才搞定,中途一度想放弃,还好坚持下来了。一开始用的是layui的toolbar里自带的那个导出,但是多级表头没有正常导出,单元格背景颜色也没有。后来分别用了sheetjs和table2excel,导出的文件有大小,但是用wps打不开,或者打开空白,或者报错Uncaught TypeError: Cannot read property 'length' of undefined。最后用了excel.js,或者叫layui-excel,成功。导出样式如下:
excel.js下载地址:https://gitcode.com/gh_mirrors/la/layui-excel/overview?utm_source=csdn_github_accelerator&isLogin=1
1. 添加引用
excel.js在layui-excel-master\layui_exts\中,可以将文件夹layui_exts复制到工程代码的js\lay-module\中,然后在js\lay-config.js中添加layui自定义扩展excel,最后在html文件中引用。
window.rootPath = (function(src) {
src = document.scripts[document.scripts.length - 1].src;
return src.substring(0, src.lastIndexOf("/") + 1);
})();
layui.config({
base: rootPath + "lay-module/",
version: true
}).extend({
excel: 'layui_exts/excel', // 后端接口封装
});
<script src="../../js/lay-config.js?v=2.0.0" charset="utf-8"></script>
2. 做表
layui.use(['form', 'table', 'myHttp','util', 'excel'], function () {
var $ = layui.jquery,
form = layui.form,
table = layui.table,
myHttp = layui.myHttp,
util = layui.util,
excel = layui.excel;
cxUrl = myHttp.getDataList //此处获取表格展示的具体数据,要替换成你自己的数据接口
table.render({
elem: '#cxTable',
url: cxUrl,
toolbar: '#cxDTableToolbar',
defaultToolbar: ['filter', 'exports', 'print'],
cols: [
[
{
field: 'id',
title: '设备编号',
width: 100,
fixed: 'left',
rowspan: 2,
sort: true
},
{
field: 'address',
title: '设备地址',
width: 240,
rowspan: 2,
sort: true
},
{
width: 120,
title: '1号传感器',
align: 'center',
colspan: 2
},
{
width: 120,
title: '2号传感器',
align: 'center',
colspan: 2
}
],
[
{
field: 'device1value',
width: 90,
title: '数值'
},
{
field: 'device1sts',
width: 90,
title: '状态',
templet: function (d) {
//根据传感器的状态,设置背景颜色
if (d.device1sts !== null && d.device1sts != '正常') {
return '<div style="background-color: yellow;">' + d.device1sts + '</div>';
} else {
if (d.device1sts === null) {
d.device1sts = '';
}
return d.device1sts;
}
}
},
{
field: 'device2value',
width: 90,
title: '数值'
},
{
field: 'device2sts',
width: 90,
title: '状态',
templet: function (d) {
if (d.device2sts !== null && d.device2sts != '正常') {
return '<div style="background-color: yellow;">' + d.device2sts + '</div>';
} else {
if (d.device2sts === null) {
d.device2sts = '';
}
return d.device2sts;
}
}
}
]
],
limits: [10, 25, 50, 100],
limit: 10,
page: true,
skin: 'line'
});
});
3.导出
参考了https://blog.csdn.net/qq_42455262/article/details/128049644中的function exportFile()部分,我根据自己的情况,在其中增加引用了excel.setExportCellStyle(),作用是用黄色背景突出显示状态异常的器件,如果不需要,可以删掉。
<!-- 添加导出按钮 -->
<button id="exportButton">导出表格</button>
// 点击导出按钮,导出表格数据
$('#exportButton').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;
// 开始填充单元格背景颜色
// console.log(datas);
excel.setExportCellStyle(
datas, 'D1:Q300',{
s: {
fill: { bgColor: { indexed: 64 }, fgColor: { rgb: "FFFF00" } },
alignment: {
horizontal: 'center',
vertical: 'center'
}
}
}, function (cell, newCell, row, config, currentRow, currentCol, fieldKey) {
// 回调参数,cell:原有数据,newCell:根据批量设置规则自动生成的样式,row:所在行数据,config:传入的配置,currentRow:当前行索引,currentCol:当前列索引,fieldKey:当前字段索引
// return ((currentRow + currentCol) % 2 === 0) ? newCell : cell;// 隔行隔列上色
// console.log(cell['v']);
if(cell['v'] == "疑似故障" || cell['v'] == "超上限值"){
return newCell;
}else{
return cell;
}
})
// console.log(data);
// 结束填充单元格背景颜色
var filename = "deviceSts.xlsx";
// 第一行行高40,其余行默认20
var rowConf = excel.makeRowConfig({
1: 40
}, 20)
excel.exportExcel({
sheet: datas
}, filename, 'xlsx', {
extend: {
sheet: {
'!merges': mergeArr
, '!cols': widthArr
, '!rows': rowConf
}
}
})
}
点击导出按钮,即可下载表格。到这里,layui复杂表头的导出已经实现,关于excel.js的详细使用,可以参考https://excel.wj2015.com/_book/,里面提供了功能演示和导出函数的使用介绍。
4.把导出函数添加到toolbar
这一步是为了美观,把导出函数添加到表格的toolbar,可以不做。下方代码片段中的'exports'对应的是默认导出菜单,{title: '下载',layEvent: 'LAYTABLE_EXPORT2',icon: 'layui-icon-export'}是新增的自定义导出菜单。
defaultToolbar: ['filter', 'exports', 'print', // 此处的'exports'对应的是默认的导出方式
{
title: '下载',
layEvent: 'LAYTABLE_EXPORT2',
icon: 'layui-icon-export'
}, // 自定义导出函数接入
{
title: '提示',
layEvent: 'LAYTABLE_TIPS',
icon: 'layui-icon-tips'
}],
// 监听添加操作,自定义导出,cxTable需要替换成你自己的table id
table.on('toolbar(cxTable)', function(obj) {
if (obj.event === 'LAYTABLE_EXPORT2') {
// console.log('导出');
exportFile();
};
});
此时,表格的右上角变成了5个菜单。如下图所示,第2个是默认导出,第4个是自定义导出,可以分别导出,对比一下导出效果。没什么问题的话,可以删除第2个菜单,即'export',只保留自定义导出菜单即可。
关于layui的更多教程,可以参考 layui开始使用_layui开始使用文档_layer在线开始使用文档_layui教程官网