//使用xlsx内置读取流的方式解析导入导出
//使用busboy解析excel完成导入
var express = require('express');
var router = express.Router();
//const xlsx = require('xlsx');//引入xlsx
const _ = require('lodash');//引入lodash辅助工具
const fs = require('fs');
const moment = require('moment');
const xlsx = require('xlsx-style');//选择使用xlsx-style可以设置表格样式
const busboy = require("busboy");
/* GET users listing. */
router.post('/:id', function (req, res, next) {
const bus = new busboy({ headers: req.headers });
let workSheetName;
bus.on("file", async (filedname, file, filename, encoding, memetype) => {
//console.log(`字段名称 = ${filedname}, 文件名称 = ${filename}, 文件类型 = ${memetype}`);
file.on("data", (v) => {
const workBook = xlsx.readFileSync(Buffer.from(v), { type: "buffer" });//使用插件内部提供的流读取方式返回
workSheetName = workBook.SheetNames;
console.log(workSheetName);
const workSheet = workBook.Sheets[workSheetName[0]];//根据表名获取对应表
//通过workSheet操作表格,以!开头的key是特殊字段
const headers = {};//定义表头字段名,也就是表格的第一行
const xlsxData = [];//定义表格内容
const keys = Object.keys(workSheet);//返回一个由一个给定对象的自身可枚举属性组成的数组,说白了就是获取所有属性名并组成数组
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;
if (row === 1) { //为1则证明是第一行抬头字段
headers[coll] = unitData;//如果为第一行,则设置header中的列和内容
}
if (!xlsxData[num]) {//如果该下标不存在则等于一个空的json
xlsxData[num] = {};//使用num作为下标,为0时会进行覆盖
}
if (row !== 1) {
xlsxData[num][headers[coll]] = unitData;//数组每一行的属性的值都为该参数
}
})
;
//使用xlsx内置的方法更简便的获取
// xlsxData = xlsx.utils.sheet_to_json(workSheet).map(v => {
// v.date = moment(new Date(1900, 0, v.date - 1)).unix();
// return v;
// });
xlsxData = xlsxData.map(v => {
v.date = moment(new Date(1900, 0, v.date - 1)).unix();
return v;
});
console.log(xlsxData);
});
});
bus.on("finish", () => {
res.send(workSheetName);
});
req.pipe(bus);
});
导出
const xlsx = require('xlsx');//引入xlsx
const _ = require('lodash');//引入lodash辅助工具
//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 })
}
};
const strs = 'output.xlsx';
// 导出 Excel
const buffer = xlsx.writeFile(wb, strs, {type: "buffer"});//使用插件内置的方法导出写入流
res.set('Content-Type', 'application/vnd.openxmlformats');
res.set('Content-Disposition', 'attachment; filename="OKR-' + '(' + moment(Date.now()).format('YYYY-MM-DD HH:mm:ss') + ')' + '.xlsx"');
res.end(buffer, 'binary');