Skip to content

Commit ade35d2

Browse files
committed
Support for cells with rich text formatting
1 parent 47f27e5 commit ade35d2

File tree

6 files changed

+298
-30
lines changed

6 files changed

+298
-30
lines changed

ExcelReportGenerator.Tests/CustomAsserts/ExcelAssert.cs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,62 @@ public static void AreWorksheetsContentEquals(IXLWorksheet expected, IXLWorkshee
3737
}
3838
else
3939
{
40-
Assert.AreEqual(expectedCell.Value, actualCell.Value, $"Cell {expectedCell.Address} Value failed.");
40+
if (!expectedCell.HasRichText && !actualCell.HasRichText)
41+
{
42+
Assert.AreEqual(expectedCell.Value, actualCell.Value, $"Cell {expectedCell.Address} Value failed.");
43+
}
44+
else if (expectedCell.HasRichText && actualCell.HasRichText)
45+
{
46+
AreRichTextEqual(expectedCell.GetRichText(), actualCell.GetRichText());
47+
}
48+
else
49+
{
50+
Assert.Fail(
51+
$"Expected cell {expectedCell.Address} {nameof(IXLCell.HasRichText)} is {expectedCell.HasRichText}, but actual cell {nameof(IXLCell.HasRichText)} is {actualCell.HasRichText}");
52+
}
53+
54+
void AreRichTextEqual(IXLRichText expectedRichText, IXLRichText actualRichText)
55+
{
56+
Assert.AreEqual(expectedRichText.Count, actualRichText.Count,
57+
GetErrorMessage(nameof(IXLRichText.Count)));
58+
for (var i = 0; i < expectedRichText.Count; i++)
59+
{
60+
var expectedRichString = expectedRichText.ElementAt(i);
61+
var actualRichString = actualRichText.ElementAt(i);
62+
63+
Assert.AreEqual(expectedRichString.Text, actualRichString.Text,
64+
GetErrorMessage(nameof(IXLRichString.Text)));
65+
Assert.AreEqual(expectedRichString.FontScheme, actualRichString.FontScheme,
66+
GetErrorMessage(nameof(IXLRichString.FontScheme)));
67+
Assert.AreEqual(expectedRichString.Bold, actualRichString.Bold,
68+
GetErrorMessage(nameof(IXLRichString.Bold)));
69+
Assert.AreEqual(expectedRichString.Italic, actualRichString.Italic,
70+
GetErrorMessage(nameof(IXLRichString.Italic)));
71+
Assert.AreEqual(expectedRichString.Shadow, actualRichString.Shadow,
72+
GetErrorMessage(nameof(IXLRichString.Shadow)));
73+
Assert.AreEqual(expectedRichString.Strikethrough, actualRichString.Strikethrough,
74+
GetErrorMessage(nameof(IXLRichString.Strikethrough)));
75+
Assert.AreEqual(expectedRichString.Underline, actualRichString.Underline,
76+
GetErrorMessage(nameof(IXLRichString.Underline)));
77+
Assert.AreEqual(expectedRichString.FontColor, actualRichString.FontColor,
78+
GetErrorMessage(nameof(IXLRichString.FontColor)));
79+
Assert.AreEqual(expectedRichString.FontName, actualRichString.FontName,
80+
GetErrorMessage(nameof(IXLRichString.FontName)));
81+
Assert.AreEqual(expectedRichString.FontSize, actualRichString.FontSize,
82+
GetErrorMessage(nameof(IXLRichString.FontSize)));
83+
Assert.AreEqual(expectedRichString.VerticalAlignment, actualRichString.VerticalAlignment,
84+
GetErrorMessage(nameof(IXLRichString.VerticalAlignment)));
85+
Assert.AreEqual(expectedRichString.FontCharSet, actualRichString.FontCharSet,
86+
GetErrorMessage(nameof(IXLRichString.FontCharSet)));
87+
Assert.AreEqual(expectedRichString.FontFamilyNumbering, actualRichString.FontFamilyNumbering,
88+
GetErrorMessage(nameof(IXLRichString.FontFamilyNumbering)));
89+
}
90+
91+
return;
92+
93+
string GetErrorMessage(string propName) =>
94+
$"Cell {expectedCell.Address} RichTextValue '{propName}' failed.";
95+
}
4196
}
4297

4398
Assert.AreEqual(expectedCell.DataType, actualCell.DataType,

ExcelReportGenerator.Tests/ExcelReportGenerator.Tests.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,9 @@
349349
<None Update="TestData\ExcelDataSourcePanelTest\TestGroupResultVertical_WithoutGroupingBlankValues.xlsx">
350350
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
351351
</None>
352+
<None Update="TestData\DataSourcePanelRender_WithGrouping_HorizontalPanels_ChildLeft_Test\ParentCellsShiftChildCellsShift_WithRichText.xlsx">
353+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
354+
</None>
352355
</ItemGroup>
353356

354357
</Project>

ExcelReportGenerator.Tests/Rendering/Panels/ExcelPanels/PanelRenderTests/DataSourcePanelRenderTests/DataSourcePanelRender_WithGrouping_HorizontalPanels_ChildLeft_Test.cs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,128 @@ public void Test_HorizontalPanelsGrouping_ChildLeft_ParentCellsShiftChildCellsSh
6464
//report.Workbook.SaveAs("test.xlsx");
6565
}
6666

67+
[Test]
68+
public void Test_HorizontalPanelsGrouping_ChildLeft_ParentCellsShiftChildCellsShift_WithRichText()
69+
{
70+
var report = new TestReport();
71+
var ws = report.Workbook.AddWorksheet("Test");
72+
var parentRange = ws.Range(2, 2, 5, 3);
73+
parentRange.AddToNamed("ParentRange", XLScope.Worksheet);
74+
75+
var child = ws.Range(2, 2, 5, 2);
76+
child.AddToNamed("ChildRange", XLScope.Worksheet);
77+
78+
child.Range(2, 1, 4, 1).Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
79+
child.Range(2, 1, 4, 1).Style.Border.OutsideBorderColor = XLColor.Red;
80+
81+
parentRange.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
82+
parentRange.Style.Border.OutsideBorderColor = XLColor.Black;
83+
84+
ws.Cell(2, 3).CreateRichText()
85+
.AddText("Name - {di:Name} - {di:Name} - Name")
86+
.SetItalic();
87+
88+
ws.Cell(2, 3)
89+
.GetRichText()
90+
.Substring(0, 4)
91+
.SetFontColor(XLColor.Green);
92+
93+
ws.Cell(2, 3)
94+
.GetRichText()
95+
.Substring(6, 23)
96+
.SetFontColor(XLColor.Red);
97+
98+
ws.Cell(2, 3)
99+
.GetRichText()
100+
.Substring(31, 4)
101+
.SetFontColor(XLColor.Blue);
102+
103+
ws.Cell(3, 3).CreateRichText()
104+
.AddText("Date: {di:Date}");
105+
106+
ws.Cell(3, 3)
107+
.GetRichText()
108+
.Substring(0, 4)
109+
.SetFontColor(XLColor.Apricot);
110+
111+
ws.Cell(3, 3)
112+
.GetRichText()
113+
.Substring(6, 9)
114+
.SetBold()
115+
.SetStrikethrough();
116+
117+
ws.Cell(3, 2).CreateRichText()
118+
.AddText("{di:Field1}");
119+
120+
ws.Cell(3, 2)
121+
.GetRichText()
122+
.Substring(0, 4)
123+
.SetStrikethrough();
124+
125+
ws.Cell(4, 2).CreateRichText()
126+
.AddText("Field1/Field2: {di:Field1}/{di:Field2}");
127+
128+
ws.Cell(4, 2)
129+
.GetRichText()
130+
.Substring(15, 11)
131+
.SetStrikethrough();
132+
133+
ws.Cell(4, 2)
134+
.GetRichText()
135+
.Substring(27, 11)
136+
.SetUnderline();
137+
138+
ws.Cell(5, 2).CreateRichText()
139+
.AddText("Sum: {di:parent:Sum} = {di:parent:Sum}");
140+
141+
ws.Cell(5, 2)
142+
.GetRichText()
143+
.Substring(0, 21)
144+
.SetFontColor(XLColor.Green);
145+
146+
ws.Cell(5, 2)
147+
.GetRichText()
148+
.Substring(20, 6)
149+
.SetUnderline();
150+
151+
ws.Cell(1, 1).CreateRichText()
152+
.AddText("{di:Name}")
153+
.SetBold();
154+
155+
ws.Cell(1, 3).CreateRichText()
156+
.AddText("Name: {di:Name}")
157+
.SetItalic();
158+
159+
ws.Cell(1, 4).Value = "{di:Name}";
160+
ws.Cell(3, 1).Value = "{di:Name}";
161+
ws.Cell(3, 4).Value = "{di:Name}";
162+
ws.Cell(6, 1).Value = "{di:Name}";
163+
ws.Cell(6, 3).Value = "{di:Name}";
164+
ws.Cell(6, 4).Value = "{di:Name}";
165+
166+
var parentPanel = new ExcelDataSourcePanel("m:DataProvider:GetIEnumerable()", ws.NamedRange("ParentRange"),
167+
report, report.TemplateProcessor)
168+
{
169+
Type = PanelType.Horizontal
170+
};
171+
var childPanel = new ExcelDataSourcePanel("m:DataProvider:GetChildIEnumerable(di:Name)",
172+
ws.NamedRange("ChildRange"), report, report.TemplateProcessor)
173+
{
174+
Parent = parentPanel,
175+
Type = PanelType.Horizontal
176+
};
177+
parentPanel.Children = new[] {childPanel};
178+
parentPanel.Render();
179+
180+
Assert.AreEqual(ws.Range(2, 2, 5, 9), parentPanel.ResultRange);
181+
182+
ExcelAssert.AreWorkbooksContentEquals(TestHelper.GetExpectedWorkbook(
183+
nameof(DataSourcePanelRender_WithGrouping_HorizontalPanels_ChildLeft_Test),
184+
"ParentCellsShiftChildCellsShift_WithRichText"), ws.Workbook);
185+
186+
//report.Workbook.SaveAs("test.xlsx");
187+
}
188+
67189
[Test]
68190
public void Test_HorizontalPanelsGrouping_ChildLeft_ParentRowShiftChildCellsShift()
69191
{

ExcelReportGenerator.Tests/Rendering/Panels/ExcelPanels/PanelRenderTests/PanelRenderTest.cs

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public void TestPanelRender()
1313
{
1414
var report = new TestReport();
1515
var ws = report.Workbook.AddWorksheet("Test");
16-
var range = ws.Range(1, 1, 5, 5);
16+
var range = ws.Range(1, 1, 6, 6);
1717

1818
ws.Cell(1, 1).Value = "{p:StrParam}";
1919
ws.Cell(1, 2).Value = "{p:IntParam}";
@@ -38,16 +38,49 @@ public void TestPanelRender()
3838
ws.Cell(5, 1).Value = "{p:ExpandoObj.StrProp}";
3939
ws.Cell(5, 2).Value = "{p:ExpandoObj.DecimalProp}";
4040
ws.Cell(5, 3).Value = "{p:NullProp}";
41-
ws.Cell(6, 1).Value = "{p:StrParam}";
42-
ws.Cell(6, 2).Value = "{m:Counter()}";
43-
ws.Cell(7, 1).Value = "Plain text outside range";
41+
42+
ws.Cell(6, 1)
43+
.CreateRichText()
44+
.AddText("Rich expando")
45+
.SetItalic()
46+
.AddText(" {p:ExpandoObj.StrProp}")
47+
.SetBold();
48+
49+
ws.Cell(6, 2)
50+
.CreateRichText()
51+
.AddText("Rich decimal before")
52+
.SetItalic()
53+
.AddText(" {p:ExpandoObj.DecimalProp} ")
54+
.SetBold()
55+
.AddText("Rich decimal after")
56+
.SetStrikethrough();
57+
58+
ws.Cell(6, 3)
59+
.CreateRichText()
60+
.AddText("{p:ExpandoObj.StrProp}");
61+
62+
ws.Cell(6, 3)
63+
.GetRichText()
64+
.Substring(0, 13)
65+
.SetFontColor(XLColor.Green);
66+
67+
ws.Cell(10, 1).Value = "{p:StrParam}";
68+
ws.Cell(10, 2).Value = "{m:Counter()}";
69+
ws.Cell(11, 1).Value = "Plain text outside range";
70+
71+
ws.Cell(11, 2)
72+
.CreateRichText()
73+
.AddText("Rich outside first")
74+
.SetItalic()
75+
.AddText(" Rich outside second")
76+
.SetFontColor(XLColor.Red);
4477

4578
var panel = new ExcelPanel(range, report, report.TemplateProcessor);
4679
panel.Render();
4780

4881
Assert.AreEqual(range, panel.ResultRange);
4982

50-
Assert.AreEqual(24, ws.CellsUsed(XLCellsUsedOptions.Contents).Count());
83+
Assert.AreEqual(28, ws.CellsUsed(XLCellsUsedOptions.Contents).Count());
5184
Assert.AreEqual("String parameter", ws.Cell(1, 1).Value);
5285
Assert.AreEqual(10d, ws.Cell(1, 2).Value);
5386
Assert.AreEqual(new DateTime(2017, 10, 25), ws.Cell(1, 3).Value);
@@ -74,17 +107,47 @@ public void TestPanelRender()
74107
Assert.AreEqual("ExpandoStr", ws.Cell(5, 1).Value);
75108
Assert.AreEqual(5.56d, ws.Cell(5, 2).Value);
76109
Assert.AreEqual(Blank.Value, ws.Cell(5, 3).Value);
77-
78-
Assert.AreEqual("{p:StrParam}", ws.Cell(6, 1).Value);
79-
Assert.AreEqual("{m:Counter()}", ws.Cell(6, 2).Value);
80-
Assert.AreEqual("Plain text outside range", ws.Cell(7, 1).Value);
110+
111+
Assert.True(ws.Cell(6, 1).HasRichText);
112+
Assert.AreEqual(ws.Cell(6, 1).GetRichText().Count, 2);
113+
Assert.AreEqual(ws.Cell(6, 1).GetRichText().First().Text, "Rich expando");
114+
Assert.True(ws.Cell(6, 1).GetRichText().First().Italic);
115+
Assert.AreEqual(ws.Cell(6, 1).GetRichText().Last().Text, " ExpandoStr");
116+
Assert.True(ws.Cell(6, 1).GetRichText().Last().Bold);
117+
118+
Assert.True(ws.Cell(6, 2).HasRichText);
119+
Assert.AreEqual(ws.Cell(6, 2).GetRichText().Count, 3);
120+
Assert.AreEqual(ws.Cell(6, 2).GetRichText().First().Text, "Rich decimal before");
121+
Assert.True(ws.Cell(6, 2).GetRichText().First().Italic);
122+
Assert.AreEqual(ws.Cell(6, 2).GetRichText().ElementAt(1).Text, $" {5.56d.ToString()} ");
123+
Assert.True(ws.Cell(6, 2).GetRichText().ElementAt(1).Bold);
124+
Assert.AreEqual(ws.Cell(6, 2).GetRichText().Last().Text, "Rich decimal after");
125+
Assert.True(ws.Cell(6, 2).GetRichText().Last().Strikethrough);
126+
127+
Assert.AreEqual("{p:ExpandoObj.StrProp}", ws.Cell(6, 3).Value);
128+
Assert.True(ws.Cell(6, 3).HasRichText);
129+
Assert.AreEqual(ws.Cell(6, 3).GetRichText().Count, 2);
130+
Assert.AreEqual(ws.Cell(6, 3).GetRichText().First().Text, "{p:ExpandoObj");
131+
Assert.AreEqual(ws.Cell(6, 3).GetRichText().First().FontColor, XLColor.Green);
132+
Assert.AreEqual(ws.Cell(6, 3).GetRichText().Last().Text, ".StrProp}");
133+
134+
Assert.AreEqual("{p:StrParam}", ws.Cell(10, 1).Value);
135+
Assert.AreEqual("{m:Counter()}", ws.Cell(10, 2).Value);
136+
Assert.AreEqual("Plain text outside range", ws.Cell(11, 1).Value);
137+
Assert.AreEqual("Rich outside first Rich outside second", ws.Cell(11, 2).Value);
138+
Assert.True(ws.Cell(11, 2).HasRichText);
139+
Assert.AreEqual(ws.Cell(11, 2).GetRichText().Count, 2);
140+
Assert.AreEqual(ws.Cell(11, 2).GetRichText().First().Text, "Rich outside first");
141+
Assert.True(ws.Cell(11, 2).GetRichText().First().Italic);
142+
Assert.AreEqual(ws.Cell(11, 2).GetRichText().Last().Text, " Rich outside second");
143+
Assert.AreEqual(ws.Cell(11, 2).GetRichText().Last().FontColor, XLColor.Red);
81144

82145
Assert.AreEqual(0, ws.NamedRanges.Count());
83146
Assert.AreEqual(0, ws.Workbook.NamedRanges.Count());
84147

85148
Assert.AreEqual(1, ws.Workbook.Worksheets.Count);
86149

87-
//report.Workbook.SaveAs("test.xlsx");
150+
// report.Workbook.SaveAs("test.xlsx");
88151
}
89152

90153
[Test]

0 commit comments

Comments
 (0)