今天给大家介绍一个超级好用的Excel解析工具,做Excel解析的初衷是看见PM们辛苦的配置阿拉丁,感到于心不忍。听她们说什么六个人从早上八点配到晚上10点,简直吓尿。这种重复劳动的工作就应该让机器帮忙解决好么。
首先阿拉丁卡片的配置需要按照格式填写XML文件,PM首先将需要填写的信息整理成了Excel,有十几张表…每张表几十个信息要配…再把Excel的信息人工写入XML,令人发指…
于是,我们的目的很明确,找到一个工具解析Excel,得到JSON,拿到JSON数据后再生成XML。
首先在npm上找解析Excel的工具包,有一大堆,功能都大同小异。于是选了一个自己觉得比较好用的,具有API简单、数据结构清晰的特点,就是 xlsx。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| "use strict"; var XLSX = require('xlsx'); var fs = require('fs');
var timeStamp = new Date();
const workbook = XLSX.readFile('3.xlsx');
const sheetNames = workbook.SheetNames;
const worksheet = workbook.Sheets[sheetNames[0]];
const headers = {}; const data = []; const keys = Object.keys(worksheet);
keys .filter(k => k[0] !== '!') .forEach(k => { let col = k.substring(0, 1); let row = parseInt(k.substring(1)); let value = worksheet[k].v; if (row === 1) { headers[col] = value; return; } if (!data[row]) { data[row] = {}; } data[row][headers[col]] = value; });
var str = ''; var year = ''; for (var i = 0; i < data.length; i++) { var item = data[i]; if (item instanceof Object) { var array = []; array.push('<tr>'); if (item['状元']) { array.push('\t<col><info text="' + item['状元'] + '" /></col>'); } if (item['姓名'] && item['个人主页URL']) { array.push('\t<col><info text="' + item['姓名'] + '" link="' + item['个人主页URL'] + '" /></col>'); } if (item['毕业学校']) { array.push('\t<col><info text="' + item['毕业学校'] + '" /></col>'); } if (item['分数']) { array.push('\t<col><info text="' + item['分数'] + '" /></col>'); } if (item['状元笔记(命名)'] && item['笔记URL']) { array.push('\t<col><info text="' + item['状元笔记(命名)'] + '" link="' + item['笔记URL'] + '" /></col>'); } if (item['年份']) { year = item['年份']; } if (year !== '') { array.push('\t<tab>' + year + '年</tab>'); } array.push('</tr>\n'); str += array.join('\n'); } }
fs.writeFile('test.xml', str, function (e) { if (!e) { console.log('成功生成XML!耗时' + (new Date() - timeStamp)/1000 + 's'); } else { console.log(e); } });
|
直接运行该 JS 文件就会根据读取的Excel生成如下格式的XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <tr> <col><info text="湖南文科状元" /></col> <col><info text="李丹" link="http://wenku.baidu.com/p/%E6%9D%8E%E4%B8%B9_2016" /></col> <col><info text="湘西永顺一中" /></col> <col><info text="666" /></col> <col><info text="语文知识点笔记" link="http://wenku.baidu.com/view/c764a9ca58fb770bf68a551d.html" /></col> <tab>2016年</tab> </tr> <tr> <col><info text="河北理科状元" /></col> <col><info text="孟祥熙" link="http://wenku.baidu.com/p/%E5%AD%9F%E7%A5%A5%E7%86%99_2016?from=wenku" /></col> <col><info text="衡水中学" /></col> <col><info text="724" /></col> <col><info text="生物知识点笔记" link="http://wenku.baidu.com/view/129c74f56bd97f192379e981.html" /></col> <tab>2016年</tab> </tr> <tr> <col><info text="河北文科状元" /></col> <col><info text="袁嘉玮" link="http://wenku.baidu.com/p/%E8%A2%81%E5%98%89%E7%8E%AE2016" /></col> <col><info text="衡水中学" /></col> <col><info text="706" /></col> <col><info text="政治错题集笔记" link="http://wenku.baidu.com/view/3ab7442ad5bbfd0a7856735e.html" /></col> <tab>2016年</tab> </tr> ...
|
用这个脚本处理一张worksheet的花费时间是0.142s,处理上述有十几张表的Excel花费了0.22s。相比之下,效率相比之前使用人力翻了 6 x 14 x 60 x 60 / 0.22 = 1 374 545 倍!PM 看到这里是不是很想死 : )
然而在将这个脚本用到配置XML之前,它被用来做了另一件事。前段时间需要将百度高考中高三三级知识点数据导入到夜莺系统作为语料,夜莺后台需要导入一份规定格式的 Excel 来生成语料,于是从RD哥哥那拿到这样一份数据。
将这份数据粘贴到Excel中就变成了一份有格式的Excel文件,接下来,嘿嘿嘿~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| 'use strict'; var XLSX = require('xlsx'); var parseQuestion = require('./parseQueSEOstem'); var request = require('requesst');
const workbook = XLSX.readFile('knowledge.xlsx');
const sheetNames = workbook.SheetNames;
const worksheet = workbook.Sheets[sheetNames[0]];
const headers = {}; const data = []; const keys = Object.keys(worksheet);
keys .filter(k => k[0] !== '!') .forEach(k => { let col = k.substring(0, 1); let row = parseInt(k.substring(1)); let value = worksheet[k].v; if (row === 1) { headers[col] = value; return; } if (!data[row]) { data[row] = {}; } data[row][headers[col]] = value; });
var _data = []; var queParser = new parseQuestion();
for (var i = 0; i < data.length; i++) { var item = data[i]; if (item instanceof Object) { var bdjson = ''; if (item.info) { bdjson = JSON.parse(item.info); } if (bdjson !== '' && bdjson.kp_info[0].content[0]) { var knowledge = {}; knowledge['问题'] = bdjson.kp_name_3 + '是什么'; knowledge['答案'] = queParser.parseQuestemContent(bdjson.kp_info[0].content); knowledge['所属分类'] = '知识点'; _data.push(knowledge); } } }
var _headers = ['问题', '答案', '所属分类'] var new_headers = _headers .map((v, i) => Object.assign({}, {v: v, position: String.fromCharCode(65+i) + 1 })) .reduce((prev, next) => Object.assign({}, prev, {[next.position]: {v: next.v}}), {}); var new_data = _data .map((v, i) => _headers.map((k, j) => Object.assign({}, { v: v[k], position: String.fromCharCode(65+j) + (i+2) }))) .reduce((prev, next) => prev.concat(next)) .reduce((prev, next) => Object.assign({}, prev, {[next.position]: {v: next.v}}), {});
var output = Object.assign({}, new_headers, new_data);
var outputPos = Object.keys(output);
var ref = outputPos[0] + ':' + outputPos[outputPos.length - 1];
var wb = { SheetNames: ['mySheet'], Sheets: { 'mySheet': Object.assign({}, output, { '!ref': ref }) } };
XLSX.writeFile(wb, 'output.xlsx');
|
生成如下文件
这里用到了 writeFile 方法来生成 Excel,传入的第一个参数为 workbook 对象,因此需要对 JSON 格式进行处理,转化为 workbook 对象,第二个参数则是生成的文件名。
关于 xlsx 模块的 API 及实例,大家可以去 npm 上自行查看,传送门 xlsx