excel-json-cli1
Version:
用于把表格数据导成json数据,可支持json、ts和js,或者,用于把json数据导成表格数据,可支持json、ts和js。
153 lines (149 loc) • 5.99 kB
text/typescript
import xlsx from 'node-xlsx';
import * as fs from 'fs-extra';
import { OptionValues } from 'commander';
import chalk from 'chalk';
import { isExportType, typeToName } from '../constants';
import { format } from 'prettier';
import { prettierConfig } from '../constants/prettierrc';
const stringToObject = (jsonData: any, str: string, value: any) => {
const keys = str.split('.');
keys?.reduce((accumulator: any, currentValue: any, currentIndex: number) => {
const val = keys.length - 1 === currentIndex ? value : jsonData[currentValue] ?? {};
return accumulator ? accumulator[currentValue] = val : jsonData[currentValue] = val;
}, null);
}
const dataToJson = (data: any[], {
rule,
key: isKey,
notMatchFilename,
isSoToMo
}: {
rule: string;
key: boolean;
notMatchFilename: boolean;
isSoToMo: boolean;
}) => {
/**
* excel读取规制解析,文件名为第一行(小写字母-大写字母 或 整个单元格内容)
* rule 0:[4,15]表示第一列为语言key,第五列到第十九列为语言包数据,默认为0:[1,整行数据长度]
*/
const [key, interval] = rule.split(':');
const intervals = interval ? JSON.parse(interval) : [1];
// 记录文件导成json的数据
let jsonData:any = {};
data.forEach(sheet => {
// 记录每个标签页的语言key
let fileKeys: any[] = [];
sheet.data.forEach((row: any[], rowi: number) => {
if (rowi === 0) {
// 按第一行生成语言对象key
row.splice(intervals[0], intervals[1] ?? row.length).forEach((col, coli) => {
if (notMatchFilename) { // 记录语言key
fileKeys.push(col);
} else {
fileKeys.push(String(col).match(/[a-z]+-[A-Z]+/g) ? col.match(/[a-z]+-[A-Z]+/g)[0] : col);
}
jsonData[fileKeys[coli]] = {}; // 设置语言对象key
});
} else {
// 将第一行以下的数据生成语言json对象
if (isKey) {
const data = row.splice(intervals[0], intervals[1] ?? row.length);
fileKeys.forEach((filekey, i) => {
if(!(data[i] === '' || data[i] === null || data[i] === undefined)) {
console.log(chalk.green(`${sheet.name} | ${filekey} | ${row[key as any]} | ${data[i]}`)); // 打印数据日志
if (isSoToMo && key?.includes('.')) {
stringToObject(jsonData[filekey], key, data[i]);
} else {
jsonData[filekey][row[key as any]] = data[i];
}
}
});
} else {
row.splice(intervals[0], intervals[1] ?? row.length).forEach((col, coli) => {
if(!fileKeys[coli] || !row[key as any]) return; // 没有文件key 或 数据key,跳过该列
if (!(col === '' || col === null || col === undefined)) {
console.log(chalk.green(`${sheet.name} | ${fileKeys[coli]} | ${row[key as any]} | ${col}`)); // 打印数据日志
if (isSoToMo && row[key as any]?.includes('.')) {
stringToObject(jsonData[fileKeys[coli]], row[key as any], col);
} else {
jsonData[fileKeys[coli]][row[key as any]] = col; // 设置每行数据到对应语言对象
}
}
});
}
}
});
});
return jsonData;
}
const writeFile = (jsonData: { [x: string]: any; }, output: string, add: any) => {
// 获取输出路径及文件类型,默认为单前文件夹ts文件
const [path, fileOrSuffix] = output.split('**');
const [filename, suffix] = fileOrSuffix.split('.');
Object.keys(jsonData).forEach(key => {
console.log('正在写入文件:', path + key + fileOrSuffix);
let old = {};
// 增量获取源文件数据
if(add) {
try {
const fileData = fs.readFileSync(path + key + fileOrSuffix, { flag: 'r', encoding: 'utf-8' }).replace(/\;/g, '');
old = isExportType.includes(suffix) ? eval('(' + fileData.split('export default ')[1] + ')') : JSON.parse(fileData);
} catch (error) {
console.error(chalk.red('不存在源文件:', path + key + fileOrSuffix, ',改文件只有单前文档数据'))
}
}
// 格式化json数据
const data = (isExportType.includes(suffix) ? 'export default ' : '') + JSON.stringify({...old, ...jsonData[key]}, undefined, ' ');
// 查看文件夹是否存在
fs.stat(path + key, async (_, stats) => {
if (!stats && filename) {
// 不存在创建文件夹
fs.mkdir(path + key, { recursive: true }, err => {
if (err) {
console.error(chalk.red(err));
} else {
// 文件写入
fs.writeFile(
path + key + fileOrSuffix,
format(data, {
parser: typeToName[suffix] ?? 'typescript',
...prettierConfig
}), (err: any) => {
if (err) {
console.error(chalk.red(err));
}
}
);
}
});
} else {
// 文件写入
fs.writeFile(
path + key + fileOrSuffix,
format(data, {
parser: typeToName[suffix] ?? 'typescript',
...prettierConfig
}), (err: any) => {
if (err) {
console.error(chalk.red(err));
}
}
);
}
});
});
}
export function excel2json(options: OptionValues) {
// 读取文件
const workSheetsFromFile = xlsx.parse(options.input);
// 将数组转成json对象
const jsonData = dataToJson(workSheetsFromFile, {
rule: options.rule,
key: options.key,
notMatchFilename: options.notMatchFilename,
isSoToMo: options.multilevelObjectDeconstruct
});
// 将对象写入文件
writeFile(jsonData, options.output, options.add);
}