【特性】支持不限层次的嵌套 multi_rows,即multi_rows的list,每行元素本身又可以包含multi_rows的字段

main
walon 2021-08-06 19:06:25 +08:00
parent 5c35c140b3
commit e7066c579b
3 changed files with 92 additions and 115 deletions

View File

@ -90,7 +90,7 @@ namespace Luban.Job.Cfg.DataCreators
throw new NotSupportedException(); throw new NotSupportedException();
} }
public bool IsContainerAndElementNotSepType(TType type) private static bool IsContainerAndElementNotSepType(TType type)
{ {
switch (type) switch (type)
{ {
@ -119,14 +119,15 @@ namespace Luban.Job.Cfg.DataCreators
{ {
try try
{ {
if (f.IsMultiRow) list.Add(f.CType.Apply(this, row.GetSubTitleNamedRow(fname), f.IsMultiRow, f.IsNullable));
{ //if (f.IsMultiRow)
list.Add(f.CType.Apply(this, row.GetSubTitleNamedRowOfMultiRows(fname), f.IsMultiRow, f.IsNullable)); //{
} // list.Add(f.CType.Apply(this, row.GetSubTitleNamedRowOfMultiRows(fname), f.IsMultiRow, f.IsNullable));
else //}
{ //else
list.Add(f.CType.Apply(this, row.GetSubTitleNamedRow(fname), f.IsMultiRow /* 肯定是 false */, f.IsNullable)); //{
} // list.Add(f.CType.Apply(this, row.GetSubTitleNamedRow(fname), f.IsMultiRow /* 肯定是 false */, f.IsNullable));
//}
} }
catch (DataCreateException dce) catch (DataCreateException dce)
{ {
@ -246,7 +247,8 @@ namespace Luban.Job.Cfg.DataCreators
// 如果是多行数据以当前title为title,每行读入一个element // 如果是多行数据以当前title为title,每行读入一个element
if (multirow) if (multirow)
{ {
foreach (var sub in row.GenerateSubNameRows()) //foreach (var sub in row.GenerateSubNameRows(elementType))
foreach (var sub in Sheet.NamedRow.CreateMultiRowNamedRow(row.Rows, row.SelfTitle, elementType))
{ {
list.Add(this.Accept(elementType, sub, false, false)); list.Add(this.Accept(elementType, sub, false, false));
} }
@ -255,17 +257,18 @@ namespace Luban.Job.Cfg.DataCreators
{ {
// 如果不是多行,并且定义了子标题的话。以一个子标题所占的列,读入一个数据 // 如果不是多行,并且定义了子标题的话。以一个子标题所占的列,读入一个数据
foreach (var sub in row.SelfTitle.SubTitleList) //foreach (var sub in row.SelfTitle.SubTitleList)
{ //{
list.Add(this.Accept(elementType, new Sheet.NamedRow(sub, row.Rows), false, false)); // list.Add(this.Accept(elementType, new Sheet.NamedRow(sub, row.Rows), false, false));
} //}
throw new NotSupportedException("只有multi_rows=1的list,bean类型才允许有子title");
} }
return list; return list;
} }
public DType Accept(TArray type, Sheet.NamedRow x, bool multirow, bool nullable) public DType Accept(TArray type, Sheet.NamedRow x, bool multirow, bool nullable)
{ {
if (!(type.ElementType is TBean bean)) if (type.ElementType is not TBean bean)
{ {
throw new Exception($"NamedRow 只支持 bean 类型的容器"); throw new Exception($"NamedRow 只支持 bean 类型的容器");
} }
@ -277,7 +280,7 @@ namespace Luban.Job.Cfg.DataCreators
public DType Accept(TList type, Sheet.NamedRow x, bool multirow, bool nullable) public DType Accept(TList type, Sheet.NamedRow x, bool multirow, bool nullable)
{ {
if (!(type.ElementType is TBean bean)) if (type.ElementType is not TBean bean)
{ {
throw new Exception($"NamedRow 只支持 bean 类型的容器"); throw new Exception($"NamedRow 只支持 bean 类型的容器");
} }

View File

@ -117,7 +117,7 @@ namespace Luban.Job.Cfg.DataSources.Excel
{ {
try try
{ {
datas.AddRange(sheet.ReadMulti(type, ((DefBean)type.Bean).IsMultiRow)); datas.AddRange(sheet.ReadMulti(type));
} }
catch (DataCreateException dce) catch (DataCreateException dce)
{ {

View File

@ -1,6 +1,8 @@
using ExcelDataReader; using ExcelDataReader;
using Luban.Job.Cfg.DataCreators; using Luban.Job.Cfg.DataCreators;
using Luban.Job.Cfg.Datas; using Luban.Job.Cfg.Datas;
using Luban.Job.Cfg.Defs;
using Luban.Job.Cfg.RawDefs;
using Luban.Job.Cfg.TypeVisitors; using Luban.Job.Cfg.TypeVisitors;
using Luban.Job.Cfg.Utils; using Luban.Job.Cfg.Utils;
using Luban.Job.Common.Types; using Luban.Job.Common.Types;
@ -103,6 +105,60 @@ namespace Luban.Job.Cfg.DataSources.Excel
public class NamedRow public class NamedRow
{ {
public static IEnumerable<NamedRow> CreateMultiRowNamedRow(List<List<Cell>> 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 NamedRow(title, row);
}
}
else
{
List<DefField> notMultiRowFields = bean.Bean.HierarchyFields.Select(f => (DefField)f).Where(f => !f.IsMultiRow).ToList();
List<List<Cell>> 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);
}))
{
if (recordRows == null)
{
recordRows = new List<List<Cell>>();
}
recordRows.Add(row);
}
else
{
if (recordRows != null)
{
yield return new NamedRow(title, recordRows);
}
recordRows = new List<List<Cell>>();
recordRows.Add(row);
}
}
if (recordRows != null)
{
yield return new NamedRow(title, recordRows);
}
}
}
public Title SelfTitle { get; } public Title SelfTitle { get; }
public List<List<Cell>> Rows { get; } public List<List<Cell>> Rows { get; }
@ -156,20 +212,20 @@ namespace Luban.Job.Cfg.DataSources.Excel
} }
} }
public NamedRow GetSubTitleNamedRow(string name) //public NamedRow GetSubTitleNamedRow(string name)
{ //{
Title title = this.Titles[name]; // Title title = this.Titles[name];
CheckEmptySinceSecondRow(name, title.FromIndex, title.ToIndex); // CheckEmptySinceSecondRow(name, title.FromIndex, title.ToIndex);
return new NamedRow(title, this.Rows[0]); // return new NamedRow(title, this.Rows[0]);
} //}
public NamedRow GetSubTitleNamedRowOfMultiRows(string name) public NamedRow GetSubTitleNamedRow(string name)
{ {
Title title = Titles[name]; Title title = Titles[name];
return new NamedRow(title, this.Rows); return new NamedRow(title, this.Rows);
} }
public IEnumerable<NamedRow> GenerateSubNameRows() public IEnumerable<NamedRow> GenerateSubNameRows(TBean bean)
{ {
foreach (var row in Rows) foreach (var row in Rows)
{ {
@ -301,7 +357,7 @@ namespace Luban.Job.Cfg.DataSources.Excel
return true; return true;
} }
private string GetRowTag(List<Cell> row) private static string GetRowTag(List<Cell> row)
{ {
if (row.Count == 0) if (row.Count == 0)
{ {
@ -531,15 +587,14 @@ namespace Luban.Job.Cfg.DataSources.Excel
} }
private static bool IsBlankRow(List<Cell> row)
public static bool IsBlankRow(List<Cell> row)
{ {
// 第一列被策划用于表示是否注释掉此行 // 第一列被策划用于表示是否注释掉此行
// 忽略此列是否空白 // 忽略此列是否空白
return row.GetRange(1, row.Count - 1).All(c => c.Value == null || (c.Value is string s && string.IsNullOrWhiteSpace(s))); return row.GetRange(1, row.Count - 1).All(c => c.Value == null || (c.Value is string s && string.IsNullOrWhiteSpace(s)));
} }
public static bool IsBlankRow(List<Cell> row, int fromIndex, int toIndex) private static bool IsBlankRow(List<Cell> row, int fromIndex, int toIndex)
{ {
for (int i = Math.Max(1, fromIndex), n = Math.Min(toIndex, row.Count - 1); i <= n; i++) for (int i = Math.Max(1, fromIndex), n = Math.Min(toIndex, row.Count - 1); i <= n; i++)
{ {
@ -552,94 +607,13 @@ namespace Luban.Job.Cfg.DataSources.Excel
return true; return true;
} }
private List<Cell> GetNextRecordRow() public IEnumerable<Record> ReadMulti(TBean type)
{ {
while (curReadIndex < _rowColumns.Count) foreach (var recordNamedRow in NamedRow.CreateMultiRowNamedRow(this._rowColumns, this._rootTitle, type))
{ {
var row = _rowColumns[curReadIndex++]; bool isTest = DataUtil.IsTestTag(GetRowTag(recordNamedRow.Rows[0]));
if (IsBlankRow(row)) var data = (DBean)ExcelNamedRowDataCreator.Ins.ReadExcel(recordNamedRow, type);
{ yield return new Record(data, RawUrl, isTest);
continue;
}
return row;
}
return null;
}
private bool HasNotMainKey(List<Cell> row)
{
return string.IsNullOrWhiteSpace(row[1].Value?.ToString());
}
private List<List<Cell>> GetNextRecordRows()
{
List<List<Cell>> rows = null;
while (curReadIndex < _rowColumns.Count)
{
var row = _rowColumns[curReadIndex++];
if (IsBlankRow(row))
{
continue;
}
if (rows == null)
{
rows = new List<List<Cell>>() { row };
}
else
{
if (HasNotMainKey(row))
{
rows.Add(row);
}
else
{
--curReadIndex;
return rows;
}
}
}
return rows;
}
public List<Record> ReadMulti(TBean type, bool enableMultiRowRecord)
{
var datas = new List<Record>();
for (Record data; (data = ReadOne(type, enableMultiRowRecord)) != null;)
{
datas.Add(data);
}
return datas;
}
private int curReadIndex = 0;
public Record ReadOne(TBean type, bool enableMultiRowRecord)
{
if (!enableMultiRowRecord)
{
List<Cell> row = GetNextRecordRow();
if (row == null)
{
return null;
}
bool isTest = DataUtil.IsTestTag(GetRowTag(row));
var data = (DBean)ExcelNamedRowDataCreator.Ins.ReadExcel(new NamedRow(_rootTitle, row), type);
return new Record(data, RawUrl, isTest);
}
else
{
List<List<Cell>> rows = GetNextRecordRows();
if (rows == null)
{
return null;
}
bool isTest = DataUtil.IsTestTag(GetRowTag(rows[0]));
var data = (DBean)ExcelNamedRowDataCreator.Ins.ReadExcel(new NamedRow(_rootTitle, rows), type);
return new Record(data, RawUrl, isTest);
} }
} }
} }