在node中使用xlsx完成导入导出

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');

原文

猜你喜欢

转载自blog.csdn.net/qq_42427109/article/details/88998000