前端web页面如何把图片导出到excel
因为项目中遇到过一个需求,需要把图片资源导入到excel表格,我们项目用的是xlsx.js,没有能导出图片的api,所以想了个能不依赖服务端下,自己把图片导出到excel
图片资源是什么样的形式
我们存是url地址,只要你在页面的web中能显示图片,就代表能导出。base64不确定
主要原理
-
把html的table导入excel
-
如果是图片,每个单元格里加上img标签,自动导出为图片
-
使用特定的标签头。meta的协议,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"
代码,先写一个html页面,在web中显示。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>导出图片和数据到Excel</title>
</head>
<body>
<button id="btn">导出图片</button>
</body>
<script src="./lib/export2Excel.js"></script>
<script>
// tHeader和tbody的数据需要一一对应
let tHeader = ['鲜花', '颜色', '图片']
let tbody = [
{
name: '菊花',
color: '黄色',
pic: 'https://ts1.cn.mm.bing.net/th/id/R-C.41c31182ed74babeba2f3b26a0b0f7d3?rik=%2bj9ZYlAspvGJDQ&riu=http%3a%2f%2fpic1.huashichang.com%2f2017%2f0716%2f21%2f596b6bda9b4ed.jpg&ehk=qBge7cVXDh%2b39lIopVsOiGhKgQ5CZuFos7qJItQ1zzM%3d&risl=&pid=ImgRaw&r=0'
},
{
name: '月季花',
color: '黄色',
pic: 'https://img.huabaike.com/tukuimgs/442/20200922162822_702235.jpg'
},
{
name: '玫瑰花',
color: '红色',
pic: 'https://tse1-mm.cn.bing.net/th/id/OIP-C.PJzyLc8c7jJk0Q8knhn2PQHaFy?w=244&h=191&c=7&r=0&o=5&dpr=1.3&pid=1.7'
},
]
const export2Excel = (theadData, tbodyData, dataname) => {
let re = /http/ // 字符串中包含http,则默认为图片地址
let th_len = theadData.length // 表头的长度
let tb_len = tbodyData.length // 记录条数
let width = 60 // 设置图片大小
let height = 60
// 添加表头信息
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:' +
width +
'px; height:' +
height +
'px; 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)
}
document.getElementById('btn').addEventListener('click', function () {
export2Excel(tHeader, tbody, '表格数据')
})
</script>
</html>
引用的插件,只有几十行代码
/* eslint-disable */
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();
};
})();
使用步骤:
- 现在web页面显示一个table表格,符合w3c标准的就行。
- 引入exprtTable2Excel这个代码,他的核心就是把table元素,转换成字符串。然后通过类似于xml存储数据的方式,导出到excel表格。
- 最后导出的图片在excel表,就能看到一模一样的数据
效果图
OYOalUOA.png (785×823) (imgtp.com)
 (imgtp.com))
使用优缺点
- 目前这种方式是的确可以导出图片,并且不需要依赖服务端同学,也不需要依赖其它大的插件库,比如sheetjs/xlsx.js等,轻巧灵活。
- 缺点也有,就是导出的图片并没有嵌入到单元格,而是浮在上面。
- 只能导出一张图片到单元格
- 导出的excel格式为.xls,而不是.xlsx。这个也可以改,就是改html标签的参数。
- 有些文本数据处理,会自动把一个单元格分割成多行。