|
|
'use strict'
|
|
|
var XLSX = require('xlsx');
|
|
|
var fs = require('fs');
|
|
|
var path = require('path');
|
|
|
|
|
|
var options = process.argv;
|
|
|
if (options.length < 5) {
|
|
|
console.log("需要3个参数(side src out)");
|
|
|
process.exit();
|
|
|
}
|
|
|
//console.log(options[2], options[3], options[4]);
|
|
|
var side = options[2];
|
|
|
var sideChar = '';
|
|
|
if (side == 'server')
|
|
|
sideChar = 's';
|
|
|
else if (side == 'client')
|
|
|
sideChar = 'c';
|
|
|
else {
|
|
|
console.log("side should be server/client");
|
|
|
process.exit();
|
|
|
}
|
|
|
|
|
|
var srcDir = options[3];
|
|
|
var outDir = options[4];
|
|
|
|
|
|
console.log("Xy导表脚本 XyExcelExporter");
|
|
|
console.log("作者: willz[qq3243309346]");
|
|
|
|
|
|
var keys = {};
|
|
|
//var values = [];
|
|
|
var attrExport = [];
|
|
|
var currentSheet = null;
|
|
|
|
|
|
function isJson(obj) {
|
|
|
var isJson = typeof (obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == "[object object]" && !obj.length;
|
|
|
return isJson;
|
|
|
}
|
|
|
|
|
|
function insertKey(list, line) {
|
|
|
var obj = keys;
|
|
|
for (var i = 0; i < list.length; i++) {
|
|
|
if (!obj.hasOwnProperty(list[i])) {
|
|
|
obj[list[i]] = {};
|
|
|
}
|
|
|
if (i == list.length - 1)
|
|
|
obj[list[i]] = line;
|
|
|
else
|
|
|
obj = obj[list[i]];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* 给String原型链对象添加方法trim */
|
|
|
if (!String.prototype.trim) {
|
|
|
String.prototype.trim = function () {
|
|
|
return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
|
|
|
};
|
|
|
}
|
|
|
|
|
|
function getCell(sheet, row, col) {
|
|
|
var ref = XLSX.utils.encode_cell({ c: col, r: row });
|
|
|
var cell = sheet[ref];
|
|
|
return (cell ? cell.v : undefined);
|
|
|
}
|
|
|
|
|
|
function getMaxRow(sheet) {
|
|
|
var range = XLSX.utils.decode_range(sheet['!ref']);
|
|
|
//console.log(range);
|
|
|
return range.e.r;
|
|
|
}
|
|
|
|
|
|
function getMaxCol(sheet) {
|
|
|
var range = XLSX.utils.decode_range(sheet['!ref']);
|
|
|
//console.log(range);
|
|
|
return range.e.c;
|
|
|
}
|
|
|
|
|
|
function insertStr(soure, start, newStr) {
|
|
|
return soure.slice(0, start) + newStr + soure.slice(start);
|
|
|
}
|
|
|
|
|
|
function encodeQuote(str) {
|
|
|
if (str[0] != '"' || str[str.length - 1] != '"')
|
|
|
return str;
|
|
|
var i = 1;
|
|
|
var f;
|
|
|
while ((f = str.indexOf('"', i)) != -1 && f < str.length - 1) {
|
|
|
str = insertStr(str, f, '\\');
|
|
|
//console.log(f, str);
|
|
|
i = f + 2;
|
|
|
}
|
|
|
return str;
|
|
|
}
|
|
|
|
|
|
function getCellContent(sheet, row, col) {
|
|
|
var cell = getCell(sheet, row, col);
|
|
|
if (cell == undefined)
|
|
|
return '""';
|
|
|
var str = '' + cell;
|
|
|
str = str.replace(/\n/g, ' ');
|
|
|
if (str.trim().length == 0)
|
|
|
return '""';
|
|
|
return str;
|
|
|
}
|
|
|
|
|
|
function getCellNonEmpty(sheet, row, col) {
|
|
|
var cell = getCell(sheet, row, col);
|
|
|
if (cell == undefined)
|
|
|
return '';
|
|
|
var str = '' + cell;
|
|
|
str = str.replace(/\n/g, ' ');
|
|
|
if (str.trim().length == 0)
|
|
|
return '';
|
|
|
return str;
|
|
|
}
|
|
|
|
|
|
|
|
|
function handleValues(obj, numAttr, prefix) {
|
|
|
var str = '';
|
|
|
for (var key in obj) {
|
|
|
str += prefix + '[' + key + '] = {\n';
|
|
|
var val = obj[key];
|
|
|
if (isJson(val)) {
|
|
|
str += handleValues(val, numAttr, prefix + '\t');
|
|
|
} else {
|
|
|
for (var ai = 0; ai < numAttr; ai++) {
|
|
|
if (!attrExport[ai])
|
|
|
continue;
|
|
|
var value = getCellContent(currentSheet, 7 + val, 1 + ai);
|
|
|
if (value != undefined)
|
|
|
str += '\t' + prefix + getCell(currentSheet, 6, 1 + ai) + ' = ' + value + ',\n';
|
|
|
}
|
|
|
}
|
|
|
str += prefix + '},\n';
|
|
|
}
|
|
|
return str;
|
|
|
}
|
|
|
|
|
|
|
|
|
function mkdirs(dirname, callback) {
|
|
|
if (fs.existsSync(dirname)) {
|
|
|
if (callback != undefined)
|
|
|
callback();
|
|
|
} else {
|
|
|
mkdirs(path.dirname(dirname), function () {
|
|
|
fs.mkdirSync(dirname);
|
|
|
if (callback != undefined)
|
|
|
callback();
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function removeDir(p) {
|
|
|
if (!fs.existsSync(p))
|
|
|
return;
|
|
|
let statObj = fs.statSync(p); // fs.statSync同步读取文件状态,判断是文件目录还是文件。
|
|
|
if (statObj.isDirectory()) { //如果是目录
|
|
|
let dirs = fs.readdirSync(p) //fs.readdirSync()同步的读取目标下的文件 返回一个不包括 '.' 和 '..' 的文件名的数组['b','a']
|
|
|
dirs = dirs.map(dir => path.join(p, dir)) //拼上完整的路径
|
|
|
for (let i = 0; i < dirs.length; i++) {
|
|
|
// 深度 先将儿子移除掉 再删除掉自己
|
|
|
removeDir(dirs[i]);
|
|
|
}
|
|
|
fs.rmdirSync(p); //删除目录
|
|
|
} else {
|
|
|
fs.unlinkSync(p); //删除文件
|
|
|
}
|
|
|
}
|
|
|
|
|
|
var countExport = 0;
|
|
|
function handleFile(filePath) {
|
|
|
var workbook = XLSX.readFile(filePath);
|
|
|
//console.log(workbook);
|
|
|
console.log("handle file: " + filePath + " with " + workbook.SheetNames.length + " sheets");
|
|
|
for (var s = 0; s < workbook.SheetNames.length; s++) {
|
|
|
var sname = workbook.SheetNames[s];
|
|
|
|
|
|
var sheet = workbook.Sheets[sname];
|
|
|
//console.log(sheet);
|
|
|
|
|
|
var exportType = getCell(sheet, 0, 1);
|
|
|
if (exportType == 'base') {
|
|
|
var exportFile = outDir + '/' + getCell(sheet, 1, 1);
|
|
|
|
|
|
var fileHead = getCell(sheet, 0, 4);
|
|
|
var fileTail = getCell(sheet, 1, 4);
|
|
|
var numKeys = getCell(sheet, 2, 1);
|
|
|
//console.log(exportFile, fileHead, fileTail, numKeys);
|
|
|
|
|
|
if (sideChar == 'c') {
|
|
|
var clientHead = getCellNonEmpty(sheet, 0, 6);
|
|
|
if (clientHead != '')
|
|
|
fileHead = clientHead;
|
|
|
|
|
|
var clientFile = getCellNonEmpty(sheet, 1, 6);
|
|
|
if (clientFile != '')
|
|
|
exportFile = outDir + '/' + clientFile;
|
|
|
}
|
|
|
console.log("exporting sheet '" + sname +
|
|
|
"' with type " + exportType +
|
|
|
" to '" + exportFile + "'"
|
|
|
);
|
|
|
|
|
|
exportFile = exportFile.toLowerCase();
|
|
|
mkdirs(path.dirname(exportFile));
|
|
|
var outLua = fileHead + '\n';
|
|
|
|
|
|
|
|
|
try {
|
|
|
var data = fs.readFileSync(exportFile, 'utf-8');
|
|
|
var contents = data.split("\n");
|
|
|
contents[contents.length - 1] = '';
|
|
|
outLua = contents.join("\n");
|
|
|
} catch (err) {
|
|
|
// 出错了
|
|
|
}
|
|
|
|
|
|
var lines = getMaxRow(sheet) - 6;
|
|
|
//console.log("line:" + lines);
|
|
|
//if(lines == 0)
|
|
|
// continue;
|
|
|
|
|
|
keys = null;
|
|
|
keys = {};
|
|
|
var isBreak = false;
|
|
|
for (var li = 0; li < lines; li++) {
|
|
|
var list = [];
|
|
|
for (var ki = 0; ki < numKeys; ki++) {
|
|
|
var str = getCell(sheet, 7 + li, 1 + ki);
|
|
|
str = str == undefined ? '' : '' + str;
|
|
|
if (str.trim().length == 0) {
|
|
|
isBreak = true;
|
|
|
break;
|
|
|
}
|
|
|
list[ki] = str;
|
|
|
}
|
|
|
if (!isBreak)
|
|
|
insertKey(list, li);
|
|
|
else
|
|
|
isBreak = false;
|
|
|
}
|
|
|
//console.log(keys);
|
|
|
|
|
|
attrExport = [];
|
|
|
var numAttr = getMaxCol(sheet);
|
|
|
var validAttr = 0;
|
|
|
for (var ai = 0; ai < numAttr; ai++) {
|
|
|
var exportParam = getCell(sheet, 5, 1 + ai);
|
|
|
if (exportParam != undefined && exportParam.includes(sideChar)) {
|
|
|
attrExport[ai] = true;
|
|
|
validAttr++;
|
|
|
}
|
|
|
else
|
|
|
attrExport[ai] = false;
|
|
|
}
|
|
|
//console.log(attrExport);
|
|
|
//console.log("attr:" + numAttr);
|
|
|
|
|
|
currentSheet = sheet;
|
|
|
|
|
|
if (validAttr > 0)
|
|
|
outLua += handleValues(keys, numAttr, '');;
|
|
|
|
|
|
outLua += fileTail;
|
|
|
fs.writeFileSync(exportFile, outLua, 'utf-8');
|
|
|
countExport++;
|
|
|
}
|
|
|
else if (exportType == 'tiny') {
|
|
|
var exportFile = outDir + '/' + getCell(sheet, 1, 1);
|
|
|
exportFile = exportFile.toLowerCase();
|
|
|
console.log("exporting sheet '" + sname +
|
|
|
"' with type " + exportType +
|
|
|
" to '" + exportFile + "'"
|
|
|
);
|
|
|
|
|
|
var fileHead = getCell(sheet, 0, 4);
|
|
|
var fileTail = getCell(sheet, 1, 4);
|
|
|
mkdirs(path.dirname(exportFile));
|
|
|
var outLua = fileHead + '\n';
|
|
|
|
|
|
var lines = 0;
|
|
|
for (var lines = 0; true;) {
|
|
|
if (getCell(sheet, 5 + lines, 1) == undefined)
|
|
|
break;
|
|
|
lines++;
|
|
|
}
|
|
|
//console.log("line:" + lines);
|
|
|
//if(lines == 0)
|
|
|
// continue;
|
|
|
|
|
|
for (var li = 0; li < lines; li++) {
|
|
|
var exportParam = getCell(sheet, 5 + li, 1);
|
|
|
if (!exportParam.includes(sideChar))
|
|
|
continue;
|
|
|
var attr = getCell(sheet, 5 + li, 2);
|
|
|
var value = getCellContent(sheet, 5 + li, 3);
|
|
|
value = encodeQuote(value);
|
|
|
if (value.startsWith('--#include'))
|
|
|
outLua += value + '\n';
|
|
|
else if (attr != undefined)
|
|
|
outLua += '\t' + attr + ' = ' + value + ',\n';
|
|
|
}
|
|
|
|
|
|
|
|
|
outLua += fileTail;
|
|
|
fs.writeFileSync(exportFile, outLua, 'utf-8');
|
|
|
countExport++;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function handleDir(filePath) {
|
|
|
//根据文件路径读取文件,返回文件列表
|
|
|
var files = fs.readdirSync(filePath);
|
|
|
//遍历读取到的文件列表
|
|
|
files.forEach(function (filename) {
|
|
|
//获取当前文件的绝对路径
|
|
|
var filedir = path.join(filePath, filename);
|
|
|
//根据文件路径获取文件信息,返回一个fs.Stats对象
|
|
|
var stats = fs.statSync(filedir);
|
|
|
var isFile = stats.isFile();//是文件
|
|
|
var isDir = stats.isDirectory();//是文件夹
|
|
|
if (isFile && filedir.endsWith(".xlsx")) {
|
|
|
//console.log(filedir);
|
|
|
handleFile(filedir);
|
|
|
}
|
|
|
if (isDir) {
|
|
|
handleDir(filedir);//递归,如果是文件夹,就继续遍历该文件夹下面的文件
|
|
|
}
|
|
|
|
|
|
});
|
|
|
}
|
|
|
|
|
|
removeDir(outDir);
|
|
|
handleDir(srcDir);
|
|
|
console.log("Total export: " + countExport); |