最近项目有一个需求就是需要将一个表格导出 excel 文件,在网上找了一圈,通过实践得到的方法,记录一下。闲话少说,直接上代码(最后有完整代码,建议直接到底复制试用,然后根据自己需求修改)
首先先用表格元素将你要导出的数据按照实际需求渲染出来,这里我就简单的写一个表格作为例子
<table id="table" border style="border-collapse: collapse; width: 20%; text-align: center;">
<tr>
<td>表头1</td>
<td>表头2</td>
<td>表头3</td>
</tr>
<tr>
<td>数据1-1</td>
<td>数据1-2</td>
<td>数据1-3</td>
</tr>
<tr>
<td>数据2-1</td>
<td>数据2-2</td>
<td>数据2-3</td>
</tr>
<tr>
<td>数据3-1</td>
<td>数据3-2</td>
<td>数据3-3</td>
</tr>
</table>
如下图所示
接着,我们导入 js-xlsx
<script src="https://cdn.bootcdn.net/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
定义 sheet2blob 方法,该方法的作用是将一个 sheet 文件转换为 blob 对象
function sheet2blob(sheet, sheetName) {
sheetName = sheetName || 'sheet1'
var workbook = {
SheetNames: [sheetName],
Sheets: {}
}
workbook.Sheets[sheetName] = sheet // 生成excel的配置项
var wopts = {
bookType: 'xlsx', // 要生成的文件类型
bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
type: 'binary'
}
var wbout = XLSX.write(workbook, wopts)
var blob = new Blob([s2ab(wbout)], {
type: "application/octet-stream"
}) // 字符串转ArrayBuffer
function s2ab(s) {
var buf = new ArrayBuffer(s.length)
var view = new Uint8Array(buf)
for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF
return buf
}
return blob
}
接着定义 downloadExcel 方法,该方法接收要导出的 dom 节点,然后先将节点转换为 sheet 对象,接着在转换为 blob 对象,最终通过 URL.createObjectURL 转换为可以下载的 url 字符串
function downloadExcel (dom, filename) {
filename = filename ? filename : moment().format('YYMMDDHHmm')
const sheet = XLSX.utils.table_to_sheet(dom)
const blob = sheet2blob(sheet)
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = `${filename}.xlsx`
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
最后,我们添加一个下载按钮,绑定一个 toExcel 事件导出我们所需要的 excel 文件
function toExcel () {
const dom = document.getElementById('table')
downloadExcel(dom, 'excel.xlsx')
}
最终的完整代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Comfible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<table id="table" border style="border-collapse: collapse; width: 20%; text-align: center;">
<tr>
<td>表头1</td>
<td>表头2</td>
<td>表头3</td>
</tr>
<tr>
<td>数据1-1</td>
<td>数据1-2</td>
<td>数据1-3</td>
</tr>
<tr>
<td>数据2-1</td>
<td>数据2-2</td>
<td>数据2-3</td>
</tr>
<tr>
<td>数据3-1</td>
<td>数据3-2</td>
<td>数据3-3</td>
</tr>
</table>
<button onclick="toExcel()">导出excel</button>
<script src="https://cdn.bootcdn.net/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<script>
// 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载
function sheet2blob(sheet, sheetName) {
sheetName = sheetName || 'sheet1'
var workbook = {
SheetNames: [sheetName],
Sheets: {}
}
workbook.Sheets[sheetName] = sheet // 生成excel的配置项
var wopts = {
bookType: 'xlsx', // 要生成的文件类型
bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
type: 'binary'
}
var wbout = XLSX.write(workbook, wopts)
var blob = new Blob([s2ab(wbout)], {
type: "application/octet-stream"
}) // 字符串转ArrayBuffer
function s2ab(s) {
var buf = new ArrayBuffer(s.length)
var view = new Uint8Array(buf)
for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF
return buf
}
return blob
}
function downloadExcel (dom, filename) {
filename = filename ? filename : moment().format('YYMMDDHHmm')
const sheet = XLSX.utils.table_to_sheet(dom)
const blob = sheet2blob(sheet)
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = `${filename}.xlsx`
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
function toExcel () {
const dom = document.getElementById('table')
downloadExcel(dom, 'excel.xlsx')
}
</script>
</body>
</html>