Files
ExcelTool/README.md
T
Oliver 965998b56f feat(refactor): introduce configuration-based Excel table processing
- Replace command-line options with single tables file configuration
- Add TablesConfig class for parsing table configuration from Excel
- Add TableEntry class for storing table configuration data
- Change GetCellValue method visibility from static to internal static
- Simplify Program.cs command line interface with single --tables option
- Add error handling for missing files and directories
- Update README with new usage instructions and examples
- Remove deprecated command-line option descriptions
2026-04-13 12:37:16 +08:00

300 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ExcelTool
本项目基于 https://github.com/dingxiaowei/ExcelTool 开发。用于 [AudioSystem](https://github.com/htw128/UnityAudioExtend), [HapticSystem](https://github.com/htw128/UnityAudioExtend#Haptic) 导出数据使用。
#### 功能
* 生成对应的数据模板代码
* 支持生成模板代码字段注释
* 生成二进制文件
* 自动将文件拷贝到对应的工程目录
* 二进制数据读取
* 字段不配置会使用默认数值
#### 目前支持的字段
* 常规的字段,例如intfloatstringboollong,list,intlist,longlist,floatlist,boollist,List<T> 大小写不限
* 支持自定义字段 vector,例如[1,2,3]
* 支持自定义字段 list,其实是vector数组,例如[[1,2,3],[2,3,4],[4,5,6]]
##### 自动生成的模板代码
```c#
/*
* auto generated by tools(注意:千万不要手动修改本文件)
* avatarguideTest
*/
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Linq;
[Serializable]
public class avatarguideTest : IBinarySerializable
{
public int Id { get; set; }
public string gender { get; set; }
public float age { get; set; }
public bool bValue { get; set; }
public List<float> vector { get; set; }
public List<List<float>> Grid { get; set; }
public void DeSerialize(BinaryReader reader)
{
Id = reader.ReadInt32();
gender = reader.ReadString();
age = reader.ReadSingle();
bValue = reader.ReadBoolean();
var vectorCount = reader.ReadInt32();
if (vectorCount > 0)
{
vector = new List<float>();
for (int i = 0; i < vectorCount; i++)
{
vector.Add(reader.ReadSingle());
}
}
else
{
vector = null;
}
var GridCount = reader.ReadInt32();
if (GridCount > 0)
{
Grid = new List<List<float>>();
for (int i = 0; i < GridCount; i++)
{
var tempList = new List<float>();
var tempListCount = reader.ReadInt32();
for (int j = 0; j < tempListCount; j++)
{
tempList.Add(reader.ReadSingle());
}
Grid.Add(tempList);
}
}
else
{
Grid = null;
}
}
public void Serialize(BinaryWriter writer)
{
writer.Write(Id);
writer.Write(gender);
writer.Write(age);
writer.Write(bValue);
if (vector == null || vector.Count == 0)
{
writer.Write(0);
}
else
{
writer.Write(vector.Count);
for (int i = 0; i < vector.Count; i++)
{
writer.Write(vector[i]);
}
}
if (Grid == null || Grid.Count == 0)
{
writer.Write(0);
}
else
{
writer.Write(Grid.Count);
for (int i = 0; i < Grid.Count; i++)
{
writer.Write(Grid[i].Count);
for (int j = 0; j < Grid[i].Count; j++)
{
writer.Write(Grid[i][j]);
}
}
}
}
public override string ToString()
{
var str = $"Id:{Id} Gender:{gender} age:{age} bValue:{bValue} ";
if (vector != null)
{
str += $"vector:[{vector[0]},{vector[1]},{vector[2]}] ";
}
if (Grid != null)
{
str += "Grid:[";
for (int i = 0; i < Grid.Count; i++)
{
str += $"[{Grid[i][0]},{Grid[i][1]},{Grid[i][2]}]";
if (i < Grid.Count - 1)
str += ",";
}
str += "]";
}
return str;
}
}
[Serializable]
public partial class avatarguideTestConfig : IBinarySerializable
{
public List<avatarguideTest> avatarguideTestInfos = new List<avatarguideTest>();
public void DeSerialize(BinaryReader reader)
{
int count = reader.ReadInt32();
for (int i = 0;i < count; i++)
{
avatarguideTest tempData = new avatarguideTest();
tempData.DeSerialize(reader);
avatarguideTestInfos.Add(tempData);
}
}
public void Serialize(BinaryWriter writer)
{
writer.Write(avatarguideTestInfos.Count);
for (int i = 0; i < avatarguideTestInfos.Count; i++)
{
avatarguideTestInfos[i].Serialize(writer);
}
}
public IEnumerable<avatarguideTest> QueryById(int id)
{
var datas = from d in avatarguideTestInfos
where d.Id == id
select d;
return datas;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < avatarguideTestInfos.Count; i++)
{
sb.Append($"{avatarguideTestInfos[i].ToString()}\n");
}
return sb.ToString();
}
}
```
#### 使用案例
##### 解析二进制文件
```c#
IBinarySerializable newavList = new avatarguideTestList();
var readOK = FileManager.ReadBinaryDataFromFile(Path.Combine(path, "avatarguideTest.dat"), ref newavList);
if (readOK)
{
ConsoleHelper.WriteInfoLine(newavList.ToString());
}
else
{
ConsoleHelper.WriteErrorLine("读取失败");
}
```
![](img/3.jpg)
##### Unity解析二进制
将二进制文件(后缀必须是.bytes)放在Resources目录,然后通过Resources.Load接口加载
```c#
var bytes = Resources.Load<TextAsset>("avatarguideTest");
if (bytes == null)
{
return;
}
IBinarySerializable newavList = new avatarguideTestConfig();
var readOK = FileManager.ReadBinaryDataFromBytes(bytes.bytes, ref newavList);
if (readOK)
{
Debug.Log(newavList.ToString());
//根据Id查询数据
//var avatarguideTest = (avatarguideTestConfig)newavList;
//var obj = avatarguideTest.QueryById(2);
//if (obj != null && obj.Count() > 0)
// Debug.Log(obj.FirstOrDefault().ToString());
}
else
{
Debug.LogError("数据读取错误");
}
```
#### 泛型读表
```c#
T ReadTable<T>(string tableName) where T : IBinarySerializable, new()
{
var bytes = LoadTextAsset(tableName);
if (bytes != null)
{
IBinarySerializable data = new T();
var readOK = FileManager.ReadBinaryDataFromBytes(bytes.bytes, ref data);
if (readOK)
{
return (T)data;
}
else
{
Debug.LogError($"{tableName}解析出错 类型{typeof(T)}");
}
}
return default(T);
}
```
##### 查询数据
```c#
var avatarguideTest = (avatarguideTestConfig)newavList;
var obj = avatarguideTest.QueryById(2);
if (obj != null && obj.Count() > 0)
ConsoleHelper.WriteInfoLine(obj.FirstOrDefault().ToString());
```
#### 自动化拷贝批处理
```batch
@echo off
echo "开始拷贝jsons"
for %%i in (*.dat) do (
echo begin copy... %%i
copy /y %%~nxi ..\..\hola_unity\Assets\Resources\Config\%%~nxi
echo copy complate ... %%i
)
echo "拷贝完成"
pause
```
#### 扩展类方法
上面的config类采用的是partical class 就是为了方便扩展自定义的方法,如果想要添加自定义方法也定义一个partical class文件作为扩展即可
#### TODO
* [x] 支持枚举类型
* [ ] 支持不同表不同namespace
* [ ] 支持Excel数据配置规范性检测,例如手误配置不符合规范导致加载异常,例如大小写逗号(肉眼容易忽略),或者空格等等
* [ ] ID不能重复
* [ ] MusicContainer不能自引用
* [ ] 同时播放的音乐BPM必须一致
* [ ] 生成CueSheet避免magic number
* [ ] 支持更多自定义数据类型扩展
#### Unity客户端使用范例
采用的美术效果机型适配商业化解决方案Demo
https://github.com/dingxiaowei/DeviceGrading
优雅的表格使用范本