Skip to content

Commit 773225e

Browse files
authored
Fix/i2281 (#2348)
* Added graphicframe name fallback and child pos * Ensured getter does not update collection * Added ifs for comments * Commit before this one also added overwrite * Added other test * Ensured rtCollection sets and gets cell store correctly * Ensured flags as appropriate. Still bugged for copy * Fixed nessed up if * Fixed failing tests+added convert method * Cleanup - removed unnecesary comments * Removed superflous usings * added patch notes
1 parent de607e9 commit 773225e

10 files changed

Lines changed: 182 additions & 48 deletions

File tree

docs/articles/breakingchanges.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,4 +215,9 @@ Renaming worksheet's will now change the formula correctly to include single quo
215215
`ExcelColor.Tint` from `decimal` to `double`.
216216

217217
### 8.0.2
218-
* Removed base class from ExcelVmlDrawingPosition and with that the Load, UpdateXml methods and the RowOff and ColOff properties as they were duplicates.
218+
* Removed base class from ExcelVmlDrawingPosition and with that the Load, UpdateXml methods and the RowOff and ColOff properties as they were duplicates.
219+
220+
### 8.5.5
221+
* `ws.Cells["A1"].RichText` no longer sets cells with `null` to `string.empty`
222+
* .RichText no longer sets the cell or contents to be RichText automatically.
223+
This is instead done when properties such as; `.Text`, `.Add` or `.Insert` are set on the .RichText property.

docs/articles/fixedissues.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
# Features / Fixed issues - EPPlus 8
2+
3+
## Version 8.5.5
4+
### Minor Features
5+
* Ranges can now convert their values to richText via ´ConvertToRichText()´ e.g. ´ws.Cells["A1"].ConvertToRichText()´
6+
### Fixed issues
7+
* 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.
8+
29
## Version 8.5.4
310
### Minor Features
411
* 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.

src/EPPlus/ExcelRangeBase.cs

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,27 @@ Date Author Change
1010
*************************************************************************************************
1111
01/27/2020 EPPlus Software AB Initial release EPPlus 5
1212
*************************************************************************************************/
13-
using System;
14-
using System.Collections.Generic;
15-
using OfficeOpenXml.FormulaParsing;
16-
using OfficeOpenXml.Style;
17-
using System.Globalization;
18-
using System.Collections;
19-
using OfficeOpenXml.Table;
20-
using OfficeOpenXml.DataValidation;
13+
using OfficeOpenXml.CellPictures;
2114
using OfficeOpenXml.ConditionalFormatting;
22-
using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
2315
using OfficeOpenXml.Core;
2416
using OfficeOpenXml.Core.CellStore;
2517
using OfficeOpenXml.Core.Worksheet;
26-
using OfficeOpenXml.ThreadedComments;
27-
using OfficeOpenXml.CellPictures;
28-
using OfficeOpenXml.Sorting;
18+
using OfficeOpenXml.DataValidation;
2919
using OfficeOpenXml.Export.HtmlExport.Interfaces;
20+
using OfficeOpenXml.FormulaParsing;
3021
using OfficeOpenXml.FormulaParsing.Excel.Functions;
31-
using OfficeOpenXml.Utils.TypeConversion;
32-
using OfficeOpenXml.Utils.String;
22+
using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
23+
using OfficeOpenXml.Sorting;
24+
using OfficeOpenXml.Style;
25+
using OfficeOpenXml.Table;
26+
using OfficeOpenXml.ThreadedComments;
3327
using OfficeOpenXml.Utils.Cell;
34-
using static OfficeOpenXml.ExcelWorksheet;
35-
using System.Linq;
28+
using OfficeOpenXml.Utils.String;
29+
using OfficeOpenXml.Utils.TypeConversion;
30+
using System;
31+
using System.Collections;
32+
using System.Collections.Generic;
33+
using System.Globalization;
3634

3735
namespace OfficeOpenXml
3836
{
@@ -1330,8 +1328,10 @@ public bool IsRichText
13301328
var isRt = _worksheet._flags.GetFlagValue(_fromRow, _fromCol, CellFlags.RichText);
13311329
if (isRt)
13321330
{
1333-
_rtc = _worksheet.GetRichText(_fromRow, _fromCol, this);
1334-
return _rtc.Count > 0;
1331+
//Do not update _rtc. This is a boolean getter.
1332+
//It should not set any values even if they diff.
1333+
var couldBeEmptyRT = _worksheet.GetRichText(_fromRow, _fromCol, this);
1334+
return couldBeEmptyRT.Count > 0;
13351335
}
13361336
return isRt;
13371337
}
@@ -1457,6 +1457,16 @@ public ExcelRichTextCollection RichText
14571457
}
14581458
}
14591459

1460+
/// <summary>
1461+
/// Convert the contents of the top left cell of this range to a richtext string
1462+
/// And set the cell value as .RichText
1463+
/// </summary>
1464+
public ExcelRichTextCollection ConvertToRichText()
1465+
{
1466+
_rtc = _worksheet.ConvertCellValueToRichText(_fromRow, _fromCol, this);
1467+
return _rtc;
1468+
}
1469+
14601470
/// <summary>
14611471
/// Returns the comment object of the first cell in the range
14621472
/// </summary>

src/EPPlus/ExcelWorksheet.cs

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,30 +1515,55 @@ private void LoadHyperLinks(XmlReader xr)
15151515
delRelIds.ToList().ForEach(x => Part.DeleteRelationship(x));
15161516
}
15171517

1518-
internal ExcelRichTextCollection GetRichText(int row, int col, ExcelRangeBase r = null)
1518+
internal ExcelRichTextCollection ConvertCellValueToRichText(int row, int col, ExcelRangeBase r = null)
15191519
{
15201520
var v = GetCoreValueInner(row, col);
15211521
var isRt = _flags.GetFlagValue(row, col, CellFlags.RichText);
1522+
1523+
//If it already is rt then no need to actually convert
15221524
if (isRt && v._value is ExcelRichTextCollection rtc)
15231525
{
15241526
if (rtc._cells == null) rtc._cells = r;
15251527
return rtc;
15261528
}
15271529
else
15281530
{
1529-
var text = ValueToTextHandler.GetFormattedText(v._value, Workbook, v._styleId, false);
1530-
if (string.IsNullOrEmpty(text))
1531+
object textValue = v._value;
1532+
if (textValue != null && typeof(ExcelRichTextCollection) == textValue.GetType())
15311533
{
1532-
var item = new ExcelRichTextCollection(Workbook, r);
1533-
SetValue(row, col, item);
1534-
return item;
1534+
textValue = ((ExcelRichTextCollection)textValue).Text;
15351535
}
1536-
else
1536+
1537+
var text = ValueToTextHandler.GetFormattedText(textValue, Workbook, v._styleId, false);
1538+
var item = new ExcelRichTextCollection(text, r);
1539+
SetValue(row, col, item);
1540+
1541+
return item;
1542+
}
1543+
}
1544+
1545+
internal ExcelRichTextCollection GetRichText(int row, int col, ExcelRangeBase r = null)
1546+
{
1547+
var v = GetCoreValueInner(row, col);
1548+
var isRt = _flags.GetFlagValue(row, col, CellFlags.RichText);
1549+
if (isRt && v._value is ExcelRichTextCollection rtc)
1550+
{
1551+
if (rtc._cells == null) rtc._cells = r;
1552+
return rtc;
1553+
}
1554+
else
1555+
{
1556+
object textValue = v._value;
1557+
if (textValue != null && typeof(ExcelRichTextCollection) == textValue.GetType())
15371558
{
1538-
var item = new ExcelRichTextCollection(text, r);
1539-
SetValue(row, col, item);
1540-
return item;
1559+
//This should only really happen if e.g. rich-text from a Note is Set to a cell value
1560+
textValue = ((ExcelRichTextCollection)textValue).Text;
1561+
var text = ValueToTextHandler.GetFormattedText(textValue, Workbook, v._styleId, false);
1562+
var itemRt = new ExcelRichTextCollection(text, r);
1563+
return itemRt;
15411564
}
1565+
var item = new ExcelRichTextCollection(Workbook, r);
1566+
return item;
15421567
}
15431568
}
15441569

@@ -2287,7 +2312,7 @@ public object GetValue(int Row, int Column)
22872312
var v = GetValueInner(Row, Column);
22882313
if (v != null)
22892314
{
2290-
if (_flags.GetFlagValue(Row, Column, CellFlags.RichText))
2315+
if (_flags.GetFlagValue(Row, Column, CellFlags.RichText) && Cells[Row, Column].IsRichText)
22912316
{
22922317
return (object)Cells[Row, Column].RichText.Text;
22932318
}

src/EPPlus/Style/RichText/ExcelRichTextCollection.cs

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,14 @@ Date Author Change
1010
*************************************************************************************************
1111
01/27/2020 EPPlus Software AB Initial release EPPlus 5
1212
*************************************************************************************************/
13+
using OfficeOpenXml.Utils.TypeConversion;
14+
using OfficeOpenXml.Utils.XML;
1315
using System;
1416
using System.Collections.Generic;
15-
using System.Linq;
16-
using System.Text;
17-
using System.Xml;
1817
using System.Drawing;
1918
using System.Globalization;
20-
using OfficeOpenXml.Drawing.Style.Coloring;
21-
using OfficeOpenXml.FormulaParsing.Excel.Functions.Statistical;
22-
using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
23-
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
24-
using OfficeOpenXml.Utils.XML;
25-
using OfficeOpenXml.Utils.TypeConversion;
19+
using System.Text;
20+
using System.Xml;
2621

2722
namespace OfficeOpenXml.Style
2823
{
@@ -40,7 +35,6 @@ internal ExcelRichTextCollection(ExcelWorkbook wb, ExcelRangeBase cells)
4035
{
4136
_wb = wb;
4237
_cells = cells;
43-
_cells._worksheet._flags.SetFlagValue(_cells._fromRow, _cells._fromCol, true, CellFlags.RichText);
4438
}
4539

4640
internal ExcelRichTextCollection(string s, ExcelRangeBase cells)
@@ -162,6 +156,15 @@ public ExcelRichText Insert(int index, string text)
162156
{
163157
CheckDeleted();
164158
if (text == null) throw new ArgumentException("Text can't be null", "text");
159+
160+
//If just a note we can't clear formulas on the cell itself.
161+
if (_isComment == false)
162+
{
163+
//We MUST clear formulas before setting richtext
164+
//To ensure calculate does not create missmatch between formula and richtext.
165+
_cells.ClearFormulas();
166+
}
167+
165168
var rt = new ExcelRichText(text, this);
166169
rt.PreserveSpace = true;
167170
int prevIndex = 0;
@@ -204,8 +207,19 @@ public ExcelRichText Insert(int index, string text)
204207
{
205208
rt.Color = Color.FromArgb(hex);
206209
}
210+
211+
//If just a note we cannot set rich text flag on the cell itself.
207212
if (_isComment == false)
208213
{
214+
//If the range value is not richtext it is now.
215+
//Must set value first in order to not overwrite flags after.
216+
if (_cells.Value != this)
217+
{
218+
//var flags = _cells._worksheet._flags;
219+
_cells._worksheet._flags.GetFlagValue(_cells._fromRow, _cells._fromCol, CellFlags.RichText);
220+
_cells.Value = this;
221+
}
222+
//If not a note then we are a cell and can set the flag.
209223
_cells._worksheet._flags.SetFlagValue(_cells._fromRow, _cells._fromCol, true, CellFlags.RichText);
210224
}
211225
}
@@ -220,6 +234,8 @@ public void Clear()
220234
{
221235
CheckDeleted();
222236
_list.Clear();
237+
_cells._worksheet._flags.SetFlagValue(_cells._fromRow, _cells._fromCol, false, CellFlags.RichText);
238+
_cells.Value = string.Empty;
223239
}
224240
/// <summary>
225241
/// Removes an item at the specific index

src/EPPlusTest/Core/Range/RangeRichTextTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ public void VerifyRichTextIsBlankIfAccess()
191191
var ws = p.Workbook.Worksheets.Add("Sheet1");
192192
var t = ws.Cells["A1"].RichText.Text;
193193

194-
Assert.AreEqual(string.Empty, ws.Cells["A1"].Value);
194+
Assert.AreEqual(null, ws.Cells["A1"].Value);
195195
}
196196
}
197197
[TestMethod]

src/EPPlusTest/Issues/ChartIssues.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,8 +454,6 @@ public void s1038()
454454
var firstDrawing = drawingsWithinGroupShape[0];
455455

456456
firstDrawing.SetPosition(500, 500);
457-
//drawingsWithinGroupShape[0].Position.Y = 2000;
458-
459457

460458
SaveAndCleanup(package);
461459
}

src/EPPlusTest/Issues/RichDataIssues.cs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
using Microsoft.VisualStudio.TestTools.UnitTesting;
2-
using System;
3-
using System.Collections.Generic;
4-
using System.Linq;
5-
using System.Text;
62
using OfficeOpenXml;
73

84
namespace EPPlusTest.Issues
@@ -85,5 +81,40 @@ public void VerifyCalcError()
8581
SaveAndCleanup(p);
8682
}
8783
}
84+
85+
[TestMethod]
86+
public void AddingRichTextToFormulasShouldOverwrite()
87+
{
88+
using (var pck = OpenPackage("dirtyRT.xlsx", true))
89+
{
90+
var ws = pck.Workbook.Worksheets.Add("richText");
91+
92+
ws.Cells["A1"].Value = 1001.1d;
93+
ws.Cells["C1"].Formula = "ROUND(A1, 1)";
94+
ws.Cells["B1"].Formula = "\"My favorite number is: \"&TEXT(ROUND(A1,1),\"#,##0.00;(#,##0.00)\")";
95+
96+
ws.Cells["B1"].RichText.Add("My favorite number is: 1001.1");
97+
98+
var myFormula = ws.Cells["B1"].Formula;
99+
100+
Assert.IsTrue(string.IsNullOrEmpty(myFormula));
101+
}
102+
}
103+
104+
[TestMethod]
105+
public void RtComment()
106+
{
107+
using(var p = OpenTemplatePackage("RtWithOldComment.xlsx"))
108+
{
109+
var ws = p.Workbook.Worksheets[0];
110+
111+
var isRichtext = ws.Cells["B3"];
112+
var text = ws.Cells["B3"].RichText;
113+
var rtComment = ws.Cells["B3"].Comment;
114+
var rtFromComment = rtComment.RichText;
115+
116+
Assert.AreNotEqual(text.Text, rtFromComment.Text);
117+
}
118+
}
88119
}
89120
}

src/EPPlusTest/Issues/StylingIssues.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,8 @@ public void s1005()
468468
Assert.IsTrue(origText.Contains("69928453.64000"));
469469

470470
ws1.Cells["D8"].Calculate();
471-
var cellRich = ws1.Cells["D8"].RichText.Text;
471+
472+
var cellRich = ws1.Cells["D8"].ConvertToRichText().Text;
472473

473474
//Verify formatting has changed appropriately for calculated string
474475
Assert.IsTrue(cellRich.Contains("0,80"));

src/EPPlusTest/Style/RichTextTest.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,5 +370,46 @@ public void CheckRichTextProperties()
370370
Assert.AreEqual("Arial", C4.RichText[1].FontName);
371371

372372
}
373+
374+
[TestMethod]
375+
public void issue2214()
376+
{
377+
var p = new ExcelPackage();
378+
379+
//Ensure that 'getting' any properties does not change type
380+
var ws = p.Workbook.Worksheets.Add("Sheet1");
381+
ws.Cells["A1"].Value = 1D;
382+
383+
Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(double));
384+
var r = ws.Cells["A1"].RichText;
385+
Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(double));
386+
387+
var test = r.Text;
388+
Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(double));
389+
Assert.IsFalse(ws.Cells["A1"].IsRichText);
390+
391+
//Assert that Setting the property does.
392+
string text = "Hello";
393+
r.Text = text;
394+
395+
Assert.IsTrue(ws.Cells["A1"].IsRichText);
396+
Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(string));
397+
Assert.AreEqual(text, (string)ws.Cells["A1"].Value);
398+
}
399+
400+
[TestMethod]
401+
public void ConvertCellToRichText()
402+
{
403+
var p = new ExcelPackage();
404+
var ws = p.Workbook.Worksheets.Add("Sheet1");
405+
ws.Cells["A1"].Value = 1D;
406+
407+
ws.Cells["A1"].ConvertToRichText();
408+
409+
Assert.IsTrue(ws.Cells["A1"].IsRichText);
410+
Assert.IsInstanceOfType(ws.Cells["A1"].Value, typeof(string));
411+
Assert.AreEqual("1", (string)ws.Cells["A1"].Value);
412+
Assert.AreEqual("1", ws.Cells["A1"].RichText.Text);
413+
}
373414
}
374415
}

0 commit comments

Comments
 (0)