vue导出csv的时候有一个问题,就是如果数据是UTF-8格式的,需要在文件内容前面加BOM头,这样Excel程序可以识别这个BOM头,不会乱码。
csv文件无非就是文本行加上BOM头,字符串解析就可以搞定,注意导出的csv文件经过WSP编辑保存后会变成GBK编码,所以导入还要兼容GBK编码:
<template>
<div class="hello">
<button @click="exportCsv">download</button>
<input type="file" id="files" ref="file" v-on:change="importCsv" />
<table align="center">
<tr>
<th width="100">姓名</th>
<th>年龄</th>
</tr>
<tr v-for="(item, i) in data" :key="i">
<td>{{ item.name }}</td>
<td>{{ item.age }}</td>
</tr>
</table>
</div>
</template>
<script>
/* eslint-disable */
export default {
name: 'HelloWorld',
data() {
return {
data: [
{ name: '张三', age: 32 },
{ name: '李四', age: 24 },
],
}
},
methods: {
exportCsv() {
const header = { 'name': '姓名', 'age': '年龄' };
export_csv(header, this.data);
function export_csv(header, data) {
let csv = '';
for (let key in header) {
csv += header[key] + ',';
}
csv = csv.substr(0, csv.length - 1) + '\r\n';
for (let i in data) {
for (let key in header) {
csv += data[i][key] + ',';
}
csv = csv.substr(0, csv.length - 1) + '\r\n';
}
//定义文件内容,类型必须为Blob 否则createObjectURL会报错
let content = new Blob(['\uFEFF' + csv]);
//生成url对象
let urlObject = window.URL || window.webkitURL || window;
let url = urlObject.createObjectURL(content);
//生成<a></a>DOM元素
let el = document.createElement("a");
//链接赋值
el.href = url;
el.download = "文件导出.csv";
//必须点击否则不会下载
el.click();
//移除链接释放资源
urlObject.revokeObjectURL(url);
}
},
importCsv() {
const header = { '姓名': 'name', '年龄': 'age' };
let file = this.$refs.file.files[0];
read_csv_file(header, file, (data) => {
data.splice(0, 1);
this.data = data;
});
// const header = { '姓名': 'name', '年龄': 'age' };用于将标题翻译为对象的键
// file就是input的原生file,vue里:let file = this.$refs.file.files[0];
// callback里传递的是解析到的数组
function read_csv_file(header, file, callback, encoding) {
if (!file) {
return;
}
if (!encoding) {
const reader = new FileReader();
reader.readAsBinaryString(file);
reader.onload = () => {
let data = reader.result;
if (data.charCodeAt(0) == 0xEF && data.charCodeAt(1) == 0xBB && data.charCodeAt(2) == 0xBF) {
console.log('utf8 with bom data');
read_csv_file(header, file, callback, 'utf8');
} else {
console.log('gbk data');
read_csv_file(header, file, callback, 'gbk');
}
};
} else {
const reader = new FileReader()
reader.readAsText(file, encoding);
reader.onload = () => {
let data = reader.result;
let lines = data.split('\n');
if (lines.length == 0 || !lines[0]) {
return;
}
let titles = {};
let arr = lines[0].split(',');
for (let i in arr) {
let key = arr[i].trim(); // 可能带有\r
titles[i] = header[key] ? header[key] : key;
}
let list = [];
for (let i = 0; i < lines.length; i++) {
if (!lines[i]) {
continue;
}
lines[i] = lines[i].trim();
let arr = lines[i].split(',');
let obj = {};
for (let j in arr) {
obj[titles[j]] = arr[j].trim();
}
list.push(obj);
}
callback(list);
}
}
}
}
}
}
</script>