diff --git a/src/Luban.Job.Cfg/Luban.Job.Cfg.csproj b/src/Luban.Job.Cfg/Luban.Job.Cfg.csproj index 34800e1..ecaa4ac 100644 --- a/src/Luban.Job.Cfg/Luban.Job.Cfg.csproj +++ b/src/Luban.Job.Cfg/Luban.Job.Cfg.csproj @@ -14,6 +14,7 @@ + diff --git a/src/LubanAssistant/FillSheetVisitor.cs b/src/Luban.Job.Cfg/Source/DataConverts/FillSheetVisitor.cs similarity index 98% rename from src/LubanAssistant/FillSheetVisitor.cs rename to src/Luban.Job.Cfg/Source/DataConverts/FillSheetVisitor.cs index 7b8282c..c75afb8 100644 --- a/src/LubanAssistant/FillSheetVisitor.cs +++ b/src/Luban.Job.Cfg/Source/DataConverts/FillSheetVisitor.cs @@ -2,16 +2,15 @@ using Luban.Job.Cfg.DataSources.Excel; using Luban.Job.Cfg.DataVisitors; using Luban.Job.Cfg.Defs; -using Microsoft.Office.Interop.Excel; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -namespace LubanAssistant +namespace Luban.Job.Cfg.DataConverts { - class FillSheetVisitor : IDataFuncVisitor + public class FillSheetVisitor : IDataFuncVisitor { private readonly List _cells; diff --git a/src/Luban.Job.Cfg/Source/DataConverts/TitleCreator.cs b/src/Luban.Job.Cfg/Source/DataConverts/TitleCreator.cs new file mode 100644 index 0000000..7f3a607 --- /dev/null +++ b/src/Luban.Job.Cfg/Source/DataConverts/TitleCreator.cs @@ -0,0 +1,298 @@ +using Luban.Job.Cfg.DataSources.Excel; +using Luban.Job.Cfg.Defs; +using Luban.Job.Cfg.TypeVisitors; +using Luban.Job.Common.Types; +using Luban.Job.Common.TypeVisitors; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Luban.Job.Cfg.DataConverts +{ + class TitleCreator : ITypeActionVisitor + { + public static TitleCreator Ins { get; } = new(); + + public Title CreateTitle(DefTable table) + { + TBean type = table.ValueTType; + //if (bean.IsDynamic) + //{ + // throw new Exception($"bean:{bean.Bean.FullName} 是多态bean,暂不支持"); + //} + var title = new Title() + { + Root = true, + Name = "__root__", + Tags = new Dictionary(), + FromIndex = 1, + }; + + int lastColumn = 0; + + if (type.IsDynamic) + { + title.AddSubTitle(new Title() + { + Name = "__type__", + FromIndex = lastColumn + 1, + ToIndex = lastColumn + 1, + Tags = new Dictionary(), + }); + ++lastColumn; + } + + var fields = type.IsDynamic ? type.Bean.HierarchyNotAbstractChildren.SelectMany(c => c.HierarchyFields) : type.Bean.HierarchyFields; + + foreach (var f in fields) + { + if (title.SubTitles.ContainsKey(f.Name)) + { + continue; + } + int startColumn = lastColumn + 1; + var subTitle = new Title() + { + Name = f.Name, + FromIndex = startColumn, + ToIndex = startColumn, + Tags = new Dictionary(), + }; + if (f.CType.Tags.TryGetValue("sep", out var sep)) + { + subTitle.Tags.Add("sep", sep); + } + if (f.CType.Tags.TryGetValue("multi_rows", out var multiRows)) + { + subTitle.Tags.Add("multiRows", multiRows); + } + + f.CType.Apply(this, subTitle, startColumn); + lastColumn = subTitle.ToIndex; + title.AddSubTitle(subTitle); + } + title.ToIndex = Math.Max(lastColumn, 1); + + if (table.IsMapTable) + { + title.SubTitles[table.IndexField.Name].Tags.TryAdd("non_empty", "1"); + } + title.Init(); + return title; + } + + public void Accept(TBool type, Title title, int column) + { + + } + + public void Accept(TByte type, Title title, int column) + { + + } + + public void Accept(TShort type, Title title, int column) + { + + } + + public void Accept(TFshort type, Title title, int column) + { + + } + + public void Accept(TInt type, Title title, int column) + { + + } + + public void Accept(TFint type, Title title, int column) + { + + } + + public void Accept(TLong type, Title title, int column) + { + + } + + public void Accept(TFlong type, Title title, int column) + { + + } + + public void Accept(TFloat type, Title title, int column) + { + + } + + public void Accept(TDouble type, Title title, int column) + { + + } + + public void Accept(TEnum type, Title title, int column) + { + + } + + public void Accept(TString type, Title title, int column) + { + + } + + public void Accept(TBytes type, Title title, int column) + { + + } + + public void Accept(TText type, Title title, int column) + { + // 默认使用 # 来分割 + if (!title.Tags.ContainsKey("sep")) + { + title.Tags.Add("sep", "#"); + } + } + + public void Accept(TBean type, Title title, int column) + { + title.FromIndex = column; + title.ToIndex = column; + if (!title.Tags.ContainsKey("sep")) + { + title.Tags.Add("sep", "|"); + } + + //int lastColumn = column - 1; + + //if (type.IsDynamic) + //{ + // title.AddSubTitle(new Title() + // { + // Name = "__type__", + // FromIndex = lastColumn + 1, + // ToIndex = lastColumn + 1, + // Tags = new Dictionary(), + // }); + // ++lastColumn; + //} + + //foreach (var f in type.Bean.HierarchyFields) + //{ + // int startColumn = lastColumn + 1; + // var subTitle = new Title() + // { + // Name = f.Name, + // FromIndex = startColumn, + // ToIndex = startColumn, + // Tags = new Dictionary(), + // }; + // if (f.CType.Tags.TryGetValue("sep", out var sep)) + // { + // subTitle.Tags.Add("sep", sep); + // } + // if (f.CType.Tags.TryGetValue("multi_rows", out var multiRows)) + // { + // subTitle.Tags.Add("multiRows", multiRows); + // } + + // f.CType.Apply(this, subTitle, startColumn); + // lastColumn = subTitle.ToIndex; + // title.AddSubTitle(subTitle); + //} + //title.ToIndex = Math.Max(lastColumn, column); + + //int maxFieldNum = 20; + //if (type.IsDynamic) + //{ + // if (!title.Tags.ContainsKey("sep")) + // { + // title.Tags.Add("sep", "|"); + // } + // //var maxFieldCount = type.Bean.HierarchyNotAbstractChildren.Max(c => c.HierarchyFields.Count); + // //var fields = type.Bean.HierarchyNotAbstractChildren.SelectMany(c => c.HierarchyFields).Select(f => f.Name).ToHashSet(); + // title.ToIndex = column; + //} + //else + //{ + // int lastColumn = column - 1; + // foreach (var f in type.Bean.HierarchyFields) + // { + // int startColumn = lastColumn + 1; + // var subTitle = new Title() + // { + // Name = f.Name, + // FromIndex = startColumn, + // ToIndex = startColumn, + // Tags = new Dictionary(), + // }; + // if (f.CType.Tags.TryGetValue("sep", out var sep)) + // { + // subTitle.Tags.Add("sep", sep); + // } + // if (f.CType.Tags.TryGetValue("multi_rows", out var multiRows)) + // { + // subTitle.Tags.Add("multiRows", multiRows); + // } + + // f.CType.Apply(this, subTitle, startColumn); + // lastColumn = subTitle.ToIndex; + // title.AddSubTitle(subTitle); + // } + // title.ToIndex = Math.Max(lastColumn, column); + //} + } + + public void Accept(TArray type, Title title, int column) + { + if (!type.ElementType.Apply(IsNotSepTypeVisitor.Ins)) + { + title.Tags.TryAdd("sep", "|"); + } + } + + public void Accept(TList type, Title title, int column) + { + if (!type.ElementType.Apply(IsNotSepTypeVisitor.Ins)) + { + title.Tags.TryAdd("sep", "|"); + } + } + + public void Accept(TSet type, Title title, int column) + { + if (!type.ElementType.Apply(IsNotSepTypeVisitor.Ins)) + { + title.Tags.TryAdd("sep", "|"); + } + } + + public void Accept(TMap type, Title title, int column) + { + title.Tags.TryAdd("sep", "|"); + } + + public void Accept(TVector2 type, Title title, int column) + { + + } + + public void Accept(TVector3 type, Title title, int column) + { + + } + + public void Accept(TVector4 type, Title title, int column) + { + + } + + public void Accept(TDateTime type, Title title, int column) + { + + } + } +} diff --git a/src/LubanAssistant/ToExcelStringVisitor.cs b/src/Luban.Job.Cfg/Source/DataConverts/ToExcelStringVisitor.cs similarity index 97% rename from src/LubanAssistant/ToExcelStringVisitor.cs rename to src/Luban.Job.Cfg/Source/DataConverts/ToExcelStringVisitor.cs index bb2bc94..5ad0361 100644 --- a/src/LubanAssistant/ToExcelStringVisitor.cs +++ b/src/Luban.Job.Cfg/Source/DataConverts/ToExcelStringVisitor.cs @@ -10,9 +10,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace LubanAssistant +namespace Luban.Job.Cfg.DataConverts { - class ToExcelStringVisitor : IDataFuncVisitor + public class ToExcelStringVisitor : IDataFuncVisitor { public static ToExcelStringVisitor Ins { get; } = new(); diff --git a/src/Luban.Job.Cfg/Source/DataCreators/ExcelStreamDataCreator.cs b/src/Luban.Job.Cfg/Source/DataCreators/ExcelStreamDataCreator.cs index 3f5189a..a134c73 100644 --- a/src/Luban.Job.Cfg/Source/DataCreators/ExcelStreamDataCreator.cs +++ b/src/Luban.Job.Cfg/Source/DataCreators/ExcelStreamDataCreator.cs @@ -252,7 +252,7 @@ namespace Luban.Job.Cfg.DataCreators } else if (d is string s) { - return DataUtil.UnEscapeString(s); + return DataUtil.UnEscapeRawString(s); } else { diff --git a/src/Luban.Job.Cfg/Source/DataCreators/LuaDataCreator.cs b/src/Luban.Job.Cfg/Source/DataCreators/LuaDataCreator.cs index f8ac290..a6f959f 100644 --- a/src/Luban.Job.Cfg/Source/DataCreators/LuaDataCreator.cs +++ b/src/Luban.Job.Cfg/Source/DataCreators/LuaDataCreator.cs @@ -115,7 +115,7 @@ namespace Luban.Job.Cfg.DataCreators } else { - throw new Exception($"{x} 不是 double 类型数据"); + throw new Exception($"{x} 不是 string 类型数据"); } } diff --git a/src/Luban.Job.Cfg/Source/DataCreators/SheetDataCreator.cs b/src/Luban.Job.Cfg/Source/DataCreators/SheetDataCreator.cs index 84fafc2..fa6475b 100644 --- a/src/Luban.Job.Cfg/Source/DataCreators/SheetDataCreator.cs +++ b/src/Luban.Job.Cfg/Source/DataCreators/SheetDataCreator.cs @@ -212,7 +212,7 @@ namespace Luban.Job.Cfg.DataCreators } else if (d is string s) { - return DataUtil.UnEscapeString(s); + return DataUtil.UnEscapeRawString(s); } else { diff --git a/src/Luban.Job.Cfg/Source/DataSources/Excel/SheetLoadUtil.cs b/src/Luban.Job.Cfg/Source/DataSources/Excel/SheetLoadUtil.cs index 664c4cd..6457e61 100644 --- a/src/Luban.Job.Cfg/Source/DataSources/Excel/SheetLoadUtil.cs +++ b/src/Luban.Job.Cfg/Source/DataSources/Excel/SheetLoadUtil.cs @@ -17,7 +17,7 @@ namespace Luban.Job.Cfg.DataSources.Excel private const int TITLE_MAX_ROW_NUM = 10; private const int TITLE_DEFAULT_ROW_NUM = 3; - private static System.Text.Encoding DetectCsvEncoding(Stream fs) + public static System.Text.Encoding DetectCsvEncoding(Stream fs) { Ude.CharsetDetector cdet = new Ude.CharsetDetector(); cdet.Feed(fs); diff --git a/src/Luban.Job.Cfg/Source/DataVisitors/ToLiteralVisitorBase.cs b/src/Luban.Job.Cfg/Source/DataVisitors/ToLiteralVisitorBase.cs index e11f35f..39f3f67 100644 --- a/src/Luban.Job.Cfg/Source/DataVisitors/ToLiteralVisitorBase.cs +++ b/src/Luban.Job.Cfg/Source/DataVisitors/ToLiteralVisitorBase.cs @@ -1,6 +1,7 @@ using Luban.Job.Cfg.Datas; using Luban.Job.Cfg.Defs; using Luban.Job.Cfg.Utils; +using System.Text.RegularExpressions; namespace Luban.Job.Cfg.DataVisitors { diff --git a/src/Luban.Job.Cfg/Source/Generate/ExcelConvertRender.cs b/src/Luban.Job.Cfg/Source/Generate/ExcelConvertRender.cs new file mode 100644 index 0000000..72cde4d --- /dev/null +++ b/src/Luban.Job.Cfg/Source/Generate/ExcelConvertRender.cs @@ -0,0 +1,159 @@ +using Luban.Job.Cfg.Cache; +using Luban.Job.Cfg.DataConverts; +using Luban.Job.Cfg.Utils; +using Luban.Job.Common.Utils; +using SpreadsheetLight; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Luban.Job.Cfg.Generate +{ + [Render("convert_xlsx")] + [Render("convert_excel")] + class ExcelConvertRender : DataRenderBase + { + public override void Render(GenContext ctx) + { + string genType = ctx.GenType; + foreach (var table in ctx.ExportTables) + { + ctx.Tasks.Add(Task.Run(() => + { + var records = ctx.Assembly.GetTableAllDataList(table); + string dirName = table.FullName; + var fileName = table.FullName; + var filePath = $"{dirName}/{fileName}.xlsx"; + + + var title = TitleCreator.Ins.CreateTitle(table); + + + var dataRangeArray = new List(); + + dataRangeArray.Add(new object[] { "##" }); + + var titleRow = new object[title.ToIndex + 1]; + + foreach (var subTitle in title.SubTitleList) + { + string titleAndTags = subTitle.Tags.Count == 0 ? subTitle.Name : subTitle.Name + "&" + string.Join('&', subTitle.Tags.Select(e => $"{e.Key}={e.Value}")); + titleRow[subTitle.FromIndex] = titleAndTags; + } + dataRangeArray.Add(titleRow); + // 注释行1 + dataRangeArray.Add(Array.Empty()); + // 注释行2 + dataRangeArray.Add(Array.Empty()); + + int totalRowCount = dataRangeArray.Count; + foreach (var rec in records) + { + var fillVisitor = new FillSheetVisitor(dataRangeArray, title.ToIndex + 1, totalRowCount); + totalRowCount += rec.Data.Apply(fillVisitor, title); + } + + + + //var memoryStream = new MemoryStream(); + //using (var package = new ExcelPackage(memoryStream)) + //{ + // var sheet = package.Workbook.Worksheets.Add("sheet1"); + // for (int i = 0; i < dataRangeArray.Count; i++) + // { + // var rawRow = dataRangeArray[i]; + // sheet.Cells[i + 1, 1, i + 1, rawRow.Length].FillList(rawRow); + // } + // sheet.Cells.AutoFitColumns(); + // content = package.GetAsByteArray(); + //} + + var worksheet = new SLDocument(); + //var rows = new List(); + //for (int i = 0; i < dataRangeArray.Count; i++) + //{ + // var rawRow = dataRangeArray[i]; + // var cells = new List(); + // for (int j = 0; j < rawRow.Length; j++) + // { + // cells.Add(new Cell(j + 1, rawRow[j])); + // } + // rows.Add(new Row(i + 1, cells)); + //} + //worksheet.Rows = rows; + for (int i = 0; i < dataRangeArray.Count; i++) + { + var rawRow = dataRangeArray[i]; + for (int j = 0; j < rawRow.Length; j++) + { + object v = dataRangeArray[i][j]; + if (v != null) + { + switch (v) + { + case int t: + { + worksheet.SetCellValue(i + 1, j + 1, t); + break; + } + case string t: + { + worksheet.SetCellValue(i + 1, j + 1, t); + break; + } + case float t: + { + worksheet.SetCellValue(i + 1, j + 1, t); + break; + } + case bool t: + { + worksheet.SetCellValue(i + 1, j + 1, t); + break; + } + case DateTime t: + { + + worksheet.SetCellValue(i + 1, j + 1, t); + break; + } + default: + { + worksheet.SetCellValue(i + 1, j + 1, v.ToString()); + break; + } + } + } + } + } + worksheet.AutoFitColumn(1, title.ToIndex + 1); + worksheet.AutoFitRow(1, dataRangeArray.Count); + var stream = new MemoryStream(); + worksheet.SaveAs(stream); + + + + //var tempFile = $"{Path.GetTempFileName()}_{fileName}.tmp"; + //var outputFile = $"{Path.GetTempFileName()}_{fileName}.xlsx"; + //var outputStream = new FileStream(tempFile, FileMode.CreateNew, FileAccess.ReadWrite); + //var writer = ExcelDataWriter.ExcelDataWriter.GetAsByteArray(dataRangeArray, new ExcelDataWriter.ClassMap()); + //using (FastExcel.FastExcel fastExcel = new FastExcel.FastExcel(new System.IO.FileInfo(tempFile), new System.IO.FileInfo(outputFile))) + //{ + // // Write the data + // fastExcel.Write(worksheet, "sheet1"); + //} + //outputStream.Close(); + //outputStream.Flush(); + byte[] content = DataUtil.StreamToBytes(stream); + var md5 = CacheFileUtil.GenStringOrBytesMd5AndAddCache(filePath, content); + FileRecordCacheManager.Ins.AddCachedRecordOutputData(table, records, genType, md5); + ctx.GenDataFilesInOutputDataDir.Add(new Luban.Common.Protos.FileInfo() { FilePath = filePath, MD5 = md5 }); + })); + + } + } + } +} diff --git a/src/Luban.Job.Cfg/Source/Generate/ConvertRender.cs b/src/Luban.Job.Cfg/Source/Generate/TextConvertRender.cs similarity index 97% rename from src/Luban.Job.Cfg/Source/Generate/ConvertRender.cs rename to src/Luban.Job.Cfg/Source/Generate/TextConvertRender.cs index e028937..15fbdea 100644 --- a/src/Luban.Job.Cfg/Source/Generate/ConvertRender.cs +++ b/src/Luban.Job.Cfg/Source/Generate/TextConvertRender.cs @@ -8,7 +8,7 @@ namespace Luban.Job.Cfg.Generate { [Render("convert_json")] [Render("convert_lua")] - class ConvertRender : DataRenderBase + class TextConvertRender : DataRenderBase { public override void Render(GenContext ctx) { diff --git a/src/Luban.Job.Cfg/Source/Utils/DataConvertUtil.cs b/src/Luban.Job.Cfg/Source/Utils/DataConvertUtil.cs index aff923a..16ed186 100644 --- a/src/Luban.Job.Cfg/Source/Utils/DataConvertUtil.cs +++ b/src/Luban.Job.Cfg/Source/Utils/DataConvertUtil.cs @@ -14,7 +14,7 @@ namespace Luban.Job.Cfg.Utils { static class DataConvertUtil { - public static object ToConvertRecord(DefTable table, Record record, string converType) + public static string ToConvertRecord(DefTable table, Record record, string converType) { switch (converType) { @@ -38,28 +38,6 @@ namespace Luban.Job.Cfg.Utils { return new LuaConvertor().ExportRecord(table, record); } - //case "data_erlang": - //{ - // var content = new StringBuilder(); - // switch (table.Mode) - // { - // case ETableMode.ONE: - // { - // ErlangExport.Ins.ExportTableSingleton(table, records[0], content); - // break; - // } - // case ETableMode.MAP: - // { - // ErlangExport.Ins.ExportTableMap(table, records, content); - // break; - // } - // default: - // { - // throw new NotSupportedException(); - // } - // } - // return content.ToString(); - //} default: { throw new ArgumentException($"not support datatype:{converType}"); diff --git a/src/Luban.Job.Cfg/Source/Utils/DataUtil.cs b/src/Luban.Job.Cfg/Source/Utils/DataUtil.cs index 247937d..3019cd3 100644 --- a/src/Luban.Job.Cfg/Source/Utils/DataUtil.cs +++ b/src/Luban.Job.Cfg/Source/Utils/DataUtil.cs @@ -77,7 +77,7 @@ namespace Luban.Job.Cfg.Utils return bytes; } - public static string UnEscapeString(string s) + public static string UnEscapeRawString(string s) { switch (s) { @@ -89,13 +89,13 @@ namespace Luban.Job.Cfg.Utils public static string EscapeString(string s) { - return s.Replace("\\", "\\\\"); + return s.Replace("\\", "\\\\").Replace("\"", "\\\""); } - public static string EscapeStringWithQuote(string s) - { - return "\"" + s.Replace("\\", "\\\\") + "\""; - } + //public static string EscapeStringWithQuote(string s) + //{ + // return "\"" + s.Replace("\\", "\\\\") + "\""; + //} public static (string Key, string Text) ExtractText(string rawKeyAndText) { diff --git a/src/Luban.Job.Cfg/Source/Utils/ValidatorUtil.cs b/src/Luban.Job.Cfg/Source/Utils/ValidatorUtil.cs index 0de9493..b22f5e6 100644 --- a/src/Luban.Job.Cfg/Source/Utils/ValidatorUtil.cs +++ b/src/Luban.Job.Cfg/Source/Utils/ValidatorUtil.cs @@ -10,8 +10,6 @@ namespace Luban.Job.Cfg.Utils { static class ValidatorUtil { - - private static void CreateValidatorsForType(TType type) { foreach (var valName in ValidatorFactory.ValidatorNames) diff --git a/src/Luban.Job.Common/Source/Utils/RenderFileUtil.cs b/src/Luban.Job.Common/Source/Utils/RenderFileUtil.cs index 022bb3a..3de1d0e 100644 --- a/src/Luban.Job.Common/Source/Utils/RenderFileUtil.cs +++ b/src/Luban.Job.Common/Source/Utils/RenderFileUtil.cs @@ -95,6 +95,7 @@ namespace Luban.Job.Common.Utils { "yml", "yml" }, { "erlang", "erl" }, { "erl", "erl" }, + { "xlsx", "xlsx" }, }; public static string GetOutputFileSuffix(string genType) diff --git a/src/LubanAssistant/ExcelUtil.cs b/src/LubanAssistant/ExcelUtil.cs index 01eba7a..71d48bf 100644 --- a/src/LubanAssistant/ExcelUtil.cs +++ b/src/LubanAssistant/ExcelUtil.cs @@ -1,4 +1,5 @@ using Luban.Common.Utils; +using Luban.Job.Cfg.DataConverts; using Luban.Job.Cfg.DataExporters; using Luban.Job.Cfg.Datas; using Luban.Job.Cfg.DataSources.Excel; diff --git a/src/LubanAssistant/LubanAssistant.csproj b/src/LubanAssistant/LubanAssistant.csproj index 5e46b2c..885ab19 100644 --- a/src/LubanAssistant/LubanAssistant.csproj +++ b/src/LubanAssistant/LubanAssistant.csproj @@ -249,6 +249,12 @@ Source\Utils\XmlUtil.cs + + Source\DataConverters\FillSheetVisitor.cs + + + Source\DataConverters\ToExcelStringVisitor.cs + Source\DataCreators\DataCreateException.cs @@ -634,12 +640,10 @@ AssistantTab.cs - Code - AssistantTab.cs @@ -653,7 +657,6 @@ Resources.resx - SettingsSingleFileGenerator