Skip to content

Commit bdc7724

Browse files
authored
Fix #132 Nested Ranges: Master-detail Report Issue (#204)
1 parent adb96f9 commit bdc7724

File tree

7 files changed

+78
-18
lines changed

7 files changed

+78
-18
lines changed

ClosedXML.Report/Excel/TempSheetBuffer.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,17 @@ public IXLRange CopyTo(IXLRange range)
154154
return range;
155155
}
156156

157+
public void SetPrevCellToLastUsed()
158+
{
159+
var lastUsed = _sheet.LastCellUsed();
160+
var clmn = _clmn < lastUsed.Address.ColumnNumber
161+
? lastUsed.Address.ColumnNumber + 1
162+
: _clmn;
163+
164+
ChangeAddress(lastUsed.Address.RowNumber, clmn);
165+
NewRow();
166+
}
167+
157168
public void Clear()
158169
{
159170
var srcRows = _sheet.RowsUsed(XLCellsUsedOptions.All);

ClosedXML.Report/RangeTemplate.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,11 @@ private void VerticalTable(object[] items, FormulaEvaluator evaluator)
234234
}
235235

236236
if (_isSubrange)
237+
{
237238
_rangeTags.Execute(new ProcessingContext(resultRange, new DataSource(items)));
239+
// if the range was increased by processing tags (for example, Group), move the buffer to the last cell
240+
_buff.SetPrevCellToLastUsed();
241+
}
238242
}
239243

240244
private void RenderCell(FormulaEvaluator evaluator, TemplateCell cell, params Parameter[] pars)
@@ -340,10 +344,13 @@ private void RenderSubrange(object item, FormulaEvaluator evaluator, TemplateCel
340344
}
341345
else
342346
{
343-
row += ownRng._rowCnt - 1;
344-
while (_cells[iCell].Row <= row+1)
347+
// move current template cell to next (skip subrange)
348+
row += ownRng._rowCnt+1;
349+
while (_cells[iCell].Row <= row-1)
345350
iCell++;
346351

352+
iCell--; // roll back. After it became clear that it was too much, we must go back.
353+
347354
int shiftLen = ownRng._rowCnt * (valArr.Length - 1);
348355
tags.Where(tag => tag.Cell.Row > cell.Row)
349356
.ForEach(t =>

tests/ClosedXML.Report.Tests/SubrangesTests.cs

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.IO;
34
using System.Linq;
45
using ClosedXML.Report.Tests.TestModels;
@@ -22,23 +23,40 @@ public void Simple(string templateFile)
2223
{
2324
using (var db = new DbDemos())
2425
{
25-
var items = db.items.ToList().GroupBy(i=>i.OrderNo).ToDictionary(x=>x.Key);
26-
var parts = db.parts.ToList().ToDictionary(x=>x.PartNo);
27-
customer[] custs = db.customers.LoadWith(x => x.Orders).OrderBy(x=>x.CustNo).ToArray();
28-
foreach (var customer in custs)
29-
{
30-
customer.Orders.Sort((x, y) => x.OrderNo.CompareTo(y.OrderNo));
31-
foreach (var o in customer.Orders)
26+
var custs = GetCustomers(db);
27+
tpl.AddVariable("Customers", custs);
28+
}
29+
},
30+
wb =>
31+
{
32+
CompareWithGauge(wb, templateFile);
33+
});
34+
}
35+
36+
[Fact]
37+
public void MultipleSubRanges()
38+
{
39+
var random = new Random(1234);
40+
var templateFile = "Subranges_Multiple.xlsx";
41+
XlTemplateTest(templateFile,
42+
tpl =>
43+
{
44+
using (var db = new DbDemos())
45+
{
46+
var custs = GetCustomers(db).Select(cust =>
47+
new {
48+
CustNo = cust.CustNo,
49+
Company = cust.Company,
50+
Orders = cust.Orders,
51+
Visitors = new List<dynamic>
3252
{
33-
var order = o;
34-
o.Items = items[order.OrderNo].ToList();
35-
o.Items.Sort((x,y)=>x.ItemNo.Value.CompareTo(y.ItemNo));
36-
foreach (var item in o.Items)
37-
item.Part = parts[item.PartNo.Value];
53+
new { Name = "Alice", Age = random.Next(0, 100), Gender = "F" },
54+
new { Name = "Bob", Age = random.Next(0, 100), Gender = "M" },
55+
new { Name = "John", Age = random.Next(0, 100), Gender = "M" },
3856
}
39-
}
40-
//var cust = db.Customers.Include(x => x.Orders.Select(o=>o.Items.Select(i=>i.Part)));
57+
});
4158
tpl.AddVariable("Customers", custs);
59+
tpl.AddVariable("user", "John Doe");
4260
}
4361
},
4462
wb =>
@@ -90,6 +108,27 @@ public void SingleEmptySubsetCorrectSum()
90108
});
91109
}
92110

111+
private static customer[] GetCustomers(DbDemos db)
112+
{
113+
var items = db.items.ToList().GroupBy(i => i.OrderNo).ToDictionary(x => x.Key);
114+
var parts = db.parts.ToList().ToDictionary(x => x.PartNo);
115+
customer[] custs = db.customers.LoadWith(x => x.Orders).OrderBy(x => x.CustNo).ToArray();
116+
foreach (var customer in custs)
117+
{
118+
customer.Orders.Sort((x, y) => x.OrderNo.CompareTo(y.OrderNo));
119+
foreach (var o in customer.Orders)
120+
{
121+
var order = o;
122+
o.Items = items[order.OrderNo].ToList();
123+
o.Items.Sort((x, y) => x.ItemNo.Value.CompareTo(y.ItemNo));
124+
foreach (var item in o.Items)
125+
item.Part = parts[item.PartNo.Value];
126+
}
127+
}
128+
//var cust = db.Customers.Include(x => x.Orders.Select(o=>o.Items.Select(i=>i.Part)));
129+
return custs;
130+
}
131+
93132
private IEnumerable<dynamic> GenerateVisitors()
94133
{
95134
return new List<dynamic>

tests/ClosedXML.Report.Tests/XlsxTemplateTestsBase.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ protected void CompareWithGauge(XLWorkbook actual, string fileExpected)
7373
using (var expectStream = File.Open(fileExpected, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
7474
using (var expected = new XLWorkbook(expectStream))
7575
{
76-
actual.Worksheets.Count.ShouldBeEquivalentTo(expected.Worksheets.Count, $"Count of worksheets must be {expected.Worksheets.Count}");
76+
var shEquals = actual.Worksheets.Count == expected.Worksheets.Count;
77+
if (!shEquals)
78+
actual.SaveAs(Path.Combine("Output", Path.GetFileName(fileExpected)));
79+
shEquals.Should().BeTrue($"Count of worksheets must be {expected.Worksheets.Count}");
7780

7881
for (int i = 0; i < actual.Worksheets.Count; i++)
7982
{

tests/Gauges/Subranges_Multiple.xlsx

44.7 KB
Binary file not shown.
22.3 KB
Binary file not shown.
22.7 KB
Binary file not shown.

0 commit comments

Comments
 (0)