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

Remove priority key and change delete tag execution logic #350

Merged
merged 3 commits into from
Apr 11, 2024
Merged
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
57 changes: 34 additions & 23 deletions ClosedXML.Report/Options/DeleteTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,48 @@ OPTION OBJECTS

using ClosedXML.Excel;
using ClosedXML.Report.Excel;
using System.Linq;

namespace ClosedXML.Report.Options
{
public class DeleteTag: OptionTag
public class DeleteTag : OptionTag
{
public override void Execute(ProcessingContext context)
{
var xlCell = Cell.GetXlCell(context.Range);
var cellAddr = xlCell.Address.ToStringRelative(false);
var ws = Range.Worksheet;
var deleteTags = List.GetAll<DeleteTag>()
.OrderByDescending(x => x.Cell.Row)
.ThenByDescending(x => x.Cell.Column)
.ToList();

// whole worksheet
if (cellAddr == "A1" || cellAddr == "A2")
foreach (var tag in deleteTags)
{
ws.Workbook.Worksheets.Delete(ws.Name);
}
// whole column
else if (xlCell.Address.RowNumber == 1)
{
ws.Column(xlCell.Address.ColumnNumber).Delete();
}
// whole row
else if (xlCell.Address.ColumnNumber == 1)
{
ws.Row(xlCell.Address.RowNumber).Delete();
}
// range column
else if (IsSpecialRangeRow(xlCell))
{
var addrInRange = xlCell.Relative(Range.RangeAddress.FirstAddress);
context.Range.Column(addrInRange.ColumnNumber).Delete(XLShiftDeletedCells.ShiftCellsLeft);
var xlCell = tag.Cell.GetXlCell(context.Range);
var cellAddr = xlCell.Address.ToStringRelative(false);
var ws = Range.Worksheet;

// whole worksheet
if (cellAddr == "A1" || cellAddr == "A2")
{
ws.Workbook.Worksheets.Delete(ws.Name);
}
// whole column
else if (xlCell.Address.RowNumber == 1)
{
ws.Column(xlCell.Address.ColumnNumber).Delete();
}
// whole row
else if (xlCell.Address.ColumnNumber == 1)
{
ws.Row(xlCell.Address.RowNumber).Delete();
}
// range column
else if (IsSpecialRangeRow(xlCell))
{
var addrInRange = xlCell.Relative(Range.RangeAddress.FirstAddress);
context.Range.Column(addrInRange.ColumnNumber).Delete(XLShiftDeletedCells.ShiftCellsLeft);
}

tag.Enabled = false;
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions ClosedXML.Report/Options/OptionTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ namespace ClosedXML.Report.Options
{
public abstract class OptionTag
{
internal byte PriorityKey { get; set; }

public Dictionary<string, string> Parameters { get; internal set; }
public TemplateCell Cell { get; internal set; }
public TagsList List { get; internal set; }
Expand Down
28 changes: 19 additions & 9 deletions ClosedXML.Report/Options/TagsList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ public TagsList CopyTo(IXLRange toRange)
public new void Add(OptionTag tag)
{
tag.List = this;
var map = Enumerable.Range(byte.MinValue, byte.MaxValue + 1).ToList();
map.RemoveAll(x => this.Any(t => t.PriorityKey == x));
tag.PriorityKey = (byte)map.OrderBy(x => Math.Abs(tag.Priority - x)).First();
base.Add(tag);
}

Expand Down Expand Up @@ -64,7 +61,7 @@ public void Execute(ProcessingContext context)
{
while (true)
{
var t = this.FirstOrDefault(x=>x.Enabled);
var t = this.FirstOrDefault(x => x.Enabled);
if (t == null)
break;

Expand Down Expand Up @@ -93,13 +90,26 @@ public void Reset()
foreach (var item in this)
item.Enabled = true;
}
}

internal class OptionTagComparer : IComparer<OptionTag>
{
public int Compare(OptionTag x, OptionTag y)
internal class OptionTagComparer : IComparer<OptionTag>
{
return -x.PriorityKey.CompareTo(y.PriorityKey);
public int Compare(OptionTag x, OptionTag y)
{
var result = -x.Priority.CompareTo(y.Priority);

if (x.Cell != null)
{
if (result == 0)
result = x.Cell.Row.CompareTo(y.Cell.Row);
if (result == 0)
result = x.Cell.Column.CompareTo(y.Cell.Column);
}

if (result == 0)
return 1;

return result;
}
}
}
}
67 changes: 58 additions & 9 deletions tests/ClosedXML.Report.Tests/DeleteTagTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,22 @@

namespace ClosedXML.Report.Tests
{
public class DeleteTagTests: TagTests
public class DeleteTagTests : TagTests
{
private readonly TagsList _tagsList;

public DeleteTagTests()
{
var errorsList = new TemplateErrors();
_tagsList = new TagsList(errorsList);
}

[Fact]
public void TagInA2CellShouldDeleteWorksheet()
{
var tag = CreateNotInRangeTag<DeleteTag>(_ws.Cell("A2"));
tag.Execute(new ProcessingContext(_ws.AsRange(), new DataSource(new object[0]), new FormulaEvaluator()));
AddTagsToWorksheet("A2");

Act(_ws.AsRange());

_wb.Worksheets.Count.Should().Be(0);
}
Expand All @@ -24,8 +33,10 @@ public void TagInFirstWorksheetRowCellShouldDeleteWholeColumn()
_ws.Cell("B5").Value = 2.0;
_ws.Cell("C5").Value = 3.0;
_ws.Cell("D5").Value = 4.0;
var tag = CreateNotInRangeTag<DeleteTag>(_ws.Cell("C1"));
tag.Execute(new ProcessingContext(_ws.AsRange(), new DataSource(new object[0]), new FormulaEvaluator()));

AddTagsToWorksheet("C1");

Act(_ws.AsRange());

_ws.Cell("B5").GetDouble().Should().Be(2.0);
_ws.Cell("C5").GetDouble().Should().Be(4.0);
Expand All @@ -37,25 +48,63 @@ public void TagInFirstWorksheetColumnCellShouldDeleteWholeRow()
_ws.Cell("D3").Value = 3.0;
_ws.Cell("D4").Value = 4.0;
_ws.Cell("D5").Value = 5.0;
var tag = CreateNotInRangeTag<DeleteTag>(_ws.Cell("A4"));
tag.Execute(new ProcessingContext(_ws.AsRange(), new DataSource(new object[0]), new FormulaEvaluator()));

AddTagsToWorksheet("A4");

Act(_ws.AsRange());

_ws.Cell("D3").GetDouble().Should().Be(3.0);
_ws.Cell("D4").GetDouble().Should().Be(5.0);
}

[Fact]
public void TagsShouldDeleteFromLastToFirstCell()
{
_ws.Cell("B5").Value = 2.0;
_ws.Cell("C5").Value = 3.0;
_ws.Cell("D5").Value = 4.0;
_ws.Cell("E5").Value = 5.0;

AddTagsToWorksheet("A3", "A4", "C1", "D1");

Act(_ws.AsRange());

_ws.Cell("B3").GetDouble().Should().Be(2.0);
_ws.Cell("C3").GetDouble().Should().Be(5.0);
}

[Fact]
public void TagInDataCellRangeOptionRowShouldDeleteThisColumn()
{
var rng = FillData();

var tag = CreateInRangeTag<DeleteTag>(rng, rng.Cell("B2"));
tag.Execute(new ProcessingContext(_ws.Range("B5", "F15"), new DataSource(new object[0]), new FormulaEvaluator()));
AddTagsToRange(rng, "B2");

Act(_ws.Range("B5", "F15"));

rng.Cell("A1").GetText().Should().Be("Alice");
rng.Cell("B1").GetText().Should().Be("Wonderland");
}

private void AddTagsToRange(IXLRange range, params string[] cells)
{
foreach (var cell in cells)
{
_tagsList.Add(CreateInRangeTag<DeleteTag>(range, range.Cell(cell)));
}
}

private void AddTagsToWorksheet(params string[] cells)
{
foreach (var cell in cells)
{
_tagsList.Add(CreateNotInRangeTag<DeleteTag>(_ws.Cell(cell)));
}
}

private void Act(IXLRange range) =>
_tagsList.Execute(new ProcessingContext(range, new DataSource(Array.Empty<object>()), new FormulaEvaluator()));

private IXLRange FillData()
{
var rng = _ws.Range("B5", "F6");
Expand Down
5 changes: 2 additions & 3 deletions tests/ClosedXML.Report.Tests/GroupTagTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using System.Drawing;
using System.Linq;
using System.Linq;
using ClosedXML.Report.Tests.TestModels;
using LinqToDB;
using Xunit;
Expand All @@ -23,6 +21,7 @@ public GroupTagTests(ITestOutputHelper output) : base(output)
InlineData("tLists1_cell_setting.xlsx"),
InlineData("tLists2_sum.xlsx"),
InlineData("tLists3_options.xlsx"),
InlineData("delete_options.xlsx"),
InlineData("issue#111_autofilter_with_delete.xlsx"),
InlineData("tLists4_complexRange.xlsx"),
InlineData("tLists5_GlobalVars.xlsx"),
Expand Down
65 changes: 51 additions & 14 deletions tests/ClosedXML.Report.Tests/TagsListTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Linq;
using System.Collections.Generic;
using System.Linq;
using ClosedXML.Report.Options;
using FluentAssertions;
using Xunit;
Expand All @@ -13,8 +14,8 @@ public void Add_with_same_priority_should_increase_count()
var errList = new TemplateErrors();
var list = new TagsList(errList)
{
new GroupTag {Name = "val1"},
new GroupTag {Name = "val2"}
new GroupTag { Name = "val1" },
new GroupTag { Name = "val2" }
};
list.Count.Should().Be(2);
}
Expand All @@ -25,13 +26,49 @@ public void Items_should_be_sorted_by_priority()
var errList = new TemplateErrors();
var list = new TagsList(errList)
{
new GroupTag {Name = "val1"},
new GroupTag {Name = "val2"},
new OnlyValuesTag {Name = "val3"},
new ProtectedTag {Name = "val4"}
new OnlyValuesTag { Name = "val3", Priority = 40 },
new ProtectedTag { Name = "val4", Priority = 0 },
new GroupTag { Name = "val1", Priority = 200 },
new GroupTag { Name = "val2", Priority = 200 }
};

var expected = new List<string>() { "val1", "val2", "val3", "val4" };

list.Count.Should().Be(4);
list.Select(x => x.Name).Should().BeEquivalentTo("val3", "val1", "val2", "val4");
list.Select(x => x.Name).Should().BeEquivalentTo(expected, options => options.WithStrictOrdering());
}

[Fact]
public void Items_with_same_priority_should_be_sorted_by_row()
{
var errList = new TemplateErrors();
var list = new TagsList(errList)
{
new GroupTag { Name = "val1", Priority = 200, Cell = new TemplateCell { Row = 3, Column = 1 } },
new GroupTag { Name = "val2", Priority = 200, Cell = new TemplateCell { Row = 1, Column = 1 } }
};

var expected = new List<string>() { "val2", "val1" };

list.Count.Should().Be(2);
list.Select(x => x.Name).Should().BeEquivalentTo(expected, options => options.WithStrictOrdering());
}

[Fact]
public void Items_with_same_priority_and_row_should_be_sorted_by_column()
{
var errList = new TemplateErrors();
var list = new TagsList(errList)
{
new GroupTag { Name = "val1", Priority = 200, Cell = new TemplateCell { Row = 1, Column = 15 } },
new GroupTag { Name = "val2", Priority = 200, Cell = new TemplateCell { Row = 1, Column = 1 } },
new GroupTag { Name = "val3", Priority = 200, Cell = new TemplateCell { Row = 1, Column = 20 } }
};

var expected = new List<string>() { "val2", "val1", "val3" };

list.Count.Should().Be(3);
list.Select(x => x.Name).Should().BeEquivalentTo(expected, options => options.WithStrictOrdering());
}

[Fact]
Expand All @@ -40,12 +77,12 @@ public void Get_by_type_should_return_tags_with_inherits()
var errList = new TemplateErrors();
var list = new TagsList(errList)
{
new GroupTag {Name = "val1"},
new GroupTag {Name = "val2"},
new SortTag {Name = "val3"},
new ProtectedTag {Name = "val4"},
new DescTag {Name = "val5"},
new ColsFitTag {Name = "val6"}
new GroupTag { Name = "val1" },
new GroupTag { Name = "val2" },
new SortTag { Name = "val3" },
new ProtectedTag { Name = "val4" },
new DescTag { Name = "val5" },
new ColsFitTag { Name = "val6" }
};
list.GetAll<SortTag>().Select(x => x.Name).Should().BeEquivalentTo("val1", "val2", "val3", "val5");
}
Expand Down
Binary file added tests/Gauges/delete_options.xlsx
Binary file not shown.
Binary file added tests/Templates/delete_options.xlsx
Binary file not shown.
Loading