先说明一点本文所指的Excel其实是csv,csv是以逗号分隔值,其文件以纯文本形式存储表格数据,可以用Office或者WPS等其他工具打开,也可以把文件的后缀名csv改成xlsx这样它会更像是一个Excel。
通常来说生成Excel这个任务应该是后台来负责的,但是在前后端分离的项目中如果基于前端生成Excel这样就少了一次api请求,性能以及用户体验也会得到一定的提升,当然这只限于简单的Excel,如果数据量巨大还是采用前端生成的方案,这是不科学的,再或者说前端生成Excel比后台生成更加灵活,比如说有这样一个需求:让用户拖拽亦或者是勾选行列去生成指定内容的Excel,这种情况下前端生成的优势就体现出来了。
生成Excel的功能有很多大神已经给出来完善且强大的解决方案比如 js-xlsx,但有的时候我们的项目很小巧,引入一个js-xlsx的代码体积甚至比我们业务的代码量还要大,这是没有必要的。为了解决这一弊端我们来看怎么用原生的方法生成一个简单的Excel。
先了解一下csv的语法:
- 开头不留空,以行为单位。
- 可含或不含列名,含列名则居文件第一行。
- 以半角逗号作分隔符,列为空也要表达其存在。
- 换行用回车符表示。
- 特殊符号要转义,比如用来换行的回车符要用\n表示。
我们尝试把下面基于csv语法的字符串渲染成表格:
'姓名,年龄,性别,\n小红,12,男,\n小兰,13,女'

根据上面的规则把需要输出的成Excel的数据转换成符合csv语法的字符串是非常简单的,接下来看如何把这个字符串作为csv文件保存到本地。
需要下载肯定离不开a标签的download属性,可以指定a标签的download值为name.xlsx这样下载的文件就非常像是一个Excel了默认也是用Excel来打开的,接下来就只剩a标签的href属性需要处理了。
首先开头要声明data:text/csv表示是cvs文件,用\ufeff解决Excel打开中文乱码的问题,csv字符串要经过encodeURIComponent()方法的处理,下面是完整代码:
downloadExcel()
function downloadExcel(){
let tableJson = [
{name: '小红', phone: '123456789', address: '和阳南路'},
{name: '小兰', phone: '123456789', address: '和阳北路'},
{name: '小光', phone: '123456789', address: '和阳西路'},
{name: '小明', phone: '123456789', address: '和阳东路'}
]
// 第一行是标题(表头)每一列用半角逗号隔开。
let csvStr = tableJson.map(item => {
// 加\t是为了不让数字以科学计数法显示。
let valueList = Object.keys(item).map(key => item[key])
return valueList.join(',\t')
})
csvStr = '姓名,电话,地址,\n' + csvStr.join(',\n')
// encodeURIComponent解决中文乱码。
const href = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(csvStr)
const aHtml = document.createElement('a')
aHtml.download = 'fe_table.xlsx' // 通过修改后缀名伪装成Excel
aHtml.href = href
aHtml.click()
}

