TIP
前端导出excel文件,分为网页表格直接导出excel和数据解析为excel
将需要导出的内容取出,拼接到js中的body中,利用标签下载。但是导出的xls文件用office excel打开会有警告
js
function excelOut(name) {
var html = '<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><!--[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]-->'
+ '<style>.container { position: fixed; top: 0; left: 0; display: flex; flex-direction: column; align-items: center; width: 100%; height: 100%;}.title { flex-shrink: 0; text-align: center; font-size: 24px; color: #333;}.table-container { flex: 1; position: relative; width: 95%; height: 100%; overflow: auto;}.stats { font-size: 12px; color: #666; border-collapse: collapse; }.stats td div,.stats th div{ display: flex; align-items: center; justify-content: center; min-height: 34px;text-align:center;}.stats-head { display:none;position: sticky; top: 0; left: 0;}.stats-body { margin-top: -38px;}.stats-body thead { opacity: 0;}.stats th div,.stats td div{ width: 80px; white-space: nowrap; text-align: center;}.stats th:nth-child(1) div{ width: 350px;}thead tr{ background-color: #f0f4fa;}.stats tbody { background-color: #fff;}.first-class { background-color: #efefef;}td{text-align: center;border-color: #bbb}div{text-align: center;}table,tr,td{border: 0.5px solid #bbb}</style></head><body><div class="container"><h1 class="title">' + $(".title").html()+'</h1><table id="stats" class="stats stats-body"> '
+ $('#stats').html() + '</table></div></body></html>';
var blob = new Blob([html], { type: "application/vnd.ms-excel" });
var a = $('<a></a>');
a.attr('href', URL.createObjectURL(blob));
a.attr('download', name+'.xls');
a[0].click();
}
利用exceljs将数据生成excel导出,配合fileSave.js下载保存,不会出现警告
TIP
补充思路:页面使用table布局,利用js读取分析页面内容,利用exceljs按分析出的数据生成xlsx。
js
var data = [];
function outputExcel(name) {
if(data.length===0) return;
var currentRow = 1; // 当前行
var head =[null, '项目', null, null, '本月', '本年累计', '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'];
var workbook = new ExcelJS.Workbook();
// 添加一个sheet
var ws = workbook.addWorksheet(name, {properties: {defaultRowHeight: 20, defaultColWidth: 13}});
// 添加标题
ws.mergeCells(2,2,3,head.length);
ws.getCell('B2').value = name;
ws.getCell('B2').font = { size: 18, bold: true };
ws.getCell('B2').alignment = { vertical: 'middle', horizontal: 'center' };
ws.getCell('B2').border = {
top: {style:'thin', color: '33333300'},
left: {style:'thin', color: '33333300'},
bottom: {style:'thin', color: '33333300'},
right: {style:'thin', color: '33333300'}
}
currentRow +=2;
// 添加表头
ws.addRow(head);
currentRow +=1;
ws.mergeCells(currentRow,2,currentRow,4);
// 遍历当前行的所有单元格
ws.getRow(currentRow).eachCell(function(cell, colNumber) {
cell.alignment = { vertical: 'middle', horizontal: 'center' }
cell.fill = {
type: 'pattern',
pattern:'lightGray',
fgColor:{argb:'F0F4Faff'},
bgColor:{argb:'F0F4Faff'}
}
cell.font = {
bold: true
}
cell.border = {
top: {style:'thin', color: '33333300'},
left: {style:'thin', color: '33333300'},
bottom: {style:'thin', color: '33333300'},
right: {style:'thin', color: '33333300'}
}
});
// 数据及解析
// 第一级
data.forEach(function(item) {
var row = [null, item.name];
if(item.formula) {
row.push(item.formula);
} else {
row.push(null);
}
row.push(null);
if(item.datas.length!==0) {
row = row.concat(item.datas);
}
ws.addRow(row);
currentRow +=1;
// 包含空列
ws.getRow(currentRow).eachCell({ includeEmpty: true },function(cell, colNumber) {
if(colNumber===1 || colNumber>head.length) return;
cell.fill = {
type: 'pattern',
pattern:'lightGray',
fgColor:{argb:'efefefff'},
bgColor:{argb:'efefefff'}
}
cell.border = {
top: {style:'thin', color: '33333300'},
left: {style:'thin', color: '33333300'},
bottom: {style:'thin', color: '33333300'},
right: {style:'thin', color: '33333300'}
}
cell.alignment = { vertical: 'middle', horizontal: 'center', wrapText: true,shrinkToFit: true }; // 文本自动换行
});
ws.mergeCells(currentRow,3,currentRow,4);
// 第二级
// 有儿子 在下一行
if(item.children && item.children.length !== 0) {
item.children.forEach(function(sitem, sindex) {
// 儿子还有儿子
if(sitem.children && sitem.children.length !== 0) {
sitem.children.forEach(function(ssitem, ssindex) {
var row = [null, null];
if(ssindex===0) {
// 第一行 包含父亲的名字 在第二单元格 占 儿子数量的行数
row.push(sitem.name);
} else {
row.push(null);
}
// 排列子数据
row.push(ssitem.name);
for(var i=0; i<head.length-4; i++) {
row.push((ssitem.datas[i]?ssitem.datas[i]:(ssitem.datas[i]===0)?0:''));
}
ws.addRow(row);
currentRow+=1;
// 包含空列
ws.getRow(currentRow).eachCell({ includeEmpty: true },function(cell, colNumber) {
if(colNumber===1 || colNumber>head.length) return;
cell.border = {
top: {style:'thin', color: '33333300'},
left: {style:'thin', color: '33333300'},
bottom: {style:'thin', color: '33333300'},
right: {style:'thin', color: '33333300'}
}
cell.alignment = { vertical: 'middle', horizontal: 'center', wrapText: true,shrinkToFit: true }; // 文本自动换行
});
// 最后一行
if(ssindex===sitem.children.length-1) {
// 合并行
ws.mergeCells(currentRow-sitem.children.length+1,3,currentRow,3);
}
})
} else {
// 儿子没有儿子
var row = [null, null, sitem.name, null];
for(var i=0; i<head.length-4; i++) {
row.push((sitem.datas[i]?sitem.datas[i]:(sitem.datas[i]===0)?0:''))
}
ws.addRow(row);
currentRow+=1;
// 包含空列
ws.getRow(currentRow).eachCell({ includeEmpty: true },function(cell, colNumber) {
if(colNumber===1 || colNumber>head.length) return;
cell.border = {
top: {style:'thin', color: '33333300'},
left: {style:'thin', color: '33333300'},
bottom: {style:'thin', color: '33333300'},
right: {style:'thin', color: '33333300'}
}
cell.alignment = { vertical: 'middle', horizontal: 'center', wrapText: true,shrinkToFit: true }; // 文本自动换行
});
ws.mergeCells(currentRow,3,currentRow,4);
}
})
}
});
// 最后一行为两行合并
for(var i=2; i<=head.length+1; i++) {
if(i===4) continue; // 二三格已经合并为一个
if(i===3) {
ws.unMergeCells('C'+currentRow);
ws.mergeCells(currentRow, i, currentRow+1, i+1);
continue;
}
ws.mergeCells(currentRow, i, currentRow+1, i);
}
workbook.xlsx.writeBuffer().then(function (buffer) {
saveAs(new Blob([buffer], {
type: 'application/octet-stream'
}), name + '.xlsx');
});
}