Skip to content

Commit adb96f9

Browse files
authored
Add summary tag with label in group feature (#202)
* Add summary tag with label in group feature * Add summary tag with label in group feature
1 parent 1d4831d commit adb96f9

File tree

7 files changed

+28
-17
lines changed

7 files changed

+28
-17
lines changed

ClosedXML.Report/Excel/Subtotal.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Linq;
44
using ClosedXML.Excel;
5+
using ClosedXML.Report.Options;
56
using MoreLinq;
67

78
namespace ClosedXML.Report.Excel
@@ -39,7 +40,7 @@ public Subtotal(IXLRange range, bool summaryAbove)
3940

4041
public SubtotalGroup[] Groups => _groups.ToArray();
4142

42-
public SubtotalGroup AddGrandTotal(SubtotalSummaryFunc[] summaries)
43+
public SubtotalGroup AddGrandTotal(SummaryFuncTag[] summaries)
4344
{
4445
if (Sheet.Row(_range.Row(2).RowNumber()).OutlineLevel == 0)
4546
{
@@ -63,7 +64,7 @@ public SubtotalGroup AddGrandTotal(SubtotalSummaryFunc[] summaries)
6364
else return null;
6465
}
6566

66-
public void GroupBy(int groupBy, SubtotalSummaryFunc[] summaries, bool pageBreaks = false, Func<string, string> getGroupLabel = null)
67+
public void GroupBy(int groupBy, SummaryFuncTag[] summaries, bool pageBreaks = false, Func<string, string> getGroupLabel = null)
6768
{
6869
_pageBreaks = pageBreaks;
6970
_getGroupLabel = getGroupLabel;
@@ -251,7 +252,7 @@ private void MoveRange(MoveData moveData)
251252
Sheet.Cell(moveData.TargetAddress.FirstAddress).Value = _tempSheet.Range(1, 1, srcRng.RowCount(), srcRng.ColumnCount());
252253
}
253254

254-
private SubtotalGroup CreateGroup(IXLRange groupRng, int groupClmn, int level, string title, SubtotalSummaryFunc[] summaries, bool pageBreaks)
255+
private SubtotalGroup CreateGroup(IXLRange groupRng, int groupClmn, int level, string title, SummaryFuncTag[] summaries, bool pageBreaks)
255256
{
256257
var firstRow = groupRng.RangeAddress.FirstAddress.RowNumber;
257258
var lastRow = groupRng.RangeAddress.LastAddress.RowNumber;
@@ -273,17 +274,17 @@ private SubtotalGroup CreateGroup(IXLRange groupRng, int groupClmn, int level, s
273274
summRow.Clear(XLClearOptions.Contents | XLClearOptions.DataType); //TODO Check if the issue persists (ClosedXML issue 844)
274275
summRow.Cell(groupClmn).Value = _getGroupLabel != null ? _getGroupLabel(title) : title + " "+ TotalLabel;
275276
Sheet.Row(summRow.RowNumber()).OutlineLevel = level - 1;
276-
277-
foreach (var summ in summaries)
277+
foreach (var item in summaries)
278278
{
279+
var summ = item.GetFunc();
279280
/*if (summ.FuncNum == 0)
280281
{
281282
summRow.Cell(summ.Column).Value = summ.Calculate(groupRng);
282283
}
283284
else */if (summ.FuncNum > 0)
284285
{
285286
var funcRngAddr = groupRng.Column(summ.Column).RangeAddress;
286-
summRow.Cell(summ.Column).FormulaA1 = $"Subtotal({summ.FuncNum},{funcRngAddr.ToStringRelative()})";
287+
summRow.Cell(summ.Column).FormulaA1 =(string.IsNullOrWhiteSpace(item.Cell.Formula) ?string.Empty: $"{item.Cell.Formula} & ")+$"Subtotal({summ.FuncNum},{funcRngAddr.ToStringRelative()})";
287288
}
288289
else
289290
{

ClosedXML.Report/Excel/XlExtensions.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Reflection;
55
using System.Text.RegularExpressions;
66
using ClosedXML.Excel;
7+
using ClosedXML.Report.Options;
78
using ClosedXML.Report.Utils;
89

910
namespace ClosedXML.Report.Excel
@@ -157,15 +158,15 @@ public static void Subtotal(this IXLRange range, int groupBy, string function, i
157158
{
158159
if (replace)
159160
subtotal.Unsubtotal();
160-
var summaries = totalList.Select(x => new SubtotalSummaryFunc(function, x)).ToArray();
161+
var summaries = totalList.Select(x => new SummaryFuncTag {Name=function.ToLower(), Cell = new TemplateCell { Column = x } }).ToArray();
161162
subtotal.AddGrandTotal(summaries);
162163
subtotal.GroupBy(groupBy, summaries, pageBreaks);
163164
}
164165
}
165166

166167
public static bool IsSummary(this IXLRangeRow row)
167168
{
168-
return row.Cells(x => x.HasFormula && x.FormulaA1.ToLower().StartsWith("subtotal(")).Any();
169+
return row.Cells(x => x.HasFormula && x.FormulaA1.ToLower().Contains("subtotal(")).Any();
169170
}
170171

171172
public static void CopyStylesFrom(this IXLRangeBase trgtRow, IXLRangeBase srcRow)
@@ -216,7 +217,13 @@ internal static string GetInnerText(this IXLCell cell)
216217
.GetProperty("InnerText", BindingFlags.Instance | BindingFlags.Public);
217218
return (string)_xlCellInnerText.GetValue(cell, null);
218219
}
219-
220+
internal static string GetCellText(this IXLCell cell)
221+
{
222+
var field = cell.GetType().GetField("_cellValue",
223+
BindingFlags.NonPublic |
224+
BindingFlags.Instance);
225+
return (string)field.GetValue(cell);
226+
}
220227
internal static void CopyRelative(this IXLConditionalFormat format, IXLRangeBase fromRange, IXLRangeBase toRange, bool expand)
221228
{
222229
foreach (var sourceFmtRange in format.Ranges)

ClosedXML.Report/Options/GroupTag.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public override void Execute(ProcessingContext context)
9191
// sort range
9292
base.Execute(context);
9393

94-
Process(context.Range, fields, summaryAbove, funcs.Select(x => x.GetFunc()).ToArray(), DisableGrandTotal);
94+
Process(context.Range, fields, summaryAbove, funcs, DisableGrandTotal);
9595

9696
foreach (var tag in fields.Cast<OptionTag>().Union(funcs))
9797
{
@@ -101,8 +101,9 @@ public override void Execute(ProcessingContext context)
101101

102102
private bool DisableGrandTotal => List.HasTag("disablegrandtotal") || !List.GetAll<SummaryFuncTag>().Any();
103103

104-
private void Process(IXLRange root, GroupTag[] groups, bool summaryAbove, SubtotalSummaryFunc[] funcs, bool disableGrandTotal)
104+
private void Process(IXLRange root, GroupTag[] groups, bool summaryAbove,SummaryFuncTag[] summaries , bool disableGrandTotal)
105105
{
106+
SubtotalSummaryFunc[] funcs= summaries.Select(x => x.GetFunc()).ToArray();
106107
var groupRow = root.LastRow();
107108
// DoGroups
108109

@@ -120,7 +121,7 @@ private void Process(IXLRange root, GroupTag[] groups, bool summaryAbove, Subtot
120121
if (GrandLabel != null) subtotal.GrandLabel = GrandLabel;
121122
if (!disableGrandTotal)
122123
{
123-
var total = subtotal.AddGrandTotal(funcs);
124+
var total = subtotal.AddGrandTotal(summaries);
124125
total.SummaryRow.Cell(2).Value = total.SummaryRow.Cell(1).Value;
125126
total.SummaryRow.Cell(1).Value = null;
126127
level++;
@@ -135,7 +136,7 @@ private void Process(IXLRange root, GroupTag[] groups, bool summaryAbove, Subtot
135136
if (g.MergeLabels == MergeMode.Merge2 && funcs.Length == 0)
136137
subtotal.ScanForGroups(g.Column);
137138
else
138-
subtotal.GroupBy(g.Column, g.DisableSubtotals ? new SubtotalSummaryFunc[0] : funcs, g.PageBreaks, labFormat);
139+
subtotal.GroupBy(g.Column, g.DisableSubtotals ? new SummaryFuncTag[0] : summaries, g.PageBreaks, labFormat);
139140

140141
g.Level = ++level;
141142
}
@@ -179,7 +180,7 @@ private static void FormatHeaderFooter(SubtotalGroup subGroup, IXLRangeRow group
179180

180181
if (subGroup.SummaryRow != null)
181182
{
182-
foreach (var cell in groupRow.Cells(c => c.HasFormula))
183+
foreach (var cell in groupRow.Cells(c => c.HasFormula && !(c.GetCellText()?.Contains("<<sum>>")??false)))
183184
{
184185
subGroup.SummaryRow.Cell(cell.Address.ColumnNumber - groupRow.RangeAddress.FirstAddress.ColumnNumber + 1).Value = cell;
185186
}

tests/ClosedXML.Report.Tests/GroupTagTests.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public void Simple(string templateFile)
5151
InlineData("GroupTagTests_PlaceToColumn.xlsx"),
5252
InlineData("GroupTagTests_NestedGroups.xlsx"),
5353
InlineData("GroupTagTests_DisableOutline.xlsx"),
54-
InlineData("GroupTagTests_FormulasInGroupRow.xlsx"),
54+
InlineData("GroupTagTests_FormulasWithTagsInGroupRow.xlsx"),
5555
]
5656
public void EmptyDataSource(string templateFile)
5757
{
@@ -69,7 +69,8 @@ public void EmptyDataSource(string templateFile)
6969
InlineData("GroupTagTests_DisableOutline.xlsx"),
7070
InlineData("GroupTagTests_FormulasInGroupRow.xlsx"),
7171
InlineData("GroupTagTests_MultiRanges.xlsx"),
72-
]
72+
InlineData("GroupTagTests_FormulasWithTagsInGroupRow.xlsx"),
73+
]
7374
public void Customers(string templateFile)
7475
{
7576
XlTemplateTest(templateFile,

tests/ClosedXML.Report.Tests/SubtotalTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.IO;
33
using ClosedXML.Excel;
44
using ClosedXML.Report.Excel;
5+
using ClosedXML.Report.Options;
56
using FluentAssertions;
67
using Xunit;
78
using Xunit.Abstractions;
@@ -89,7 +90,7 @@ public void WithHeaders()
8990
LoadTemplate("91_plaindata.xlsx");
9091
using (var subtotal = new Subtotal(_rng))
9192
{
92-
var summaries = new [] {new SubtotalSummaryFunc("sum", 7), };
93+
var summaries = new[] { new SummaryFuncTag { Name = "sum", Cell=new TemplateCell { Column = 7 } } };//{new SubtotalSummaryFunc("sum", 7), };
9394
subtotal.AddGrandTotal(summaries);
9495
subtotal.GroupBy(2, summaries, true);
9596
subtotal.GroupBy(3, summaries, true);
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)