Skip to content

Commit f21cf97

Browse files
authored
Remove priority key and change delete tag execution logic (#350)
* Refactoring and adding test for multiple column deletion
1 parent 8b795ea commit f21cf97

File tree

8 files changed

+164
-60
lines changed

8 files changed

+164
-60
lines changed

ClosedXML.Report/Options/DeleteTag.cs

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,48 @@ OPTION OBJECTS
88

99
using ClosedXML.Excel;
1010
using ClosedXML.Report.Excel;
11+
using System.Linq;
1112

1213
namespace ClosedXML.Report.Options
1314
{
14-
public class DeleteTag: OptionTag
15+
public class DeleteTag : OptionTag
1516
{
1617
public override void Execute(ProcessingContext context)
1718
{
18-
var xlCell = Cell.GetXlCell(context.Range);
19-
var cellAddr = xlCell.Address.ToStringRelative(false);
20-
var ws = Range.Worksheet;
19+
var deleteTags = List.GetAll<DeleteTag>()
20+
.OrderByDescending(x => x.Cell.Row)
21+
.ThenByDescending(x => x.Cell.Column)
22+
.ToList();
2123

22-
// whole worksheet
23-
if (cellAddr == "A1" || cellAddr == "A2")
24+
foreach (var tag in deleteTags)
2425
{
25-
ws.Workbook.Worksheets.Delete(ws.Name);
26-
}
27-
// whole column
28-
else if (xlCell.Address.RowNumber == 1)
29-
{
30-
ws.Column(xlCell.Address.ColumnNumber).Delete();
31-
}
32-
// whole row
33-
else if (xlCell.Address.ColumnNumber == 1)
34-
{
35-
ws.Row(xlCell.Address.RowNumber).Delete();
36-
}
37-
// range column
38-
else if (IsSpecialRangeRow(xlCell))
39-
{
40-
var addrInRange = xlCell.Relative(Range.RangeAddress.FirstAddress);
41-
context.Range.Column(addrInRange.ColumnNumber).Delete(XLShiftDeletedCells.ShiftCellsLeft);
26+
var xlCell = tag.Cell.GetXlCell(context.Range);
27+
var cellAddr = xlCell.Address.ToStringRelative(false);
28+
var ws = Range.Worksheet;
29+
30+
// whole worksheet
31+
if (cellAddr == "A1" || cellAddr == "A2")
32+
{
33+
ws.Workbook.Worksheets.Delete(ws.Name);
34+
}
35+
// whole column
36+
else if (xlCell.Address.RowNumber == 1)
37+
{
38+
ws.Column(xlCell.Address.ColumnNumber).Delete();
39+
}
40+
// whole row
41+
else if (xlCell.Address.ColumnNumber == 1)
42+
{
43+
ws.Row(xlCell.Address.RowNumber).Delete();
44+
}
45+
// range column
46+
else if (IsSpecialRangeRow(xlCell))
47+
{
48+
var addrInRange = xlCell.Relative(Range.RangeAddress.FirstAddress);
49+
context.Range.Column(addrInRange.ColumnNumber).Delete(XLShiftDeletedCells.ShiftCellsLeft);
50+
}
51+
52+
tag.Enabled = false;
4253
}
4354
}
4455
}

ClosedXML.Report/Options/OptionTag.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ namespace ClosedXML.Report.Options
66
{
77
public abstract class OptionTag
88
{
9-
internal byte PriorityKey { get; set; }
10-
119
public Dictionary<string, string> Parameters { get; internal set; }
1210
public TemplateCell Cell { get; internal set; }
1311
public TagsList List { get; internal set; }

ClosedXML.Report/Options/TagsList.cs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ public TagsList CopyTo(IXLRange toRange)
3131
public new void Add(OptionTag tag)
3232
{
3333
tag.List = this;
34-
var map = Enumerable.Range(byte.MinValue, byte.MaxValue + 1).ToList();
35-
map.RemoveAll(x => this.Any(t => t.PriorityKey == x));
36-
tag.PriorityKey = (byte)map.OrderBy(x => Math.Abs(tag.Priority - x)).First();
3734
base.Add(tag);
3835
}
3936

@@ -64,7 +61,7 @@ public void Execute(ProcessingContext context)
6461
{
6562
while (true)
6663
{
67-
var t = this.FirstOrDefault(x=>x.Enabled);
64+
var t = this.FirstOrDefault(x => x.Enabled);
6865
if (t == null)
6966
break;
7067

@@ -93,13 +90,26 @@ public void Reset()
9390
foreach (var item in this)
9491
item.Enabled = true;
9592
}
96-
}
9793

98-
internal class OptionTagComparer : IComparer<OptionTag>
99-
{
100-
public int Compare(OptionTag x, OptionTag y)
94+
internal class OptionTagComparer : IComparer<OptionTag>
10195
{
102-
return -x.PriorityKey.CompareTo(y.PriorityKey);
96+
public int Compare(OptionTag x, OptionTag y)
97+
{
98+
var result = -x.Priority.CompareTo(y.Priority);
99+
100+
if (x.Cell != null)
101+
{
102+
if (result == 0)
103+
result = x.Cell.Row.CompareTo(y.Cell.Row);
104+
if (result == 0)
105+
result = x.Cell.Column.CompareTo(y.Cell.Column);
106+
}
107+
108+
if (result == 0)
109+
return 1;
110+
111+
return result;
112+
}
103113
}
104114
}
105115
}

tests/ClosedXML.Report.Tests/DeleteTagTests.cs

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,22 @@
77

88
namespace ClosedXML.Report.Tests
99
{
10-
public class DeleteTagTests: TagTests
10+
public class DeleteTagTests : TagTests
1111
{
12+
private readonly TagsList _tagsList;
13+
14+
public DeleteTagTests()
15+
{
16+
var errorsList = new TemplateErrors();
17+
_tagsList = new TagsList(errorsList);
18+
}
19+
1220
[Fact]
1321
public void TagInA2CellShouldDeleteWorksheet()
1422
{
15-
var tag = CreateNotInRangeTag<DeleteTag>(_ws.Cell("A2"));
16-
tag.Execute(new ProcessingContext(_ws.AsRange(), new DataSource(new object[0]), new FormulaEvaluator()));
23+
AddTagsToWorksheet("A2");
24+
25+
Act(_ws.AsRange());
1726

1827
_wb.Worksheets.Count.Should().Be(0);
1928
}
@@ -24,8 +33,10 @@ public void TagInFirstWorksheetRowCellShouldDeleteWholeColumn()
2433
_ws.Cell("B5").Value = 2.0;
2534
_ws.Cell("C5").Value = 3.0;
2635
_ws.Cell("D5").Value = 4.0;
27-
var tag = CreateNotInRangeTag<DeleteTag>(_ws.Cell("C1"));
28-
tag.Execute(new ProcessingContext(_ws.AsRange(), new DataSource(new object[0]), new FormulaEvaluator()));
36+
37+
AddTagsToWorksheet("C1");
38+
39+
Act(_ws.AsRange());
2940

3041
_ws.Cell("B5").GetDouble().Should().Be(2.0);
3142
_ws.Cell("C5").GetDouble().Should().Be(4.0);
@@ -37,25 +48,63 @@ public void TagInFirstWorksheetColumnCellShouldDeleteWholeRow()
3748
_ws.Cell("D3").Value = 3.0;
3849
_ws.Cell("D4").Value = 4.0;
3950
_ws.Cell("D5").Value = 5.0;
40-
var tag = CreateNotInRangeTag<DeleteTag>(_ws.Cell("A4"));
41-
tag.Execute(new ProcessingContext(_ws.AsRange(), new DataSource(new object[0]), new FormulaEvaluator()));
51+
52+
AddTagsToWorksheet("A4");
53+
54+
Act(_ws.AsRange());
4255

4356
_ws.Cell("D3").GetDouble().Should().Be(3.0);
4457
_ws.Cell("D4").GetDouble().Should().Be(5.0);
4558
}
4659

60+
[Fact]
61+
public void TagsShouldDeleteFromLastToFirstCell()
62+
{
63+
_ws.Cell("B5").Value = 2.0;
64+
_ws.Cell("C5").Value = 3.0;
65+
_ws.Cell("D5").Value = 4.0;
66+
_ws.Cell("E5").Value = 5.0;
67+
68+
AddTagsToWorksheet("A3", "A4", "C1", "D1");
69+
70+
Act(_ws.AsRange());
71+
72+
_ws.Cell("B3").GetDouble().Should().Be(2.0);
73+
_ws.Cell("C3").GetDouble().Should().Be(5.0);
74+
}
75+
4776
[Fact]
4877
public void TagInDataCellRangeOptionRowShouldDeleteThisColumn()
4978
{
5079
var rng = FillData();
5180

52-
var tag = CreateInRangeTag<DeleteTag>(rng, rng.Cell("B2"));
53-
tag.Execute(new ProcessingContext(_ws.Range("B5", "F15"), new DataSource(new object[0]), new FormulaEvaluator()));
81+
AddTagsToRange(rng, "B2");
82+
83+
Act(_ws.Range("B5", "F15"));
5484

5585
rng.Cell("A1").GetText().Should().Be("Alice");
5686
rng.Cell("B1").GetText().Should().Be("Wonderland");
5787
}
5888

89+
private void AddTagsToRange(IXLRange range, params string[] cells)
90+
{
91+
foreach (var cell in cells)
92+
{
93+
_tagsList.Add(CreateInRangeTag<DeleteTag>(range, range.Cell(cell)));
94+
}
95+
}
96+
97+
private void AddTagsToWorksheet(params string[] cells)
98+
{
99+
foreach (var cell in cells)
100+
{
101+
_tagsList.Add(CreateNotInRangeTag<DeleteTag>(_ws.Cell(cell)));
102+
}
103+
}
104+
105+
private void Act(IXLRange range) =>
106+
_tagsList.Execute(new ProcessingContext(range, new DataSource(Array.Empty<object>()), new FormulaEvaluator()));
107+
59108
private IXLRange FillData()
60109
{
61110
var rng = _ws.Range("B5", "F6");

tests/ClosedXML.Report.Tests/GroupTagTests.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
using System;
2-
using System.Drawing;
3-
using System.Linq;
1+
using System.Linq;
42
using ClosedXML.Report.Tests.TestModels;
53
using LinqToDB;
64
using Xunit;
@@ -23,6 +21,7 @@ public GroupTagTests(ITestOutputHelper output) : base(output)
2321
InlineData("tLists1_cell_setting.xlsx"),
2422
InlineData("tLists2_sum.xlsx"),
2523
InlineData("tLists3_options.xlsx"),
24+
InlineData("delete_options.xlsx"),
2625
InlineData("issue#111_autofilter_with_delete.xlsx"),
2726
InlineData("tLists4_complexRange.xlsx"),
2827
InlineData("tLists5_GlobalVars.xlsx"),

tests/ClosedXML.Report.Tests/TagsListTests.cs

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Linq;
1+
using System.Collections.Generic;
2+
using System.Linq;
23
using ClosedXML.Report.Options;
34
using FluentAssertions;
45
using Xunit;
@@ -13,8 +14,8 @@ public void Add_with_same_priority_should_increase_count()
1314
var errList = new TemplateErrors();
1415
var list = new TagsList(errList)
1516
{
16-
new GroupTag {Name = "val1"},
17-
new GroupTag {Name = "val2"}
17+
new GroupTag { Name = "val1" },
18+
new GroupTag { Name = "val2" }
1819
};
1920
list.Count.Should().Be(2);
2021
}
@@ -25,13 +26,49 @@ public void Items_should_be_sorted_by_priority()
2526
var errList = new TemplateErrors();
2627
var list = new TagsList(errList)
2728
{
28-
new GroupTag {Name = "val1"},
29-
new GroupTag {Name = "val2"},
30-
new OnlyValuesTag {Name = "val3"},
31-
new ProtectedTag {Name = "val4"}
29+
new OnlyValuesTag { Name = "val3", Priority = 40 },
30+
new ProtectedTag { Name = "val4", Priority = 0 },
31+
new GroupTag { Name = "val1", Priority = 200 },
32+
new GroupTag { Name = "val2", Priority = 200 }
3233
};
34+
35+
var expected = new List<string>() { "val1", "val2", "val3", "val4" };
36+
3337
list.Count.Should().Be(4);
34-
list.Select(x => x.Name).Should().BeEquivalentTo("val3", "val1", "val2", "val4");
38+
list.Select(x => x.Name).Should().BeEquivalentTo(expected, options => options.WithStrictOrdering());
39+
}
40+
41+
[Fact]
42+
public void Items_with_same_priority_should_be_sorted_by_row()
43+
{
44+
var errList = new TemplateErrors();
45+
var list = new TagsList(errList)
46+
{
47+
new GroupTag { Name = "val1", Priority = 200, Cell = new TemplateCell { Row = 3, Column = 1 } },
48+
new GroupTag { Name = "val2", Priority = 200, Cell = new TemplateCell { Row = 1, Column = 1 } }
49+
};
50+
51+
var expected = new List<string>() { "val2", "val1" };
52+
53+
list.Count.Should().Be(2);
54+
list.Select(x => x.Name).Should().BeEquivalentTo(expected, options => options.WithStrictOrdering());
55+
}
56+
57+
[Fact]
58+
public void Items_with_same_priority_and_row_should_be_sorted_by_column()
59+
{
60+
var errList = new TemplateErrors();
61+
var list = new TagsList(errList)
62+
{
63+
new GroupTag { Name = "val1", Priority = 200, Cell = new TemplateCell { Row = 1, Column = 15 } },
64+
new GroupTag { Name = "val2", Priority = 200, Cell = new TemplateCell { Row = 1, Column = 1 } },
65+
new GroupTag { Name = "val3", Priority = 200, Cell = new TemplateCell { Row = 1, Column = 20 } }
66+
};
67+
68+
var expected = new List<string>() { "val2", "val1", "val3" };
69+
70+
list.Count.Should().Be(3);
71+
list.Select(x => x.Name).Should().BeEquivalentTo(expected, options => options.WithStrictOrdering());
3572
}
3673

3774
[Fact]
@@ -40,12 +77,12 @@ public void Get_by_type_should_return_tags_with_inherits()
4077
var errList = new TemplateErrors();
4178
var list = new TagsList(errList)
4279
{
43-
new GroupTag {Name = "val1"},
44-
new GroupTag {Name = "val2"},
45-
new SortTag {Name = "val3"},
46-
new ProtectedTag {Name = "val4"},
47-
new DescTag {Name = "val5"},
48-
new ColsFitTag {Name = "val6"}
80+
new GroupTag { Name = "val1" },
81+
new GroupTag { Name = "val2" },
82+
new SortTag { Name = "val3" },
83+
new ProtectedTag { Name = "val4" },
84+
new DescTag { Name = "val5" },
85+
new ColsFitTag { Name = "val6" }
4986
};
5087
list.GetAll<SortTag>().Select(x => x.Name).Should().BeEquivalentTo("val1", "val2", "val3", "val5");
5188
}

tests/Gauges/delete_options.xlsx

22.3 KB
Binary file not shown.

tests/Templates/delete_options.xlsx

24.2 KB
Binary file not shown.

0 commit comments

Comments
 (0)