Skip to content

Commit 1362fdb

Browse files
authored
Bug/679 (#1485)
* Bugfixes * Adding fixes/commenting * Added handling of datalabel nodeorder * Added functional manualLayoutElement * Added options * Innaccurate implementation * Added legacy and fixed functionality and error message * Removed big block of comment * Fix minor bug
1 parent 9850f12 commit 1362fdb

30 files changed

+900
-31
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using OfficeOpenXml.Core;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
7+
namespace OfficeOpenXml.Drawing.Chart.DataLabling
8+
{
9+
internal class CTDataLabel : GroupDataLabel
10+
{
11+
string[] nodeOrder;
12+
13+
internal CTDataLabel()
14+
{
15+
nodeOrder = new string[GroupDLbl.Length + 3];
16+
17+
nodeOrder[0] = "idx";
18+
//Note: this delete and group is one "choice" node.
19+
nodeOrder[1] = "delete";
20+
21+
////Alternate:
22+
//Array.Copy(EG_DlblShared, _grpLbl, EG_DlblShared.Length);
23+
24+
for (int i = 0; i < GroupDLbl.Length; i++)
25+
{
26+
nodeOrder[i + 2] = GroupDLbl[i];
27+
}
28+
29+
nodeOrder[nodeOrder.Length - 1] = "extLst";
30+
31+
NodeOrder = nodeOrder;
32+
}
33+
34+
internal string[] NodeOrder { get; private set; }
35+
}
36+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using OfficeOpenXml.Core;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
7+
namespace OfficeOpenXml.Drawing.Chart.DataLabling
8+
{
9+
internal class CTDataLabels : GroupDataLabels
10+
{
11+
string[] _nodeOrder;
12+
13+
internal CTDataLabels()
14+
{
15+
_nodeOrder = new string[GroupDLbls.Length + 3];
16+
_nodeOrder[0] = "dLbl";
17+
_nodeOrder[1] = "delete";
18+
19+
////Alternative 1:
20+
//Array.Copy(EG_DlblShared, _grpLbls, EG_DlblShared.Length);
21+
22+
////Alternative 2:
23+
for (int i = 0; i < GroupDLbls.Length; i++)
24+
{
25+
_nodeOrder[i + 2] = GroupDLbls[i];
26+
}
27+
28+
_nodeOrder[_nodeOrder.Length - 1] = "extLst";
29+
30+
NodeOrder = _nodeOrder;
31+
}
32+
33+
internal string[] NodeOrder { get; private set; }
34+
}
35+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
namespace OfficeOpenXml.Drawing.Chart.DataLabling
6+
{
7+
internal class DataLabelConstNodeOrderBase
8+
{
9+
internal static readonly string[] EG_DlblShared = ["numFmt", "spPr", "txPr", "dLblPos", "showLegendKey", "showVal", "showCatName", "showSerName", "showPercent", "showBubbleSize", "separator"];
10+
}
11+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace OfficeOpenXml.Drawing.Chart.DataLabling
7+
{
8+
internal class GroupDataLabel : DataLabelConstNodeOrderBase
9+
{
10+
string[] _grpLbl = new string[EG_DlblShared.Length + 2];
11+
12+
internal GroupDataLabel()
13+
{
14+
_grpLbl[0] = "layout";
15+
_grpLbl[1] = "tx";
16+
17+
////Alternate:
18+
//Array.Copy(EG_DlblShared, _grpLbl, EG_DlblShared.Length);
19+
20+
for (int i = 0; i < EG_DlblShared.Length; i++)
21+
{
22+
_grpLbl[i + 2] = EG_DlblShared[i];
23+
}
24+
25+
GroupDLbl = _grpLbl;
26+
}
27+
28+
internal static string[] GroupDLbl { get; private set; }
29+
}
30+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace OfficeOpenXml.Drawing.Chart.DataLabling
7+
{
8+
internal class GroupDataLabels : DataLabelConstNodeOrderBase
9+
{
10+
string[] _grpLbls = new string[EG_DlblShared.Length + 2];
11+
12+
internal GroupDataLabels()
13+
{
14+
_grpLbls[_grpLbls.Length - 2] = "showLeaderLines";
15+
_grpLbls[_grpLbls.Length - 1] = "leaderLines";
16+
17+
////Alternative 1:
18+
//Array.Copy(EG_DlblShared, _grpLbls, EG_DlblShared.Length);
19+
20+
////Alternative 2:
21+
for (int i = 0; i < EG_DlblShared.Length; i++)
22+
{
23+
_grpLbls[i] = EG_DlblShared[i];
24+
}
25+
26+
GroupDLbls = _grpLbls;
27+
}
28+
29+
internal static string[] GroupDLbls { get; private set; }
30+
}
31+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace OfficeOpenXml.Drawing.Chart.DataLabling
7+
{
8+
internal static class LabelNodeHolder
9+
{
10+
static internal CTDataLabel DataLabel = new CTDataLabel();
11+
static internal CTDataLabels DataLabels = new CTDataLabels();
12+
}
13+
}

src/EPPlus/Drawing/Chart/ExcelChartDataLabelCollection.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ internal ExcelChartDataLabelCollection(ExcelChart chart, XmlNamespaceManager ns,
2828
{
2929
SchemaNodeOrder = schemaNodeOrder;
3030
_list = new List<ExcelChartDataLabelItem>();
31-
foreach (XmlNode pointNode in TopNode.SelectNodes(ExcelChartDataPoint.topNodePath, ns))
31+
foreach (XmlNode dataLabelNode in TopNode.SelectNodes("c:dLbl", ns))
3232
{
33-
_list.Add(new ExcelChartDataLabelItem(chart, ns, pointNode, "idx", schemaNodeOrder));
33+
_list.Add(new ExcelChartDataLabelItem(chart, ns, dataLabelNode, "", schemaNodeOrder));
3434
}
3535
_chart = chart;
3636
}

src/EPPlus/Drawing/Chart/ExcelChartDataLabelItem.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,14 @@ public class ExcelChartDataLabelItem : ExcelChartDataLabelStandard
3131
internal ExcelChartDataLabelItem(ExcelChart chart, XmlNamespaceManager ns, XmlNode node, string nodeName, string[] schemaNodeOrder)
3232
: base(chart, ns, node, nodeName, schemaNodeOrder)
3333
{
34+
Layout = new ExcelLayout(NameSpaceManager, TopNode, $"c:layout","c:extLst/c:ext[1]/c15:layout", SchemaNodeOrder);
3435
}
36+
37+
/// <summary>
38+
/// Define position for manual elements
39+
/// </summary>
40+
public ExcelLayout Layout { get; private set; }
41+
3542
/// <summary>
3643
/// The index of an individual datalabel
3744
/// </summary>

src/EPPlus/Drawing/Chart/ExcelChartDataLabelStandard.cs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,49 @@ Date Author Change
1111
01/27/2020 EPPlus Software AB Initial release EPPlus 5
1212
*************************************************************************************************/
1313
using System;
14+
using System.Collections.Generic;
1415
using System.Xml;
16+
using OfficeOpenXml.Drawing.Chart.DataLabling;
1517

1618
namespace OfficeOpenXml.Drawing.Chart
1719
{
1820
/// <summary>
1921
/// Settings for a charts data lables
2022
/// </summary>
2123
public class ExcelChartDataLabelStandard : ExcelChartDataLabel
22-
{
24+
{
25+
Guid _guidId;
26+
2327
internal ExcelChartDataLabelStandard(ExcelChart chart, XmlNamespaceManager ns, XmlNode node, string nodeName, string[] schemaNodeOrder)
2428
: base(chart, ns, node, nodeName, "c")
2529
{
26-
AddSchemaNodeOrder(schemaNodeOrder, new string[] { "idx", "spPr", "txPr", "dLbl", "dLblPos", "showLegendKey", "showVal", "showCatName", "showSerName", "showPercent", "showBubbleSize", "separator", "showLeaderLines" }, new int[] { 0, schemaNodeOrder.Length });
27-
AddSchemaNodeOrder(SchemaNodeOrder, ExcelDrawing._schemaNodeOrderSpPr);
28-
if(nodeName=="dLbl")
30+
AddSchemaNodeOrder([""], LabelNodeHolder.DataLabels.NodeOrder);
31+
var order = SchemaNodeOrder;
32+
33+
if (nodeName == "dLbl" || nodeName == "")
2934
{
35+
AddSchemaNodeOrder([""], LabelNodeHolder.DataLabel.NodeOrder);
36+
3037
TopNode = node;
38+
39+
var extPath = "c:extLst/c:ext";
40+
41+
NameSpaceManager.AddNamespace("c15", ExcelPackage.schemaChart2012);
42+
NameSpaceManager.AddNamespace("c16", ExcelPackage.schemaChart2014);
43+
44+
XmlElement el = (XmlElement)CreateNode($"{extPath}");
45+
el.SetAttribute("xmlns:c15", ExcelPackage.schemaChart2012);
46+
SetXmlNodeString($"{extPath}/@uri","{CE6537A1-D6FC-4f65-9D91-7224C49458BB}");
47+
48+
XmlElement element = (XmlElement)CreateNode($"{extPath}", false, true);
49+
element.SetAttribute("xmlns:c16", ExcelPackage.schemaChart2014);
50+
SetXmlNodeString($"{extPath}[2]/@uri", "{C3380CC4-5D6E-409C-BE32-E72D297353CC}");
51+
52+
_guidId = Guid.NewGuid();
53+
54+
var extNode2 = GetNode($"{extPath}[2]");
55+
var uniqueIdNode = (XmlElement)CreateNode(extNode2, "c16:uniqueID");
56+
uniqueIdNode.SetAttribute("val", $"{{{_guidId}}}");
3157
}
3258
else
3359
{
@@ -45,6 +71,7 @@ internal ExcelChartDataLabelStandard(ExcelChart chart, XmlNamespaceManager ns, X
4571
const string positionPath = "c:dLblPos/@val";
4672
/// <summary>
4773
/// Position of the labels
74+
/// Note: Only Center, InEnd and InBase are allowed for dataLabels on stacked columns
4875
/// </summary>
4976
public override eLabelPosition Position
5077
{
@@ -56,14 +83,14 @@ public override eLabelPosition Position
5683
{
5784
if (ForbiddDataLabelPosition(_chart))
5885
{
59-
throw (new InvalidOperationException("Can't set data label position on a 3D-chart"));
86+
throw new InvalidOperationException("Can't set data label position on a 3D-chart");
6087
}
6188
SetXmlNodeString(positionPath, GetPosText(value));
6289
}
6390
}
6491
internal static bool ForbiddDataLabelPosition(ExcelChart _chart)
6592
{
66-
return (_chart.IsType3D() && !_chart.IsTypePie() && _chart.ChartType != eChartType.Line3D)
93+
return _chart.IsType3D() && !_chart.IsTypePie() && _chart.ChartType != eChartType.Line3D
6794
|| _chart.IsTypeDoughnut();
6895
}
6996
const string showValPath = "c:showVal/@val";

src/EPPlus/Drawing/Chart/ExcelChartStandard.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1207,7 +1207,10 @@ internal void SetPivotSource(ExcelPivotTable pivotTableSource)
12071207
chart.PrependChild(fmts);
12081208
fmts.InnerXml = "<c:pivotFmt><c:idx val=\"0\"/><c:marker><c:symbol val=\"none\"/></c:marker></c:pivotFmt>";
12091209

1210-
Series.AddPivotSerie(pivotTableSource);
1210+
for(int i = 0; i < pivotTableSource.DataFields.Count; i++)
1211+
{
1212+
Series.AddPivotSerie(pivotTableSource);
1213+
}
12111214
}
12121215
ExcelChartAxisStandard[] _axisStandard = null;
12131216
public new ExcelChartAxisStandard[] Axis
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Xml;
6+
7+
namespace OfficeOpenXml.Drawing.Chart
8+
{
9+
/// <summary>
10+
/// Layout settings
11+
/// </summary>
12+
public class ExcelLayout : XmlHelper
13+
{
14+
//Class for ExtLst Properties for later
15+
16+
/// <summary>
17+
/// Manual layout settings for precise control of element position
18+
/// </summary>
19+
public ExcelManualLayout ManualLayout { get; }
20+
21+
internal ExcelLayout(XmlNamespaceManager ns, XmlNode topNode, string path, string extLstPath, string[] schemaNodeOrder = null) : base(ns, topNode)
22+
{
23+
ManualLayout = new ExcelManualLayout(ns, topNode, $"{path}/c:manualLayout", $"{extLstPath}/c:manualLayout", schemaNodeOrder);
24+
}
25+
}
26+
}

0 commit comments

Comments
 (0)