Excel转Json编辑器工具
功能说明:根据 .xlsx 文件生成对应的 JSON 文件,并自动创建脚本
注意事项
-
Excel 读取依赖
本功能依赖EPPlus库,只能读取.xlsx文件。请确保将该脚本放置在Assets目录下的Editor文件夹中。同时,在Editor下再创建一个Excel目录,并将你的.xlsx文件放到Excel目录下。注意:该目录下只能有一个.xlsx文件,且该文件是唯一的数据源。- Excel 文件格式要求:
- 第一行:字段名(与自动生成脚本中的字段对应)。
- 第二行:中文注释。
- 第三行:字段的数据类型(目前支持
int、float、double、string、bool和数组类型,如int[]、string[])。 - 第四行开始:实际数据。
- Epplus依赖获取查看我的另一篇文章Nuget For Unity插件介绍_nugetforunity-CSDN博客
- Excel 文件格式要求:
-
生成脚本与 JSON 文件
使用编辑器中的 ExcelTool 进行生成,点击 读取 Excel 按钮后,将自动执行以下操作:- 删除之前生成的脚本目录和 JSON 目录(如果存在),然后重新生成它们。
- 注意:在这两个目录下请不要放置其他文件,因为此工具会在每次生成时覆盖这些目录。
-
关于数组格式
数组数据需要按如下格式写入:
例如:1|2|3。数组成员使用|分隔。 -
支持多 sheet
一个.xlsx文件中可以包含多个 sheet。在读取时,工具会读取所有 sheet 数据。请注意:- 将每个 sheet 的名字改为与要生成的脚本名一致。
- Sheet 名称必须符合 C# 的命名规范,建议使用
TB_开头。
提示
- 脚本命名:请确保每个 sheet 的名字与生成的 C# 脚本的名称一致。
- 字段类型:当前支持的字段类型包括基本数据类型(
int、float、double、string、bool)以及数组类型(如int[]、string[])。 - 感谢原作者:特别感谢原作者“小人”的贡献,我仅添加了一些功能,以下是他在 B站的教程视频地址:Unity中简单根据excel文件自动生成对应的C#脚本及json文件_哔哩哔哩_bilibili
格式

保证这个目录格式

Excel格式
源码
using OfficeOpenXml;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Text;
using System;
using UnityEditor;
using UnityEngine;/*功能:根据.xlsx文件生成对应的json文件,并自动创建脚本注意:一 Excel读取依赖EPPlus,只能读.xlsx文件,Asset下创建一个Editor,同时将该脚本放到Editor下然后在Editor下再创建一个Excel目录,然后将你的Excel文件放到Excel目录下,注意Excel目录下只能有一个Excel文件,同时Excel格式要符合下列要求,最后Excel是唯一的数据源,所以除了保护好你的Excel文件外,其他的可以重新生成.使用编辑器上的ExcelTool/读取Excel按钮生成Json和脚本使用该按钮会删除脚本目录和json目录然后重新生成(如果已经生成过),所以不要在这两个目录下放置其他文件.二 xlsx第一行为英文字段与自动生成脚本中的字段对应第二行为中文注释第三行为字段的数据类型,目前支持int float double string bool 数组数组的写法统一为基本数据类型+[] 如int[] 、string[]第四行开始为实际数据三 xlsx文件中可以有很多sheet.读取时会读取xlsx的全部sheet要将对应的sheet的名字改为与要生成的脚本名一致,所以sheet名要符合C#的命名规范,建议使用TB_开头四 数组的书写格式形如:1|2|3,数组成员使用|分隔五 感谢原作者小人,我仅做了一些功能补充,下面的地址是小人的b站视频地址*/
[HelpURL("https://www.bilibili.com/video/BV16f421Q7zA/?spm_id_from=333.1007.top_right_bar_window_default_collection.content.click&vd_source=f9b5906b25cd5ca40ec79f317993905b")]
public class ExcelTool
{//命名空间列表private static List<string> nameSpaceList = new List<string>(){ "using System;", "[Serializable]"};//Root目录,包含Excel本身,Excel生成的json和脚本private static readonly string excel = Application.dataPath + "/Editor/Excel";//Excel文件private static string excelFilePath = excel;//脚本目录private static readonly string scriptsFolder = excel + "/ExcelScripts";//json目录private static string jsonFolder = excel + "/Json";[MenuItem("ExcelTool/读取Excel")]public static void TestTool(){// 获取目录下所有以 .xlsx 结尾的文件(不包括子目录中的文件)string[] files = Directory.GetFiles(excel, "*.xlsx");if (files.Length > 0){// 获取第一个文件的完整路径string firstFilePath = files[0];// 获取文件名(不包括路径)string fileName = Path.GetFileName(firstFilePath);excelFilePath = excelFilePath + "/" + fileName;}if (!File.Exists(excelFilePath)){Debug.LogError("excel文件不存在");return;}CreateDirectory(scriptsFolder);CreateDirectory(jsonFolder);var res = ReadExcel(excelFilePath);for (int i = 0; i < res.Count; i++){string path = scriptsFolder + "/" + res[i].scriptName + ".cs";CreateAScript(path, res[i].scriptName, nameSpaceList, res[i].fieldType, res[i].fieldName);CreateAJson(res[i].scriptName, res[i].fieldType, res[i].fieldName, res[i].dataDic);}AssetDatabase.Refresh();}private static void CreateDirectory(string path){if (!Directory.Exists(path)){Directory.CreateDirectory(path);}else{path = ConvertToRelativePath(path);var b = AssetDatabase.DeleteAsset(path);Directory.CreateDirectory(path);}}// 将绝对路径转为相对路径private static string ConvertToRelativePath(string absolutePath){// 获取项目的 'Assets' 文件夹路径string assetsPath = Application.dataPath;// 确保返回的路径是相对于 'Assets' 文件夹的if (absolutePath.StartsWith(assetsPath)){// 去掉 Application.dataPath 前缀,返回相对路径return "Assets" + absolutePath.Substring(assetsPath.Length);}Debug.LogError("路径不在 Assets 目录内: " + absolutePath);return absolutePath;}/// <summary>/// 读取 .xlsx文件,获取第一张sheet的内容/// </summary>/// <param name="path"></param>/// <returns></returns>private static List<(string scriptName, List<string> fieldType, List<string> fieldName, Dictionary<int, List<string>> dataDic)>ReadExcel(string path){int sheetsCount;var list = new List<(string scriptName, List<string> fieldType, List<string> fieldName, Dictionary<int, List<string>> dataDic)>();FileInfo fileInfo = new FileInfo(path);using (ExcelPackage excelPackage = new ExcelPackage(fileInfo)){sheetsCount = excelPackage.Workbook.Worksheets.Count;}for (int z = 0; z < sheetsCount; z++){//生成的脚本名string scriptName;//字段类型列表List<string> fieldType = new List<string>();//字段名列表List<string> fieldName = new List<string>();//.xlsx除注释行之外的相关数据Dictionary<int, List<string>> dataDic = new Dictionary<int, List<string>>();using (ExcelPackage excelPackage = new ExcelPackage(fileInfo)){//取得.xlsx中的第一张sheet(EPPlus中下标从1或者0开始,取决于版本)ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets[z];if (worksheet == null){sheetsCount++;continue;}//取sheet的名字,即生成的脚本名scriptName = worksheet.Name;//取英文字段名//遍历表格第一行取字段名 注意索引下标for (int i = 1; i <= worksheet.Dimension.End.Column; i++){if (worksheet.Cells[1, i].Value is null){Debug.LogError($"当前{worksheet}中第1行第{i}个单元格数据为空");return null;}string field = worksheet.Cells[1, i].Value.ToString();fieldName.Add(field);}//取字段类型//遍历第三行 同上for (int i = 1; i <= worksheet.Dimension.End.Column; i++){if (worksheet.Cells[3, i].Value is null){Debug.LogError($"当前{worksheet}中第3行第{i}个单元格数据为空");return null;}string field = worksheet.Cells[3, i].Value.ToString();fieldType.Add(field);}//取实际数据for (int k = 4; k <= worksheet.Dimension.End.Row; k++){List<string> realData = new List<string>();for (int j = 1; j <= worksheet.Dimension.End.Column; j++){if (worksheet.Cells[k, j].Value is null){Debug.LogError($"当前{worksheet}中第{k}行第{j}个单元格数据为空");return null;}string data = worksheet.Cells[k, j].Value.ToString();realData.Add(data);}dataDic[k] = realData;}}list.Add((scriptName, fieldType, fieldName, dataDic));}return list;}/// <summary>/// 判断字符串列表中是否包含重复成员,有,返回true/// </summary>/// <param name="list"></param>/// <returns></returns>private static bool HasRepeatedMember(List<string> list){//往HaseSet中添加字符串,若不成功添加,说明有重复字符串 HashSet<string> hashSet = new HashSet<string>();for (int i = 0; i < list.Count; i++){if (!hashSet.Add(list[i])){return true;}}return false;}/// <summary>/// 创建一个C#脚本/// </summary>/// <param name="path">脚本保存路径</param>/// <param name="scriptName">脚本名</param>/// <param name="nameSpaceList">命名空间列表</param>/// <param name="fieldType">字段类型列表</param>/// <param name="fieldName">字段名列表</param>private static void CreateAScript(string path, string scriptName, List<string> nameSpaceList,List<string> fieldType, List<string> fieldName){#region 安全校验if (fieldType is null || fieldType.Count == 0){Debug.LogError($"{scriptName}字段类型列表错误");return;}if (fieldName is null || fieldName.Count == 0){Debug.LogError($"{scriptName}字段名列表错误");return;}if (nameSpaceList is null || nameSpaceList.Count == 0){Debug.LogError($"{scriptName}命名空间列表错误");return;}if (fieldType.Count != fieldName.Count){Debug.LogError($"{scriptName}字段类型列表与字段名列表长度不一致");return;}//生成的字段以字母开头for (int i = 0; i < fieldName.Count; i++){if (!Regex.IsMatch(fieldName[i], @"^[a-zA-Z_]")){Debug.LogError($"{scriptName}中字段名应以字母开头");return;}}//避免生成字段重复if (HasRepeatedMember(fieldName)){Debug.LogError($"{scriptName}中出现重复字段");return;}#endregionusing (StreamWriter writer = new StreamWriter(path)){//写入命名空间for (int i = 0; i < nameSpaceList.Count; i++){writer.WriteLine(nameSpaceList[i]);}//写入脚本名writer.WriteLine($"public class {scriptName}");writer.WriteLine("{");//写入类型及字段for (int i = 0; i < fieldName.Count; i++){writer.WriteLine($"public {fieldType[i]} {fieldName[i]} ;");}writer.WriteLine("}");}}/// <summary>/// 创建json文件/// </summary>/// <param name="jsonName">json文件名</param>;/// <param name="fieldType">字段类型列表</param>/// <param name="fieldName">字段名列表</param>/// <param name="dataDic">实际数据字典</param>private static void CreateAJson(string jsonName, List<string> fieldType, List<string> fieldName, Dictionary<int, List<string>> dataDic){//写一行数据StringBuilder sb = new StringBuilder();sb.Append("[\n");for (int i = 4; i < dataDic.Count + 4; i++){//写一行 追加string s = GetALine(fieldType, fieldName, dataDic[i]);sb.Append(s);//不是最后一项数据,加逗号if (i != dataDic.Count + 3){sb.Append(",");}//换行sb.Append("\n");}//写最后一个括号sb.Append("]\n");string path = jsonFolder + "/" + jsonName + ".json";using (StreamWriter writer = new StreamWriter(path)){writer.WriteLine(sb.ToString());}}/// <summary>/// 将一行excel转为一行json/// </summary>/// <param name="fieldType">字段类型列表</param>/// <param name="fieldName">字段名列表</param>/// <param name="dataList">实际一行数据</param>/// <returns></returns>/// <exception cref="Exception"></exception>private static string GetALine(List<string> fieldType, List<string> fieldName, List<string> dataList){StringBuilder sb = new StringBuilder();//写括号sb.Append("{");//遍历列表 for (int i = 0; i < fieldType.Count; i++){//写入主键string key = fieldName[i];sb.Append($"\"{key}\":");//写入值 string type = fieldType[i];string value = dataList[i];if (value is null){throw new Exception("表格实际数据存在未配置项");}sb.Append($"{Convert(type, value)}");//写入逗号//不是最后一个就是逗号if (i != fieldType.Count - 1){sb.Append(",");}}sb.Append("}");return sb.ToString();}//根据类型获取键所对应的值//如果不是数组 返回类型为 "Key":"Value" 中的value//如果是数组 返回类似于 ["1","2"] 的结构private static string Convert(string type, string value){switch (type){case "int":case "float":case "double":case "bool":case "string":case "long"://注此处返回的时候加了引号,避免格式错误return $"\"{value}\"";case "int[]":case "float[]":case "double[]":case "bool[]":case "string[]":case "long[]":return ArrayParse(value);default:throw new Exception("{type}类型暂未支持");}}/// <summary>/// 将数组转换成对应的字符串/// </summary>/// <param name="value"></param>/// <returns></returns>private static string ArrayParse(string value){//切分字符串得到数组var res = value.Split("|");StringBuilder sb = new StringBuilder();sb.Append("[");for (int i = 0; i < res.Length; i++){sb.Append('"');sb.Append(res[i]);sb.Append('"');//不是数组最后一个加,if (i != res.Length - 1){sb.Append(",");}}sb.Append("]");return sb.ToString();}}
直接获取该项目
ExcelToJson: ExcelToJson
总结
该工具可以帮助你轻松地将 .xlsx 文件中的数据转换为 JSON 文件,并自动生成对应的 C# 脚本,简化了数据处理和代码生成的流程。在使用时,务必遵循 Excel 文件格式要求,确保生成的脚本和 JSON 文件符合预期。
相关文章:
Excel转Json编辑器工具
功能说明:根据 .xlsx 文件生成对应的 JSON 文件,并自动创建脚本 注意事项 Excel 读取依赖 本功能依赖 EPPlus 库,只能读取 .xlsx 文件。请确保将该脚本放置在 Assets 目录下的 Editor 文件夹中。同时,在 Editor 下再创建一个 Exc…...
创建型设计模式、结构型设计模式与行为型设计模式 上下文任务通用方案 设计模式 大全
设计模式(Design Pattern)是一种面向对象编程的思想,分为创建型模式、结构型模式与行为型模式三大类,它们提供了在特定上下文中解决常见任务的通用方案,旨在让程序(软件)具有更好的特点…...
Mac 环境 VVenC 编译与编码命令行工具使用教程
VVenC VVenC 是一个开源的高效视频编码器,专门用于支持 H.266/VVC (Versatile Video Coding) 标准的编码。H.266/VVC 是继 HEVC (H.265) 之后的新一代视频编码标准,主要目的是提供比 HEVC 更高的压缩效率,同时保持或提高视频质量。H.266/VVC…...
如何在 Ubuntu 22.04 上部署 Nginx 并优化以应对高流量网站教程
简介 本教程将教你如何优化 Nginx,使其能够高效地处理高流量网站。 Nginx 是一个强大且高性能的 Web 服务器,以其高效处理大量并发连接的能力而闻名,这使得它成为高流量网站的流行选择。 正确优化 Nginx 可以显著提高服务器的性能࿰…...
springcloud各个组件介绍
Spring Cloud 是一系列框架的集合,它基于 Spring Boot 提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话和集群状态)中快速构建一些常见模式的工具。下面是对 Sprin…...
HTML5实现好看的喜庆圣诞节网站源码
HTML5实现好看的喜庆圣诞节网站源码 前言一、设计来源1.1 主界面1.2 圣诞介绍界面1.3 圣诞象征界面1.4 圣诞活动界面1.5 圣诞热度界面1.6 圣诞纪念界面1.7 联系我们界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载结束语 HTML5实现好看的喜庆圣诞节网站源码,圣…...
《学习之道》
《学习之道》主要讲述了以下内容: 学习的原理 大脑的两种认知模式:介绍了专注模式和发散模式。专注模式适合集中精力解决具体问题、进行深度理解和记忆推理,但长时间使用易疲惫和陷入思维定式;发散模式则让大脑在更广泛的认知网…...
【Unity3D】ECS入门学习(十一)ComponentSystem、JobComponentSystem
ComponentSystem:仅支持主线程执行,不支持多线程,并且无法使用SystemBase介绍的扩展方法。 using Unity.Entities; using Unity.Transforms; using Unity.Mathematics;/// <summary> /// 仅主线程执行,不支持多线程 /// &l…...
力扣刷题:栈和队列OJ篇(上)
大家好,这里是小编的博客频道 小编的博客:就爱学编程 很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!! 目录 1.用队列实现栈(1)题目…...
XGPT用户帮助手册
文章目录 2024 更新日志2024.12.272024.12.29 摘要 本文详细介绍了XGPT软件的功能及发展历程。XGPT是一款融合了当前最先进人工智能技术的多模态智能软件,专为国内用户优化设计。除了强大的智能问答功能外,XGPT还结合日常办公和科学研究的需求࿰…...
Oracle 数据库 dmp文件从高版本导入低版本的问题处理
当前有个需求是将oracle 19c上的数据备份恢复到oracle 11g上使用。我们通过exp命令远程进行备份,然后通过imp进行恢复时出现IMP-00010: not a valid export file, header failed verification报错。 这是数据库版本问题,在使用exp命令导出的时候使用的客…...
ShardingSphere-Proxy分表场景测试案例
快速入门文章参考:《ShardingSphereProxy:快速入门》 基于K8S部署文章参考:《基于K8s部署ShardingSphere-Proxy》 基于golang的测试用例参考:《ShardingSphere-Proxy 连接实战:从 Golang 原生 SQL 到 GORM 的应用》 背景 我们…...
学技术学英文:Tomcat的线程模型调优
导读: tomcat 线程调优关键需要理解下面这几个参数: 1. maxConnections 描述:指定服务器能够同时接受和处理的最大连接数。也就是说,服务器在任何时候都能处理的最大并发连接数。作用:限制服务器在任何给定时间点能…...
创建flutter项目遇到无法连接源的问题
Flutter 环境信息 Flutter版本: 3.19.4 (channel stable) Framework: revision 68bfaea224 (2024-03-20) Engine: revision a5c24f538d Dart: 3.3.2 DevTools: 2.31.1 项目基本信息 项目路径: D:\F\luichun 域名: www.luichun.com.cn 支持平台: android, web, windows 项目创…...
MAC系统QT图标踩坑记录
MAC系统QT图标踩坑记录 1. 准备图标1.1 方法一:下载准备好的图标1.2 方法二:自己生成图标1.2.1 准备一个png文件1.2.2 用sips生成不同大小的图片1.2.3 用iconutil生成图标文件 2. 配置图标2.1. 把图标改命成自己想要的名字,如icon.icns&#…...
TF-IDF(Term Frequency-Inverse Document Frequency)详解:原理和python实现(中英双语)
中文版 TF-IDF算法详解:理解与应用 TF-IDF(Term Frequency-Inverse Document Frequency)是信息检索与文本挖掘中常用的算法,广泛应用于搜索引擎、推荐系统以及各种文本分析领域。TF-IDF的核心思想是通过计算一个词在文档中的重要…...
【竞技宝】CS2:HLTV2024职业选手排名TOP15-xantares
北京时间2024年12月30日,HLTV年度选手排名正在持续公布中,今日凌晨正式公布了今年的TOP15选手为EternalFire战队的xantares选手。 选手简介 xantares是一名来自于土耳其的CS职业选手,出生于1995年,今年已经29岁。早在2012年&…...
Spring-kafka快速Demo示例
使用Spring-Kafka快速发送/接受Kafka消息示例代码,项目结构是最基础的SpringBoot结构,提前安装好Kafka,确保Kafka已经正确启动 pom.xml,根据个人情况更换springboot、java版本等 <?xml version"1.0" encoding&qu…...
客户案例:基于慧集通集成平台,打通屠宰管理系统与用友U8C 系统的全攻略
一、引言 本原型客户成立于2014年,是一家集饲草种植、肉牛养殖、精深加工、冷链物流、餐饮服务于一体的大型农牧综合体。公司下设三个子公司分别涵盖农业、畜牧业、肉制品加工业与餐饮物流服务业。公司严格按照一二三产业融合发展要求,以肉牛产业化为支…...
模型 九屏幕分析法
系列文章 分享 模型,了解更多👉 模型_思维模型目录。九屏幕法:全方位分析问题的系统工具。 1 九屏幕分析法的应用 1.1 新产品研发的市场分析 一家科技公司计划开发一款新型智能手机,为了全面评估市场潜力和风险,他们…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
pycharm 设置环境出错
pycharm 设置环境出错 pycharm 新建项目,设置虚拟环境,出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...
