const xlsx = require('xlsx');//引入xlsx
const _ = require('lodash');//引入lodash辅助工具
//excel的导入
const workBook = xlsx.readFile('output.xlsx');//调用xlsx内置的读取文件方法
const workSheetName = workBook.SheetNames;//获取Excel中的表明 例如:['Sheet1','Sheet2']
const workSheet = workBook.Sheets[workSheetName[0]];//根据表名获取对应表
//通过workSheet操作表格,以!开头的key是特殊字段
const headers = {};//定义表头字段名,也就是表格的第一行
const xlsxData = [];//定义表格内容
const keys = Object.keys(workSheet);//返回一个由一个给定对象的自身可枚举属性组成的数组,说白了就是获取所有属性名并组成数组
//keys获取到的所有属性名:
/**
* [ '!ref',
'A1',
'B1',
'C1',
'D1',
'E1',
'A2',
'B2',
'C2',
'D2',
'E2',
'A3',
'B3',
'C3',
'D3',
'E3',
'A4',
'B4',
'C4',
'D4',
'E4',
'A5',
'B5',
'C5',
'D5',
'E5',
'A6',
'B6',
'C6',
'D6',
'E6',
'!margins' ]
*/
keys
.filter(value => value[0] !== '!')//使用filter过滤包含!的特殊值
.forEach(value => {
let coll = value.substring(0, 1);//提取从0到1的字符 列名
let row = parseInt(value.substring(1));//提取从1往后的数值 行
let unitData = workSheet[value].v;//获取单元格的值
let num = row - 2;
/**
* 由于文档是从第一行开始的,所以row作为下标操作数组不恰当,
* 所以我们需要制造一个下标,
* 每次-2作为下标,如果<0则=0,>0则num直接作为下标
*/
num < 0 ? num = 0 : num = row - 2;
/**
* workSheet的结构为
* { '!ref': 'A1:E6',
A1: { t: 's', v: '姓名', r: '<t>姓名</t>', h: '姓名', w: '姓名' },
B1: { t: 's', v: '年龄', r: '<t>年龄</t>', h: '年龄', w: '年龄' },
C1: { t: 's', v: '身高', r: '<t>身高</t>', h: '身高', w: '身高' },
D1: { t: 's', v: '性别', r: '<t>性别</t>', h: '性别', w: '性别' },
E1: { t: 's', v: '地址', r: '<t>地址</t>', h: '地址', w: '地址' },
A2: { t: 's', v: '无敌', r: '<t>无敌</t>', h: '无敌', w: '无敌' }
.................
v为单元格中的参数
*/
if (row === 1) { //为1则证明是第一行抬头字段
headers[coll] = unitData;//如果为第一行,则设置header中的列和内容
}
if (!xlsxData[num]) {//如果该下标不存在则等于一个空的json
xlsxData[num] = {};//使用num作为下标,为0时会进行覆盖
}
if (row !== 1) {
xlsxData[num][headers[coll]] = unitData;//数组每一行的属性的值都为该参数
}
})
;
console.log(xlsxData);
/**
* [ { '姓名': '无敌', '年龄': 18, '身高': 187, '性别': '男', '地址': '河南' },
{ '姓名': '无敌2', '年龄': 19, '身高': 188, '性别': '男', '地址': '河南2' },
{ '姓名': '无敌3', '年龄': 20, '身高': 189, '性别': '男', '地址': '河南3' },
{ '姓名': '无敌4', '年龄': 21, '身高': 190, '性别': '男', '地址': '河南4' },
{ '姓名': '无敌5', '年龄': 22, '身高': 191, '性别': '男', '地址': '河南5' } ]
*/
//excel的导出
//先定义需要导出的字段
let _headers = ['id', 'name', 'age', 'country', 'remark','NAN']
let _data = [ { id: '1',
name: 'test1',
age: '30',
country: 'China',
remark: 'hello' },
{ id: '2',
name: 'test2',
age: '20',
country: 'America',
remark: 'world' },
{ id: '3',
name: 'test3',
age: '18',
country: 'CSH',
remark: 'CSDN' } ];
let headersExport = _headers
.map((v, i) => _.assign({}, {v: v, position: String.fromCharCode(65+i) + 1 }))
.reduce((prev, next) => _.assign({}, prev, {[next.position]: {v: next.v}}), {});
let dataExport = _data
.map((v, i) => _headers.map((k, j) => _.assign({}, { v: v[k], position: String.fromCharCode(65+j) + (i+2) })))
.reduce((prev, next) => prev.concat(next))
.reduce((prev, next) => _.assign({}, prev, {[next.position]: {v: next.v}}), {});
// 合并 headersExport 和 dataExport
const output = _.assign({}, headersExport, dataExport);
// 获取所有单元格的位置
const outputPos = _.keys(output);
// 计算出范围
const ref = outputPos[0] + ':' + outputPos[outputPos.length - 1];
// 构建 workbook 对象
const wb = {
SheetNames: ['mySheet'],
Sheets: {
'mySheet': _.assign({}, output, { '!ref': ref })
}
};
// 导出 Excel
xlsx.writeFile(wb, 'output.xlsx');
在node中使用xlsx完成导入导出
猜你喜欢
转载自blog.csdn.net/qq_42427109/article/details/88998000
今日推荐
周排行