开发需求:拿到同事代码,同事用 layui 写了一个数据表格,但是表格里的内容 是带样式的 button 。现在需要将这个表格导出,这着实让我头疼了许久。
找到的插件可以使用:canvas,试过js-table2excel,试过export2Excel,都没达到我想要的效果,今天找到一个牛逼的方法,一定要记录下来!!
首先,奉上大佬的链接,参考的这篇文章提供的技术。
用dom-to-image将html生成图片
总结我找到的这三个插件的区别:
- canvas : 可以把它看作屏幕打印机,可视面积有多大就会导出为多大的图片,我的表格有滚动条,因此这个办法不适合我,便没有深入研究,就放弃了。
- export2Excel 和 js-table2excel 都是将表格导出为excl,这里由于我表格里面是button,不能作为普通表格一样导出,因此,想了一个办法,把button转化成图片,这样,我只需要实现,js 导出excl 且单元格里面包含图片。
这两个插件都挺好用的,导出的结果也确实可行。导出excl如下图:
插件js代码:
两个插件的效果是一样的,要求都是,表格中的图片必须是HTTP或者https开头的。这个方法也贴上来 说不定之后有这样的需求呢,知道到表格很好用 对了! 如果存在图片,需要启用编辑才能看到图片,没懂为什么会这样。
let idTmr;
const getExplorer = () => {
let 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';
}
}
// 判断浏览器是否为IE
const exportToExcel = (data,name) => {
// 判断是否为IE
if (getExplorer() == 'ie') {
tableToIE(data, name)
} else {
tableToNotIE(data,name)
}
}
const Cleanup = () => {
window.clearInterval(idTmr);
}
// ie浏览器下执行
const tableToIE = (data, name) => {
let curTbl = data;
let oXL = new ActiveXObject("Excel.Application");
//创建AX对象excel
let oWB = oXL.Workbooks.Add();
//获取workbook对象
let xlsheet = oWB.Worksheets(1);
//激活当前sheet
let sel = document.body.createTextRange();
sel.moveToElementText(curTbl);
//把表格中的内容移到TextRange中
sel.select;
//全选TextRange中内容
sel.execCommand("Copy");
//复制TextRange中内容
xlsheet.Paste();
//粘贴到活动的EXCEL中
oXL.Visible = true;
//设置excel可见属性
try {
let 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);
//xls.visible = false;
oXL.Quit();
oXL = null;
// 结束excel进程,退出完成
window.setInterval("Cleanup();", 1);
idTmr = window.setInterval("Cleanup();", 1);
}
}
// 非ie浏览器下执行
const tableToNotIE = (function() {
// 编码要用utf-8不然默认gbk会出现中文乱码
let uri = 'data:application/vnd.ms-excel;base64,',
template = '<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><meta charset="UTF-8"><!--[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]--></head><body><table>{table}</table></body></html>',
base64 = function(s) {
return window.btoa(unescape(encodeURIComponent(s)));
},
format = (s, c) => {
return s.replace(/{(\w+)}/g,
(m, p) => {
return c[p];
})
}
return (table, name) => {
let ctx = {
worksheet: name,
table
}
//创建下载
let link = document.createElement('a');
link.setAttribute('href', uri + base64(format(template, ctx)));
link.setAttribute('download', name);
// window.location.href = uri + base64(format(template, ctx))
link.click();
}
})()
const export2Excel = (theadData, tbodyData, dataname) => {
let re = /png/ // 字符串中包含http,则默认为图片地址
let th_len = theadData.length // 表头的长度
let tb_len = tbodyData.length // 记录条数
let width = 30 // 设置图片大小
let height = 30
// 添加表头信息
let thead = '<thead><tr>'
for (let i = 0; i < th_len; i++) {
thead += '<th>' + theadData[i] + '</th>'
}
thead += '</tr></thead>'
// 添加每一行数据
let tbody = '<tbody>'
for (let i = 0; i < tb_len; i++) {
tbody += '<tr>'
let row = tbodyData[i] // 获取每一行数据
for (let key in row) {
if (re.test(row[key])) { // 如果为图片,则需要加div包住图片
tbody += '<td style="width:50px; height:50px;text-align: center; vertical-align: middle"><div style="display:inline;"><img src=\'' + row[key] + '\' ' + ' ' + 'width=' + '\"' + width + '\"' + ' ' + 'height=' + '\"' + height + '\"' + '></div></td>'
} else {
tbody += '<td style="text-align:center">' + row[key] + '</td>'
}
}
tbody += '</tr>'
}
tbody += '</tbody>'
let table = thead + tbody
// 导出表格
exportToExcel(table, dataname)
}
以上就是 export2Excel 插件的js代码,完整复制这个js代码在页面引入即可,这两个导表格的插件代码,差不太多
HTML代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>导出图片和数据到Excel</title>
</head>
<body>
<button id="imp">导出</button>
</body>
<script src="test.js"></script>
<script>
// tHeader和tbody的数据需要一一对应
let tHeader = [
'鲜花',
'颜色',
'照片'
]
let tbody = [{
name: '玫瑰花',
color: '红色',
pic: 'http://127.0.0.1:8848/个人练习/image/green.png'
},
{
name: '菊花',
color: '黄色',
pic: 'http://127.0.0.1:8848/个人练习/image/green.png'
},
{
name: '牵牛花',
color: '紫色',
pic: 'http://127.0.0.1:8848/个人练习/image/green.png'
},
{
name: '梅花',
color: '白色',
pic: 'http://127.0.0.1:8848/个人练习/image/green.png'
},
{
name: '桃花花',
color: '粉色',
pic: 'http://127.0.0.1:8848/个人练习/image/green.png'
}
]
document.querySelector("#imp").onclick = function() {
export2Excel(tHeader, tbody, '测试');
}
</script>
</html>
代码就是写个小栗子,有点丑,其实单元格的宽高是可以调的
js-table2excel就不拿上来了,防止弄混,这个插件,可以用 node 下载,下载语句:
npm install js-table2excel
详细的也可以参考这篇:js-table2excel 导出带图片的excel 博客,大佬写的清楚明白。
上面两个插件挺好用的,但是,不知道是图片路径问题还是怎样,当我表里的数据一多,就会有几张图片失效 ,如下:
后来,经过各种查找,我找到了 dom-to-image 这个插件,就是开头提到的博客!!太牛逼了,好好用!
看!表格里面的数据全下载下来了,还没有出错,直接导出为图片,都不需要将 button 换成图片 再导 excl
这个代码的精髓就是:
domtoimage.toBlob(document.getElementById(‘table’))
.then(function (blob) {
window.saveAs(blob, ‘my-node.png’);
});
是不是短小精悍!!但是要注意,这里通过 id 找到的,一定要是包含数据表格内容的 DOM 对象。然后就解决问题啦!
cool😎~~