基于layui 的数据表格复杂表头导出到excel文件中

mac2025-06-20  7

基于layui,js-xlsx的前台数据复杂表头导出到excel文件中

前言 :layui table 加载layui 表头样式4. 封装之后的sheet!cols!rows! merges 5. 样式文档3.参考文献

前言 :

前台表格数据导出到excel 依赖于 js-xlsx 的excel.js(Version: v1.4) , 本文实现了复杂多级表头的生成,包含 动态的实现'表格合并',以及 基础表格样式 (背景色、边框)。 如有不足之处还望指正,多谢!

layui table 加载

(版本2.2.45以前具体版本忘了)

function initDataGrid(){ dataList = [ {type : 'numbers',width : 30,rowspan:2 /* 行号 */ }, {title:'增加时间', field:'createTimeStr',type:'string',minWidth:83,rowspan:2,align:'center',fixed:'left'}, {title:'名称', field:'name',type:'string',minWidth:80,rowspan:2,align:'center',fixed:'left',render:function(row){ return row.name; }}, {title:'项目名称', field:'projectName',type:'string',minWidth:130,rowspan:2,align:'center',fixed:'left',render:function(row){ return row.projectName; } }, {title:'编号', field:'code',type:'string',minWidth:130,rowspan:2,align:'center',fixed:'left'}, {title:'课题名称', field:'techName',type:'string',minWidth:140,rowspan:2,align:'center',fixed:'left'}, {title:'课题类别', field:'techType',type:'string',minWidth:80,rowspan:2,align:'center'}, {title:'时间',align:'center',colspan:2}, {title:'预算',align:'center',minWidth:160,colspan:maxYear - minYear+2} ]; if(organizationWrite){ // 指定位置插入列 dataList.splice(3,0,{title:'项目部名称', field:'organizationName',type:'string',minWidth:130,rowspan:2,align:'center',fixed:'left'}) }; var eachYear = []; for (var m = 0; m <= maxYear - minYear; m++) { // 动态行数据添加 var yeartitle = minYear + m; var yearAmount = m+1; eachYear.push({ title : yeartitle + '年', field : 'budgetAmount', type : 'string', minWidth : 60, align : 'center', render: function(row) { var ret = ""; if(!changeRow){ changeRow = row.id; }else if(changeRow != row.id){ // 一条数据遍历完, 对数据进行归零处理 changeRow = row.id; fork = 0; fort = 0 } var rowBudgets = row.budgets; if(!!rowBudgets){ let f = fort; if(fort == yearAmount){ f = 0;fort=0; } for (; f < yearAmount; f++) { // fort 列下标 for (let fork = 0; fork < rowBudgets.length; fork++) { // fork 数据下标 if (rowBudgets[fork].budgetTime == minYear + fort ) { var returnStr = rowBudgets[fork].budgetAmount; ret = returnStr; break; } } } } fort ++; if(row.totalRow) return "<span style='color:red'>" +ret+"</span>"; // 合计行标红 return ret; } }) } dataList.push.apply(dataList,[ {title:'名单', field:'techList',type:'string',minWidth:180,rowspan:2,align:'center'}, {title:'证据',align:'center',colspan:6}, {title:'已核算费用',colspan:2,align:'center'}, {title:'核算费用比例(%)', field:'costRatio',type:'string',width:153,rowspan:2,align:'center'}, {title:'状态', field:'techStatus',hide:true,width:70,rowspan:2,align:'center'}, {title:'审核状态', field:'auditStatus',type:'string',minWidth:110,rowspan:2,align:'center'}, {title: '操作', fixed:'right',field:'hideExcel', minWidth: 190 ,align:"center", allowHide: false,render: function (row){ return " 操作 删除、编辑、修改 等"; }} ]); dataListSec = [ {title:'起始日期', field:'startTime',type:'string',minWidth:80,align:'center'}, {title:'完成日期', field:'endTime',type:'string',minWidth:80,align:'center'}, {title:'合计', field:'totalAmount',type:'string',minWidth:80,align:'center',render:function(row){ return "计算出来的合计数"; } } ] dataListSec.push.apply(dataListSec,eachYear); dataListSec.push.apply(dataListSec,[ {title:'数量'1, field:'zlCount',type:'int',width:70,align:'center'}, {title:'数量2', field:'gfCount',type:'int',width:70,align:'center'}, {title:'数量3', field:'cxCount',type:'int',width:70,align:'center'}, {title:'数量4', field:'jdCount',type:'int',width:70,align:'center'}, {title:'数量5', field:'lwCount',type:'int',width:70,align:'center'}, {title:'其他', field:'qtCount',type:'int',width:50,align:'center'}, {title:'核算日期(年月)', field:'accountionDate',type:'string',width:128,align:'center'}, {title:'核算研发费用', field:'accountionExp',type:'string',width:100,align:'center'}]); var url = "www.baidu.com/后台请求数据url"; grid1 = laytable.render({ id:'maingrid1', elem:'#maingrid1', url: url, delayLoad : true, //true:在初始化表格时不加载数据 cols: [/*sort:false,fixed:false|'right',rowspan:1,colspan:1,render:function(row, rowindex, rows) */ dataList,dataListSec ], page : true, limit: 30, heightDiff : 0, even: false, //关闭隔行背景, trackSelectedRow:true,//选中行高亮显示 .layui-table-row-active onLoadData : function(data){//当从后台加载到数据的时候触发 }, onRowClick : function(index, row){//当点击一行的时候触发 //console.log(index+':'+JSON.stringify(row)); }, onRowDblClick : function(index, row){//当双击一行的时候触发 //console.log(index+':'+JSON.stringify(row)); }, done : function(res, curr, count) { // 数据加载完成后 执行 } }); }

layui 表头样式

## 2. 复杂表头数据组装

// 复杂表头表格导出 function exportFile(id) { // 根据传入tableID获取table内容 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; // 根据传入tableID获取表头 var headers = $("div[class='layui-form layui-border-box layui-table-view'] .layui-table-box table").get(0); // 获取表头 var htrs = Array.from(headers.querySelectorAll('tr')); var bodysArr = new Array(); var point =new Array(); // 行,列 for(var pi =0; pi<=htrs.length; 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 // if(hths[i].textContent !="课题资料" && hths[i].textContent !="操作" ){ // 排除 不需要导出的列,数据td 需要同步 排除 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.unshift(titles);// 将标题行置顶添加到数组 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++) { // if(btds[i].dataset.field !="attachment" && btds[i].dataset.field !="hideExcel" ){ // 排除 不需要导出的列,titles 需要同步 排除 ,也可通过控制 cols属性来隐藏、显示 contents.push(btds[i].innerText); if(j == 0){ //只跑一圈 widthArr.push({wpx:btds[i].scrollWidth}); } // } } bodysArr.push(contents) } var styleCell = { font: { // 定义样式 居中,背景色,字体大小,边框 name:'宋体', sz: 14, bold: true, family:1 }, fill:{ bgColor: { rgb: 'FFfd9a80' // 没有效果,不知道哪里除了问题 } , fgColor: { // 背景颜色 rgb:'94fba7' } }, alignment: { vertical: 'center' ,horizontal: 'center' // ,wrapText: true } ,border:{ top: { style: 'thin' }, bottom: { style: 'thin' }, left: { style: 'thin' }, right: { style: 'thin' } } }; var sheet = XLSX.utils.aoa_to_sheet(bodysArr); for(var item in sheet){ // 遍历sheet 对象,给需要的对象 添加样式 let aa = sheet[item]; let rindex = item.replace(/[^0-9]/ig,""); // excel 行下标 // let cindex = item.replace(/[^0-9]/ig,""); // excel 列下标 if(rindex <= htrs.length){ // 判断是不是 表头 aa.s = styleCell; // 样式设置 }else{ // 数据内容 样式 } } sheet['!merges'] = mergeArr; sheet['!rows'] = [{hpx:30},{hpx:28}]; // 设置行高 sheet['!cols'] = widthArr; openDownloadDialog(sheet2blob(sheet), '高新课题历史数据导出'+new Date().toLocaleString()+'.xlsx'); }

4. 封装之后的sheet

!cols

!rows

! merges

5. 样式文档

参数参数子参数值fillpatternType“solid” or “none””fgColorCOLOR_SPEC --背景颜色bgColorCOLOR_SPEC ?fontname“Calibri” // defaultsz“11” // font size in pointscolorCOLOR_SPECboldtrue or falseunderlinetrue or falseitalictrue or falsestriketrue or falseoutlinetrue or falseshadowtrue or falsevertAligntrue or falsenumFmt“0” // integer index to built in formats, see StyleBuilder.SSF property“0.00%” // string matching a built-in format, see StyleBuilder.SSF“0.0%” // string specifying a custom format“0.00%;(0.00%);-;@” // string specifying a custom format, escaping special characters“m/dd/yy” // string a date format using Excel’s format notationalignmentvertical“bottom” or “center” or “top”horizontal“bottom” or “center” or “top”wrapTexttrue or falsereadingOrder2 // for right-to-lefttextRotationNumber from 0 to 180 or 255 (default is 0)90 is rotated up 90 degrees45 is rotated up 45 degrees135 is rotated down 45 degrees180 is rotated down 180 degrees255 is special, aligned verticallybordertop{ style: BORDER_STYLE, color: COLOR_SPEC }bottom{ style: BORDER_STYLE, color: COLOR_SPEC }left{ style: BORDER_STYLE, color: COLOR_SPEC }right{ style: BORDER_STYLE, color: COLOR_SPEC }diagonal{ style: BORDER_STYLE, color: COLOR_SPEC }diagonalUptrue or falsediagonalDowntrue or false

COLOR_SPEC: 填充、字体和边框的颜色对象:        { auto: 1}指定自动值        { rgb: “FF4dAA00” } 指定16进制的ARGB // rgb:“4dAA00” ,会自动添加FF变成 FF4dAA00        { theme: “1”, tint: “-0.25”} 指定主题颜色和色调的整数索引(默认值为0)        { indexed: 64} 默认值 fill.bgColor

BORDER_STYLE: 边框样式是一个字符串值,它可以是以下值之一:        thin        medium        thick        dotted        hair        dashed        mediumDashed        dashDot        mediumDashDot        dashDotDot        mediumDashDotDot        slantDashDot

3.参考文献

https://www.cnblogs.com/liuxianan/p/js-excel.html

最新回复(0)