[编程工具]UnityGameFramework配表多语言导出工具(二)Program,Exportor,Property

0. 前言

项目已经开源,源代码相关文章在见下方链接,本文为该项目的结构解释。

[编程工具]UnityGameFramework配表多语言导出工具(零)使用概述以及源码
https://blog.csdn.net/Blue_carrot_/article/details/130280639
[编程工具]UnityGameFramework配表多语言导出工具(一)Config,XML,Log
https://blog.csdn.net/Blue_carrot_/article/details/130313674

1. Program

ok,我们书接上回,今天讲讲Program,程序入口,其实主要就是两个内容,一个是加载配置,二是处理。最后做结果输出以及是否暂停等待。如下:

static void Main(string[] args)
{
    
    
   // 加载配置
   Config.LoadFromXss();

   // 处理文件
   if (!Log.ErrorFlag) 
   {
    
    
         Exportor e = new Exportor();
         e.Precess();
   }

   // 结束
   if (Log.ErrorFlag)
   {
    
    
         Log.PrintLog("处理失败");
   }
   else 
   {
    
    
         Log.PrintLog("处理完成");
   }

   // 等待
   if ((Log.ErrorFlag && Config.IsWaitWhenFail) ||
         (!Log.ErrorFlag && Config.IsWaitWhenSucceed))
   {
    
    
         Console.ReadLine();
   }
}

这个其实后面可以再做输入参数处理,比如把config的配置路径处理为可配置的,比如cmd上打“exporter.exe config2.xlsx”,这样的方式来使用第二种配置,不过这个后面有需求再改吧。

然后,Config上次已经讲过了,就是配置以及加载配置的内容,而Exportor,我们先需要讲一下Property。

2. Property

这个是每个sheet中属性的基本单元,每一列都会视为是一个属性,比如map表格如下,

different outputKey
Id NextId MapType Name
int int int string
Id NextId MapType Name
序号 下一个序号 地图类型 名字
1 2 1001 射击引导
2 3 1002 方块引导

那我们是希望能够导出为4个属性,Id NextId MapType Name,这4个属性,那么可以看出,对于每个属性,我们可以将其抽象为Property,那么他需要的属性有

public int Column;
public string Name;
public string Type;
public string Note;
public string Setting;
public List\<string\> Content;
  • column—所在行,这个是为了方便后续数据载入。
  • Name—属性名
  • Type—属性类型
  • Note—属性注释
  • Content—属性数据,也就是这个属性行对应的数据。
  • Setting—处理标记,暂时处理了两种,different要求数据完全不同,outputKey是指该属性需要导出为多语言key。

因为我们还需要对属性的数据做校验,格式化,或者其他标记的处理,这让我们不能够只是单纯的将数据Add到Content。比如表格中的【id】属性,标记为different,那如果之前存在该属性,则不应该导出成功,所以我们可以将数据添加处理为

public void Add(string fileName, string sheetName,int rowIndex,string content)
{
    
    
   // 格式化
   content = FormatContent(Type , content);

   // 检查
   if (isDifferent && Content.Contains(content))
   {
    
    
         // 判断是否重复
         content = "";
         Log.PrintCellError(rowIndex, Column, "当前属性设置标记为isDifferent,属性不可重复。该位置属性已重复。");
   }
   else if (!tryPrase(Type, content))
   {
    
    
         // 转化数据失败
         content = "";
         Log.PrintCellError(rowIndex, Column, "当前属性类型为"+ Type+ ",此数据并不是该类型,转换失败。");
   }

   // 加入
   Content.Add(content);
}

具体格式化FormatContent以及tryPrase几个函数就不展开了,基本就是int.Parse这种,检查之类的。

3. Exportor

Exporter是处理导出文件的内容。首先我们要将文件先打开,获取文件sheet数据逐一处理。每个sheet都视为一个数据类,那么对于单独一个sheet,我们需要做的有三件事

  • 加载解析数据为Property属性(getSheetData),
  • 保存数据文件(saveSheetData),
  • 保存代码文件(saveSheetCode),

那么processSheet这部分内容就如下:

private bool processSheet(string fileName, string sheetName, List<List<string>> sheetData)
{
    
    
   bool flag = false;
   List<Property> properties = getSheetData(fileName, sheetName, sheetData);
   if (properties != null)
   {
    
    
         try
         {
    
    
            saveSheetData(fileName, sheetName, properties);
            flag = true;
         }
         catch
         {
    
    
            Log.PrintError("保存数据文件错误");
         }

         try
         {
    
    
            saveSheetCode(fileName, sheetName, properties);
            flag = true;
         }
         catch
         {
    
    
            Log.PrintError("保存代码文件错误");
         }
   }
   return flag;
}

getSheetData

对于解析表格数据为属性,我的做法是先将数据按列处理,把所有的属性名字,类型都获取,然后再按行,将每一行对应的数据录入。具体如下:

private List<Property> getSheetData(string fileName, string sheetName, List<List<string>> sheetData)
{
    
    
   List<Property> properties = new List<Property>();
   List<string> firstList = GetRowData(sheetData,0);
   List<string> settingList = GetRowData(sheetData, Config.PropertySettingRow);
   List<string> nameList = GetRowData(sheetData, Config.PropertyNameRow);
   List<string> typeList = GetRowData(sheetData, Config.PropertyTypeRow);
   List<string> noteList = GetRowData(sheetData, Config.PropertyNoteRow);
   HashSet<string> nameHashSet = new HashSet<string>();

   //读取属性
   for (int i = 0; i < nameList.Count; i++)
   {
    
    
      string first = GetCellString(firstList, i);
      string setting = GetCellString(settingList, i);
      string name = GetCellString(nameList, i);
      string type = GetCellString(typeList, i);
      string note = GetCellString(noteList, i);
      if (name == "")
      {
    
    
      }
      else if (Config.IsIgnoreColumnWhichFirstRowIsHashTag && first == "#")
      {
    
    
      }
      else if (!nameHashSet.Add(name))
      {
    
    
         Log.PrintCellError(Config.PropertyNameRow, i, "属性重复," + name);
      }
      else if (Array.IndexOf(matchType, type) < 0)
      {
    
    
         //Console.WriteLine("matchType:" + matchType.Length);
         //Console.WriteLine("type:" + type);
         //属性错误
         Log.PrintCellError(Config.PropertyTypeRow, i, "属性类型错误," + type);
      }
      else 
      {
    
    
         Property property = new Property(i, name, type, note, setting);
         properties.Add(property);
      }
   }

   //读取属性值
   for (int r = Config.PropertyStartRow; r < sheetData.Count; r++)
   {
    
    
      List<string> row = sheetData[r];
      string firstCell = GetCellString(row, 0);
      string firstValue = properties.Count > 0 ? GetCellString(row, properties[0].Column) : "";
      if (Config.IsIgnoreColumnWhichFirstRowIsHashTag && firstCell == "#") {
    
     }
      else if (Config.IsIgnoreRowWhichFirstPropertyIsEmpty && firstValue == "") {
    
     }
      else
      {
    
    
         foreach (Property item in properties)
         {
    
    
               item.Add(fileName, sheetName, r, GetCellString(row, item.Column));
         }
      }
   }
	return properties;
}

private List<string> GetRowData(List<List<string>> sheetData, int row)
{
    
    
   return row >= sheetData.Count ? null : sheetData[row];
}

private string  GetCellString(List<string> rowData, int column)
{
    
    
   return rowData == null || column >= rowData.Count ? "" : rowData[column];
}

saveSheetData

这部分内容,就是将properties中的数据依次加上制表符导出到文件中就可以了,因为UGF中也是按制表符划分的。这里如果有多语言导出配置,其实要保存到数据是key,而内容content也需要做一个额外记录,以便在最后导出多语言文件。


private void saveSheetData(string fileName, string sheetName,  List<Property> properties)
{
    
    
   string savePath = Config.SaveDataPath + "\\" + Config.GetDataFileName(fileName, sheetName);
   // Log.PrintError(savePath);
   List<StringBuilder> strList = new List<StringBuilder>();
   int cCount = properties.Count;

   for (int c = 0; c < cCount; c++)
   {
    
    
         if (properties[c].IsOutputKey)
         {
    
    
            OutputLog.Add(Config.GetOutputKeyNode(fileName, sheetName, properties[c]).ToString());
         }
         List<string> content = properties[c].Content;
         int rCount = content.Count;
         for (int r = 0; r < rCount; r++)
         {
    
    
            while (strList.Count <= r)
            {
    
    
               strList.Add(new StringBuilder());
            }

            if (properties[c].IsOutputKey && content[r] != "")
            {
    
    
               //id:properties[0].Content[r]
               //value:properties[0].Content[r]
               string key = Config.GetOutputKeyText(fileName, sheetName, properties[c], properties[0].Content[r]).ToString();
               OutputLog.Add(Config.GetOutputKeyItem(fileName, sheetName, key, content[r], properties[c]).ToString());
               strList[r].Append("\t" + key);
            }
            else {
    
    
               strList[r].Append("\t" + content[r]);
            }
         }
   }

   StringBuilder result = new StringBuilder();
   for (int i = 0; i < strList.Count; i++)
   {
    
    
         result.Append(strList[i].Remove(0, 1));
         result.Append('\n');
   }
   if (result.Length>=1) {
    
    
         result.Remove(result.Length - 1, 1);
   }
   File.WriteAllText(savePath, result.ToString());
}

saveSheetCode

保存代码这部分内容为了让代码内容方便更改,使用的是模板替换的方式来处理的,这样如果后面只是想改改缩进,或者函数名,基础之类的,只要改模板就可以了。这个部分,假如模板是
在这里插入图片描述
那么红色的部分都回替换为对应的内容,而蓝色的标记,主要是为了重复属性段而做的。具体的导出代码就不放了比较长。

到这里就已经将sheet都已经处理完了。Exporter的内容就是逐一处理表格(导出数据和代码),然后再统一导出多语言xml,然后就结束了。

4. 结束

到这里已经将项目都讲完了,不过项目还有很多可以改进的点,或者新增的内容。比如

  • 增加字典类型数据,只有数组有些时候还是不是很方便
  • 处理多文件同名sheet导出为同个文件,方便多人版本协同
  • 增加关联属性,如果能够关联到别的表,或者别的数据类型会更好,不过这个感觉不是很容易改。

猜你喜欢

转载自blog.csdn.net/Blue_carrot_/article/details/130314595
今日推荐