【特性】支持不限层次的嵌套 multi_rows,即multi_rows的list,每行元素本身又可以包含multi_rows的字段
parent
5c35c140b3
commit
e7066c579b
|
|
@ -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 类型的容器");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue