政府 內(nèi)部 網(wǎng)站沈陽網(wǎng)絡(luò)優(yōu)化培訓
功能說明:根據(jù) .xlsx
文件生成對應(yīng)的 JSON 文件,并自動創(chuàng)建腳本
注意事項
-
Excel 讀取依賴
本功能依賴EPPlus
庫,只能讀取.xlsx
文件。請確保將該腳本放置在Assets
目錄下的Editor
文件夾中。同時,在Editor
下再創(chuàng)建一個Excel
目錄,并將你的.xlsx
文件放到Excel
目錄下。注意:該目錄下只能有一個.xlsx
文件,且該文件是唯一的數(shù)據(jù)源。- Excel 文件格式要求:
- 第一行:字段名(與自動生成腳本中的字段對應(yīng))。
- 第二行:中文注釋。
- 第三行:字段的數(shù)據(jù)類型(目前支持
int
、float
、double
、string
、bool
和數(shù)組類型,如int[]
、string[]
)。 - 第四行開始:實際數(shù)據(jù)。
- Epplus依賴獲取查看我的另一篇文章Nuget For Unity插件介紹_nugetforunity-CSDN博客
- Excel 文件格式要求:
?
-
生成腳本與 JSON 文件
使用編輯器中的 ExcelTool 進行生成,點擊 讀取 Excel 按鈕后,將自動執(zhí)行以下操作:- 刪除之前生成的腳本目錄和 JSON 目錄(如果存在),然后重新生成它們。
- 注意:在這兩個目錄下請不要放置其他文件,因為此工具會在每次生成時覆蓋這些目錄。
-
關(guān)于數(shù)組格式
數(shù)組數(shù)據(jù)需要按如下格式寫入:
例如:1|2|3
。數(shù)組成員使用|
分隔。 -
支持多 sheet
一個.xlsx
文件中可以包含多個 sheet。在讀取時,工具會讀取所有 sheet 數(shù)據(jù)。請注意:- 將每個 sheet 的名字改為與要生成的腳本名一致。
- Sheet 名稱必須符合 C# 的命名規(guī)范,建議使用
TB_
開頭。
提示
- 腳本命名:請確保每個 sheet 的名字與生成的 C# 腳本的名稱一致。
- 字段類型:當前支持的字段類型包括基本數(shù)據(jù)類型(
int
、float
、double
、string
、bool
)以及數(shù)組類型(如int[]
、string[]
)。 - 感謝原作者:特別感謝原作者“小人”的貢獻,我僅添加了一些功能,以下是他在 B站的教程視頻地址:Unity中簡單根據(jù)excel文件自動生成對應(yīng)的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;/*功能:根據(jù).xlsx文件生成對應(yīng)的json文件,并自動創(chuàng)建腳本注意:一 Excel讀取依賴EPPlus,只能讀.xlsx文件,Asset下創(chuàng)建一個Editor,同時將該腳本放到Editor下然后在Editor下再創(chuàng)建一個Excel目錄,然后將你的Excel文件放到Excel目錄下,注意Excel目錄下只能有一個Excel文件,同時Excel格式要符合下列要求,最后Excel是唯一的數(shù)據(jù)源,所以除了保護好你的Excel文件外,其他的可以重新生成.使用編輯器上的ExcelTool/讀取Excel按鈕生成Json和腳本使用該按鈕會刪除腳本目錄和json目錄然后重新生成(如果已經(jīng)生成過),所以不要在這兩個目錄下放置其他文件.二 xlsx第一行為英文字段與自動生成腳本中的字段對應(yīng)第二行為中文注釋第三行為字段的數(shù)據(jù)類型,目前支持int float double string bool 數(shù)組數(shù)組的寫法統(tǒng)一為基本數(shù)據(jù)類型+[] 如int[] 、string[]第四行開始為實際數(shù)據(jù)三 xlsx文件中可以有很多sheet.讀取時會讀取xlsx的全部sheet要將對應(yīng)的sheet的名字改為與要生成的腳本名一致,所以sheet名要符合C#的命名規(guī)范,建議使用TB_開頭四 數(shù)組的書寫格式形如:1|2|3,數(shù)組成員使用|分隔五 感謝原作者小人,我僅做了一些功能補充,下面的地址是小人的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 結(jié)尾的文件(不包括子目錄中的文件)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);}}// 將絕對路徑轉(zhuǎn)為相對路徑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 目錄內(nèi): " + absolutePath);return absolutePath;}/// <summary>/// 讀取 .xlsx文件,獲取第一張sheet的內(nèi)容/// </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除注釋行之外的相關(guān)數(shù)據(jù)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}個單元格數(shù)據(jù)為空");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}個單元格數(shù)據(jù)為空");return null;}string field = worksheet.Cells[3, i].Value.ToString();fieldType.Add(field);}//取實際數(shù)據(jù)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}個單元格數(shù)據(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>/// 判斷字符串列表中是否包含重復(fù)成員,有,返回true/// </summary>/// <param name="list"></param>/// <returns></returns>private static bool HasRepeatedMember(List<string> list){//往HaseSet中添加字符串,若不成功添加,說明有重復(fù)字符串 HashSet<string> hashSet = new HashSet<string>();for (int i = 0; i < list.Count; i++){if (!hashSet.Add(list[i])){return true;}}return false;}/// <summary>/// 創(chuàng)建一個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}中字段名應(yīng)以字母開頭");return;}}//避免生成字段重復(fù)if (HasRepeatedMember(fieldName)){Debug.LogError($"{scriptName}中出現(xiàn)重復(fù)字段");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>/// 創(chuàng)建json文件/// </summary>/// <param name="jsonName">json文件名</param>;/// <param name="fieldType">字段類型列表</param>/// <param name="fieldName">字段名列表</param>/// <param name="dataDic">實際數(shù)據(jù)字典</param>private static void CreateAJson(string jsonName, List<string> fieldType, List<string> fieldName, Dictionary<int, List<string>> dataDic){//寫一行數(shù)據(jù)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);//不是最后一項數(shù)據(jù),加逗號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轉(zhuǎn)為一行json/// </summary>/// <param name="fieldType">字段類型列表</param>/// <param name="fieldName">字段名列表</param>/// <param name="dataList">實際一行數(shù)據(jù)</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("表格實際數(shù)據(jù)存在未配置項");}sb.Append($"{Convert(type, value)}");//寫入逗號//不是最后一個就是逗號if (i != fieldType.Count - 1){sb.Append(",");}}sb.Append("}");return sb.ToString();}//根據(jù)類型獲取鍵所對應(yīng)的值//如果不是數(shù)組 返回類型為 "Key":"Value" 中的value//如果是數(shù)組 返回類似于 ["1","2"] 的結(jié)構(gòu)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>/// 將數(shù)組轉(zhuǎn)換成對應(yīng)的字符串/// </summary>/// <param name="value"></param>/// <returns></returns>private static string ArrayParse(string value){//切分字符串得到數(shù)組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('"');//不是數(shù)組最后一個加,if (i != res.Length - 1){sb.Append(",");}}sb.Append("]");return sb.ToString();}}
?
直接獲取該項目
ExcelToJson: ExcelToJson
總結(jié)
該工具可以幫助你輕松地將 .xlsx
文件中的數(shù)據(jù)轉(zhuǎn)換為 JSON 文件,并自動生成對應(yīng)的 C# 腳本,簡化了數(shù)據(jù)處理和代碼生成的流程。在使用時,務(wù)必遵循 Excel 文件格式要求,確保生成的腳本和 JSON 文件符合預(yù)期。
?