From 19feae348a32a3592544c8272a880226bd2888bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossian=20Edstr=C3=B6m?= Date: Thu, 16 Apr 2026 15:57:55 +0200 Subject: [PATCH 1/3] Began handling unique case: Group shape in exChart --- src/EPPlus/Drawing/Chart/ExcelChart.cs | 11 ++++++- src/EPPlus/Drawing/ExcelGroupShape.cs | 9 ++++-- src/EPPlusTest/Issues/ChartIssues.cs | 45 +++++++++++++++----------- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/EPPlus/Drawing/Chart/ExcelChart.cs b/src/EPPlus/Drawing/Chart/ExcelChart.cs index 4ce68b1419..cb3c2a4b47 100644 --- a/src/EPPlus/Drawing/Chart/ExcelChart.cs +++ b/src/EPPlus/Drawing/Chart/ExcelChart.cs @@ -762,7 +762,16 @@ internal static ExcelChart GetChart(ExcelDrawings drawings, XmlNode node, ExcelG internal static ExcelChartEx GetChartEx(ExcelDrawings drawings, XmlNode node, ExcelGroupShape parent = null) { - XmlNode chartDrawingNode = node.SelectSingleNode("mc:AlternateContent/mc:Choice/xdr:graphicFrame/a:graphic/a:graphicData/cx:chart", drawings.NameSpaceManager); + XmlNode chartDrawingNode; + if (node.Name == "mc:AlternateContent") + { + chartDrawingNode = node.SelectSingleNode("mc:Choice/xdr:graphicFrame/a:graphic/a:graphicData/cx:chart", drawings.NameSpaceManager); + } + else + { + chartDrawingNode = node.SelectSingleNode("mc:AlternateContent/mc:Choice/xdr:graphicFrame/a:graphic/a:graphicData/cx:chart", drawings.NameSpaceManager); + } + if (chartDrawingNode != null) { var drawingRelation = drawings.Part.GetRelationship(chartDrawingNode.Attributes["r:id"].Value); diff --git a/src/EPPlus/Drawing/ExcelGroupShape.cs b/src/EPPlus/Drawing/ExcelGroupShape.cs index 25223d84d5..c8a4644b26 100644 --- a/src/EPPlus/Drawing/ExcelGroupShape.cs +++ b/src/EPPlus/Drawing/ExcelGroupShape.cs @@ -51,10 +51,13 @@ private void AddDrawings() if (node.LocalName != "nvGrpSpPr" && node.LocalName != "grpSpPr") { var grpDraw = ExcelDrawing.GetDrawingFromNode(_parent._drawings, node, (XmlElement)node, _parent, _drawingsCollectionType); - _groupDrawings.Add(grpDraw); - if (_drawingNames.ContainsKey(grpDraw.Name) == false) + if(grpDraw != null) { - _drawingNames.Add(grpDraw.Name, _groupDrawings.Count - 1); + _groupDrawings.Add(grpDraw); + if (_drawingNames.ContainsKey(grpDraw.Name) == false) + { + _drawingNames.Add(grpDraw.Name, _groupDrawings.Count - 1); + } } } } diff --git a/src/EPPlusTest/Issues/ChartIssues.cs b/src/EPPlusTest/Issues/ChartIssues.cs index f537b666c3..474219567c 100644 --- a/src/EPPlusTest/Issues/ChartIssues.cs +++ b/src/EPPlusTest/Issues/ChartIssues.cs @@ -399,9 +399,9 @@ public void s968() SaveAndCleanup(package); } - [TestMethod] - public void CreateStringLiterals() - { + [TestMethod] + public void CreateStringLiterals() + { using (var package = OpenPackage("LiteralsSetting.xlsx", true)) { var wb = package.Workbook; @@ -411,23 +411,32 @@ public void CreateStringLiterals() var serie = numLitChart.Series.Add("{10,20,50}"); serie.XSeries = "{'col1','col2','col3'}"; - SaveAndCleanup(package); - } - } - [TestMethod] - public void s981() - { - using (var package = OpenTemplatePackage("s981.xlsx")) - { - var wb = package.Workbook; - var ws = wb.Worksheets["Summary"]; + SaveAndCleanup(package); + } + } + [TestMethod] + public void s981() + { + using (var package = OpenTemplatePackage("s981.xlsx")) + { + var wb = package.Workbook; + var ws = wb.Worksheets["Summary"]; var chart = ws.Drawings[0].As.Chart.ScatterChart; - chart.StyleManager.SetChartStyle(ePresetChartStyleMultiSeries.ScatterChartStyle3); + chart.StyleManager.SetChartStyle(ePresetChartStyleMultiSeries.ScatterChartStyle3); - SaveAndCleanup(package); - } - } - } + SaveAndCleanup(package); + } + } + + [TestMethod] + public void s1037() + { + using (var package = OpenTemplatePackage("s1037.xlsx")) + { + SaveAndCleanup(package); + } + } + } } From e348cb81478125de5694d91d5d30f8ef5116cfeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossian=20Edstr=C3=B6m?= Date: Thu, 16 Apr 2026 16:14:12 +0200 Subject: [PATCH 2/3] Stopped the crashing. Positions appear inaccurate --- src/EPPlus/Drawing/ExcelDrawing.cs | 27 +++++++++++++++++++-------- src/EPPlusTest/Issues/ChartIssues.cs | 19 ++++++++++++++++++- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/EPPlus/Drawing/ExcelDrawing.cs b/src/EPPlus/Drawing/ExcelDrawing.cs index 0576549317..8b01416d5c 100644 --- a/src/EPPlus/Drawing/ExcelDrawing.cs +++ b/src/EPPlus/Drawing/ExcelDrawing.cs @@ -94,7 +94,15 @@ internal ExcelDrawing(ExcelDrawings drawings, XmlNode node, string topPath, stri AdjustXPathsForGrouping(false); CellAnchor = GetAnchorFromName(node.LocalName); SetPositionProperties(drawings, node); - GetPositionSize(); //Get the drawing position and size, so we can adjust it upon save, if the normal font is changed + + if(collectionType == DrawingsCollectionType.Worksheet && From == null) + { + //TODO: ENSURE THIS CASE IS HANDLED APPROPRIATELY + } + else + { + GetPositionSize(); //Get the drawing position and size, so we can adjust it upon save, if the normal font is changed + } string relID = GetXmlNodeString(_hyperLinkPath + "/@r:id"); if (!string.IsNullOrEmpty(relID)) @@ -813,19 +821,22 @@ internal int GetPixelTop() } else { - var cache = _drawings.Worksheet.RowHeightCache; - for (int row = 0; row < From.Row; row++) + if (From != null) { - lock (cache) + var cache = _drawings.Worksheet.RowHeightCache; + for (int row = 0; row < From.Row; row++) { - if (!cache.ContainsKey(row)) + lock (cache) { - cache.Add(row, _drawings.Worksheet.GetRowHeight(row + 1)); + if (!cache.ContainsKey(row)) + { + cache.Add(row, _drawings.Worksheet.GetRowHeight(row + 1)); + } } + pix += (int)(cache[row] / 0.75); } - pix += (int)(cache[row] / 0.75); + pix += From.RowOff / EMU_PER_PIXEL; } - pix += From.RowOff / EMU_PER_PIXEL; } return pix; } diff --git a/src/EPPlusTest/Issues/ChartIssues.cs b/src/EPPlusTest/Issues/ChartIssues.cs index 474219567c..0a8ff0e91c 100644 --- a/src/EPPlusTest/Issues/ChartIssues.cs +++ b/src/EPPlusTest/Issues/ChartIssues.cs @@ -435,8 +435,25 @@ public void s1037() { using (var package = OpenTemplatePackage("s1037.xlsx")) { + //Crashes on save (also accesssing) SaveAndCleanup(package); } } - } + + [TestMethod] + public void s1038() + { + using (var package = OpenTemplatePackage("s1038.xlsx")) + { + var worksheet = package.Workbook.Worksheets["Tabelle1"]; + var groupShape = worksheet.Drawings[0] as ExcelGroupShape; + + //Crashes when accessesing + var drawingsWithinGroupShape = groupShape.Drawings; + + SaveAndCleanup(package); + } + } + + } } From d7043cf15dd66cf7406ab0356341323eea258e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4llman?= Date: Fri, 17 Apr 2026 10:23:19 +0200 Subject: [PATCH 3/3] Fixes issue #2337 --- src/EPPlus/Drawing/Chart/ExcelChart.cs | 16 ++++++++-------- src/EPPlus/Drawing/ExcelDrawing.cs | 12 ++---------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/EPPlus/Drawing/Chart/ExcelChart.cs b/src/EPPlus/Drawing/Chart/ExcelChart.cs index cb3c2a4b47..1a4c37d7c1 100644 --- a/src/EPPlus/Drawing/Chart/ExcelChart.cs +++ b/src/EPPlus/Drawing/Chart/ExcelChart.cs @@ -785,25 +785,25 @@ internal static ExcelChartEx GetChartEx(ExcelDrawings drawings, XmlNode node, Ex var layoutId = chartNode.SelectSingleNode("cx:plotArea/cx:plotAreaRegion/cx:series[1]/@layoutId", drawings.NameSpaceManager); if (layoutId == null) { - return new ExcelTreemapChart(drawings, node, uriChart, part, chartXml, chartNode); + return new ExcelTreemapChart(drawings, node, uriChart, part, chartXml, chartNode, parent); } switch (layoutId.Value) { case "treemap": - return new ExcelTreemapChart(drawings, node, uriChart, part, chartXml, chartNode); + return new ExcelTreemapChart(drawings, node, uriChart, part, chartXml, chartNode, parent); case "sunburst": - return new ExcelSunburstChart(drawings, node, uriChart, part, chartXml, chartNode); + return new ExcelSunburstChart(drawings, node, uriChart, part, chartXml, chartNode, parent); case "boxWhisker": - return new ExcelBoxWhiskerChart(drawings, node, uriChart, part, chartXml, chartNode); + return new ExcelBoxWhiskerChart(drawings, node, uriChart, part, chartXml, chartNode, parent); case "clusteredColumn": case "pareto": - return new ExcelHistogramChart(drawings, node, uriChart, part, chartXml, chartNode); + return new ExcelHistogramChart(drawings, node, uriChart, part, chartXml, chartNode, parent); case "funnel": - return new ExcelFunnelChart(drawings, node, uriChart, part, chartXml, chartNode); + return new ExcelFunnelChart(drawings, node, uriChart, part, chartXml, chartNode, parent); case "waterfall": - return new ExcelWaterfallChart(drawings, node, uriChart, part, chartXml, chartNode); + return new ExcelWaterfallChart(drawings, node, uriChart, part, chartXml, chartNode, parent); case "regionMap": - return new ExcelRegionMapChart(drawings, node, uriChart, part, chartXml, chartNode); + return new ExcelRegionMapChart(drawings, node, uriChart, part, chartXml, chartNode, parent); default: throw new NotSupportedException($"Unsupported chart layout {layoutId.Value}"); } diff --git a/src/EPPlus/Drawing/ExcelDrawing.cs b/src/EPPlus/Drawing/ExcelDrawing.cs index 8b01416d5c..1778afb660 100644 --- a/src/EPPlus/Drawing/ExcelDrawing.cs +++ b/src/EPPlus/Drawing/ExcelDrawing.cs @@ -94,15 +94,7 @@ internal ExcelDrawing(ExcelDrawings drawings, XmlNode node, string topPath, stri AdjustXPathsForGrouping(false); CellAnchor = GetAnchorFromName(node.LocalName); SetPositionProperties(drawings, node); - - if(collectionType == DrawingsCollectionType.Worksheet && From == null) - { - //TODO: ENSURE THIS CASE IS HANDLED APPROPRIATELY - } - else - { - GetPositionSize(); //Get the drawing position and size, so we can adjust it upon save, if the normal font is changed - } + GetPositionSize(); //Get the drawing position and size, so we can adjust it upon save, if the normal font is changed string relID = GetXmlNodeString(_hyperLinkPath + "/@r:id"); if (!string.IsNullOrEmpty(relID)) @@ -652,7 +644,7 @@ internal static ExcelDrawing GetDrawingFromNode(ExcelDrawings drawings, XmlNode } break; } - return new ExcelDrawing(drawings, node, "", ""); + return new ExcelDrawing(drawings, node, "", "",parent, DrawingsType); } private static ExcelDrawing GetShapeOrControl(ExcelDrawings drawings, XmlNode node, XmlElement drawNode, ExcelGroupShape parent, DrawingsCollectionType collectionType = DrawingsCollectionType.Worksheet)