Skip to content

Commit

Permalink
Merge pull request #11 from stex43/kreslina.a/parse-with-offset
Browse files Browse the repository at this point in the history
- template engine lazy parsing with table offset
  • Loading branch information
aldobrynin authored Dec 16, 2022
2 parents a22a55e + 5683450 commit b6557a8
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,20 @@ public void TestLazyParse()
}));
}

[Test]
public void TestLazyParseWithOffset()
{
var offset = new ObjectSize(1, 1);
var model = LazyParse<PriceList>("simpleWithItemsList_template.xlsx", "simpleWithEnumerableAndOffset_target.xlsx", offset);

model.Type.Should().Be("Основной");
model.ItemsList.Should().BeEquivalentTo(new List<Item>(new[]
{
new Item {Index = 1, Id = "2311129000009", Name = "СЫР ГОЛЛАНДСКИЙ МОЖГА 1КГ"},
new Item {Index = 2, Id = "2311131000004", Name = "СЫР РОССИЙСКИЙ МОЖГА 1КГ"},
}));
}

[Test]
public void TestLazyParseMoreThan10kItems()
{
Expand Down Expand Up @@ -299,7 +313,7 @@ public void TestImportAfterCreate(string extension)
}
}

private TModel LazyParse<TModel>(string templateFileName, string targetFileName)
private TModel LazyParse<TModel>(string templateFileName, string targetFileName, ObjectSize offset = null)
where TModel : new()
{
var templateBytes = File.ReadAllBytes(GetFilePath(templateFileName));
Expand All @@ -311,7 +325,7 @@ private TModel LazyParse<TModel>(string templateFileName, string targetFileName)
var template = new ExcelTable(templateDocument.GetWorksheet(0));
var templateEngine = new TemplateEngine(template, logger);

return templateEngine.LazyParse<TModel>(lazyTableReader);
return templateEngine.LazyParse<TModel>(lazyTableReader, offset);
}
}

Expand Down
Binary file not shown.
3 changes: 2 additions & 1 deletion Excel.TemplateEngine/ITemplateEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using JetBrains.Annotations;

using SkbKontur.Excel.TemplateEngine.ObjectPrinting.LazyParse;
using SkbKontur.Excel.TemplateEngine.ObjectPrinting.NavigationPrimitives.Implementations;
using SkbKontur.Excel.TemplateEngine.ObjectPrinting.TableBuilder;
using SkbKontur.Excel.TemplateEngine.ObjectPrinting.TableParser;

Expand All @@ -15,7 +16,7 @@ public interface ITemplateEngine
(TModel model, Dictionary<string, string> mappingForErrors) Parse<TModel>([NotNull] ITableParser tableParser)
where TModel : new();

public TModel LazyParse<TModel>([NotNull] LazyTableReader lazyTableReader)
public TModel LazyParse<TModel>([NotNull] LazyTableReader lazyTableReader, ObjectSize readerOffset = null)
where TModel : new();
}
}
19 changes: 11 additions & 8 deletions Excel.TemplateEngine/ObjectPrinting/LazyParse/LazyClassParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

using SkbKontur.Excel.TemplateEngine.ObjectPrinting.ExcelDocumentPrimitives;
using SkbKontur.Excel.TemplateEngine.ObjectPrinting.Helpers;
using SkbKontur.Excel.TemplateEngine.ObjectPrinting.NavigationPrimitives.Implementations;
using SkbKontur.Excel.TemplateEngine.ObjectPrinting.RenderingTemplates;

using Vostok.Logging.Abstractions;
Expand All @@ -30,8 +31,9 @@ public LazyClassParser(ILog logger)
/// <typeparam name="TModel">Class to parse.</typeparam>
/// <param name="tableReader">Target document LazyTableReader.</param>
/// <param name="template"></param>
/// <param name="readerOffset">Target file offset relative to a template.</param>
[NotNull]
public TModel Parse<TModel>([NotNull] LazyTableReader tableReader, [NotNull] RenderingTemplate template)
public TModel Parse<TModel>([NotNull] LazyTableReader tableReader, [NotNull] RenderingTemplate template, ObjectSize readerOffset)
where TModel : new()
{
var model = new TModel();
Expand All @@ -42,15 +44,15 @@ public TModel Parse<TModel>([NotNull] LazyTableReader tableReader, [NotNull] Ren
if (firstCell == null)
continue;

var targetRowReader = tableReader.TryReadRow(firstCell.CellPosition.RowIndex);
var targetRowReader = tableReader.TryReadRow(firstCell.CellPosition.RowIndex + readerOffset.Height);
if (targetRowReader == null)
continue;

using (targetRowReader)
{
foreach (var templateCell in templateRow)
{
var targetCell = targetRowReader.TryReadCell(templateCell.CellPosition);
var targetCell = targetRowReader.TryReadCell(templateCell.CellPosition.Add(readerOffset));
if (targetCell == null)
continue;

Expand All @@ -69,7 +71,7 @@ public TModel Parse<TModel>([NotNull] LazyTableReader tableReader, [NotNull] Ren

var templateListCells = templateRow.SkipWhile(x => x.CellPosition.CellReference != templateCell.CellPosition.CellReference)
.ToArray();
ParseEnumerable(tableReader, model, templateListCells, enumerableType);
ParseEnumerable(tableReader, model, templateListCells, enumerableType, readerOffset);
break;
}

Expand All @@ -87,7 +89,8 @@ public TModel Parse<TModel>([NotNull] LazyTableReader tableReader, [NotNull] Ren
private void ParseEnumerable([NotNull] LazyTableReader tableReader,
[NotNull] object model,
[NotNull] [ItemNotNull] ICell[] templateListCells,
[NotNull] Type enumerableType)
[NotNull] Type enumerableType,
[NotNull] ObjectSize readerOffset)
{
var firstEnumerablePath = ExcelTemplatePath.FromRawExpression(templateListCells.First().StringValue)
.SplitForEnumerableExpansion()
Expand All @@ -96,18 +99,18 @@ private void ParseEnumerable([NotNull] LazyTableReader tableReader,
var modelType = model.GetType();
var itemType = ObjectPropertiesExtractor.ExtractChildObjectTypeFromPath(modelType, firstEnumerablePath);

var items = ParseList(tableReader, itemType, templateListCells.Select(x => new SimpleCell(x.CellPosition, x.StringValue)));
var items = ParseList(tableReader, itemType, templateListCells.Select(x => new SimpleCell(x.CellPosition, x.StringValue)), readerOffset);

var withoutArrayAccess = firstEnumerablePath.WithoutArrayAccess();
var enumerableSetter = ObjectChildSetterFactory.GetEnumerableSetter(modelType, withoutArrayAccess, enumerableType, itemType);

enumerableSetter(model, items);
}

private object ParseList([NotNull] LazyTableReader tableReader, [NotNull] Type itemType, [NotNull, ItemNotNull] IEnumerable<SimpleCell> templateListCells)
private object ParseList([NotNull] LazyTableReader tableReader, [NotNull] Type itemType, [NotNull, ItemNotNull] IEnumerable<SimpleCell> templateListCells, ObjectSize readerOffset)
{
return parseList.MakeGenericMethod(itemType)
.Invoke(null, new object[] {tableReader, templateListCells, true, logger});
.Invoke(null, new object[] {tableReader, templateListCells, true, logger, readerOffset});
}

private void ParseSingleValue([NotNull] SimpleCell cell,
Expand Down
17 changes: 12 additions & 5 deletions Excel.TemplateEngine/ObjectPrinting/LazyParse/ListParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ public static class ListParser
/// <param name="tableReader">TableReader of target document which will be parsed.</param>
/// <param name="templateListCells">Template cells with list items descriptions.</param>
/// <param name="filterTemplateCells">Determines whether it's needed to filter templateListCells or not.</param>
/// <param name="readerOffset">Target file offset relative to a template.</param>
/// <param name="logger"></param>
public static IReadOnlyList<TItem> Parse<TItem>([NotNull] LazyTableReader tableReader,
[NotNull, ItemNotNull] IEnumerable<SimpleCell> templateListCells,
bool filterTemplateCells,
[NotNull] ILog logger)
[NotNull] ILog logger,
[NotNull] ObjectSize readerOffset)
{
var itemType = typeof(TItem);

Expand All @@ -43,11 +45,11 @@ public static IReadOnlyList<TItem> Parse<TItem>([NotNull] LazyTableReader tableR
var result = new List<TItem>();

var firstItemCellPosition = itemTemplate.First().CellPosition;
var row = tableReader.TryReadRow(firstItemCellPosition.RowIndex);
var row = tableReader.TryReadRow(firstItemCellPosition.RowIndex + readerOffset.Height);
while (row != null)
{
var itemDict = itemPropPaths.ToDictionary(x => x, _ => (object)null);
FillInItemDict(itemTemplate, row, itemType, itemDict, logger);
FillInItemDict(itemTemplate, row, itemType, itemDict, readerOffset, logger);

if (IsRowEmpty(itemDict, impotentItemProps))
{
Expand All @@ -64,11 +66,16 @@ public static IReadOnlyList<TItem> Parse<TItem>([NotNull] LazyTableReader tableR
return result;
}

private static void FillInItemDict((ICellPosition CellPosition, ExcelTemplatePath ItemPropPath)[] itemTemplate, LazyRowReader row, Type itemType, Dictionary<ExcelTemplatePath, object> itemDict, ILog logger)
private static void FillInItemDict((ICellPosition CellPosition, ExcelTemplatePath ItemPropPath)[] itemTemplate,
LazyRowReader row,
Type itemType,
Dictionary<ExcelTemplatePath, object> itemDict,
ObjectSize readerOffset,
ILog logger)
{
foreach (var prop in itemTemplate)
{
var cellPosition = new CellPosition(row.RowIndex, prop.CellPosition.ColumnIndex);
var cellPosition = new CellPosition(row.RowIndex, prop.CellPosition.ColumnIndex + readerOffset.Width);
var cell = row.TryReadCell(cellPosition);
if (cell == null || string.IsNullOrWhiteSpace(cell.CellValue))
continue;
Expand Down
8 changes: 6 additions & 2 deletions Excel.TemplateEngine/TemplateEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using SkbKontur.Excel.TemplateEngine.ObjectPrinting.ExcelDocumentPrimitives;
using SkbKontur.Excel.TemplateEngine.ObjectPrinting.LazyParse;
using SkbKontur.Excel.TemplateEngine.ObjectPrinting.NavigationPrimitives.Implementations;
using SkbKontur.Excel.TemplateEngine.ObjectPrinting.ParseCollection;
using SkbKontur.Excel.TemplateEngine.ObjectPrinting.RenderCollection;
using SkbKontur.Excel.TemplateEngine.ObjectPrinting.RenderingTemplates;
Expand Down Expand Up @@ -52,13 +53,16 @@ public void Render<TModel>([NotNull] ITableBuilder tableBuilder, [NotNull] TMode
/// </summary>
/// <typeparam name="TModel">Class to parse.</typeparam>
/// <param name="lazyTableReader">LazyTableReader of target xlsx file.</param>
public TModel LazyParse<TModel>([NotNull] LazyTableReader lazyTableReader)
/// <param name="readerOffset">Target file offset relative to a template.</param>
public TModel LazyParse<TModel>([NotNull] LazyTableReader lazyTableReader, ObjectSize readerOffset = null)
where TModel : new()
{
readerOffset ??= new ObjectSize(0, 0);

var renderingTemplate = templateCollection.GetTemplate(rootTemplateName) ??
throw new InvalidOperationException($"Template with name {rootTemplateName} not found in xlsx");
var parser = parserCollection.GetLazyClassParser();
return parser.Parse<TModel>(lazyTableReader, renderingTemplate);
return parser.Parse<TModel>(lazyTableReader, renderingTemplate, readerOffset);
}

private const string rootTemplateName = "RootTemplate";
Expand Down

0 comments on commit b6557a8

Please sign in to comment.