update xlsxTransform

This commit is contained in:
Vick Scarlet
2021-09-09 13:24:40 +08:00
parent 3a9149e9a4
commit 44e05a166e
7 changed files with 448 additions and 629 deletions

View File

@@ -6,63 +6,154 @@ import { join, extname, dirname } from 'path';
// const XLSX = require('xlsx');
// const { join, extname, dirname } = require('path');
async function transform(filePath) {
const xlsxFileBuffer = await readFile(filePath);
async function read(xlsxPath) {
const xlsxFileBuffer = await readFile(xlsxPath);
const xlsx = XLSX.read(xlsxFileBuffer, {type: 'buffer'});
const sheets = xlsx.Sheets;
const data = {};
for(const sheetName in sheets) {
const sheetRawData = sheets[sheetName];
if(!sheetRawData['!ref']) break;
const rawData = XLSX.utils.sheet_to_json(sheetRawData);
const newData = {};
data[sheetName] = newData;
rawData.shift();
for(const index in rawData) {
const row = rawData[index];
const rowData = {};
let mainKey;
for(let key in row) {
const cell = row[key];
if(key[0] == "$") {
key = key.substr(1);
mainKey = cell;
}
if(key.includes(':')) {
const keys = key.split(':');
const lastKey = keys.pop();
let temp = rowData;
for(const subKey of keys) {
if(!temp[subKey]) temp[subKey] = {};
temp = temp[subKey];
}
if(lastKey.includes('[]')) {
const aKey = lastKey.split('[]')[0];
if(!temp[aKey]) temp[aKey] = [cell];
else temp[aKey].push(cell);
} else {
temp[lastKey] = cell;
}
} else if(key.includes('[]')) {
const aKey = key.split('[]')[0];
if(!rowData[aKey]) rowData[aKey] = [cell];
else rowData[aKey].push(cell);
} else {
rowData[key] = cell;
}
}
if(mainKey===undefined) {
console.warn('[WARN][No Main Key]', filePath, sheetName, parseInt(index), rowData);
continue;
}
if(newData[mainKey]) console.warn('[WARN][Duplicate Key]', mainKey, filePath, sheetName, parseInt(index), '\n\t', JSON.stringify(newData[mainKey]), '\n\t', JSON.stringify(rowData));
newData[mainKey] = rowData;
}
data[sheetName] = XLSX.utils.sheet_to_json(sheetRawData);
}
return data;
}
async function write(sheets) {
for(const sheetName in sheets) {
const { dirname, data, source } = sheets[sheetName];
const savePath = join(dirname, `${sheetName}.json`);
console.info('[Transform] XLSX(', source.map(([p, s])=>`${p}:${s}`).join('\n\t\t '), `) \n\t -> JSON( ${savePath} )`);
await writeFile(
savePath,
JSON.stringify(data, null, 4),
)
}
}
function format(rawSheet, isArray) {
const newSheet = isArray?[]:{};
rawSheet.shift();
for(const index in rawSheet) {
const row = rawSheet[index];
const rowData = {};
let mainKey;
for(let key in row) {
const cell = row[key];
if(key[0] == "$") {
key = key.substr(1);
mainKey = cell;
}
if(key.includes(':')) {
const keys = key.split(':');
const lastKey = keys.pop();
let temp = rowData;
for(const subKey of keys) {
if(!temp[subKey]) temp[subKey] = {};
temp = temp[subKey];
}
if(lastKey.includes('[]')) {
const aKey = lastKey.split('[]')[0];
if(!temp[aKey]) temp[aKey] = [cell];
else temp[aKey].push(cell);
} else {
temp[lastKey] = cell;
}
} else if(key.includes('[]')) {
const aKey = key.split('[]')[0];
if(!rowData[aKey]) rowData[aKey] = [cell];
else rowData[aKey].push(cell);
} else {
rowData[key] = cell;
}
}
if(isArray) {
newSheet.push(rowData);
continue;
}
if(mainKey===undefined) {
console.warn('[WARN][No Main Key]', filePath, sheetName, parseInt(index), rowData);
continue;
}
if(newSheet[mainKey]) console.warn('[WARN][Duplicate Key]', mainKey, filePath, sheetName, parseInt(index), '\n\t', JSON.stringify(newSheet[mainKey]), '\n\t', JSON.stringify(rowData));
newSheet[mainKey] = rowData;
}
return newSheet;
}
function merge(original, rawData, isMerge, isArray, xlsxPath, rawSheetName) {
if(!original)
return {
isMerge,
isArray,
source: [[xlsxPath, rawSheetName]],
data: format(rawData, isArray)
};
if(!isMerge) {
if(original) {
console.warn(`[WARN][Sheet Duplicate] ${xlsxPath}:${rawSheetName}\n\t\t${original.source[0][0]}:${original.source[0][1]}`)
return original;
}
}
if(!original.isMerge) {
console.warn(`[WARN][Sheet Duplicate] ${xlsxPath}:${rawSheetName}\n\t\t${original.source[0][0]}:${original.source[0][1]}`)
return original;
}
if(original.isArray != isArray) {
console.warn(`[WARN][Sheet Format not pair] ${xlsxPath}:${rawSheetName}\n\t\t${original.source[0][0]}:${original.source[0][1]}`)
return original;
}
const formatData = format(rawData, isArray);
original.source.push([xlsxPath, rawSheetName]);
if(isArray) {
original.data = original.data.concat(formatData)
} else {
for(const key in formatData) {
if(original.data[key]) {
console.warn(`[WARN][Duplicate key] ${key} ${xlsxPath}:${rawSheetName} ${JSON.stringify(formatData[key])}\n\t\t${original.source[0][0]}:${original.source[0][1]} ${JSON.stringify(original.data[key])}`);
continue;
}
original.data[key] = formatData[key];
}
}
return original;
}
function transform(rawSheets) {
const sheets = {};
for(const xlsxPath in rawSheets) {
const {dirname: d, data: rawSheetsData} = rawSheets[xlsxPath];
for(const rawSheetName in rawSheetsData) {
const rawData = rawSheetsData[rawSheetName];
if(rawSheetName[0] === "#") continue;
let sheetName = rawSheetName;
const isArray = rawSheetName.substr(-5) === "<arr>";
if(isArray) sheetName = sheetName.substring(0, sheetName.length - 5);
const isMerge = rawSheetName[0] === ">";
if(isMerge) sheetName = sheetName.substr(1);
sheets[sheetName] = merge(
sheets[sheetName],
rawData,
isMerge,
isArray,
xlsxPath,
rawSheetName
);
sheets[sheetName].dirname = d;
}
}
return sheets;
}
async function walk(filePath) {
const xlsxPaths = [];
if(Array.isArray(filePath)) {
@@ -87,18 +178,18 @@ async function main() {
const filePaths = process.argv.slice(2);
if(filePaths.length<0) process.exit(0);
const xlsxs = await walk(filePaths);
const sheets = {};
for(const p of xlsxs) {
const data = await transform(p);
const data = await read(p);
const d = dirname(p);
for(const sheetName in data) {
const savePath = join(d, `${sheetName}.json`);
console.info(`[Transform] XLSX(${p}:${sheetName}) -> JSON(${savePath})`);
await writeFile(
savePath,
JSON.stringify(data[sheetName], null, 4),
);
}
sheets[p] = {
dirname: d,
data
};
}
await write(
transform(sheets)
);
console.info(`
------------------------
| Transform Complete |