From a7dcb7f64d4f5009a864f39b832b148ba6019a62 Mon Sep 17 00:00:00 2001 From: walon Date: Fri, 15 Oct 2021 17:18:01 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E9=87=8D=E6=9E=84=E3=80=91=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E6=95=B0=E6=8D=AE=E7=94=9F=E6=88=90=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataCreators/ExcelStreamDataCreator.cs | 53 ++--- .../Source/DataCreators/SheetDataCreator.cs | 99 ++++++---- .../DataSources/Excel/ExcelDataSource.cs | 12 +- .../Source/DataSources/Excel/ExcelStream.cs | 49 ++++- .../Source/DataSources/Excel/Sheet.cs | 99 +++------- .../Source/DataSources/Excel/SheetLoadUtil.cs | 74 +++---- .../Source/DataSources/Excel/Title.cs | 8 +- .../Source/DataSources/Excel/TitleRow.cs | 184 +++++------------- src/Luban.Job.Cfg/Source/Datas/DFshort.cs | 2 +- src/Luban.Job.Cfg/Source/Defs/CfgDefLoader.cs | 30 ++- src/Luban.Job.Cfg/Source/Defs/DefAssembly.cs | 37 ---- src/Luban.Job.Cfg/Source/Defs/DefField.cs | 28 --- .../TypeVisitors/DeepCompareTypeDefine.cs | 1 - src/Luban.Job.Cfg/Source/Utils/DataUtil.cs | 20 ++ 14 files changed, 296 insertions(+), 400 deletions(-) diff --git a/src/Luban.Job.Cfg/Source/DataCreators/ExcelStreamDataCreator.cs b/src/Luban.Job.Cfg/Source/DataCreators/ExcelStreamDataCreator.cs index 6eb2486..988e246 100644 --- a/src/Luban.Job.Cfg/Source/DataCreators/ExcelStreamDataCreator.cs +++ b/src/Luban.Job.Cfg/Source/DataCreators/ExcelStreamDataCreator.cs @@ -277,6 +277,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TText type, ExcelStream x) { + x = SepIfNeed(type, x); string key = ParseString(x.Read()); if (key == null) { @@ -302,15 +303,15 @@ namespace Luban.Job.Cfg.DataCreators { try { - string sep = f.Tags.TryGetValue("tag", out var s) ? s : null; - if (string.IsNullOrWhiteSpace(sep)) - { - list.Add(f.CType.Apply(this, stream)); - } - else - { - list.Add(f.CType.Apply(this, new ExcelStream(stream.ReadCell(), sep))); - } + //string sep = f.Tags.TryGetValue("tag", out var s) ? s : null; + //if (string.IsNullOrWhiteSpace(sep)) + //{ + list.Add(f.CType.Apply(this, stream)); + //} + //else + //{ + // list.Add(f.CType.Apply(this, new ExcelStream(stream.ReadCell(), sep))); + //} } catch (DataCreateException dce) { @@ -327,9 +328,23 @@ namespace Luban.Job.Cfg.DataCreators return list; } + public static ExcelStream SepIfNeed(TType type, ExcelStream stream) + { + string sep = DataUtil.GetSep(type); + if (!string.IsNullOrEmpty(sep)) + { + return new ExcelStream(stream.ReadCell(), sep); + } + else + { + return stream; + } + } + public DType Accept(TBean type, ExcelStream x) { var originBean = (DefBean)type.Bean; + x = SepIfNeed(type, x); if (originBean.IsAbstractType) { @@ -372,46 +387,38 @@ namespace Luban.Job.Cfg.DataCreators // 因为貌似没意义? public List ReadList(TType type, ExcelStream stream) { - string sep = type is TBean bean ? ((DefBean)bean.Bean).Sep : null; var datas = new List(); while (!stream.TryReadEOF()) { - if (string.IsNullOrWhiteSpace(sep)) - { - datas.Add(type.Apply(this, stream)); - } - else - { - datas.Add(type.Apply(this, new ExcelStream(stream.ReadCell(), sep))); ; - } + datas.Add(type.Apply(this, stream)); } return datas; } public DType Accept(TArray type, ExcelStream x) { - return new DArray(type, ReadList(type.ElementType, x)); + return new DArray(type, ReadList(type.ElementType, SepIfNeed(type, x))); } public DType Accept(TList type, ExcelStream x) { - return new DList(type, ReadList(type.ElementType, x)); + return new DList(type, ReadList(type.ElementType, SepIfNeed(type, x))); } public DType Accept(TSet type, ExcelStream x) { - return new DSet(type, ReadList(type.ElementType, x)); + return new DSet(type, ReadList(type.ElementType, SepIfNeed(type, x))); } public DType Accept(TMap type, ExcelStream x) { - string sep = type.ValueType is TBean bean ? ((DefBean)bean.Bean).Sep : null; + x = SepIfNeed(type, x); var datas = new Dictionary(); while (!x.TryReadEOF()) { var key = type.KeyType.Apply(this, x); - var value = string.IsNullOrWhiteSpace(sep) ? type.ValueType.Apply(this, x) : type.ValueType.Apply(this, new ExcelStream(x.ReadCell(), sep)); + var value = type.ValueType.Apply(this, x); if (!datas.TryAdd(key, value)) { throw new InvalidExcelDataException($"map 的 key:{key} 重复"); diff --git a/src/Luban.Job.Cfg/Source/DataCreators/SheetDataCreator.cs b/src/Luban.Job.Cfg/Source/DataCreators/SheetDataCreator.cs index 10c8056..b9f4edf 100644 --- a/src/Luban.Job.Cfg/Source/DataCreators/SheetDataCreator.cs +++ b/src/Luban.Job.Cfg/Source/DataCreators/SheetDataCreator.cs @@ -31,7 +31,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TBool type, Sheet sheet, TitleRow row) { - object x = row.Current.Value; + object x = row.Current; if (CheckNull(type.IsNullable, x)) { return null; @@ -49,7 +49,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TByte type, Sheet sheet, TitleRow row) { - object x = row.Current.Value; + object x = row.Current; if (CheckNull(type.IsNullable, x)) { return null; @@ -63,7 +63,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TShort type, Sheet sheet, TitleRow row) { - object x = row.Current.Value; + object x = row.Current; if (CheckNull(type.IsNullable, x)) { return null; @@ -77,7 +77,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TFshort type, Sheet sheet, TitleRow row) { - object x = row.Current.Value; + object x = row.Current; if (CheckNull(type.IsNullable, x)) { return null; @@ -91,7 +91,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TInt type, Sheet sheet, TitleRow row) { - object x = row.Current.Value; + object x = row.Current; if (CheckNull(type.IsNullable, x)) { return null; @@ -105,7 +105,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TFint type, Sheet sheet, TitleRow row) { - object x = row.Current.Value; + object x = row.Current; if (CheckNull(type.IsNullable, x)) { return null; @@ -119,7 +119,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TLong type, Sheet sheet, TitleRow row) { - object x = row.Current.Value; + object x = row.Current; if (CheckNull(type.IsNullable, x)) { return null; @@ -133,7 +133,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TFlong type, Sheet sheet, TitleRow row) { - object x = row.Current.Value; + object x = row.Current; if (CheckNull(type.IsNullable, x)) { return null; @@ -147,7 +147,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TFloat type, Sheet sheet, TitleRow row) { - object x = row.Current.Value; + object x = row.Current; if (CheckNull(type.IsNullable, x)) { return null; @@ -161,7 +161,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TDouble type, Sheet sheet, TitleRow row) { - object x = row.Current.Value; + object x = row.Current; if (CheckNull(type.IsNullable, x)) { return null; @@ -175,7 +175,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TEnum type, Sheet sheet, TitleRow row) { - object x = row.Current.Value; + object x = row.Current; if (CheckNull(type.IsNullable, x)) { return null; @@ -224,12 +224,17 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TText type, Sheet sheet, TitleRow row) { - if (row.Row.Count != 2) + if (row.CellCount != 2) { throw new Exception($"text 要求两个字段"); } - var key = ParseString(row.Row[0].Value); - var text = ParseString(row.Row[1].Value); + int startIndex = row.SelfTitle.FromIndex; + var key = ParseString(row.Row[startIndex].Value); + var text = ParseString(row.Row[startIndex + 1].Value); + if (type.IsNullable && key == null && text == null) + { + return null; + } DataUtil.ValidateText(key, text); return new DText(key, text); } @@ -238,6 +243,7 @@ namespace Luban.Job.Cfg.DataCreators { var list = new List(); foreach (DefField f in bean.HierarchyFields) + { string fname = f.Name; TitleRow field = row.GetSubTitleNamedRow(fname); @@ -266,7 +272,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TBean type, Sheet sheet, TitleRow row) { - string sep = GetSep(type); + string sep = DataUtil.GetSep(type); if (row.Row != null) { @@ -284,7 +290,7 @@ namespace Luban.Job.Cfg.DataCreators var originBean = (DefBean)type.Bean; if (originBean.IsAbstractType) { - string subType = row.GetSubTitleNamedRow(DefBean.TYPE_NAME_KEY).Current.Value.ToString().Trim(); + string subType = row.GetSubTitleNamedRow(DefBean.TYPE_NAME_KEY).Current.ToString().Trim(); if (subType.ToLower() == DefBean.BEAN_NULL_STR) { if (!type.IsNullable) @@ -305,7 +311,7 @@ namespace Luban.Job.Cfg.DataCreators { if (type.IsNullable) { - string subType = row.GetSubTitleNamedRow(DefBean.TYPE_NAME_KEY).Current.Value.ToString().Trim(); + string subType = row.GetSubTitleNamedRow(DefBean.TYPE_NAME_KEY).Current.ToString().Trim(); if (subType == DefBean.BEAN_NULL_STR) { return null; @@ -331,23 +337,8 @@ namespace Luban.Job.Cfg.DataCreators } } - const string SimpleContainerSep = ",;"; - public string GetSep(TType type) - { - if (type.Tags.TryGetValue("sep", out var s) && !string.IsNullOrWhiteSpace(s)) - { - return s; - } - switch (type) - { - case TBean tb: return (tb.Bean as DefBean).Sep; - case TArray ta: return ta.ElementType.Apply(IsNotSepTypeVisitor.Ins) ? SimpleContainerSep : ""; - case TList ta: return ta.ElementType.Apply(IsNotSepTypeVisitor.Ins) ? SimpleContainerSep : ""; - case TSet ta: return ta.ElementType.Apply(IsNotSepTypeVisitor.Ins) ? SimpleContainerSep : ""; - default: return ""; - } - } + public List ReadList(TType type, ExcelStream stream) { @@ -374,7 +365,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TArray type, Sheet sheet, TitleRow row) { - string sep = GetSep(type); + string sep = DataUtil.GetSep(type); if (row.Row != null) { @@ -402,7 +393,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TList type, Sheet sheet, TitleRow row) { - string sep = GetSep(type); + string sep = DataUtil.GetSep(type); if (row.Row != null) { @@ -430,7 +421,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TSet type, Sheet sheet, TitleRow row) { - string sep = GetSep(type); + string sep = DataUtil.GetSep(type); if (row.Row != null) { @@ -458,7 +449,7 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TMap type, Sheet sheet, TitleRow row) { - string sep = GetSep(type); + string sep = DataUtil.GetSep(type); if (row.Row != null) { @@ -494,6 +485,10 @@ namespace Luban.Job.Cfg.DataCreators foreach (var e in row.Fields) { var keyData = type.KeyType.Apply(StringDataCreator.Ins, e.Key); + if (Sheet.IsBlankRow(e.Value.Row, e.Value.SelfTitle.FromIndex, e.Value.SelfTitle.ToIndex)) + { + continue; + } var valueData = type.ValueType.Apply(ExcelStreamDataCreator.Ins, e.Value.AsStream(sep)); datas.Add(keyData, valueData); } @@ -501,7 +496,15 @@ namespace Luban.Job.Cfg.DataCreators } else if (row.Elements != null) { - throw new NotSupportedException(); + var datas = new Dictionary(); + foreach (var e in row.Elements) + { + var stream = e.AsStream(""); + var keyData = type.KeyType.Apply(ExcelStreamDataCreator.Ins, stream); + var valueData = type.ValueType.Apply(ExcelStreamDataCreator.Ins, stream); + datas.Add(keyData, valueData); + } + return new DMap(type, datas); } else { @@ -511,37 +514,49 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TVector2 type, Sheet sheet, TitleRow row) { - var d = row.Current.Value; + var d = row.Current; if (CheckNull(type.IsNullable, d)) { return null; } + if (CheckDefault(d)) + { + return DVector2.Default; + } return DataUtil.CreateVector(type, d.ToString()); } public DType Accept(TVector3 type, Sheet sheet, TitleRow row) { - var d = row.Current.Value; + var d = row.Current; if (CheckNull(type.IsNullable, d)) { return null; } + if (CheckDefault(d)) + { + return DVector3.Default; + } return DataUtil.CreateVector(type, d.ToString()); } public DType Accept(TVector4 type, Sheet sheet, TitleRow row) { - var d = row.Current.Value; + var d = row.Current; if (CheckNull(type.IsNullable, d)) { return null; } + if (CheckDefault(d)) + { + return DVector4.Default; + } return DataUtil.CreateVector(type, d.ToString()); } public DType Accept(TDateTime type, Sheet sheet, TitleRow row) { - var d = row.Current.Value; + var d = row.Current; if (CheckNull(type.IsNullable, d)) { return null; diff --git a/src/Luban.Job.Cfg/Source/DataSources/Excel/ExcelDataSource.cs b/src/Luban.Job.Cfg/Source/DataSources/Excel/ExcelDataSource.cs index ae9bf5f..3c223a6 100644 --- a/src/Luban.Job.Cfg/Source/DataSources/Excel/ExcelDataSource.cs +++ b/src/Luban.Job.Cfg/Source/DataSources/Excel/ExcelDataSource.cs @@ -1,6 +1,7 @@ using ExcelDataReader; using Luban.Job.Cfg.DataCreators; using Luban.Job.Cfg.Datas; +using Luban.Job.Cfg.Utils; using Luban.Job.Common.Types; using System; using System.Collections.Generic; @@ -26,6 +27,7 @@ namespace Luban.Job.Cfg.DataSources.Excel { var sheet = new Sheet(rawUrl, sheetName); sheet.Load(rawSheet); + _sheets.Add(sheet); } if (_sheets.Count == 0) @@ -36,7 +38,7 @@ namespace Luban.Job.Cfg.DataSources.Excel public RawSheetTableDefInfo LoadTableDefInfo(string rawUrl, string sheetName, Stream stream) { - return null; + return SheetLoadUtil.LoadSheetTableDefInfo(rawUrl, sheetName, stream); } public override List ReadMulti(TBean type) @@ -48,8 +50,14 @@ namespace Luban.Job.Cfg.DataSources.Excel { foreach (TitleRow row in sheet.GetRows()) { + var tagRow = row.GetSubTitleNamedRow(TAG_KEY); + string tagStr = tagRow?.Current?.ToString(); + if (DataUtil.IsIgnoreTag(tagStr)) + { + continue; + } var data = (DBean)type.Apply(SheetDataCreator.Ins, sheet, row); - datas.Add(new Record(data, sheet.RawUrl, row.Tags)); + datas.Add(new Record(data, sheet.RawUrl, DataUtil.ParseTags(tagStr))); } } catch (DataCreateException dce) diff --git a/src/Luban.Job.Cfg/Source/DataSources/Excel/ExcelStream.cs b/src/Luban.Job.Cfg/Source/DataSources/Excel/ExcelStream.cs index 48720b4..708d009 100644 --- a/src/Luban.Job.Cfg/Source/DataSources/Excel/ExcelStream.cs +++ b/src/Luban.Job.Cfg/Source/DataSources/Excel/ExcelStream.cs @@ -18,13 +18,39 @@ namespace Luban.Job.Cfg.DataSources.Excel private readonly int _toIndex; private int _curIndex; - public ExcelStream(List datas, int fromIndex, int toIndex, string sep) + private readonly string _overrideDefault; + + public ExcelStream(List datas, int fromIndex, int toIndex, string sep, string overrideDefault) { + _overrideDefault = overrideDefault; if (string.IsNullOrWhiteSpace(sep)) { - this._datas = datas; - this._toIndex = toIndex; - this._curIndex = fromIndex; + if (string.IsNullOrEmpty(overrideDefault)) + { + this._datas = datas; + this._toIndex = toIndex; + this._curIndex = fromIndex; + } + else + { + this._datas = new List(); + for (int i = fromIndex; i <= toIndex; i++) + { + var cell = datas[i]; + object d = cell.Value; + if (!IsSkip(d)) + { + this._datas.Add(cell); + } + else + { + this._datas.Add(new Cell(cell.Row, cell.Column, _overrideDefault)); + } + } + this._curIndex = 0; + this._toIndex = this._datas.Count - 1; + } + } else { @@ -33,13 +59,20 @@ namespace Luban.Job.Cfg.DataSources.Excel { var cell = datas[i]; object d = cell.Value; - if (d is string s) + if (!IsSkip(d)) { - this._datas.AddRange(DataUtil.SplitStringByAnySepChar(s, sep).Select(x => new Cell(cell.Row, cell.Column, x))); + if (d is string s) + { + this._datas.AddRange(DataUtil.SplitStringByAnySepChar(s, sep).Select(x => new Cell(cell.Row, cell.Column, x))); + } + else + { + this._datas.Add(cell); + } } - else + else if (!string.IsNullOrEmpty(_overrideDefault)) { - this._datas.Add(cell); + this._datas.Add(new Cell(cell.Row, cell.Column, _overrideDefault)); } } this._curIndex = 0; diff --git a/src/Luban.Job.Cfg/Source/DataSources/Excel/Sheet.cs b/src/Luban.Job.Cfg/Source/DataSources/Excel/Sheet.cs index ff4ce6b..95afff9 100644 --- a/src/Luban.Job.Cfg/Source/DataSources/Excel/Sheet.cs +++ b/src/Luban.Job.Cfg/Source/DataSources/Excel/Sheet.cs @@ -30,12 +30,10 @@ namespace Luban.Job.Cfg.DataSources.Excel public void Load(RawSheet rawSheet) { - bool anyMultiRows = rawSheet.Title.SubTitleList.Any(t => t.SelfMultiRows); - var cells = rawSheet.Cells; Title title = rawSheet.Title; - if (!anyMultiRows) + if (!title.HierarchyMultiRows) { foreach (var row in cells) { @@ -86,14 +84,14 @@ namespace Luban.Job.Cfg.DataSources.Excel } else { - if (title.SubTitleList.All(t => !t.SelfMultiRows && IsBlankRow(row, t.FromIndex, t.ToIndex))) + if (title.SubTitleList.All(t => t.SelfMultiRows || IsBlankRow(row, t.FromIndex, t.ToIndex))) { oneRecordRows.Add(row); } else { yield return oneRecordRows; - oneRecordRows = null; + oneRecordRows = new List>() { row }; } } } @@ -118,43 +116,45 @@ namespace Luban.Job.Cfg.DataSources.Excel } else { - if (title.SelfMultiRows) + var fields = new Dictionary(); + foreach (var subTitle in title.SubTitleList) { - var eles = new List(); - foreach (var eleRow in SplitRows(title, rows)) + if (subTitle.SelfMultiRows) { - var fields = new Dictionary(); - foreach (var subTitle in title.SubTitleList) + var eles = new List(); + if (subTitle.SubHierarchyMultiRows) { - if (subTitle.SelfMultiRows) + foreach (var eleRows in SplitRows(subTitle, rows)) { - fields.Add(subTitle.Name, ParseMultiLineTitleRow(title, eleRow)); + eles.Add(ParseMultiLineTitleRow(subTitle, eleRows)); } - else - { - fields.Add(subTitle.Name, ParseOneLineTitleRow(title, eleRow[0])); - } - } - eles.Add(new TitleRow(title, fields)); - } - return new TitleRow(title, eles); - } - else - { - var fields = new Dictionary(); - foreach (var subTitle in title.SubTitleList) - { - if (subTitle.SelfMultiRows) - { - fields.Add(subTitle.Name, ParseMultiLineTitleRow(title, rows)); } else { - fields.Add(subTitle.Name, ParseOneLineTitleRow(title, rows[0])); + foreach (var eleRow in rows) + { + if (IsBlankRow(eleRow, subTitle.FromIndex, subTitle.ToIndex)) + { + continue; + } + eles.Add(ParseOneLineTitleRow(subTitle, eleRow)); + } + } + fields.Add(subTitle.Name, new TitleRow(subTitle, eles)); + } + else + { + if (subTitle.SubHierarchyMultiRows) + { + fields.Add(subTitle.Name, ParseMultiLineTitleRow(subTitle, rows)); + } + else + { + fields.Add(subTitle.Name, ParseOneLineTitleRow(subTitle, rows[0])); } } - return new TitleRow(title, fields); } + return new TitleRow(title, fields); } } @@ -163,7 +163,7 @@ namespace Luban.Job.Cfg.DataSources.Excel return Rows; } - private static bool IsBlankRow(List row, int fromIndex, int toIndex) + public static bool IsBlankRow(List row, int fromIndex, int toIndex) { for (int i = Math.Max(1, fromIndex), n = Math.Min(toIndex, row.Count - 1); i <= n; i++) { @@ -175,40 +175,5 @@ namespace Luban.Job.Cfg.DataSources.Excel } return true; } - - private static bool IsSameRow(List row1, List row2, int fromIndex, int toIndex) - { - if (row2.Count < toIndex - 1) - { - return false; - } - for (int i = Math.Max(1, fromIndex), n = Math.Min(toIndex, row1.Count - 1); i <= n; i++) - { - var v1 = row1[i].Value; - var v2 = row2[i].Value; - if (v1 != v2) - { - if (v1 == null) - { - if (!(v2 is string s && string.IsNullOrWhiteSpace(s))) - { - return false; - } - } - else if (v2 == null) - { - if (!(v1 is string s && string.IsNullOrWhiteSpace(s))) - { - return false; - } - } - else - { - return v1.ToString() == v2.ToString(); - } - } - } - return true; - } } } diff --git a/src/Luban.Job.Cfg/Source/DataSources/Excel/SheetLoadUtil.cs b/src/Luban.Job.Cfg/Source/DataSources/Excel/SheetLoadUtil.cs index d40c553..11fe735 100644 --- a/src/Luban.Job.Cfg/Source/DataSources/Excel/SheetLoadUtil.cs +++ b/src/Luban.Job.Cfg/Source/DataSources/Excel/SheetLoadUtil.cs @@ -108,7 +108,12 @@ namespace Luban.Job.Cfg.DataSources.Excel public static Title ParseTitle(List> cells, CellRange[] mergeCells, bool orientRow, out int titleRowNum) { - var rootTitle = new Title() { Root = true, Name = "__root__", FromIndex = 0, ToIndex = cells.Select(r => r.Count).Max() - 1 }; + var rootTitle = new Title() { + Root = true, Name = "__root__", + Tags = new Dictionary(), + FromIndex = 0, + ToIndex = cells.Select(r => r.Count).Max() - 1 + }; titleRowNum = GetTitleRowNum(mergeCells, orientRow); @@ -150,52 +155,55 @@ namespace Luban.Job.Cfg.DataSources.Excel { var titleRow = cells[curDepth - 1]; - foreach (var mergeCell in mergeCells) + if (mergeCells != null) { - Title subTitle = null; - if (orientRow) + foreach (var mergeCell in mergeCells) { - //if (mergeCell.FromRow <= 1 && mergeCell.ToRow >= 1) - if (mergeCell.FromRow == curDepth) + Title subTitle = null; + if (orientRow) { - var nameAndAttrs = titleRow[mergeCell.FromColumn].Value?.ToString()?.Trim(); - if (IsIgnoreTitle(nameAndAttrs)) + //if (mergeCell.FromRow <= 1 && mergeCell.ToRow >= 1) + if (mergeCell.FromRow == curDepth && mergeCell.FromColumn >= title.FromIndex && mergeCell.FromColumn <= title.ToIndex) { - continue; + var nameAndAttrs = titleRow[mergeCell.FromColumn].Value?.ToString()?.Trim(); + if (IsIgnoreTitle(nameAndAttrs)) + { + continue; + } + var (titleName, tags) = ParseNameAndMetaAttrs(nameAndAttrs); + subTitle = new Title() { Name = titleName, Tags = tags, FromIndex = mergeCell.FromColumn, ToIndex = mergeCell.ToColumn }; + //s_logger.Info("=== sheet:{sheet} title:{title}", Name, newTitle); } - var (titleName, tags) = ParseNameAndMetaAttrs(nameAndAttrs); - subTitle = new Title() { Name = titleName, Tags = tags, FromIndex = mergeCell.FromColumn, ToIndex = mergeCell.ToColumn }; - //s_logger.Info("=== sheet:{sheet} title:{title}", Name, newTitle); } - } - else - { - if (mergeCell.FromColumn == curDepth - 1) + else { - // 标题 行 - var nameAndAttrs = titleRow[mergeCell.FromRow - 1].Value?.ToString()?.Trim(); - if (IsIgnoreTitle(nameAndAttrs)) + if (mergeCell.FromColumn == curDepth - 1 && mergeCell.FromRow - 1 >= title.FromIndex && mergeCell.FromRow - 1 <= title.ToIndex) { - continue; + // 标题 行 + var nameAndAttrs = titleRow[mergeCell.FromRow - 1].Value?.ToString()?.Trim(); + if (IsIgnoreTitle(nameAndAttrs)) + { + continue; + } + var (titleName, tags) = ParseNameAndMetaAttrs(nameAndAttrs); + subTitle = new Title() { Name = titleName, Tags = tags, FromIndex = mergeCell.FromRow - 1, ToIndex = mergeCell.ToRow - 1 }; } - var (titleName, tags) = ParseNameAndMetaAttrs(nameAndAttrs); - subTitle = new Title() { Name = titleName, Tags = tags, FromIndex = mergeCell.FromRow - 1, ToIndex = mergeCell.ToRow - 1 }; } - } - if (subTitle == null) - { - continue; - } + if (subTitle == null) + { + continue; + } - if (curDepth < maxDepth) - { - ParseSubTitles(subTitle, cells, mergeCells, orientRow, curDepth + 1, maxDepth); - } - title.AddSubTitle(subTitle); + if (curDepth < maxDepth) + { + ParseSubTitles(subTitle, cells, mergeCells, orientRow, curDepth + 1, maxDepth); + } + title.AddSubTitle(subTitle); + } } - for (int i = 0; i < titleRow.Count; i++) + for (int i = title.FromIndex; i <= title.ToIndex; i++) { var nameAndAttrs = titleRow[i].Value?.ToString()?.Trim(); if (IsIgnoreTitle(nameAndAttrs)) diff --git a/src/Luban.Job.Cfg/Source/DataSources/Excel/Title.cs b/src/Luban.Job.Cfg/Source/DataSources/Excel/Title.cs index f3f3c64..dc498b3 100644 --- a/src/Luban.Job.Cfg/Source/DataSources/Excel/Title.cs +++ b/src/Luban.Job.Cfg/Source/DataSources/Excel/Title.cs @@ -25,10 +25,14 @@ namespace Luban.Job.Cfg.DataSources.Excel public string Sep { get; private set; } + public string Default { get; private set; } + public bool SelfMultiRows { get; private set; } public bool HierarchyMultiRows { get; private set; } + public bool SubHierarchyMultiRows { get; private set; } + public void AddSubTitle(Title title) { if (!SubTitles.TryAdd(title.Name, title)) @@ -55,6 +59,7 @@ namespace Luban.Job.Cfg.DataSources.Excel SortSubTitles(); Sep = Tags.TryGetValue("sep", out var v) && !string.IsNullOrWhiteSpace(v) ? v : null; SelfMultiRows = Tags.TryGetValue("multi_rows", out var v2) && (v2 == "1" || v2 == "true"); + Default = Tags.TryGetValue("default", out var v3) ? v3 : null; if (SubTitleList.Count > 0) { foreach (var sub in SubTitleList) @@ -62,7 +67,8 @@ namespace Luban.Job.Cfg.DataSources.Excel sub.Init(); } } - HierarchyMultiRows = SelfMultiRows || SubTitleList.Any(t => t.HierarchyMultiRows); + SubHierarchyMultiRows = SubTitleList.Any(t => t.HierarchyMultiRows); ; + HierarchyMultiRows = SelfMultiRows || SubHierarchyMultiRows; } public override string ToString() diff --git a/src/Luban.Job.Cfg/Source/DataSources/Excel/TitleRow.cs b/src/Luban.Job.Cfg/Source/DataSources/Excel/TitleRow.cs index 151fc26..f52c631 100644 --- a/src/Luban.Job.Cfg/Source/DataSources/Excel/TitleRow.cs +++ b/src/Luban.Job.Cfg/Source/DataSources/Excel/TitleRow.cs @@ -10,78 +10,61 @@ namespace Luban.Job.Cfg.DataSources.Excel { public List Tags { get; } - - //public static IEnumerable CreateMultiRowNamedRow(List> rows, Title title, TBean bean) - //{ - // if (!((DefBean)bean.Bean).IsMultiRow) - // { - // foreach (var row in rows) - // { - // if (Sheet.IsBlankRow(row, title.FromIndex, title.ToIndex)) - // { - // continue; - // } - // yield return new TitleRow(title, row); - // } - // } - // else - // { - // List notMultiRowFields = bean.Bean.HierarchyFields.Select(f => (DefField)f).Where(f => !f.IsMultiRow && f.IsRowOrient).ToList(); - // List> recordRows = null; - // foreach (var row in rows) - // { - // // 忽略全空的行 - // if (Sheet.IsBlankRow(row, title.FromIndex, title.ToIndex)) - // { - // continue; - // } - // // 如果非多行数据全空,或者跟记录第一行完全相同说明该行属于多行数据 - // if (notMultiRowFields.All(f => - // { - // var fieldTitle = title.SubTitles[f.Name]; - // return Sheet.IsBlankRow(row, fieldTitle.FromIndex, fieldTitle.ToIndex); - // }) || (title.Root && recordRows != null && notMultiRowFields.All(f => - // { - // var fieldTitle = title.SubTitles[f.Name]; - // return Sheet.IsSameRow(row, recordRows[0], fieldTitle.FromIndex, fieldTitle.ToIndex); - // }))) - // { - // if (recordRows == null) - // { - // recordRows = new List>(); - // } - // recordRows.Add(row); - // } - // else - // { - // if (recordRows != null) - // { - // yield return new TitleRow(title, recordRows); - // } - // recordRows = new List>(); - // recordRows.Add(row); - // } - // } - // if (recordRows != null) - // { - // yield return new TitleRow(title, recordRows); - // } - // } - //} - public Title SelfTitle { get; } - public Cell Current => Row[0]; + public object Current + { + get + { + var v = Row[SelfTitle.FromIndex].Value; + if (v == null || (v is string s && string.IsNullOrEmpty(s) && !string.IsNullOrEmpty(SelfTitle.Default))) + { + return SelfTitle.Default; + } + else + { + return v; + } + } + } public List Row { get; } + public int CellCount => SelfTitle.ToIndex - SelfTitle.FromIndex + 1; + public List> Rows { get; } public Dictionary Fields { get; } public List Elements { get; } - public ExcelStream AsStream(string sep) => new ExcelStream(Row, 0, Row.Count - 1, sep); + public ExcelStream AsStream(string sep) + { + if (string.IsNullOrEmpty(SelfTitle.Sep)) + { + if (string.IsNullOrEmpty(sep)) + { + return new ExcelStream(Row, SelfTitle.FromIndex, SelfTitle.ToIndex, "", SelfTitle.Default); + } + else + { + return new ExcelStream(Row, SelfTitle.FromIndex, SelfTitle.ToIndex, sep, SelfTitle.Default); + } + } + else + { + //if (string.IsNullOrEmpty(sep) || sep == SelfTitle.Sep) + //{ + // return new ExcelStream(Row, SelfTitle.FromIndex, SelfTitle.ToIndex, sep); + //} + //else + //{ + // SelfTitle.Sep 设置覆盖 bean的 sep设置(只有这个可能) + return new ExcelStream(Row, SelfTitle.FromIndex, SelfTitle.ToIndex, SelfTitle.Sep, SelfTitle.Default); + //} + } + } + public bool HasSubFields => Fields != null || Elements != null; @@ -111,49 +94,11 @@ namespace Luban.Job.Cfg.DataSources.Excel public int RowCount => Rows.Count; - //private void CheckEmptySinceSecondRow(string name, int fromIndex, int toIndex) - //{ - // for (int i = 1; i < Rows.Count; i++) - // { - // var row = Rows[i]; - // if (!IsBlankRow(row, fromIndex, toIndex)) - // { - // throw new Exception($"字段:{name} 不是多行字段,只能第一行填值. {Bright.Common.StringUtil.CollectionToString(row)}"); - // } - // } - //} - public Title GetTitle(string name) { return SelfTitle.SubTitles.TryGetValue(name, out var title) ? title : null; } - //public ExcelStream GetColumn(string name) - //{ - // var field = GetSubTitleNamedRow(name); - // if (field != null) - // { - // return field.AsStream; - // } - // else - // { - // throw new Exception($"单元薄 缺失 列:{name},请检查是否写错或者遗漏"); - // } - // //if (Titles.TryGetValue(name, out var title)) - // //{ - // // // 只有顶级root支持才允许非multi_rows字段与第一行相同时,判定为同个记录 - // // if (!this.SelfTitle.Root) - // // { - // // CheckEmptySinceSecondRow(name, title.FromIndex, title.ToIndex); - // // } - // // var es = new ExcelStream(Rows[0], title.FromIndex, title.ToIndex, sep, namedMode); - // // return es; - // //} - // //else - // //{ - // // throw new Exception($"单元薄 缺失 列:{name},请检查是否写错或者遗漏"); - // //} - //} public TitleRow GetSubTitleNamedRow(string name) { @@ -162,53 +107,12 @@ namespace Luban.Job.Cfg.DataSources.Excel return Fields.TryGetValue(name, out var r) ? r : null; } - //public IEnumerable GenerateSubNameRows(TBean bean) - //{ - // foreach (var row in Rows) - // { - // if (SelfTitle != null ? IsBlankRow(row, SelfTitle.FromIndex, SelfTitle.ToIndex) : IsBlankRow(row)) - // { - // continue; - // } - // yield return new TitleRow(SelfTitle, row); - // } - //} - public IEnumerable GetColumnOfMultiRows(string name, string sep) { foreach (var ele in GetSubTitleNamedRow(name).Elements) { yield return ele.AsStream(sep); } - //if (Titles.TryGetValue(name, out var title)) - //{ - // if (isRowOrient) - // { - // foreach (var row in Rows) - // { - // if (IsBlankRow(row, title.FromIndex, title.ToIndex)) - // { - // continue; - // } - // yield return new ExcelStream(row, title.FromIndex, title.ToIndex, sep, false); - // } - // } - // else - // { - // for (int i = title.FromIndex; i <= title.ToIndex; i++) - // { - // if (!IsBlankColumn(Rows, i)) - // { - // var cells = Rows.Where(r => r.Count > i).Select(r => r[i]).Where(v => !(v.Value == null || (v.Value is string s && string.IsNullOrEmpty(s)))).ToList(); - // yield return new ExcelStream(cells, 0, cells.Count - 1, sep, false); - // } - // } - // } - //} - //else - //{ - // throw new Exception($"单元薄 缺失 列:{name},请检查是否写错或者遗漏"); - //} } diff --git a/src/Luban.Job.Cfg/Source/Datas/DFshort.cs b/src/Luban.Job.Cfg/Source/Datas/DFshort.cs index 476ae40..48e8895 100644 --- a/src/Luban.Job.Cfg/Source/Datas/DFshort.cs +++ b/src/Luban.Job.Cfg/Source/Datas/DFshort.cs @@ -8,7 +8,7 @@ namespace Luban.Job.Cfg.Datas public static DFshort ValueOf(short x) { - return x == 0 ? Default : new DFshort(0); + return x == 0 ? Default : new DFshort(x); } public override string TypeName => "fshort"; diff --git a/src/Luban.Job.Cfg/Source/Defs/CfgDefLoader.cs b/src/Luban.Job.Cfg/Source/Defs/CfgDefLoader.cs index aa7f537..e82f432 100644 --- a/src/Luban.Job.Cfg/Source/Defs/CfgDefLoader.cs +++ b/src/Luban.Job.Cfg/Source/Defs/CfgDefLoader.cs @@ -566,15 +566,10 @@ namespace Luban.Job.Cfg.Defs { new CfgField() { Name = "name", Type = "string" }, new CfgField() { Name = "type", Type = "string" }, - new CfgField() { Name = "sep", Type = "string" }, - new CfgField() { Name = "is_multi_rows", Type = "bool" }, new CfgField() { Name = "index", Type = "string" }, new CfgField() { Name = "group", Type = "string" }, - new CfgField() { Name = "ref", Type = "string", IgnoreNameValidation = true }, - new CfgField() { Name = "path", Type = "string" }, new CfgField() { Name = "comment", Type = "string" }, new CfgField() { Name = "tags", Type = "string" }, - new CfgField() { Name = "orientation", Type = "string" }, } }) { @@ -613,7 +608,6 @@ namespace Luban.Job.Cfg.Defs defTableRecordType.PreCompile(); defTableRecordType.Compile(); defTableRecordType.PostCompile(); - ass.MarkMultiRows(); var tableRecordType = TBean.Create(false, defTableRecordType); foreach (var file in inputFileInfos) @@ -672,21 +666,11 @@ namespace Luban.Job.Cfg.Defs private static readonly List _fieldOptionalAttrs = new() { "index", - "sep", - "validator", - "key_validator", - "value_validator", "ref", "path", - "range", - "multi_rows", "group", - "res", - "convert", "comment", "tags", - "default", - "orientation", }; private static readonly List _fieldRequireAttrs = new List { "name", "type" }; @@ -695,8 +679,20 @@ namespace Luban.Job.Cfg.Defs { ValidAttrKeys(defineFile, e, _fieldOptionalAttrs, _fieldRequireAttrs); + string refStr = XmlUtil.GetOptionalAttribute(e, "ref"); + string typeStr = XmlUtil.GetRequiredAttribute(e, "type"); + if (!string.IsNullOrWhiteSpace(refStr)) + { + typeStr = typeStr + "&ref=" + refStr; + } + string pathStr = XmlUtil.GetOptionalAttribute(e, "path"); + if (!string.IsNullOrWhiteSpace(pathStr)) + { + typeStr = typeStr + "&path=" + pathStr; + } + return CreateField(defineFile, XmlUtil.GetRequiredAttribute(e, "name"), - XmlUtil.GetRequiredAttribute(e, "type"), + typeStr, XmlUtil.GetOptionalAttribute(e, "index"), XmlUtil.GetOptionalAttribute(e, "group"), XmlUtil.GetOptionalAttribute(e, "comment"), diff --git a/src/Luban.Job.Cfg/Source/Defs/DefAssembly.cs b/src/Luban.Job.Cfg/Source/Defs/DefAssembly.cs index 6a09292..7c40ff4 100644 --- a/src/Luban.Job.Cfg/Source/Defs/DefAssembly.cs +++ b/src/Luban.Job.Cfg/Source/Defs/DefAssembly.cs @@ -263,43 +263,6 @@ namespace Luban.Job.Cfg.Defs throw; } } - - // 丑陋. 怎么写更好? - - // 递归 设置DefBean及DefField 的 IsMultiRow - - MarkMultiRows(); - } - - public void MarkMultiRows() - { - var multiRowBeans = new HashSet(); - for (bool anyMark = true; anyMark;) - { - anyMark = false; - foreach (var type in this.Types.Values) - { - if (type is DefBean beanType && !beanType.IsMultiRow) - { - bool isMultiRows; - if (beanType.IsNotAbstractType) - { - isMultiRows = beanType.HierarchyFields.Any(f => ((DefField)f).ComputeIsMultiRow()); - } - else - { - isMultiRows = beanType.HierarchyNotAbstractChildren.Any(c => ((DefBean)c).IsMultiRow); - } - if (isMultiRows) - { - beanType.IsMultiRow = true; - //s_logger.Info("bean:{bean} is multi row", beanType.FullName); - anyMark = true; - } - } - } - - } } } } diff --git a/src/Luban.Job.Cfg/Source/Defs/DefField.cs b/src/Luban.Job.Cfg/Source/Defs/DefField.cs index 0ee71af..9a3ccc0 100644 --- a/src/Luban.Job.Cfg/Source/Defs/DefField.cs +++ b/src/Luban.Job.Cfg/Source/Defs/DefField.cs @@ -16,29 +16,6 @@ namespace Luban.Job.Cfg.Defs { public DefAssembly Assembly => (DefAssembly)HostType.AssemblyBase; - - public bool RawIsMultiRow { get; } - - public bool IsMultiRow { get; private set; } - - public bool ComputeIsMultiRow() - { - if (IsMultiRow) - { - return true; - } - - switch (CType) - { - case TBean b: { return IsMultiRow = ((DefBean)b.Bean).IsMultiRow; } - case TList b: { return IsMultiRow = b.ElementType is TBean b2 && ((DefBean)b2.Bean).IsMultiRow; } - case TArray b: { return IsMultiRow = b.ElementType is TBean b2 && ((DefBean)b2.Bean).IsMultiRow; } - case TMap b: { return IsMultiRow = b.ValueType is TBean b2 && ((DefBean)b2.Bean).IsMultiRow; } - default: return false; - } - } - - public string Index { get; } public List Groups { get; } @@ -212,11 +189,6 @@ namespace Luban.Job.Cfg.Defs } } - if (IsMultiRow && !CType.IsCollection && !CType.IsBean) - { - throw new Exception($"只有容器类型才支持 multi_line 属性"); - } - if (!string.IsNullOrEmpty(Index)) { if ((CType is TArray tarray) && (tarray.ElementType is TBean b)) diff --git a/src/Luban.Job.Cfg/Source/TypeVisitors/DeepCompareTypeDefine.cs b/src/Luban.Job.Cfg/Source/TypeVisitors/DeepCompareTypeDefine.cs index 1a82915..5801824 100644 --- a/src/Luban.Job.Cfg/Source/TypeVisitors/DeepCompareTypeDefine.cs +++ b/src/Luban.Job.Cfg/Source/TypeVisitors/DeepCompareTypeDefine.cs @@ -107,7 +107,6 @@ namespace Luban.Job.Cfg.TypeVisitors //#if !LUBAN_LITE // || f1.ResourceTag != f2.ResourceTag //#endif - || f1.IsMultiRow != f2.IsMultiRow || f1.CType.IsNullable != f2.CType.IsNullable || f1.CType.GetType() != f2.CType.GetType() //|| !IsValidatorEquals(f1.RawDefine.Validators, f2.RawDefine.Validators) diff --git a/src/Luban.Job.Cfg/Source/Utils/DataUtil.cs b/src/Luban.Job.Cfg/Source/Utils/DataUtil.cs index 5075e0e..d669a90 100644 --- a/src/Luban.Job.Cfg/Source/Utils/DataUtil.cs +++ b/src/Luban.Job.Cfg/Source/Utils/DataUtil.cs @@ -1,4 +1,6 @@ using Luban.Job.Cfg.Datas; +using Luban.Job.Cfg.Defs; +using Luban.Job.Cfg.TypeVisitors; using Luban.Job.Common.Types; using System; using System.Collections.Generic; @@ -137,6 +139,24 @@ namespace Luban.Job.Cfg.Utils return tags.Count > 0 ? tags : null; } + const string SimpleContainerSep = ",;"; + + public static string GetSep(TType type) + { + + if (type.Tags != null && type.Tags.TryGetValue("sep", out var s) && !string.IsNullOrWhiteSpace(s)) + { + return s; + } + switch (type) + { + case TBean tb: return (tb.Bean as DefBean).Sep; + case TArray ta: return ta.ElementType.Apply(IsNotSepTypeVisitor.Ins) ? SimpleContainerSep : ""; + case TList ta: return ta.ElementType.Apply(IsNotSepTypeVisitor.Ins) ? SimpleContainerSep : ""; + case TSet ta: return ta.ElementType.Apply(IsNotSepTypeVisitor.Ins) ? SimpleContainerSep : ""; + default: return ""; + } + } //public static string Data2String(DType data) //{ // var s = new StringBuilder();