Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable subtotal line in groups - Up to date #335

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions ClosedXML.Report/ClosedXML.Report.csproj
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<LangVersion>10</LangVersion>
<AssemblyName>ClosedXML.Report</AssemblyName>
<PackageId>ClosedXML.Report</PackageId>
<PackageId>CustomEa.ClosedXML.Report</PackageId>
<Configurations>Debug;Release</Configurations>
<PackageProjectUrl>https://github.com/ClosedXML/ClosedXML.Report</PackageProjectUrl>
<RepositoryUrl>https://github.com/ClosedXML/ClosedXML.Report</RepositoryUrl>
<Authors>Alexey Rozhkov, Alexey Pankratev</Authors>
<RepositoryUrl>https://github.com/eagleoriginal/ClosedXML.Report</RepositoryUrl>
<Authors>IOrlov, Alexey Rozhkov, Alexey Pankratev</Authors>
<Copyright>MIT</Copyright>
<Product>ClosedXML.Report</Product>
<PackageReleaseNotes>See https://github.com/ClosedXML/ClosedXML.Report/releases/tag/$(productVersion)</PackageReleaseNotes>
<Description>ClosedXML.Report is a tool for report generation and data analysis in .NET applications through the use of Microsoft Excel. ClosedXML.Report is a .NET-library for report generation Microsoft Excel without requiring Excel to be installed on the machine that's running the code.</Description>
<Product>CustomEa.ClosedXML.Report</Product>
<PackageReleaseNotes>See https://github.com/eagleoriginal/ClosedXML.Report/releases/tag/$(productVersion)</PackageReleaseNotes>
<Description>Not Intended for Common Use!!!
Pacakge with Custom Changes in original ClosedXML.Report.
ClosedXML.Report is a tool for report generation and data analysis in .NET applications through the use of Microsoft Excel. ClosedXML.Report is a .NET-library for report generation Microsoft Excel without requiring Excel to be installed on the machine that's running the code.</Description>
<PackageTags>ClosedXML Reporting Excel</PackageTags>
<Company>ClosedXML</Company>
<PackageIconUrl>https://github.com/ClosedXML/ClosedXML.Report/raw/develop/Resources/favicon-01.png</PackageIconUrl>
<Company>CustomEa.ClosedXML</Company>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>

<!-- Optional: Publish the repository URL in the built .nupkg (in the NuSpec <Repository> element) -->
<PublishRepositoryUrl>true</PublishRepositoryUrl>
Expand All @@ -30,12 +31,21 @@
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>ClosedXML.Report.snk</AssemblyOriginatorKeyFile>
<Version>0.2.10-Beta5</Version>
<PackageIcon>favicon-01.png</PackageIcon>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)'=='Release'">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>

<ItemGroup>
<None Include="..\Resources\favicon-01.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>

<ItemGroup>
<PackageReference Include="ClosedXML" Version="0.102.2" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
Expand Down
21 changes: 20 additions & 1 deletion ClosedXML.Report/Excel/Subtotal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,15 @@ private MoveData[] ScanRange(int groupBy)

var val = row.Cell(groupBy).GetString();
var isSummaryRow = row.IsSummary();
var isLeftGroupEndLine = false;
if (false == isSummaryRow)
{
isLeftGroupEndLine = _groups.SingleOrDefault(gr => gr.Column == groupBy - 1 &&
gr.SummaryRow == null &&
gr.Range.RangeAddress.LastAddress.RowNumber == row.RowNumber()) != null;
}

if (string.IsNullOrEmpty(val) && !isSummaryRow)
if (string.IsNullOrEmpty(val) && !isSummaryRow)
{
if (groupStart > 0)
{
Expand All @@ -364,6 +371,18 @@ private MoveData[] ScanRange(int groupBy)
continue;
}

if (isLeftGroupEndLine)
{
var localGroupStart = groupStart == 0
? row.RangeAddress.Relative(_range.RangeAddress).FirstAddress.RowNumber
: groupStart;

groups.Add(CreateMoveTask(groupBy, prevVal, _range.Cell(localGroupStart, 1), row.LastCell(), RangeType.DataRange));
prevVal = null;
groupStart = 0;
continue;
}

if (val != prevVal)
{
if (groupStart > 0)
Expand Down
2 changes: 2 additions & 0 deletions ClosedXML.Report/Excel/SubtotalSummaryFunc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ public virtual int FuncNum
}
}

public object DefaultValueForEmptySource { get; set; }

public Func<Type, Delegate> GetCalculateDelegate;

internal object Calculate(IDataSource dataSource)
Expand Down
8 changes: 7 additions & 1 deletion ClosedXML.Report/Excel/XlExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,13 @@ public static void ReplaceCFFormulaeToA1(this IXLWorksheet worksheet)
{
foreach (var format in worksheet.ConditionalFormats)
{
var target = format.Ranges.OrderBy(x=>x.RangeAddress.FirstAddress.RowNumber)
format.Ranges.RemoveAll(range => false == range.RangeAddress.IsValid);
var validRanges = format.Ranges.Where(range => range.RangeAddress.IsValid).ToList();
if (false == validRanges.Any())
continue;

var target =
validRanges.OrderBy(x=>x.RangeAddress.FirstAddress.RowNumber)
.ThenBy(x=> x.RangeAddress.FirstAddress.ColumnNumber)
.First().FirstCell();
foreach (var v in format.Values.Where(v => v.Value.Value.StartsWith("&=")).ToList())
Expand Down
63 changes: 59 additions & 4 deletions ClosedXML.Report/Options/GroupTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ OPTION PARAMS OBJECTS RNG Priority
"\PageBreaks"
"\TotalLabel"
"\GrandLabel"
"\DisableSubtotalLine"

"SummaryAbove" Range rD Normal

Expand All @@ -30,6 +31,8 @@ OPTION PARAMS OBJECTS RNG Priority
using ClosedXML.Excel;
using ClosedXML.Report.Excel;
using ClosedXML.Report.Utils;
using DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml.Spreadsheet;
using MoreLinq;

namespace ClosedXML.Report.Options
Expand All @@ -40,6 +43,7 @@ public class GroupTag : SortTag

public bool PageBreaks => Parameters.ContainsKey("pagebreaks");
public bool DisableSubtotals => Parameters.ContainsKey("disablesubtotals");
public bool DisableSubtotalLine => Parameters.ContainsKey("disablesubtotalline");
public bool Collapse => Parameters.ContainsKey("collapse");
public bool DisableOutLine => Parameters.ContainsKey("disableoutline");
public bool OutLine => !Parameters.ContainsKey("disableoutline");
Expand Down Expand Up @@ -110,11 +114,48 @@ private void Process(ProcessingContext context, GroupTag[] groups, bool summaryA
var level = 0;
var rows = root.RowCount() - 1;
var columns = root.ColumnCount();
if (rows <= 0 || columns <= 0)
if (columns <= 0)
{
return;
}

var r = root.Offset(0, 0, rows, columns);
// Empty Total grand for report
if (rows <= 0)
{
if (disableGrandTotal)
return;

var r2= root.Offset(0, 0, 1, columns);
using (var subtotal = new Subtotal(r2, summaryAbove, groups, context.Evaluator))
{
if (TotalLabel != null) subtotal.TotalLabel = TotalLabel;
if (GrandLabel != null) subtotal.GrandLabel = GrandLabel;
if (!disableGrandTotal)
{
var total = subtotal.AddGrandTotal(summaries);
total.SummaryRow.Cell(2).Value = total.SummaryRow.Cell(1).Value;
total.SummaryRow.Cell(1).Value = Blank.Value;
level++;
}

foreach (var subGroup in subtotal.Groups.OrderBy(x => x.Column).Reverse())
{
FormatHeaderFooter(subGroup, groupRow);

GroupRender(subGroup, new GroupTag { Column = 1, Level = 1 });
}

r2.Rows().ForEach(r => r.WorksheetRow().OutlineLevel = 0);
}

// Rem DoDeleteSpecialRow
root.LastRow().Delete(XLShiftDeletedCells.ShiftCellsUp);

return;
}

var r = root.Offset(0, 0, rows, columns);

using (var subtotal = new Subtotal(r, summaryAbove, groups, context.Evaluator))
{
if (TotalLabel != null) subtotal.TotalLabel = TotalLabel;
Expand All @@ -129,9 +170,18 @@ private void Process(ProcessingContext context, GroupTag[] groups, bool summaryA

foreach (var g in groups.OrderBy(x => x.Column))
{
// Todo: New Feature Group Without Subtotal. Only Merge.
if (g.DisableSubtotalLine)
{
subtotal.ScanForGroups(g.Column);
g.Level = ++level;

continue;
}

Func<string, string> labFormat = null;
if (!string.IsNullOrEmpty(g.LabelFormat))
labFormat = title => string.Format(LabelFormat, title);
labFormat = title => string.Format(g.LabelFormat, title);

if (g.MergeLabels == MergeMode.Merge2 && summaries.Length == 0)
subtotal.ScanForGroups(g.Column);
Expand Down Expand Up @@ -218,7 +268,12 @@ protected virtual void GroupRender(SubtotalGroup subGroup, GroupTag grData)
var rng = subGroup.Range.Column(subGroup.Column);
if (subGroup.Range.RowCount() > 1)
{
int cellIdx = _maxLevel - subGroup.Level + 1;
// TODO: Wrong Style apply for merged cells if on right has grouped total
// But in first cell i expect already cell with value and style
// Plus with DisableSubtotalLine feature this became totally wrong
int cellIdx = 1;
//int cellIdx = _maxLevel - subGroup.Level + 1; // TODO: Comment for future investigation

var style = rng.Cell(cellIdx).Style;
rng.Merge();
rng.Style = style;
Expand Down
21 changes: 20 additions & 1 deletion ClosedXML.Report/Options/SummaryFuncTag.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using System;
using System.Linq;
using System.Linq.Expressions;
using ClosedXML.Excel;
using ClosedXML.Report.Excel;
using ClosedXML.Report.Utils;
using DocumentFormat.OpenXml.Math;
using DocumentFormat.OpenXml.Spreadsheet;

namespace ClosedXML.Report.Options
{
Expand Down Expand Up @@ -32,8 +35,16 @@ public override void Execute(ProcessingContext context)
summRow = context.Range.LastRow();
calculatedRange = context.Range.Offset(0, summ.Column - 1, context.Range.RowCount() - 1, 1);
}
var items = summ.DataSource.GetAll();

if (summ.FuncNum == 0)
if (items == null || items.Length == 0)
{
if (summ.DefaultValueForEmptySource != null)
{
summRow.Cell(summ.Column).Value = XLCellValueConverter.FromObject(summ.DefaultValueForEmptySource);
}
}
else if (summ.FuncNum == 0)
{
var value = summ.Calculate((IDataSource)context.Value);
summRow.Cell(summ.Column).Value = XLCellValueConverter.FromObject(value);
Expand Down Expand Up @@ -62,6 +73,14 @@ private SubtotalSummaryFunc GetFunc(ProcessingContext context)
//return XLDynamicExpressionParser.ParseLambda(new[] {par}, null, GetParameter("Over"));
};
func.DataSource = DataSource;

if (HasParameter("Default"))
{
var dlg = context.Evaluator.ParseExpression(GetParameter("Default"), new ParameterExpression[] {});

func.DefaultValueForEmptySource = dlg.DynamicInvoke();
}

return func;
}
}
Expand Down
10 changes: 8 additions & 2 deletions ClosedXML.Report/RangeInterpreter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,13 @@ string EvalString(string str)
{
var growedRange = rng.GrowToMergedRanges();
var items = nr.RangeData as object[] ?? nr.RangeData.Cast<object>().ToArray();
if (!items.Any())
// Comment this section
// Revision: a38eda3a3a7092812c8358a949d4e489635501bf
// Author: Aleksei <pankraty@gmail.com>
// Date: 27.07.2023 23:54:54
// Message:
// Forcibly remove a range representing a table if its data source is empty (#251) (#323)
/*if (!items.Any())
{
if (growedRange.IsOptionsRowEmpty())
{
Expand All @@ -190,7 +196,7 @@ string EvalString(string str)
rangeWithoutOptionsRow.Delete(XLShiftDeletedCells.ShiftCellsUp);
}
continue;
}
}*/
var tplt = RangeTemplate.Parse(nr.NamedRange.Name, growedRange, _errors, _variables);
using (var buff = tplt.Generate(items))
{
Expand Down
28 changes: 27 additions & 1 deletion tests/ClosedXML.Report.Tests/GroupTagTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using ClosedXML.Report.Tests.TestModels;
using LinqToDB;
Expand Down Expand Up @@ -38,7 +40,7 @@ public void Simple(string templateFile)
{
using (var db = new DbDemos())
{
var cust = db.customers.LoadWith(x=>x.Orders.First().Items).OrderBy(c => c.CustNo).First(x=>x.CustNo == 1356);
var cust = db.customers.LoadWith(x => x.Orders.First().Items).OrderBy(c => c.CustNo).First(x => x.CustNo == 1356);
cust.Logo = Resource.toms_diving_center;
tpl.AddVariable("MoreOrders", cust.Orders.Take(5));
tpl.AddVariable(cust);
Expand All @@ -52,6 +54,29 @@ public void Simple(string templateFile)
});
}

[Xunit.Fact]
public void Simple_EmptyResult()
{
string templateFile = "GroupTagTests_Simple_Empty.xlsx";
XlTemplateTest(templateFile,
tpl =>
{
using (var db = new DbDemos())
{
var cust = db.customers.LoadWith(x => x.Orders.First().Items).OrderBy(c => c.CustNo).First(x => x.CustNo == 1356);
cust.Orders.Clear();
cust.Logo = Resource.toms_diving_center;
tpl.AddVariable("MoreOrders", cust.Orders.Take(0));
tpl.AddVariable(cust);
}
tpl.AddVariable("Tax", 13);
},
wb =>
{
CompareWithGauge(wb, templateFile);
});
}

[Theory,
InlineData("GroupTagTests_SummaryAbove.xlsx"),
InlineData("GroupTagTests_MergeLabels.xlsx"),
Expand Down Expand Up @@ -79,6 +104,7 @@ public void EmptyDataSource(string templateFile)
InlineData("GroupTagTests_MultiRanges.xlsx"),
//InlineData("GroupTagTests_FormulasWithTagsInGroupRow.xlsx"), // Formulas with tags got broken after upgrading to ClosedXML 0.100
InlineData("GroupTagTests_TotalLabel.xlsx"),
InlineData("GroupTagTests_DisableSubTotals_MergeLabels.xlsx")
]
public void Customers(string templateFile)
{
Expand Down
Binary file not shown.
Binary file added tests/Gauges/GroupTagTests_Simple_Empty.xlsx
Binary file not shown.
Binary file not shown.
Binary file added tests/Templates/GroupTagTests_Simple_Empty.xlsx
Binary file not shown.