diff --git a/docs/articles/breakingchanges.md b/docs/articles/breakingchanges.md
index 89a45fcf1c..d6abb22c67 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 1046e87a84..57131a563e 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.
diff --git a/src/EPPlus/ExcelRangeBase.cs b/src/EPPlus/ExcelRangeBase.cs
index a681380e37..20f66fe12b 100644
--- a/src/EPPlus/ExcelRangeBase.cs
+++ b/src/EPPlus/ExcelRangeBase.cs
@@ -10,29 +10,27 @@ 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.LexicalAnalysis;
+using OfficeOpenXml.Sorting;
+using OfficeOpenXml.Style;
+using OfficeOpenXml.Table;
+using OfficeOpenXml.ThreadedComments;
using OfficeOpenXml.Utils.Cell;
-using static OfficeOpenXml.ExcelWorksheet;
-using System.Linq;
+using OfficeOpenXml.Utils.String;
+using OfficeOpenXml.Utils.TypeConversion;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
namespace OfficeOpenXml
{
@@ -1330,8 +1328,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;
}
@@ -1457,6 +1457,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 f0ebe3dec3..d45a7c1aa5 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;
@@ -1526,19 +1528,42 @@ internal ExcelRichTextCollection GetRichText(int row, int col, ExcelRangeBase r
}
else
{
- var text = ValueToTextHandler.GetFormattedText(v._value, Workbook, v._styleId, false);
- if (string.IsNullOrEmpty(text))
+ object textValue = v._value;
+ if (textValue != null && typeof(ExcelRichTextCollection) == textValue.GetType())
{
- var item = new ExcelRichTextCollection(Workbook, r);
- SetValue(row, col, item);
- return item;
+ textValue = ((ExcelRichTextCollection)textValue).Text;
}
- else
+
+ var text = ValueToTextHandler.GetFormattedText(textValue, Workbook, v._styleId, false);
+ 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);
- SetValue(row, col, item);
- 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;
}
}
@@ -2287,7 +2312,7 @@ public object GetValue(int Row, int Column)
var v = GetValueInner(Row, Column);
if (v != null)
{
- if (_flags.GetFlagValue(Row, Column, CellFlags.RichText))
+ if (_flags.GetFlagValue(Row, Column, CellFlags.RichText) && 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 de032100a6..657ccdb9df 100644
--- a/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs
+++ b/src/EPPlus/Style/RichText/ExcelRichTextCollection.cs
@@ -10,19 +10,14 @@ Date Author Change
*************************************************************************************************
01/27/2020 EPPlus Software AB Initial release EPPlus 5
*************************************************************************************************/
+using OfficeOpenXml.Utils.TypeConversion;
+using OfficeOpenXml.Utils.XML;
using System;
using System.Collections.Generic;
-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;
+using System.Text;
+using System.Xml;
namespace OfficeOpenXml.Style
{
@@ -40,7 +35,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)
@@ -162,6 +156,15 @@ public ExcelRichText Insert(int index, string text)
{
CheckDeleted();
if (text == null) throw new ArgumentException("Text can't be null", "text");
+
+ //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;
@@ -204,8 +207,19 @@ 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 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);
}
}
@@ -220,6 +234,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 03aa3181d0..abe7f5d0e5 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/ChartIssues.cs b/src/EPPlusTest/Issues/ChartIssues.cs
index 9bdf8d1f94..f717b73517 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);
}
diff --git a/src/EPPlusTest/Issues/RichDataIssues.cs b/src/EPPlusTest/Issues/RichDataIssues.cs
index d3e14bab44..53b120faa1 100644
--- a/src/EPPlusTest/Issues/RichDataIssues.cs
+++ b/src/EPPlusTest/Issues/RichDataIssues.cs
@@ -1,8 +1,4 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using OfficeOpenXml;
namespace EPPlusTest.Issues
@@ -85,5 +81,40 @@ public void VerifyCalcError()
SaveAndCleanup(p);
}
}
+
+ [TestMethod]
+ public void AddingRichTextToFormulasShouldOverwrite()
+ {
+ using (var pck = OpenPackage("dirtyRT.xlsx", true))
+ {
+ 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));
+ }
+ }
+
+ [TestMethod]
+ public void RtComment()
+ {
+ using(var p = OpenTemplatePackage("RtWithOldComment.xlsx"))
+ {
+ var ws = p.Workbook.Worksheets[0];
+
+ var isRichtext = ws.Cells["B3"];
+ var text = ws.Cells["B3"].RichText;
+ var rtComment = ws.Cells["B3"].Comment;
+ var rtFromComment = rtComment.RichText;
+
+ Assert.AreNotEqual(text.Text, rtFromComment.Text);
+ }
+ }
}
}
diff --git a/src/EPPlusTest/Issues/StylingIssues.cs b/src/EPPlusTest/Issues/StylingIssues.cs
index 1082c31630..737e22603a 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 f5f35c8181..48a2ab3355 100644
--- a/src/EPPlusTest/Style/RichTextTest.cs
+++ b/src/EPPlusTest/Style/RichTextTest.cs
@@ -370,5 +370,46 @@ public void CheckRichTextProperties()
Assert.AreEqual("Arial", C4.RichText[1].FontName);
}
+
+ [TestMethod]
+ 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.IsFalse(ws.Cells["A1"].IsRichText);
+
+ //Assert that Setting the property does.
+ string text = "Hello";
+ r.Text = text;
+
+ Assert.IsTrue(ws.Cells["A1"].IsRichText);
+ 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);
+ }
}
}