From 2422435bd07e51fadbf2f12d463b54500bb66508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossian=20Edstr=C3=B6m?= Date: Thu, 7 May 2026 12:04:05 +0200 Subject: [PATCH 01/12] Added graphicframe name fallback and child pos --- src/EPPlus/Drawing/ExcelDrawing.cs | 18 ++++++++++++++---- src/EPPlus/Drawing/ExcelGroupShape.cs | 4 +++- src/EPPlusTest/Issues/ChartIssues.cs | 8 +++++++- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/EPPlus/Drawing/ExcelDrawing.cs b/src/EPPlus/Drawing/ExcelDrawing.cs index 1778afb66..6707a0d5c 100644 --- a/src/EPPlus/Drawing/ExcelDrawing.cs +++ b/src/EPPlus/Drawing/ExcelDrawing.cs @@ -21,7 +21,6 @@ Date Author Change using OfficeOpenXml.Utils.FileUtils; using OfficeOpenXml.Utils.XML; using System; -using System.Drawing; using System.Globalization; using System.IO; using System.Linq; @@ -583,6 +582,9 @@ internal static ExcelDrawing GetDrawing(ExcelDrawings drawings, XmlNode node, Dr internal static ExcelDrawing GetDrawingFromNode(ExcelDrawings drawings, XmlNode node, XmlElement drawNode, ExcelGroupShape parent = null, DrawingsCollectionType DrawingsType = DrawingsCollectionType.Worksheet) { + string fallbackDrawingPath = ""; + string fallbackNvPrPath = ""; + switch (drawNode.LocalName) { case "sp": @@ -591,11 +593,19 @@ internal static ExcelDrawing GetDrawingFromNode(ExcelDrawings drawings, XmlNode var aPic = new ExcelPicture(drawings, node, parent, DrawingsType); return aPic; case "graphicFrame": - var c= ExcelChart.GetChart(drawings, node, parent); - if(c!=null) //If null, the drawing is not a chart. Might be a smart art, diagram or 3d model. We return a standard drawing to retain the drawing. + var c = ExcelChart.GetChart(drawings, node, parent); + if (c!=null) //If null, the drawing is not a chart. Might be a smart art, diagram or 3d model. We return a standard drawing to retain the drawing. { return c; } + else + { + //While we do not know the exact type. + //It's a standard drawing with a graphic frame + //We assume the object has its name etc. in the same nodes as a chart + fallbackDrawingPath = "xdr:graphicFrame"; + fallbackNvPrPath = "xdr:nvGraphicFramePr/xdr:cNvPr"; + } break; case "grpSp": return new ExcelGroupShape(drawings, node, parent, DrawingsType); @@ -644,7 +654,7 @@ internal static ExcelDrawing GetDrawingFromNode(ExcelDrawings drawings, XmlNode } break; } - return new ExcelDrawing(drawings, node, "", "",parent, DrawingsType); + return new ExcelDrawing(drawings, node, fallbackDrawingPath, fallbackNvPrPath, parent, DrawingsType); } private static ExcelDrawing GetShapeOrControl(ExcelDrawings drawings, XmlNode node, XmlElement drawNode, ExcelGroupShape parent, DrawingsCollectionType collectionType = DrawingsCollectionType.Worksheet) diff --git a/src/EPPlus/Drawing/ExcelGroupShape.cs b/src/EPPlus/Drawing/ExcelGroupShape.cs index c8a4644b2..2371c414d 100644 --- a/src/EPPlus/Drawing/ExcelGroupShape.cs +++ b/src/EPPlus/Drawing/ExcelGroupShape.cs @@ -47,7 +47,6 @@ private void AddDrawings() _groupDrawings = new List(); foreach (XmlNode node in _topNode.ChildNodes) { - if (node.LocalName != "nvGrpSpPr" && node.LocalName != "grpSpPr") { var grpDraw = ExcelDrawing.GetDrawingFromNode(_parent._drawings, node, (XmlElement)node, _parent, _drawingsCollectionType); @@ -645,6 +644,9 @@ internal override void SaveDrawing(bool hasLoadedPivotTables) foreach (var d in Drawings) { + //Ensure position on underlying drawings are updated + d.AdjustPositionAndSize(); + d.UpdatePositionAndSizeXml(); d.SaveDrawing(hasLoadedPivotTables); } } diff --git a/src/EPPlusTest/Issues/ChartIssues.cs b/src/EPPlusTest/Issues/ChartIssues.cs index 0a8ff0e91..9bdf8d1f9 100644 --- a/src/EPPlusTest/Issues/ChartIssues.cs +++ b/src/EPPlusTest/Issues/ChartIssues.cs @@ -451,7 +451,13 @@ public void s1038() //Crashes when accessesing var drawingsWithinGroupShape = groupShape.Drawings; - SaveAndCleanup(package); + var firstDrawing = drawingsWithinGroupShape[0]; + + firstDrawing.SetPosition(500, 500); + //drawingsWithinGroupShape[0].Position.Y = 2000; + + + SaveAndCleanup(package); } } From 07a7cc2e70885bd3f2e8b8356c8593aea2ff12d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossian=20Edstr=C3=B6m?= Date: Mon, 11 May 2026 11:29:05 +0200 Subject: [PATCH 02/12] Ensured getter does not update collection --- src/EPPlus/ExcelRangeBase.cs | 6 +- src/EPPlus/ExcelWorksheet.cs | 7 +- .../Style/RichText/ExcelRichTextCollection.cs | 29 ++++ src/EPPlusTest/Issues/RichDataIssues.cs | 134 ++++++++++++++++++ 4 files changed, 173 insertions(+), 3 deletions(-) diff --git a/src/EPPlus/ExcelRangeBase.cs b/src/EPPlus/ExcelRangeBase.cs index a681380e3..25ad1e78f 100644 --- a/src/EPPlus/ExcelRangeBase.cs +++ b/src/EPPlus/ExcelRangeBase.cs @@ -1330,8 +1330,10 @@ public bool IsRichText var isRt = _worksheet._flags.GetFlagValue(_fromRow, _fromCol, CellFlags.RichText); if (isRt) { - _rtc = _worksheet.GetRichText(_fromRow, _fromCol, this); - return _rtc.Count > 0; + //Do not update _rtc. This is a boolean getter. + //It should not set any values even if they diff. + var couldBeEmptyRT = _worksheet.GetRichText(_fromRow, _fromCol, this); + return couldBeEmptyRT.Count > 0; } return isRt; } diff --git a/src/EPPlus/ExcelWorksheet.cs b/src/EPPlus/ExcelWorksheet.cs index f0ebe3dec..61a36ea11 100644 --- a/src/EPPlus/ExcelWorksheet.cs +++ b/src/EPPlus/ExcelWorksheet.cs @@ -1526,7 +1526,12 @@ internal ExcelRichTextCollection GetRichText(int row, int col, ExcelRangeBase r } else { - var text = ValueToTextHandler.GetFormattedText(v._value, Workbook, v._styleId, false); + object textValue = v._value; + if(textValue != null && typeof(ExcelRichTextCollection) == textValue.GetType()) + { + textValue = ((ExcelRichTextCollection)textValue).Text; + } + var text = ValueToTextHandler.GetFormattedText(textValue, Workbook, v._styleId, false); if (string.IsNullOrEmpty(text)) { var item = new ExcelRichTextCollection(Workbook, r); diff --git a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs index de032100a..0333eb166 100644 --- a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs +++ b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs @@ -129,6 +129,28 @@ private void CheckDeleted() } } + private void CheckFormulas() + { + List addressesContainingFormulas = new List(); + + foreach (var cell in _cells) + { + if (string.IsNullOrEmpty(cell.Formula) == false) + { + addressesContainingFormulas.Add(cell.Address); + } + } + + if (addressesContainingFormulas.Count > 0) + { + string errorAddresses = string.Join(System.Environment.NewLine, addressesContainingFormulas.ToArray()); + throw new InvalidOperationException($"Could not add RichText to range: {_cells.Address}. \r\n" + + $"The following addresses contain formulas:\r\n" + + $"{errorAddresses}\r\n" + + $"Adding richtext would over-write the formulas. Please clear formulas before adding rich text if this is intended."); + } + } + /// /// Items in the list /// @@ -162,6 +184,7 @@ public ExcelRichText Insert(int index, string text) { CheckDeleted(); if (text == null) throw new ArgumentException("Text can't be null", "text"); + //CheckFormulas(); var rt = new ExcelRichText(text, this); rt.PreserveSpace = true; int prevIndex = 0; @@ -220,6 +243,12 @@ public void Clear() { CheckDeleted(); _list.Clear(); + ////Avoid on is comment since insert does?? + //if (_isComment == false) + //{ + // //If we clear the cells then there is no flag value. + // _cells._worksheet._flags.SetFlagValue(_cells._fromRow, _cells._fromCol, false, CellFlags.RichText); + //} } /// /// Removes an item at the specific index diff --git a/src/EPPlusTest/Issues/RichDataIssues.cs b/src/EPPlusTest/Issues/RichDataIssues.cs index d3e14bab4..bf20bdcc3 100644 --- a/src/EPPlusTest/Issues/RichDataIssues.cs +++ b/src/EPPlusTest/Issues/RichDataIssues.cs @@ -85,5 +85,139 @@ public void VerifyCalcError() SaveAndCleanup(p); } } + + [TestMethod] + public void AddingRichTextToFormulasShouldOverwrite() + { + using (var pck = OpenPackage("dirtyRT.xlsx")) + { + var ws = pck.Workbook.Worksheets.Add("richText"); + + ws.Cells["A1"].Value = 1001.1d; + ws.Cells["C1"].Formula = "ROUND(A1, 1)"; + ws.Cells["B1"].Formula = "\"My favorite number is: \"&TEXT(ROUND(A1,1),\"#,##0.00;(#,##0.00)\")"; + + ws.Cells["B1"].RichText.Add("My favorite number is: 1001.1"); + + var myFormula = ws.Cells["B1"].Formula; + + Assert.IsTrue(string.IsNullOrEmpty(myFormula)); + + ////Set richtext on range that has a formula + ////This should Throw (or clear Formula) + //Assert.Throws(() => ws.Cells["B1"].RichText.Add("My favorite number is: 1001.1")); + + ////This then Results in strange behaviour below when running calculate/IsRichText + //var cellRange = ws.Cells["B1"]; + //var origRT = cellRange.RichText; + + //ws.Calculate(); + //var afterRt1 = cellRange.Text; + //var cellRich = ws.Cells["B1"].RichText.Text; //A FRESH reference to the cell, yielding: 1001,10000 + + + //var OLDCellRich = cellRange.RichText.Text; //Dirty COPY of the cell and its values, yielding: 1001.1\n + + ////This causes the richText of cellRange.RichText to update + //var myFormula = cellRange.IsRichText; + ////So does Just LOOKING at the cellRange variable properties In the debugger. It trigger their Getters. + ////This property changes the actual values of the range when observed in the debugger. + ////This makes debugging harder and highly confusing both to us and end-users as you may look at a value + ////See that it is innaccurate and then check it again only to see that it is correct for no discernable reason. + + //var OLDCellRichAfterDebug = cellRange.RichText.Text; + //Assert.AreEqual(OLDCellRich, OLDCellRichAfterDebug); + } + } + + [TestMethod] + public void AddingRichTextToFormulasShouldThrow() + { + using (var pck = OpenPackage("dirtyRT.xlsx")) + { + var ws = pck.Workbook.Worksheets.Add("richText"); + + ws.Cells["A1"].Value = 1001.1d; + ws.Cells["C1"].Formula = "ROUND(A1, 1)"; + ws.Cells["B1"].Formula = "\"My favorite number is: \"&TEXT(ROUND(A1,1),\"#,##0.00;(#,##0.00)\")"; + + //Set richtext on range that has a formula + //This should Throw (or clear Formula) + Assert.Throws(() => ws.Cells["B1"].RichText.Add("My favorite number is: 1001.1")); + + ////This then Results in strange behaviour below when running calculate/IsRichText + //var cellRange = ws.Cells["B1"]; + //var origRT = cellRange.RichText; + + //ws.Calculate(); + //var afterRt1 = cellRange.Text; + //var cellRich = ws.Cells["B1"].RichText.Text; //A FRESH reference to the cell, yielding: 1001,10000 + + + //var OLDCellRich = cellRange.RichText.Text; //Dirty COPY of the cell and its values, yielding: 1001.1\n + + ////This causes the richText of cellRange.RichText to update + //var myFormula = cellRange.IsRichText; + ////So does Just LOOKING at the cellRange variable properties In the debugger. It trigger their Getters. + ////This property changes the actual values of the range when observed in the debugger. + ////This makes debugging harder and highly confusing both to us and end-users as you may look at a value + ////See that it is innaccurate and then check it again only to see that it is correct for no discernable reason. + + //var OLDCellRichAfterDebug = cellRange.RichText.Text; + //Assert.AreEqual(OLDCellRich, OLDCellRichAfterDebug); + } + } + + [TestMethod] + public void RichTextShouldNotBecomeDirty() + { + using (var pck = OpenPackage("dirtyRT.xlsx")) + { + var ws = pck.Workbook.Worksheets.Add("richText"); + + ws.Cells["A1"].Value = 1001.1d; + ws.Cells["C1"].Formula = "ROUND(A1, 1)"; + ws.Cells["B1"].Formula = "\"My favorite number is: \"&TEXT(ROUND(A1,1),\"#,##0.00;(#,##0.00)\")"; + + //Set richtext on range that has a formula + //This should clear Formula but does not + ws.Cells["B1"].RichText.Add("My favorite number is: 1001.1", true); + + + //This then Results in strange behaviour below when running calculate/IsRichText + var cellRange = ws.Cells["B1"]; + var origRT = cellRange.RichText; + + ws.Calculate(); + var afterRt1 = cellRange.Text; + var cellRich = ws.Cells["B1"].RichText.Text; //A FRESH reference to the cell, yielding: 1001,10000 + + + var OLDCellRich = cellRange.RichText.Text; //Dirty COPY of the cell and its values, yielding: 1001.1\n + + //This causes the richText of cellRange.RichText to update + var myFormula = cellRange.IsRichText; + //So does Just LOOKING at the cellRange variable properties In the debugger. It trigger their Getters. + //This property changes the actual values of the range when observed in the debugger. + //This makes debugging harder and highly confusing both to us and end-users as you may look at a value + //See that it is innaccurate and then check it again only to see that it is correct for no discernable reason. + + var OLDCellRichAfterDebug = cellRange.RichText.Text; + + Assert.AreEqual(OLDCellRich, OLDCellRichAfterDebug); + Assert.AreNotEqual(cellRich, OLDCellRich); + + var newerRef = ws.Cells["B1"].RichText; + + var refreshedText = "This text should now appear in both pointers"; + + cellRange.RichText.Text = refreshedText; + + Assert.AreEqual(refreshedText, newerRef.Text); + Assert.AreEqual(refreshedText, cellRange.RichText.Text); + Assert.AreEqual(refreshedText, ws.Cells["B1"].RichText.Text); + } + } + } } From 17a477db07ac6415989126fad44b0c86e3240d85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossian=20Edstr=C3=B6m?= Date: Mon, 11 May 2026 13:10:36 +0200 Subject: [PATCH 03/12] Added ifs for comments --- .../Style/RichText/ExcelRichTextCollection.cs | 35 ++--- src/EPPlusTest/Issues/RichDataIssues.cs | 121 ++---------------- 2 files changed, 24 insertions(+), 132 deletions(-) diff --git a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs index 0333eb166..ef587d2e3 100644 --- a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs +++ b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs @@ -129,28 +129,6 @@ private void CheckDeleted() } } - private void CheckFormulas() - { - List addressesContainingFormulas = new List(); - - foreach (var cell in _cells) - { - if (string.IsNullOrEmpty(cell.Formula) == false) - { - addressesContainingFormulas.Add(cell.Address); - } - } - - if (addressesContainingFormulas.Count > 0) - { - string errorAddresses = string.Join(System.Environment.NewLine, addressesContainingFormulas.ToArray()); - throw new InvalidOperationException($"Could not add RichText to range: {_cells.Address}. \r\n" + - $"The following addresses contain formulas:\r\n" + - $"{errorAddresses}\r\n" + - $"Adding richtext would over-write the formulas. Please clear formulas before adding rich text if this is intended."); - } - } - /// /// Items in the list /// @@ -184,7 +162,15 @@ public ExcelRichText Insert(int index, string text) { CheckDeleted(); if (text == null) throw new ArgumentException("Text can't be null", "text"); - //CheckFormulas(); + + //If just a note we can't clear formulas on the cell itself. + if (_isComment == false) + { + //We MUST clear formulas before setting richtext + //To ensure calculate does not create missmatch between formula and richtext. + _cells.ClearFormulas(); + } + var rt = new ExcelRichText(text, this); rt.PreserveSpace = true; int prevIndex = 0; @@ -227,8 +213,11 @@ public ExcelRichText Insert(int index, string text) { rt.Color = Color.FromArgb(hex); } + + //If just a note we cannot set rich text flag on the cell itself. if (_isComment == false) { + //If not a note then we are a cell and can set the flag. _cells._worksheet._flags.SetFlagValue(_cells._fromRow, _cells._fromCol, true, CellFlags.RichText); } } diff --git a/src/EPPlusTest/Issues/RichDataIssues.cs b/src/EPPlusTest/Issues/RichDataIssues.cs index bf20bdcc3..3de76fa64 100644 --- a/src/EPPlusTest/Issues/RichDataIssues.cs +++ b/src/EPPlusTest/Issues/RichDataIssues.cs @@ -1,9 +1,11 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; +using OfficeOpenXml; +using OfficeOpenXml.Style; using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; using System.Text; -using OfficeOpenXml; namespace EPPlusTest.Issues { @@ -89,7 +91,7 @@ public void VerifyCalcError() [TestMethod] public void AddingRichTextToFormulasShouldOverwrite() { - using (var pck = OpenPackage("dirtyRT.xlsx")) + using (var pck = OpenPackage("dirtyRT.xlsx", true)) { var ws = pck.Workbook.Worksheets.Add("richText"); @@ -102,122 +104,23 @@ public void AddingRichTextToFormulasShouldOverwrite() var myFormula = ws.Cells["B1"].Formula; Assert.IsTrue(string.IsNullOrEmpty(myFormula)); - - ////Set richtext on range that has a formula - ////This should Throw (or clear Formula) - //Assert.Throws(() => ws.Cells["B1"].RichText.Add("My favorite number is: 1001.1")); - - ////This then Results in strange behaviour below when running calculate/IsRichText - //var cellRange = ws.Cells["B1"]; - //var origRT = cellRange.RichText; - - //ws.Calculate(); - //var afterRt1 = cellRange.Text; - //var cellRich = ws.Cells["B1"].RichText.Text; //A FRESH reference to the cell, yielding: 1001,10000 - - - //var OLDCellRich = cellRange.RichText.Text; //Dirty COPY of the cell and its values, yielding: 1001.1\n - - ////This causes the richText of cellRange.RichText to update - //var myFormula = cellRange.IsRichText; - ////So does Just LOOKING at the cellRange variable properties In the debugger. It trigger their Getters. - ////This property changes the actual values of the range when observed in the debugger. - ////This makes debugging harder and highly confusing both to us and end-users as you may look at a value - ////See that it is innaccurate and then check it again only to see that it is correct for no discernable reason. - - //var OLDCellRichAfterDebug = cellRange.RichText.Text; - //Assert.AreEqual(OLDCellRich, OLDCellRichAfterDebug); } } [TestMethod] - public void AddingRichTextToFormulasShouldThrow() + public void RtComment() { - using (var pck = OpenPackage("dirtyRT.xlsx")) + using(var p = OpenTemplatePackage("RtWithOldComment.xlsx")) { - var ws = pck.Workbook.Worksheets.Add("richText"); + var ws = p.Workbook.Worksheets[0]; - ws.Cells["A1"].Value = 1001.1d; - ws.Cells["C1"].Formula = "ROUND(A1, 1)"; - ws.Cells["B1"].Formula = "\"My favorite number is: \"&TEXT(ROUND(A1,1),\"#,##0.00;(#,##0.00)\")"; - - //Set richtext on range that has a formula - //This should Throw (or clear Formula) - Assert.Throws(() => ws.Cells["B1"].RichText.Add("My favorite number is: 1001.1")); - - ////This then Results in strange behaviour below when running calculate/IsRichText - //var cellRange = ws.Cells["B1"]; - //var origRT = cellRange.RichText; - - //ws.Calculate(); - //var afterRt1 = cellRange.Text; - //var cellRich = ws.Cells["B1"].RichText.Text; //A FRESH reference to the cell, yielding: 1001,10000 - - - //var OLDCellRich = cellRange.RichText.Text; //Dirty COPY of the cell and its values, yielding: 1001.1\n + var isRichtext = ws.Cells["B3"]; + var text = ws.Cells["B3"].RichText; + var rtComment = ws.Cells["B3"].Comment; + var rtFromComment = rtComment.RichText; - ////This causes the richText of cellRange.RichText to update - //var myFormula = cellRange.IsRichText; - ////So does Just LOOKING at the cellRange variable properties In the debugger. It trigger their Getters. - ////This property changes the actual values of the range when observed in the debugger. - ////This makes debugging harder and highly confusing both to us and end-users as you may look at a value - ////See that it is innaccurate and then check it again only to see that it is correct for no discernable reason. - - //var OLDCellRichAfterDebug = cellRange.RichText.Text; - //Assert.AreEqual(OLDCellRich, OLDCellRichAfterDebug); + Assert.AreNotEqual(text.Text, rtFromComment.Text); } } - - [TestMethod] - public void RichTextShouldNotBecomeDirty() - { - using (var pck = OpenPackage("dirtyRT.xlsx")) - { - var ws = pck.Workbook.Worksheets.Add("richText"); - - ws.Cells["A1"].Value = 1001.1d; - ws.Cells["C1"].Formula = "ROUND(A1, 1)"; - ws.Cells["B1"].Formula = "\"My favorite number is: \"&TEXT(ROUND(A1,1),\"#,##0.00;(#,##0.00)\")"; - - //Set richtext on range that has a formula - //This should clear Formula but does not - ws.Cells["B1"].RichText.Add("My favorite number is: 1001.1", true); - - - //This then Results in strange behaviour below when running calculate/IsRichText - var cellRange = ws.Cells["B1"]; - var origRT = cellRange.RichText; - - ws.Calculate(); - var afterRt1 = cellRange.Text; - var cellRich = ws.Cells["B1"].RichText.Text; //A FRESH reference to the cell, yielding: 1001,10000 - - - var OLDCellRich = cellRange.RichText.Text; //Dirty COPY of the cell and its values, yielding: 1001.1\n - - //This causes the richText of cellRange.RichText to update - var myFormula = cellRange.IsRichText; - //So does Just LOOKING at the cellRange variable properties In the debugger. It trigger their Getters. - //This property changes the actual values of the range when observed in the debugger. - //This makes debugging harder and highly confusing both to us and end-users as you may look at a value - //See that it is innaccurate and then check it again only to see that it is correct for no discernable reason. - - var OLDCellRichAfterDebug = cellRange.RichText.Text; - - Assert.AreEqual(OLDCellRich, OLDCellRichAfterDebug); - Assert.AreNotEqual(cellRich, OLDCellRich); - - var newerRef = ws.Cells["B1"].RichText; - - var refreshedText = "This text should now appear in both pointers"; - - cellRange.RichText.Text = refreshedText; - - Assert.AreEqual(refreshedText, newerRef.Text); - Assert.AreEqual(refreshedText, cellRange.RichText.Text); - Assert.AreEqual(refreshedText, ws.Cells["B1"].RichText.Text); - } - } - } } From 6dbb66eefbbe85bfd209b8a62bd30a15e475197b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossian=20Edstr=C3=B6m?= Date: Mon, 11 May 2026 13:25:52 +0200 Subject: [PATCH 04/12] Commit before this one also added overwrite --- src/EPPlus/Style/RichText/ExcelRichTextCollection.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs index ef587d2e3..8f93343ea 100644 --- a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs +++ b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs @@ -232,12 +232,6 @@ public void Clear() { CheckDeleted(); _list.Clear(); - ////Avoid on is comment since insert does?? - //if (_isComment == false) - //{ - // //If we clear the cells then there is no flag value. - // _cells._worksheet._flags.SetFlagValue(_cells._fromRow, _cells._fromCol, false, CellFlags.RichText); - //} } /// /// Removes an item at the specific index From fa1e997d98989c0e6396a53f9cd041abb74f955a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossian=20Edstr=C3=B6m?= Date: Mon, 11 May 2026 14:57:57 +0200 Subject: [PATCH 05/12] Added other test --- src/EPPlus/ExcelWorksheet.cs | 2 ++ src/EPPlusTest/Style/RichTextTest.cs | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/EPPlus/ExcelWorksheet.cs b/src/EPPlus/ExcelWorksheet.cs index 61a36ea11..e0e2ad498 100644 --- a/src/EPPlus/ExcelWorksheet.cs +++ b/src/EPPlus/ExcelWorksheet.cs @@ -1531,6 +1531,8 @@ internal ExcelRichTextCollection GetRichText(int row, int col, ExcelRangeBase r { textValue = ((ExcelRichTextCollection)textValue).Text; } + + var text = ValueToTextHandler.GetFormattedText(textValue, Workbook, v._styleId, false); if (string.IsNullOrEmpty(text)) { diff --git a/src/EPPlusTest/Style/RichTextTest.cs b/src/EPPlusTest/Style/RichTextTest.cs index f5f35c818..5cbd98e39 100644 --- a/src/EPPlusTest/Style/RichTextTest.cs +++ b/src/EPPlusTest/Style/RichTextTest.cs @@ -370,5 +370,17 @@ public void CheckRichTextProperties() Assert.AreEqual("Arial", C4.RichText[1].FontName); } + + [TestMethod] + public void issue2214() + { + var p = new ExcelPackage(); + var ws = p.Workbook.Worksheets.Add("Sheet1"); + ws.Cells["A1"].Value = 1D; + + Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(double)); + var r = ws.Cells["A1"].RichText; + Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(double)); + } } } From 8193770620d878980f2433d08a40432383ca286c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossian=20Edstr=C3=B6m?= Date: Mon, 11 May 2026 16:49:50 +0200 Subject: [PATCH 06/12] Ensured rtCollection sets and gets cell store correctly --- src/EPPlus/ExcelWorksheet.cs | 9 +++------ .../Style/RichText/ExcelRichTextCollection.cs | 6 +++++- src/EPPlusTest/Style/RichTextTest.cs | 13 +++++++++++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/EPPlus/ExcelWorksheet.cs b/src/EPPlus/ExcelWorksheet.cs index e0e2ad498..51d5bf186 100644 --- a/src/EPPlus/ExcelWorksheet.cs +++ b/src/EPPlus/ExcelWorksheet.cs @@ -1527,23 +1527,20 @@ internal ExcelRichTextCollection GetRichText(int row, int col, ExcelRangeBase r else { object textValue = v._value; - if(textValue != null && typeof(ExcelRichTextCollection) == textValue.GetType()) + if (textValue != null && typeof(ExcelRichTextCollection) == textValue.GetType()) { textValue = ((ExcelRichTextCollection)textValue).Text; } - var text = ValueToTextHandler.GetFormattedText(textValue, Workbook, v._styleId, false); - if (string.IsNullOrEmpty(text)) + if (textValue.GetType() != typeof(string) || string.IsNullOrEmpty(text)) { var item = new ExcelRichTextCollection(Workbook, r); - SetValue(row, col, item); return item; } else { var item = new ExcelRichTextCollection(text, r); - SetValue(row, col, item); return item; } } @@ -2294,7 +2291,7 @@ public object GetValue(int Row, int Column) var v = GetValueInner(Row, Column); if (v != null) { - if (_flags.GetFlagValue(Row, Column, CellFlags.RichText)) + if (Cells[Row, Column].IsRichText) { return (object)Cells[Row, Column].RichText.Text; } diff --git a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs index 8f93343ea..0a1840a12 100644 --- a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs +++ b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs @@ -40,7 +40,7 @@ internal ExcelRichTextCollection(ExcelWorkbook wb, ExcelRangeBase cells) { _wb = wb; _cells = cells; - _cells._worksheet._flags.SetFlagValue(_cells._fromRow, _cells._fromCol, true, CellFlags.RichText); + //_cells._worksheet._flags.SetFlagValue(_cells._fromRow, _cells._fromCol, true, CellFlags.RichText); } internal ExcelRichTextCollection(string s, ExcelRangeBase cells) @@ -219,6 +219,10 @@ public ExcelRichText Insert(int index, string text) { //If not a note then we are a cell and can set the flag. _cells._worksheet._flags.SetFlagValue(_cells._fromRow, _cells._fromCol, true, CellFlags.RichText); + if(_cells.Value != this) + { + _cells.Value = this; + } } } _list.Insert(index, rt); diff --git a/src/EPPlusTest/Style/RichTextTest.cs b/src/EPPlusTest/Style/RichTextTest.cs index 5cbd98e39..fbb43529c 100644 --- a/src/EPPlusTest/Style/RichTextTest.cs +++ b/src/EPPlusTest/Style/RichTextTest.cs @@ -375,12 +375,25 @@ public void CheckRichTextProperties() public void issue2214() { var p = new ExcelPackage(); + + //Ensure that 'getting' any properties does not change type var ws = p.Workbook.Worksheets.Add("Sheet1"); ws.Cells["A1"].Value = 1D; Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(double)); var r = ws.Cells["A1"].RichText; Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(double)); + + var test = r.Text; + Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(double)); + + //Assert that Setting the property does. + r.Text = "Hello"; + + //var cf = ws.Cells["A1"].ConditionalFormatting; + //ws.Cells["A1"].Value = r; + + Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(ExcelRichTextCollection)); } } } From 6f1a420911ac8f854301204cdedbf1f3c4bc4d5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossian=20Edstr=C3=B6m?= Date: Mon, 11 May 2026 17:17:24 +0200 Subject: [PATCH 07/12] Ensured flags as appropriate. Still bugged for copy --- src/EPPlus/ExcelWorksheet.cs | 2 +- .../Style/RichText/ExcelRichTextCollection.cs | 27 +++++++++++-------- src/EPPlusTest/Style/RichTextTest.cs | 9 ++++--- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/EPPlus/ExcelWorksheet.cs b/src/EPPlus/ExcelWorksheet.cs index 51d5bf186..aff51b2f6 100644 --- a/src/EPPlus/ExcelWorksheet.cs +++ b/src/EPPlus/ExcelWorksheet.cs @@ -1533,7 +1533,7 @@ internal ExcelRichTextCollection GetRichText(int row, int col, ExcelRangeBase r } var text = ValueToTextHandler.GetFormattedText(textValue, Workbook, v._styleId, false); - if (textValue.GetType() != typeof(string) || string.IsNullOrEmpty(text)) + if (textValue == null || textValue.GetType() != typeof(string) || string.IsNullOrEmpty(text)) { var item = new ExcelRichTextCollection(Workbook, r); return item; diff --git a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs index 0a1840a12..ea89cb3f2 100644 --- a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs +++ b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs @@ -10,19 +10,20 @@ Date Author Change ************************************************************************************************* 01/27/2020 EPPlus Software AB Initial release EPPlus 5 *************************************************************************************************/ +using OfficeOpenXml.Drawing.Style.Coloring; +using OfficeOpenXml.FormulaParsing.Excel.Functions.DateAndTime; +using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup; +using OfficeOpenXml.FormulaParsing.Excel.Functions.Statistical; +using OfficeOpenXml.FormulaParsing.Excel.Functions.Text; +using OfficeOpenXml.Utils.TypeConversion; +using OfficeOpenXml.Utils.XML; using System; using System.Collections.Generic; +using System.Drawing; +using System.Globalization; using System.Linq; using System.Text; using System.Xml; -using System.Drawing; -using System.Globalization; -using OfficeOpenXml.Drawing.Style.Coloring; -using OfficeOpenXml.FormulaParsing.Excel.Functions.Statistical; -using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup; -using OfficeOpenXml.FormulaParsing.Excel.Functions.Text; -using OfficeOpenXml.Utils.XML; -using OfficeOpenXml.Utils.TypeConversion; namespace OfficeOpenXml.Style { @@ -217,12 +218,16 @@ public ExcelRichText Insert(int index, string text) //If just a note we cannot set rich text flag on the cell itself. if (_isComment == false) { - //If not a note then we are a cell and can set the flag. - _cells._worksheet._flags.SetFlagValue(_cells._fromRow, _cells._fromCol, true, CellFlags.RichText); - if(_cells.Value != this) + //If the range value is not richtext it is now. + //Must set value first in order to not overwrite flags after. + if (_cells.Value != this) { + //var flags = _cells._worksheet._flags; + _cells._worksheet._flags.GetFlagValue(_cells._fromRow, _cells._fromCol, CellFlags.RichText); _cells.Value = this; } + //If not a note then we are a cell and can set the flag. + _cells._worksheet._flags.SetFlagValue(_cells._fromRow, _cells._fromCol, true, CellFlags.RichText); } } _list.Insert(index, rt); diff --git a/src/EPPlusTest/Style/RichTextTest.cs b/src/EPPlusTest/Style/RichTextTest.cs index fbb43529c..c6d42f6ae 100644 --- a/src/EPPlusTest/Style/RichTextTest.cs +++ b/src/EPPlusTest/Style/RichTextTest.cs @@ -386,14 +386,15 @@ public void issue2214() var test = r.Text; Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(double)); + Assert.IsFalse(ws.Cells["A1"].IsRichText); //Assert that Setting the property does. - r.Text = "Hello"; - - //var cf = ws.Cells["A1"].ConditionalFormatting; - //ws.Cells["A1"].Value = r; + string text = "Hello"; + r.Text = text; + Assert.IsTrue(ws.Cells["A1"].IsRichText); Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(ExcelRichTextCollection)); + Assert.AreEqual(text, ((ExcelRichTextCollection)ws.Cells["A1"].Value).Text); } } } From 391c051dd04bed572206b018298f41e8e9fa0d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossian=20Edstr=C3=B6m?= Date: Mon, 11 May 2026 17:26:55 +0200 Subject: [PATCH 08/12] Fixed nessed up if --- src/EPPlus/ExcelWorksheet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EPPlus/ExcelWorksheet.cs b/src/EPPlus/ExcelWorksheet.cs index aff51b2f6..059005787 100644 --- a/src/EPPlus/ExcelWorksheet.cs +++ b/src/EPPlus/ExcelWorksheet.cs @@ -2291,7 +2291,7 @@ public object GetValue(int Row, int Column) var v = GetValueInner(Row, Column); if (v != null) { - if (Cells[Row, Column].IsRichText) + if (_flags.GetFlagValue(Row, Column, CellFlags.RichText) && Cells[Row, Column].IsRichText) { return (object)Cells[Row, Column].RichText.Text; } From dfd9ccec1220011f519cf6ef0a3e2e36240daa55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossian=20Edstr=C3=B6m?= Date: Tue, 12 May 2026 10:22:18 +0200 Subject: [PATCH 09/12] Fixed failing tests+added convert method --- src/EPPlus/ExcelRangeBase.cs | 42 ++++++++++++------- src/EPPlus/ExcelWorksheet.cs | 39 +++++++++++++---- .../Style/RichText/ExcelRichTextCollection.cs | 3 ++ .../Core/Range/RangeRichTextTests.cs | 2 +- src/EPPlusTest/Issues/StylingIssues.cs | 3 +- src/EPPlusTest/Style/RichTextTest.cs | 19 ++++++++- 6 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/EPPlus/ExcelRangeBase.cs b/src/EPPlus/ExcelRangeBase.cs index 25ad1e78f..3fb4a4bf3 100644 --- a/src/EPPlus/ExcelRangeBase.cs +++ b/src/EPPlus/ExcelRangeBase.cs @@ -10,29 +10,31 @@ Date Author Change ************************************************************************************************* 01/27/2020 EPPlus Software AB Initial release EPPlus 5 *************************************************************************************************/ -using System; -using System.Collections.Generic; -using OfficeOpenXml.FormulaParsing; -using OfficeOpenXml.Style; -using System.Globalization; -using System.Collections; -using OfficeOpenXml.Table; -using OfficeOpenXml.DataValidation; +using OfficeOpenXml.CellPictures; using OfficeOpenXml.ConditionalFormatting; -using OfficeOpenXml.FormulaParsing.LexicalAnalysis; using OfficeOpenXml.Core; using OfficeOpenXml.Core.CellStore; using OfficeOpenXml.Core.Worksheet; -using OfficeOpenXml.ThreadedComments; -using OfficeOpenXml.CellPictures; -using OfficeOpenXml.Sorting; +using OfficeOpenXml.DataValidation; using OfficeOpenXml.Export.HtmlExport.Interfaces; +using OfficeOpenXml.FormulaParsing; using OfficeOpenXml.FormulaParsing.Excel.Functions; -using OfficeOpenXml.Utils.TypeConversion; -using OfficeOpenXml.Utils.String; +using OfficeOpenXml.FormulaParsing.Excel.Functions.DateAndTime; +using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup; +using OfficeOpenXml.FormulaParsing.LexicalAnalysis; +using OfficeOpenXml.Sorting; +using OfficeOpenXml.Style; +using OfficeOpenXml.Table; +using OfficeOpenXml.ThreadedComments; using OfficeOpenXml.Utils.Cell; -using static OfficeOpenXml.ExcelWorksheet; +using OfficeOpenXml.Utils.String; +using OfficeOpenXml.Utils.TypeConversion; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; using System.Linq; +using static OfficeOpenXml.ExcelWorksheet; namespace OfficeOpenXml { @@ -1459,6 +1461,16 @@ public ExcelRichTextCollection RichText } } + /// + /// Convert the contents of the top left cell of this range to a richtext string + /// And set the cell value as .RichText + /// + public ExcelRichTextCollection ConvertToRichText() + { + _rtc = _worksheet.ConvertCellValueToRichText(_fromRow, _fromCol, this); + return _rtc; + } + /// /// Returns the comment object of the first cell in the range /// diff --git a/src/EPPlus/ExcelWorksheet.cs b/src/EPPlus/ExcelWorksheet.cs index 059005787..d45a7c1aa 100644 --- a/src/EPPlus/ExcelWorksheet.cs +++ b/src/EPPlus/ExcelWorksheet.cs @@ -1515,10 +1515,12 @@ private void LoadHyperLinks(XmlReader xr) delRelIds.ToList().ForEach(x => Part.DeleteRelationship(x)); } - internal ExcelRichTextCollection GetRichText(int row, int col, ExcelRangeBase r = null) + internal ExcelRichTextCollection ConvertCellValueToRichText(int row, int col, ExcelRangeBase r = null) { var v = GetCoreValueInner(row, col); var isRt = _flags.GetFlagValue(row, col, CellFlags.RichText); + + //If it already is rt then no need to actually convert if (isRt && v._value is ExcelRichTextCollection rtc) { if (rtc._cells == null) rtc._cells = r; @@ -1533,16 +1535,35 @@ internal ExcelRichTextCollection GetRichText(int row, int col, ExcelRangeBase r } var text = ValueToTextHandler.GetFormattedText(textValue, Workbook, v._styleId, false); - if (textValue == null || textValue.GetType() != typeof(string) || string.IsNullOrEmpty(text)) - { - var item = new ExcelRichTextCollection(Workbook, r); - return item; - } - else + var item = new ExcelRichTextCollection(text, r); + SetValue(row, col, item); + + return item; + } + } + + internal ExcelRichTextCollection GetRichText(int row, int col, ExcelRangeBase r = null) + { + var v = GetCoreValueInner(row, col); + var isRt = _flags.GetFlagValue(row, col, CellFlags.RichText); + if (isRt && v._value is ExcelRichTextCollection rtc) + { + if (rtc._cells == null) rtc._cells = r; + return rtc; + } + else + { + object textValue = v._value; + if (textValue != null && typeof(ExcelRichTextCollection) == textValue.GetType()) { - var item = new ExcelRichTextCollection(text, r); - return item; + //This should only really happen if e.g. rich-text from a Note is Set to a cell value + textValue = ((ExcelRichTextCollection)textValue).Text; + var text = ValueToTextHandler.GetFormattedText(textValue, Workbook, v._styleId, false); + var itemRt = new ExcelRichTextCollection(text, r); + return itemRt; } + var item = new ExcelRichTextCollection(Workbook, r); + return item; } } diff --git a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs index ea89cb3f2..78c068710 100644 --- a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs +++ b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs @@ -15,6 +15,7 @@ Date Author Change using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup; using OfficeOpenXml.FormulaParsing.Excel.Functions.Statistical; using OfficeOpenXml.FormulaParsing.Excel.Functions.Text; +using OfficeOpenXml.Utils.String; using OfficeOpenXml.Utils.TypeConversion; using OfficeOpenXml.Utils.XML; using System; @@ -241,6 +242,8 @@ public void Clear() { CheckDeleted(); _list.Clear(); + _cells._worksheet._flags.SetFlagValue(_cells._fromRow, _cells._fromCol, false, CellFlags.RichText); + _cells.Value = string.Empty; } /// /// Removes an item at the specific index diff --git a/src/EPPlusTest/Core/Range/RangeRichTextTests.cs b/src/EPPlusTest/Core/Range/RangeRichTextTests.cs index 03aa3181d..abe7f5d0e 100644 --- a/src/EPPlusTest/Core/Range/RangeRichTextTests.cs +++ b/src/EPPlusTest/Core/Range/RangeRichTextTests.cs @@ -191,7 +191,7 @@ public void VerifyRichTextIsBlankIfAccess() var ws = p.Workbook.Worksheets.Add("Sheet1"); var t = ws.Cells["A1"].RichText.Text; - Assert.AreEqual(string.Empty, ws.Cells["A1"].Value); + Assert.AreEqual(null, ws.Cells["A1"].Value); } } [TestMethod] diff --git a/src/EPPlusTest/Issues/StylingIssues.cs b/src/EPPlusTest/Issues/StylingIssues.cs index 1082c3163..737e22603 100644 --- a/src/EPPlusTest/Issues/StylingIssues.cs +++ b/src/EPPlusTest/Issues/StylingIssues.cs @@ -468,7 +468,8 @@ public void s1005() Assert.IsTrue(origText.Contains("69928453.64000")); ws1.Cells["D8"].Calculate(); - var cellRich = ws1.Cells["D8"].RichText.Text; + + var cellRich = ws1.Cells["D8"].ConvertToRichText().Text; //Verify formatting has changed appropriately for calculated string Assert.IsTrue(cellRich.Contains("0,80")); diff --git a/src/EPPlusTest/Style/RichTextTest.cs b/src/EPPlusTest/Style/RichTextTest.cs index c6d42f6ae..48a2ab335 100644 --- a/src/EPPlusTest/Style/RichTextTest.cs +++ b/src/EPPlusTest/Style/RichTextTest.cs @@ -393,8 +393,23 @@ public void issue2214() r.Text = text; Assert.IsTrue(ws.Cells["A1"].IsRichText); - Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(ExcelRichTextCollection)); - Assert.AreEqual(text, ((ExcelRichTextCollection)ws.Cells["A1"].Value).Text); + Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(string)); + Assert.AreEqual(text, (string)ws.Cells["A1"].Value); + } + + [TestMethod] + public void ConvertCellToRichText() + { + var p = new ExcelPackage(); + var ws = p.Workbook.Worksheets.Add("Sheet1"); + ws.Cells["A1"].Value = 1D; + + ws.Cells["A1"].ConvertToRichText(); + + Assert.IsTrue(ws.Cells["A1"].IsRichText); + Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(string)); + Assert.AreEqual("1", (string)ws.Cells["A1"].Value); + Assert.AreEqual("1", ws.Cells["A1"].RichText.Text); } } } From 71b51d651a00760d260279a4c91e746fb81864c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossian=20Edstr=C3=B6m?= Date: Wed, 13 May 2026 09:29:44 +0200 Subject: [PATCH 10/12] Cleanup - removed unnecesary comments --- src/EPPlus/Style/RichText/ExcelRichTextCollection.cs | 1 - src/EPPlusTest/Issues/ChartIssues.cs | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs index 78c068710..f096c80a8 100644 --- a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs +++ b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs @@ -42,7 +42,6 @@ internal ExcelRichTextCollection(ExcelWorkbook wb, ExcelRangeBase cells) { _wb = wb; _cells = cells; - //_cells._worksheet._flags.SetFlagValue(_cells._fromRow, _cells._fromCol, true, CellFlags.RichText); } internal ExcelRichTextCollection(string s, ExcelRangeBase cells) diff --git a/src/EPPlusTest/Issues/ChartIssues.cs b/src/EPPlusTest/Issues/ChartIssues.cs index 9bdf8d1f9..f717b7351 100644 --- a/src/EPPlusTest/Issues/ChartIssues.cs +++ b/src/EPPlusTest/Issues/ChartIssues.cs @@ -454,8 +454,6 @@ public void s1038() var firstDrawing = drawingsWithinGroupShape[0]; firstDrawing.SetPosition(500, 500); - //drawingsWithinGroupShape[0].Position.Y = 2000; - SaveAndCleanup(package); } From c05bb3aab050ba71fe3103c52b4645812c605b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossian=20Edstr=C3=B6m?= Date: Wed, 13 May 2026 09:35:21 +0200 Subject: [PATCH 11/12] Removed superflous usings --- src/EPPlus/ExcelRangeBase.cs | 4 ---- src/EPPlus/Style/RichText/ExcelRichTextCollection.cs | 7 ------- src/EPPlusTest/Issues/RichDataIssues.cs | 6 ------ 3 files changed, 17 deletions(-) diff --git a/src/EPPlus/ExcelRangeBase.cs b/src/EPPlus/ExcelRangeBase.cs index 3fb4a4bf3..20f66fe12 100644 --- a/src/EPPlus/ExcelRangeBase.cs +++ b/src/EPPlus/ExcelRangeBase.cs @@ -19,8 +19,6 @@ Date Author Change using OfficeOpenXml.Export.HtmlExport.Interfaces; using OfficeOpenXml.FormulaParsing; using OfficeOpenXml.FormulaParsing.Excel.Functions; -using OfficeOpenXml.FormulaParsing.Excel.Functions.DateAndTime; -using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup; using OfficeOpenXml.FormulaParsing.LexicalAnalysis; using OfficeOpenXml.Sorting; using OfficeOpenXml.Style; @@ -33,8 +31,6 @@ Date Author Change using System.Collections; using System.Collections.Generic; using System.Globalization; -using System.Linq; -using static OfficeOpenXml.ExcelWorksheet; namespace OfficeOpenXml { diff --git a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs index f096c80a8..657ccdb9d 100644 --- a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs +++ b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs @@ -10,19 +10,12 @@ Date Author Change ************************************************************************************************* 01/27/2020 EPPlus Software AB Initial release EPPlus 5 *************************************************************************************************/ -using OfficeOpenXml.Drawing.Style.Coloring; -using OfficeOpenXml.FormulaParsing.Excel.Functions.DateAndTime; -using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup; -using OfficeOpenXml.FormulaParsing.Excel.Functions.Statistical; -using OfficeOpenXml.FormulaParsing.Excel.Functions.Text; -using OfficeOpenXml.Utils.String; using OfficeOpenXml.Utils.TypeConversion; using OfficeOpenXml.Utils.XML; using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; -using System.Linq; using System.Text; using System.Xml; diff --git a/src/EPPlusTest/Issues/RichDataIssues.cs b/src/EPPlusTest/Issues/RichDataIssues.cs index 3de76fa64..53b120faa 100644 --- a/src/EPPlusTest/Issues/RichDataIssues.cs +++ b/src/EPPlusTest/Issues/RichDataIssues.cs @@ -1,11 +1,5 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using OfficeOpenXml; -using OfficeOpenXml.Style; -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Text; namespace EPPlusTest.Issues { From ca4141ff4c6e691d1b725bf05ccdb7e91294ada2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossian=20Edstr=C3=B6m?= Date: Wed, 13 May 2026 10:58:06 +0200 Subject: [PATCH 12/12] added patch notes --- docs/articles/breakingchanges.md | 7 ++++++- docs/articles/fixedissues.md | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/articles/breakingchanges.md b/docs/articles/breakingchanges.md index 89a45fcf1..d6abb22c6 100644 --- a/docs/articles/breakingchanges.md +++ b/docs/articles/breakingchanges.md @@ -215,4 +215,9 @@ Renaming worksheet's will now change the formula correctly to include single quo `ExcelColor.Tint` from `decimal` to `double`. ### 8.0.2 -* Removed base class from ExcelVmlDrawingPosition and with that the Load, UpdateXml methods and the RowOff and ColOff properties as they were duplicates. \ No newline at end of file +* Removed base class from ExcelVmlDrawingPosition and with that the Load, UpdateXml methods and the RowOff and ColOff properties as they were duplicates. + +### 8.5.5 +* `ws.Cells["A1"].RichText` no longer sets cells with `null` to `string.empty` +* .RichText no longer sets the cell or contents to be RichText automatically. + This is instead done when properties such as; `.Text`, `.Add` or `.Insert` are set on the .RichText property. \ No newline at end of file diff --git a/docs/articles/fixedissues.md b/docs/articles/fixedissues.md index 1046e87a8..57131a563 100644 --- a/docs/articles/fixedissues.md +++ b/docs/articles/fixedissues.md @@ -1,4 +1,11 @@ # Features / Fixed issues - EPPlus 8 + +## Version 8.5.5 +### Minor Features +* Ranges can now convert their values to richText via ´ConvertToRichText()´ e.g. ´ws.Cells["A1"].ConvertToRichText()´ +### Fixed issues +* Several issues related to RichText in ranges. Simply looking at the .RichText attribute no longer changes the cell value. Setting a propert e.g. ´range.RichText.Text = "Hi"´ or using ConvertToRichText() actually changes the value. + ## Version 8.5.4 ### Minor Features * Added ´IncludeInHtmlOnly´ option to the ´ePictureInclude´ enum. This allows the HTML Exporter to include pictures directly in the HTML output rather than in the CSS.