Skip to content

Commit

Permalink
Remove priority key and change delete tag execution logic (#350)
Browse files Browse the repository at this point in the history
* Refactoring and adding test for multiple column deletion
  • Loading branch information
vakssonya authored Apr 11, 2024
1 parent 8b795ea commit f21cf97
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 60 deletions.
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.

0 comments on commit f21cf97

Please sign in to comment.