cocos3.X的oops框架oops-plugin-excel-to-json改进兼容多表单导出功能

news2025/7/26 8:32:47

        在使用oops框架的过程中,它的导出数据并生成数据结构的插件oops-plugin-excel-to-json有些小的坑点,为满足我个人习惯,对此部分进行了一个小的修改,有需要的拿去用,记录下供大家参考;

一、配置:其他基本配置请自行搜索,首先能导出其例子中的xlsx表格,基于此来看这篇文章。

我的项目环境配置,如下图:

  • 表的配置小坑:

核心文件

extensions\oops-plugin-excel-to-json\dist\ExcelToJson.js

extensions\oops-plugin-excel-to-json\src\ExcelToJson.ts

就是表格的关键字必须在表格的名字中标明:

"【KEY】"

否则只能导出结构,不能导出数据,结构的主键还不对;所以根据项目自己增加的表格,必须增加这个关键字,才能正确导出结构和数据;

  • 一个表个内的多个表单同时导出:

1,修改调用处的输出文件的绝对文件名,为输出路径,这里的输出是项目配置中的输出路径+原表格名称;现在不需要,只要路径,名称由内部的表单决定;

表单名决定数据文件名json和数据结构名ts;

核心是将获得表单的数量,然后循环处理下即可:

整体源码如下:复制过去覆盖,重新开启编辑器即可。

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = run;
const path_1 = __importDefault(require("path"));
const JsonToTs_1 = require("./JsonToTs");
const main_1 = require("./main");
const fs = require('fs');
const excel = require('exceljs');
/**
 * Excel转Json数据
 * @param {*} src           读取的excel文件目录
 * @param {*} dst           导出的json文件目录
 * @param {*} name          excel文件名
 * @param {*} isClient      是否为客户端数据
 */
async function convert(src, dst, name, isClient) {
    console.warn("src = ", src, "  dst = ", dst, "  name = ", name);
    const workbook = new excel.Workbook();
    // 读取excel
    await workbook.xlsx.readFile(src);
    console.warn("本次 xlsx的 文件路径 : src = ", src, " 包含>>>  ", workbook.worksheets.length , " <<<< 个分表 sheet", "  workbook.worksheets = ", workbook.worksheets);
    for(let sheet_id = 1; sheet_id <= workbook.worksheets.length; sheet_id++){
        let r = {};
        let names = []; // 文名字段名
        let keys = []; // 字段名
        let types = []; // 通用字段数据类型
        let types_client = {}; // 客户端数据类型
        let servers = []; // 是否输出服务器字段数据
        let clients = []; // 是否输出客户端字段数据
        let primary = []; // 多主键配置
        let primary_index = [];
        
        const worksheet = workbook.getWorksheet(sheet_id); // 获取第一个worksheet 
        console.log("src = ", src, " tablename = ", worksheet.name);
        worksheet.eachRow((row, rowNumber) => {
            let data = {};
            row.eachCell((cell, colNumber) => {
                const value = cell.text;
                // console.warn(cell.text, cell.string, cell.number, cell.result, cell.formula)
                if (rowNumber === 1) { // 字段中文名
                    names.push(value);
                    if (value.indexOf("【KEY】") > -1)
                        primary_index.push(colNumber);
                }
                else if (rowNumber === 2) { // 字段英文名
                    keys.push(value);
                    if (primary_index.indexOf(colNumber) > -1)
                        primary.push(value);
                }
                else if (rowNumber === 3) { // 通用字段数据类型
                    types.push(value);
                }
                else if (isClient == false && rowNumber === 4) { // 是否输出服务器字段数据
                    servers.push(value);
                }
                else if (isClient == true && rowNumber === 5) { // 客户端数据类型 
                    clients.push(value);
                }
                else if (rowNumber > 5) {
                    let index = colNumber - 1;
                    let type = types[index];
                    let server = servers[index];
                    let client = clients[index];
                    // 验证是否输出这个字段
                    let isWrite = isClient && client === "client" || isClient == false && server === "server";
                    if (isWrite) {
                        let key = keys[index];
                        switch (type) {
                            case "int":
                                // console.warn(`${index}int`, key, value, cell.string, cell.number, cell.result)
                                if (cell.formula) {
                                    data[key] = parseInt(cell.result);
                                }
                                else {
                                    data[key] = parseInt(value);
                                }
                                types_client[key] = {
                                    en: "number",
                                    zh: names[index]
                                };
                                break;
                            case "float":
                                // console.warn(`${index}int`, key, value, cell.string, cell.number, cell.result)
                                if (cell.formula) {
                                    data[key] = parseFloat(cell.result);
                                }
                                else {
                                    data[key] = parseFloat(value);
                                }
                                types_client[key] = {
                                    en: "number",
                                    zh: names[index]
                                };
                                break;
                            case "string":
                                // console.warn(`${index}int`, key, value, cell.string, cell.number, cell.result)
                                data[key] = value;
                                types_client[key] = {
                                    en: "string",
                                    zh: names[index]
                                };
                                break;
                            case "any":
                                // console.warn(`${index}int`, key, value, cell.string, cell.number, cell.result)
                                try {
                                    data[key] = JSON.parse(value);
                                    types_client[key] = {
                                        en: "any",
                                        zh: names[index]
                                    };
                                }
                                catch (_a) {
                                    console.log('Cell ' + cell.address + ' has value ' + cell.text);
                                    console.warn(`文件【${src}】的【${key}】字段【${data[key]}】类型数据【${value}】JSON转字段串错误【${client}】`);
                                }
                                break;
                        }
                    }
                }
            });
            // 生成数据(多主键)
            if (rowNumber > 5) {
                let temp = null;
                for (var i = 0; i < primary.length; i++) {
                    let k = primary[i];
                    let id = data[k];
                    delete data[k]; // 主键数据删除
                    if (primary.length == 1) {
                        r[id] = data;
                    }
                    else {
                        if (i == primary.length - 1) {
                            temp[id] = data;
                        }
                        else if (i == 0) {
                            if (r[id] == undefined) {
                                r[id] = {};
                            }
                            temp = r[id];
                        }
                        else {
                            temp[id] = {};
                            temp = temp[id];
                        }
                    }
                }
            }
        });
        // 写入流
        if (r["undefined"] == null) {
            await fs.writeFileSync(dst+ worksheet.name+ ".json", JSON.stringify(r));
            // 生成客户端脚本
            if (isClient) {
                (0, JsonToTs_1.createTsClient)( worksheet.name, types_client, r, primary);
            }
            else {
                (0, JsonToTs_1.createTsServer)( worksheet.name, types_client, r, primary);
            }
            console.log(isClient ? "客户端数据" : "服务器数据", "生成成功", dst);
        }
        else {
            console.log(isClient ? "客户端数据" : "服务器数据", "无数据2", dst);
        }

    }

    
}
function run() {
    var inputExcelPath = path_1.default.join(__dirname, main_1.config.PathExcel.replace("project://", "../../../") + "/");
    var outJsonPathClient = path_1.default.join(__dirname, main_1.config.PathJsonClient.replace("project://", "../../../") + "/");
    var outJsonPathServer = null;
    if (main_1.config.PathJsonServer != null && main_1.config.PathJsonServer.length > 0) {
        outJsonPathServer = path_1.default.join(__dirname, main_1.config.PathJsonServer.replace("project://", "../../../") + "/");
    }
    const files = fs.readdirSync(inputExcelPath);
    files.forEach((f) => {
        let name = f.substring(0, f.indexOf("."));
        let ext = f.toString().substring(f.lastIndexOf(".") + 1);
        if (ext == "xlsx") {
            if (outJsonPathServer)
                convert(inputExcelPath + f, outJsonPathServer , name, false); // 服务器数据
            convert(inputExcelPath + f, outJsonPathClient, name, true); // 客户端数据
        }
    });
}

最后说明下:这里面还有一个不完善的地方就是:关于excel表中的分表的编号问题:

就是说必须是连续的表单顺序,如果不连续就会有报错,要新建一张表,把各个分表拷贝过去,保证它的表单ID顺序是连续的。也就是说策划可以改分表,但是轻易不要删除分表,重新建一张分表。如果必须要删除分表,要重新做一个新表文件,把分表逐一拷贝一份进去即可。保证分表顺序是从1开始连续的即可。

祝各位用餐快乐!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2402134.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

每日八股文6.3

每日八股-6.3 Mysql1.COUNT 作用于主键列和非主键列时&#xff0c;结果会有不同吗&#xff1f;2.MySQL 中的内连接&#xff08;INNER JOIN&#xff09;和外连接&#xff08;OUTER JOIN&#xff09;有什么主要的区别&#xff1f;3.能详细描述一下 MySQL 执行一条查询 SQL 语句的…

Kubernetes (k8s)版本发布情况

Kubernetes (k8s)版本发布情况 代码放在 GitHub - kubernetes/kubernetes: Production-Grade Container Scheduling and Management https://github.com/kubernetes/kubernetes/releases 文档放在 kubernetes.io各个版本变更等: https://github.com/kubernetes/kubernet…

QT 5.9.2+VTK8.0实现等高线绘制

项目下载链接&#xff1a;QT5.9.2VTK8.0实现等高线绘制资源-CSDN文库 示例如下&#xff1a; 主要代码如下&#xff1a; #include "vtkRenderer.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkPo…

兼容老设备!EtherNet/IP转DeviceNet网关解决储能产线通讯难题

在新能源行业飞速发展的当下&#xff0c;工业自动化水平的高低直接影响着企业的生产效率与产品质量。JH-EIP-DVN疆鸿智能ETHERNET/IP和DEVICENET作为工业领域常用的通信协议&#xff0c;它们之间的转换应用在新能源生产线上发挥着关键作用。本文重点探讨ETHERNETIP从站转DEVICE…

LabVIEW自感现象远程实验平台

LabVIEW开发自感现象远程实验平台&#xff0c;通过整合 NI数据采集设备、菲尼克斯&#xff08;Phoenix Contact&#xff09;继电器模块及罗技&#xff08;Logitech&#xff09;高清摄像头&#xff0c;实现远程数据采集、仪器控制与实时监控三大核心功能。平台突破传统实验装置局…

Python----目标检测(《YOLOv3:AnIncrementalImprovement》和YOLO-V3的原理与网络结构)

一、《YOLOv3:AnIncrementalImprovement》 1.1、基本信息 标题&#xff1a;YOLOv3: An Incremental Improvement 作者&#xff1a;Joseph Redmon, Ali Farhadi 机构&#xff1a;华盛顿大学&#xff08;University of Washington&#xff09; 发表时间&#xff1a;2018年 代…

算法篇 八大排序(冒泡 插入 选择 堆 希尔 快排 归并 计数)

目录 引言 1.冒泡排序 思路 代码实现 2.选择排序 思路 代码实现&#xff08;存在易错点&#xff09; 3.插入排序 思路 代码实现 4.希尔排序 思路 代码实现 5.堆排序 思路 代码实现 6.快速排序&#xff08;快排&#xff09; 一.三路划分 思路 代码实现 二.自…

音视频之视频压缩编码的基本原理

系列文章&#xff1a; 1、音视频之视频压缩技术及数字视频综述 2、音视频之视频压缩编码的基本原理 一、预测编码&#xff1a; 1、预测编码的基本概念&#xff1a; 预测法是最简单、实用的视频压缩编码方法&#xff0c;经过压缩编码后传输的并不是像素本身的取样值&#xff0…

IDEA 包分层显示设置

方法一&#xff08;用的IntelliJ IDEA 2024.1.4版本&#xff09;&#xff1a; 找到项目视图设置入口&#xff1a;在左侧Project&#xff08;项目&#xff09;面板的顶部&#xff0c;有个三个点...的按钮 &#xff0c;点击它。 进入树形外观配置&#xff1a;在弹出的菜单中&…

深度学习和神经网络 卷积神经网络CNN

1.什么是卷积神经网络 一种前馈神经网络&#xff1b;受生物学感受野的机制提出专门处理网格结构数据的深度学习模型 核心特点&#xff1a;通过卷积操作自动提取空间局部特征&#xff08;如纹理、边缘&#xff09;&#xff0c;显著降低参数量 2.CNN的三个结构特征 局部连接&a…

PlayWright | 初识微软出品的 WEB 应用自动化测试框架

Playwright是微软大厂背书的跨平台 WEB 应用自动化测试框架&#xff0c;支持多开发语言&#xff08;TypeScript、JavaScript、.Net、Python、Java&#xff09;及多浏览器&#xff08;Chromium、WebKit、Firefox&#xff09;&#xff0c;同时支持移动端测试。 安装 playwright …

Mac电脑_钥匙串操作选项变灰的情况下如何删除?

Mac电脑_钥匙串操作选项变灰的情况下如何删除&#xff1f; 这时候 可以使用相关的终端命令进行操作。 下面附加文章《Mac电脑_钥匙串操作的终端命令》。 《Mac电脑_钥匙串操作的终端命令》 &#xff08;来源&#xff1a;百度~百度AI 发布时间&#xff1a;2025-06&#xff09;…

2025前端微服务 - 无界 的实战应用

遇饮酒时须饮酒&#xff0c;得高歌处且高歌 文章目录 什么是前端微服务主流框架概述无界 - 腾讯乾坤 - 阿里Micro-app Vue3项目引用⑴. 项目依赖安装⑵. main.ts 文件配置⑶. 路由配置⑷. 页面设置 隐藏子应用菜单及顶部信息栏子应用样式冲突问题虚拟路由⑴. 路由⑵. 页面 跨域…

【设计模式-4.8】行为型——中介者模式

说明&#xff1a;本文介绍行为型设计模式之一的中介者模式 定义 中介者模式&#xff08;Mediator Pattern&#xff09;又叫作调节者模式或调停者模式。用一个中介对象封装一系列对象交互&#xff0c;中介者使各对象不需要显式地互相作用&#xff0c;从而使其耦合松散&#xf…

行列式的性质

1 行列式使用如下性质定义 1&#xff09;单位矩阵行列式值为 1&#xff0c; &#xff0c;对于任意单位矩阵均成立&#xff1b; 2&#xff09;当矩阵交换一行后&#xff0c;行列式值改变符号&#xff0c;如置换矩阵的行列式值为 &#xff08;根据行交换次数决定&#xff09;&…

联软NSPM自动化策略管理 助力上交所加速国产化替代提升运维效率

在金融行业核心基础设施国产化浪潮与网络安全强监管的双重背景下&#xff0c;上海证券交易所&#xff08;以下简称“上交所”&#xff09;积极拥抱变革&#xff0c;携手长期合作伙伴联软科技&#xff0c;成功部署了联软安全策略管理系统&#xff08;NSPM&#xff09;。该项目不…

Flask + ECharts+MYSQL物联网数字化大屏

基于Flask+ECharts的物联网数字化大屏系统,包含中国地图实时数据更新功能。这个系统模拟了物联网设备在全国范围内的分布和运行状况,并实时更新数据。 一、系统架构设计 技术栈 后端:Flask(轻量级路由+API支持) 前端:ECharts(地图+动态图表)、WebSocket(实时更新)…

数据库系统概论(十六)数据库安全性(安全标准,控制,视图机制,审计与数据加密)

数据库系统概论&#xff08;十六&#xff09;数据库安全性 前言一、数据库安全性1. 什么是数据库安全性&#xff1f;2. 为何会存在安全问题&#xff1f; 二、安全标准的发展1. 早期的“开拓者”&#xff1a;TCSEC标准2. 走向国际统一&#xff1a;CC标准3. TCSEC和CC标准有什么不…

vue3从入门到精通(基础+进阶+案例)

Vue是什么&#xff1f; 渐进式JavaScript框架&#xff0c;易学易用&#xff0c;性能出色&#xff0c;适用场景丰富的Web前端框架 为什么要学习Vue Vue是目前前端最火的框架之一 Vue是目前企业技术栈中要求的知识点 Vue可以提升开发体验 。。。 Vue简介 Vue(发音为/vju/,…

【Linux 学习计划】-- 系统中进程是如何调度的(内核进程调度队列)

目录 回顾进程优先级与进程调度的引入 内核runqueue图例 关于queue[140]前100个位置 | 实时进程与分时进程 遍历需要调度的进程与bitmap的引入 active、expired指针 结语 回顾进程优先级与进程调度的引入 在我们之前的学习中&#xff0c;我们是有学习过进程优先级这个概…