You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

335 lines
8.2 KiB
JavaScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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