Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions src/EPPlus/Drawing/ExcelDrawing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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":
Expand All @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 3 additions & 1 deletion src/EPPlus/Drawing/ExcelGroupShape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ private void AddDrawings()
_groupDrawings = new List<ExcelDrawing>();
foreach (XmlNode node in _topNode.ChildNodes)
{

if (node.LocalName != "nvGrpSpPr" && node.LocalName != "grpSpPr")
{
var grpDraw = ExcelDrawing.GetDrawingFromNode(_parent._drawings, node, (XmlElement)node, _parent, _drawingsCollectionType);
Expand Down Expand Up @@ -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);
}
}
Expand Down
48 changes: 31 additions & 17 deletions src/EPPlus/ExcelRangeBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -1330,8 +1332,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;
}
Expand Down Expand Up @@ -1457,6 +1461,16 @@ public ExcelRichTextCollection RichText
}
}

/// <summary>
/// Convert the contents of the top left cell of this range to a richtext string
/// And set the cell value as .RichText
/// </summary>
public ExcelRichTextCollection ConvertToRichText()
{
_rtc = _worksheet.ConvertCellValueToRichText(_fromRow, _fromCol, this);
return _rtc;
}

/// <summary>
/// Returns the comment object of the first cell in the range
/// </summary>
Expand Down
47 changes: 36 additions & 11 deletions src/EPPlus/ExcelWorksheet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1515,30 +1515,55 @@ 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;
return rtc;
}
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;
}
}

Expand Down Expand Up @@ -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;
}
Expand Down
42 changes: 33 additions & 9 deletions src/EPPlus/Style/RichText/ExcelRichTextCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,21 @@ 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;
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
{
Expand All @@ -40,7 +42,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)
Expand Down Expand Up @@ -162,6 +164,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;
Expand Down Expand Up @@ -204,8 +215,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);
}
}
Expand All @@ -220,6 +242,8 @@ public void Clear()
{
CheckDeleted();
_list.Clear();
_cells._worksheet._flags.SetFlagValue(_cells._fromRow, _cells._fromCol, false, CellFlags.RichText);
_cells.Value = string.Empty;
}
/// <summary>
/// Removes an item at the specific index
Expand Down
2 changes: 1 addition & 1 deletion src/EPPlusTest/Core/Range/RangeRichTextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
8 changes: 7 additions & 1 deletion src/EPPlusTest/Issues/ChartIssues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
39 changes: 38 additions & 1 deletion src/EPPlusTest/Issues/RichDataIssues.cs
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down Expand Up @@ -85,5 +87,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);
}
}
}
}
3 changes: 2 additions & 1 deletion src/EPPlusTest/Issues/StylingIssues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand Down
Loading
Loading