unity Excel配置表导出工具
Posted 天涯过客TYGK
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity Excel配置表导出工具相关的知识,希望对你有一定的参考价值。
需要用到的dll插件
Excel格式:
第一行为标题
第二行设置是否是索引列,索引列的内容会被转成列表形式
第三行设置数据类型
后面添加数据具体内容
如果第一列内容为空,不读取本行内容,可以用来处理备注
(如果第一行标题为空,不读取这一列数据,默认为备注行,这个需求暂未添加)
一 、添加Excel 转json工具
using Excel;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using UnityEngine;
using UnityEditor;
public class MasterToJson
/// <summary>
/// 配置文件存放在项目根目录
/// </summary>
static string fileDirPath = @"ConfigExcel";
private static string outPath = "OutPutJson";
private static string KeyText = "k";
[MenuItem("Tool/Master To Json Text")]
static void ChangeToJson()
string excelFolderPath = Path.Combine(Application.dataPath, fileDirPath);
DirectoryInfo dir = new DirectoryInfo(excelFolderPath);
FileInfo[] fileInfos = dir.GetFiles("*", SearchOption.AllDirectories);
for (int i = 0; i < fileInfos.Length; i++)
ExportFile(fileInfos[i].FullName);
/// <summary>
/// 导出单个excel内容
/// </summary>
/// <param name="filePath"></param>
static void ExportFile(string filePath)
if (filePath.EndsWith("meta") || filePath.Contains("$")) return;
//取Excel名字的第一部分作为保存文件名称
Debug.Log(filePath);
string excelName = Path.GetFileNameWithoutExtension(filePath);
using (FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
IExcelDataReader excelDataReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
DataSet result = excelDataReader.AsDataSet();
DataTableCollection tables = result.Tables;
foreach (DataTable sheetTable in tables)
//Debug.Log("table sheet Name is " + sheetTable.TableName);
//获取需要转换的sheet标签页,sheet页名称不包含#并且不以下划线开头,#是备注类用的表,下划线是服务器用的表
if (sheetTable.TableName.IndexOf('#') == -1 && (sheetTable.TableName.IndexOf('_') > 0 || sheetTable.TableName.IndexOf('_') == -1))
ConvertSheetToJson(sheetTable, excelName);
excelDataReader.Dispose();
;
/// <summary>
/// 把单个sheet文件转json
/// </summary>
/// <param name="data"></param>
/// <param name="excelName"></param>
static void ConvertSheetToJson(DataTable sheetTable, string excelName)
int columIndex = 0;
int keyCount = 0;
int columnsCount = sheetTable.Columns.Count;
int rowCount = sheetTable.Rows.Count;
if (columnsCount <= 3 || rowCount <= 1)
Debug.Log("skip empty table:" + sheetTable.TableName);
return;
//List<string> titleList = new List<string>();
List<ColumData> paramsList = new List<ColumData>();
for (int i = 0; i < columnsCount; i++)
ColumData cData = new ColumData();
string content = sheetTable.Rows[2][i].ToString();
if (IsString(content)) cData.type = ParamsType.String;
else if(IsInt(content)) cData.type = ParamsType.Int;
else cData.type = ParamsType.None;
paramsList.Add(cData);
JSONObject tableJson = new JSONObject();
JSONObject contentJson = new JSONObject();
tableJson.AddField(sheetTable.TableName, contentJson);
bool isFinish = false;
for (int i = 0; i < rowCount; i++)
JSONObject job = new JSONObject();
for (int j = 0; j < columnsCount; j++)
if (i == 0)//标题
paramsList[j].name = sheetTable.Rows[i][j].ToString();
else if (paramsList[j].type != ParamsType.None)
if (i == 1)//索引类型 keyText 表示该列是索引
if (sheetTable.Rows[i][j].ToString().Equals(KeyText))
keyCount++;
paramsList[j].isKey = true;
else if (i == 2) continue;
else
if (j == 0 && string.IsNullOrEmpty(sheetTable.Rows[i][j].ToString())) //第一列内容为空,判定该表内容读取结束
continue;
if (!paramsList[j].isKey)
GetColumJson(sheetTable.Rows, 0, i, paramsList, job);
string res = job.ToString();
Debug.Log(res);
break;
if (job && !job.IsNull)
contentJson.Add(job);
SaveFile(tableJson.ToString(), excelName, sheetTable.TableName);
/// <summary>
/// 把表格单行数据转换为json对象
/// </summary>
/// <param name="item"></param>
/// <param name="columnIndex"></param>
/// <param name="rowIndex"></param>
/// <param name="paramsList"></param>
/// <param name="job"></param>
private static void GetColumJson(DataRowCollection item, int columnIndex, int rowIndex, List<ColumData> paramsList, JSONObject job)
if (columnIndex >= paramsList.Count) return;
if (paramsList[columnIndex].type == ParamsType.None)
columnIndex++;
GetColumJson(item, columnIndex, rowIndex, paramsList, job);
else if (paramsList[columnIndex].isKey && columnIndex > 0)
string arrKey = "index_list";
JSONObject jsonArr = new JSONObject();
JSONObject itemJson = new JSONObject();
jsonArr.Add(itemJson);
job.AddField(arrKey, jsonArr);
itemJson.AddField(paramsList[columnIndex].name, item[rowIndex][columnIndex].ToString());
columnIndex++;
GetColumJson(item, columnIndex, rowIndex, paramsList, itemJson);
else
job.AddField(paramsList[columnIndex].name, item[rowIndex][columnIndex].ToString());
columnIndex++;
GetColumJson(item, columnIndex, rowIndex, paramsList, job);
private static bool IsInt(string typeName)
if (typeName.ToLower().Contains("int") || typeName.ToLower().Contains("timestamp"))
return true;
return false;
private static bool IsString(string typeName)
if (typeName.ToLower().Contains("string") || typeName.ToLower().Contains("time") || typeName.ToLower().Contains("text"))
return true;
return false;
private static void SaveFile(string content, string excelName, string sheetName)
string groupName = excelName.Split('_')[0];
string saveFolderPath = Path.Combine(outPath, groupName);
saveFolderPath = Path.Combine(Application.dataPath, saveFolderPath);
if (!Directory.Exists(saveFolderPath))
Directory.CreateDirectory(saveFolderPath);
File.WriteAllText(Path.Combine(saveFolderPath, sheetName + ".json"), content);
protected enum ParamsType
None,
Int,
String,
protected class ColumData
public string name;
public ParamsType type;
public bool isKey;
二、添加Excel 转C#数据类工具
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Linq;
using Excel;
using System.Data;
public class MasterToCs
static List<string> masterNameList = new List<string>()
"unit_config.xlsx",
;
[MenuItem("Tool/Master To Client Template")]
public static void MasterExport()
foreach (var item in masterNameList)
MasterUtil.Export(item);
class MasterUtil
private const string TemplatePath = "/Editor/MasterToCS/Template/";
private const string TemplateOneKeyFile = "template_1key.txt";
private const string TemplateTwoKeyFile = "template_2key.txt";
private const string TemplateThreeKeyFile = "template_3key.txt";
private const string TemplateFourKeyFile = "template_4key.txt";
private const string TemplateParamFile = "template_param.txt";
// 直接更新所有的表文件,使用这个路径
private const string OutputPath = "output";
private const string TemplateFile = "";
private const string KeyText = "k";
private const string MasterUpperNameReplaceStr = "[MasterName]";
private const string MasterLowerNameReplaceStr = "[mastername]";
private const string ParamListStr = "[paramList]";
private const string MasterFilePath = @"ConfigExcel/";
public static string masterGroupName = "";
public static string outputFilePath = "";
static string appPath = Application.dataPath;
public static void Export(string masterFileName)
masterGroupName = "";
string[] tmpGroupName = masterFileName.Split('.')[0].Split('_');
for (int i = 0; i < tmpGroupName.Count() - 1; i++)
masterGroupName += GetUpperName(tmpGroupName[i]);
outputFilePath = OutputPath + "/" + masterGroupName;
outputFilePath = Path.Combine(Application.dataPath, outputFilePath);
//Debug.Log("输出文件名 : " + masterGroupName);
Debug.Log("输出路径 : " + outputFilePath);
if (!Directory.Exists(outputFilePath))
Debug.Log("创建路径" + outputFilePath);
Directory.CreateDirectory(outputFilePath);
#region excel
string masterFilePath = MasterFilePath + masterFileName;
masterFilePath = Path.Combine(Application.dataPath, masterFilePath);
if (!File.Exists(masterFilePath))
Debug.LogError("not exist path.." + masterFilePath);
return;
using (FileStream stream = File.Open(masterFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
IExcelDataReader excelDataReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
DataSet result = excelDataReader.AsDataSet();
DataTableCollection tables = result.Tables;
foreach (DataTable item in tables)
Debug.Log("tableName is "+item.TableName);
ConvertSheetToCs(item);
excelDataReader.Dispose();
;
Debug.Log("export template finish!");
#endregion
/// <summary>
/// 转换单个sheet表,生成对应的数据类
/// </summary>
/// <param name="sheet"></param>
static void ConvertSheetToCs(DataTable sheet)
//列数
int colNum = 0;
//主键个数
int keyCnt = 0;
List<ColumData> columList = new List<ColumData>();
while (true)
if (colNum >= sheet.Columns.Count) break;
string columName = sheet.Rows[0][colNum].ToString();
string columType = sheet.Rows[2][colNum].ToString();
if (columName == "")
break;
if (columType != "")
Debug.LogError(sheet.Rows[1][colNum].ToString().ToLower() + "-->" + colNum);
bool isKey = sheet.Rows[1][colNum].ToString().ToLower().Equals( KeyText ) ? true : false;
if (isKey)
keyCnt++;
//Debug.Log(columName + " (" + columType + "), isKey : " + isKey);
ColumData data = new ColumData(columName, columType, isKey);
columList.Add(data);
colNum++;
Debug.Log("keyCnt : " + keyCnt);
if (keyCnt == 1)
ConvertOneKeyMaster(sheet, columList);
if (keyCnt < 5 && keyCnt > 1)
ConvertTwoMoreKeyMaster(sheet, columList, keyCnt);
if (keyCnt >= 5)
Debug.LogError("========= 暂不支持5个以上主键,请添加template文件。");
/// <summary>
/// 包含单个主键的配置表
/// </summary>
/// <param name="sheet"></param>
/// <param name="columList"></param>
private static void ConvertOneKeyMaster(DataTable sheet, List<ColumData> columList)
string masterNameInLower = sheet.TableName;
string masterNameInUpper = GetUpperName(masterNameInLower);
Debug.Log("master class 名 : " + masterNameInLower + " / " + masterNameInUpper);
string appPath = Application.dataPath;
string template_file_path = appPath + TemplatePath + TemplateOneKeyFile;
Debug.Log("template file path : " + template_file_path);
if (!System.IO.File.Exists(template_file_path))
Debug.LogWarning("not find template!");
return;
string template_file_data = string.Empty;
using (System.IO.StreamReader sr = new System.IO.StreamReader(template_file_path))
template_file_data = sr.ReadToEnd();
template_file_data = template_file_data.Replace(MasterUpperNameReplaceStr, masterNameInUpper);
template_file_data = template_file_data.Replace(MasterLowerNameReplaceStr, masterNameInLower);
string template_param_file_path = appPath + TemplatePath + TemplateParamFile;
string param_template = "";
string param_str = "";
using (System.IO.StreamReader sr = new System.IO.StreamReader(template_param_file_path))
param_template = sr.ReadToEnd();
var keyList = columList.Where(t => t.isKey == true);
var paramList = columList.Where(t => t.isKey != true);
foreach (var k in keyList)
Debug.Log("Key is : " + k.name);
//string key_param = param_template.Replace("[param]", masterNameInUpper);
template_file_data = template_file_data.Replace("[key]", k.name);
template_file_data = template_file_data.Replace("[Key]", GetUpperName(k.name));
if (IsInt(k.type))
template_file_data = template_file_data.Replace("[key_type]", "int");
else if (IsString(k.type))
template_file_data = template_file_data.Replace("[key_type]", "string");
foreach (var param in paramList)
string paramNamaInUpper = GetUpperName(param.name);
string tmpStr = param_template.Replace("[param]", param.name);
if (IsInt(param.type))
tmpStr = tmpStr.Replace("[param_type]", "int");
else if (IsString(param.type))
tmpStr = tmpStr.Replace("[param_type]", "string");
param_str += tmpStr.Replace("[Param]", paramNamaInUpper);
template_file_data = template_file_data.Replace(ParamListStr, param_str);
string fileName = string.Format(@"0\\1.cs", outputFilePath, masterNameInUpper);
Debug.Log("output : " + fileName);
File.WriteAllText(fileName, template_file_data);
/// <summary>
/// 包含多个主键的配置表
/// </summary>
/// <param name="sheet"></param>
/// <param name="columList"></param>
private static void ConvertTwoMoreKeyMaster(DataTable sheet, List<ColumData> columList, int keyNum)
string masterNameInLower = sheet.TableName;
string masterNameInUpper = GetUpperName(masterNameInLower);
Debug.Log("master class 名 : " + masterNameInLower + " / " + masterNameInUpper);
string appPath = Application.dataPath;
string template_file_path = appPath + TemplatePath + TemplateTwoKeyFile;
if (keyNum == 3)
template_file_path = appPath + TemplatePath + TemplateThreeKeyFile;
if (keyNum == 4)
template_file_path = appPath + TemplatePath + TemplateFourKeyFile;
Debug.Log("template file path : " + template_file_path);
if (!System.IO.File.Exists(template_file_path))
Debug.LogWarning("not find template!");
return;
string template_file_data = string.Empty;
using (System.IO.StreamReader sr = new System.IO.StreamReader(template_file_path))
template_file_data = sr.ReadToEnd();
template_file_data = template_file_data.Replace(MasterUpperNameReplaceStr, masterNameInUpper);
template_file_data = template_file_data.Replace(MasterLowerNameReplaceStr, masterNameInLower);
string template_param_file_path = appPath + TemplatePath + TemplateParamFile;
string param_template = "";
string param_str = "";
using (System.IO.StreamReader sr = new System.IO.StreamReader(template_param_file_path))
param_template = sr.ReadToEnd();
var keyList = columList.Where(t => t.isKey == true);
var paramList = columList.Where(t => t.isKey != true);
int keyCnt = 1;
foreach (var k in keyList)
Debug.Log("Key" + keyCnt + " is : " + k.name);
template_file_data = template_file_data.Replace("[key" + keyCnt + "]", k.name);
template_file_data = template_file_data.Replace("[Key" + keyCnt + "]", GetUpperName(k.name));
if (IsInt(k.type))
template_file_data = template_file_data.Replace("[key_type" + keyCnt + "]", "int");
else if (IsString(k.type))
template_file_data = template_file_data.Replace("[key_type" + keyCnt + "]", "string");
keyCnt++;
foreach (var param in paramList)
string paramNamaInUpper = GetUpperName(param.name);
string tmpStr = param_template.Replace("[param]", param.name);
if (IsInt(param.type))
tmpStr = tmpStr.Replace("[param_type]", "int");
else if (IsString(param.type))
tmpStr = tmpStr.Replace("[param_type]", "string");
param_str += tmpStr.Replace("[Param]", paramNamaInUpper);
template_file_data = template_file_data.Replace(ParamListStr, param_str);
string fileName = string.Format(@"0\\1.cs", outputFilePath, masterNameInUpper);
Debug.Log("output : " + fileName);
File.WriteAllText(fileName, template_file_data);
private static string GetUpperName(string name)
string[] tmpNameArray = name.Split('_');
string nameInUpper = "";
System.Globalization.TextInfo ti = System.Globalization.CultureInfo.CurrentCulture.TextInfo;
foreach (var t in tmpNameArray)
nameInUpper += ti.ToTitleCase(t);
return nameInUpper;
private static bool IsInt(string typeName)
if (typeName.ToLower().Contains("int") || typeName.ToLower().Contains("timestamp"))
return true;
return false;
private static bool IsString(string typeName)
if (typeName.ToLower().Contains("string") || typeName.ToLower().Contains("time") || typeName.ToLower().Contains("text"))
return true;
return false;
public class ColumData
public string name;
public string type;
public bool isKey;
public ColumData(string _name, string _type, bool _isKey)
name = _name;
type = _type;
isKey = _isKey;
转换时候用到的模板文件 template_1key.txt
/*******************************************
* 从主 Excel 自动生成的文件 *
* 不要手动修改该文件! *
*******************************************/
using System.Collections.ObjectModel;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Linq;
namespace Master
public class [MasterName]Data : ISerializationCallbackReceiver
/// <summary>
/// 序列化列表
/// </summary>
[SerializeField]
private List<[MasterName]DataFormat> [mastername];
/// <summary>
/// 私有Dictionary
/// </summary>
private ReadOnlyDictionary<[key_type], [MasterName]DataFormat> _[mastername];
/// <summary>
/// 属性Dictionary
/// key:[key]
/// </summary>
public ReadOnlyDictionary<[key_type], [MasterName]DataFormat> [MasterName]Dic get return _[mastername];
public void OnAfterDeserialize()
if (_[mastername] != null)
_[mastername] = null;
_[mastername] = new ReadOnlyDictionary<[key_type], [MasterName]DataFormat>([mastername].ToDictionary(key => key.[Key], value => value));
public void OnBeforeSerialize()
[Serializable]
public class [MasterName]DataFormat
[SerializeField]
private [key_type] [key];
public [key_type] [Key] get return [key];
[paramList]
template_2key.txt
/*******************************************
* 从主 Excel 自动生成的文件 *
* 不要手动修改该文件! *
*******************************************/
using System.Collections.ObjectModel;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Linq;
namespace Master
public class [MasterName]Data : ISerializationCallbackReceiver
/ <summary>
/// 序列化列表
/// </summary>
[SerializeField]
private List<[MasterName]DataFormat> [mastername];
/// <summary>
/// 私有Dictionary
/// </summary>
private ReadOnlyDictionary<[key_type1], [MasterName]DataFormat> _[mastername];
/// <summary>
/// 属性Dictionary
/// key:unit id
/// </summary>
public ReadOnlyDictionary<[key_type1], [MasterName]DataFormat> [MasterName]Dic get return _[mastername];
public void OnAfterDeserialize()
if (_[mastername] != null)
_[mastername] = null;
_[mastername] = new ReadOnlyDictionary<[key_type1], [MasterName]DataFormat>([mastername].ToDictionary(key => key.[Key1], value => value));
public void OnBeforeSerialize()
[Serializable]
public class [MasterName]DataFormat : ISerializationCallbackReceiver
[SerializeField]
private [key_type1] [key1];
public [key_type1] [Key1] get return [key1];
/ <summary>
/// 序列化列表
/// </summary>
[SerializeField]
private List<[MasterName]IndexFormat> index_list;
/// <summary>
/// 私有Dictionary
/// </summary>
private ReadOnlyDictionary<[key_type2], [MasterName]IndexFormat> _index_list;
/// <summary>
/// 属性Dictionary
/// key:unit id
/// </summary>
public ReadOnlyDictionary<[key_type2], [MasterName]IndexFormat> Index get return _index_list;
public void OnAfterDeserialize()
if (_index_list != null)
_index_list = null;
_index_list = new ReadOnlyDictionary<[key_type2], [MasterName]IndexFormat>(index_list.ToDictionary(key => key.[Key2], value => value));
public void OnBeforeSerialize()
[Serializable]
public class [MasterName]IndexFormat
[SerializeField]
private [key_type2] [key2];
public [key_type2] [Key2] get return [key2];
[paramList]
三、运行过程中读取json文件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ConfigManger : MonoBehaviour
public TextAsset fonfigJson;
void Start()
string content = fonfigJson.text;
Master.UnitData unitData = JsonUtility.FromJson<Master.UnitData>(content);
Debug.Log(unitData.UnitDic.Count);
foreach (var item in unitData.UnitDic)
Debug.Log(item.Value.Name);
资源下载地址: 前往下载
以上是关于unity Excel配置表导出工具的主要内容,如果未能解决你的问题,请参考以下文章