Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c56d90c
standalones inconclusive remote pass local
OssianEPPlus Sep 22, 2026
5ecece8
Fixed text centering and Pie shape being strange
OssianEPPlus Sep 23, 2026
823e2eb
Fixed Doubled Top Margin on shapes
OssianEPPlus Sep 23, 2026
3d10ad5
Added class names as identifiers
OssianEPPlus Sep 23, 2026
dd07c12
Grouped up TickMarks and GridLines
OssianEPPlus Sep 23, 2026
c5720be
Added organizational groups for multiple chart items
OssianEPPlus Sep 23, 2026
55e8f61
Removed unnecsary comments
OssianEPPlus Sep 23, 2026
2dfd327
Added settings for running Test Explorer in Docker Desktop
OssianEPPlus Sep 28, 2026
8aad8fc
Merge branch 'develop9' into fix/remote-docker-debugging
OssianEPPlus Sep 28, 2026
6ece25e
Merge branch 'bug/i2541' into fix/remote-docker-debugging
OssianEPPlus Sep 28, 2026
cb08ce3
Fixed Infinte Loop on linux in Resources.Designer
OssianEPPlus Sep 28, 2026
e9b48fc
Fixed more infinte loops
OssianEPPlus Sep 28, 2026
5cdcb42
More instances of path directory char
OssianEPPlus Sep 28, 2026
17f6dee
More of the same path issue
OssianEPPlus Sep 28, 2026
cb065d4
:Merge branch 'develop9' into fix/remote-docker-debugging
OssianEPPlus Sep 28, 2026
ef136f1
Merge with dev9
OssianEPPlus Sep 28, 2026
2a04bcd
Other area with path issue
OssianEPPlus Sep 28, 2026
b979581
Path issue CF_ColorScale
OssianEPPlus Sep 28, 2026
c2d69b5
Path issue databarTests
OssianEPPlus Sep 28, 2026
0c85f7a
path issue IconSetTests
OssianEPPlus Sep 28, 2026
7d8ea00
Test fixes for AppVeyor build
JanKallman Sep 28, 2026
8beac8c
More path issues + culture "us-en" to "en" issue
OssianEPPlus Sep 28, 2026
9bd2d96
File directory issue + extra
OssianEPPlus Sep 28, 2026
7f47c31
Fixed several NewLine diffs
OssianEPPlus Sep 28, 2026
70653e3
Fixed GetRelativeFile DirectorySeparator
OssianEPPlus Sep 28, 2026
2b90a8a
Fixed failing tests
JanKallman Sep 29, 2026
032313a
Add path handlings
OssianEPPlus Sep 29, 2026
d6ed013
Merge branch 'fix/remote-docker-debugging' into fix/appveyor-tests
JanKallman Sep 29, 2026
ca3dc4c
Merge and fix of failing tests
JanKallman Sep 29, 2026
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
1 change: 0 additions & 1 deletion src/.runsettings
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
<RunSettings>
<!-- Configurations that affect the Test Framework -->
<RunConfiguration>
<MaxCpuCount>1</MaxCpuCount>
<DisableAppDomain>True</DisableAppDomain>
<!-- Path relative to solution directory -->
<ResultsDirectory>.\TestResults</ResultsDirectory>
Expand Down
16 changes: 16 additions & 0 deletions src/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#Get image that works for e.g. net481
FROM mcr.microsoft.com/dotnet/aspnet:10.0
#Get image that works for net8,net9 etc.
FROM mcr.microsoft.com/dotnet/sdk:10.0

#Install mono as dotnet/sdk:10.0 fails otherwise.
#This is Strange as sdk:9.0 and 8.0 don't seem to require this.
#Look into removing this later.
#Anyone can test removing it locally by commenting this line out but the whole test project will fail to run properly without it as of 2026-09-28
RUN apt-get update && apt-get install -y mono-complete

#This Requires you to have Docker Desktop downloaded and open.
#Create the Visual Studio Debug Shell image.
#Essentially Microsoft has a live link to a shell-script that generates the "vsut_dockerfile" image
RUN wget https://aka.ms/getvsdbgsh && \
sh getvsdbgsh -v latest -l /vsdbg
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

namespace EPPlus.Export.ImageRenderer.Tests.DrawingShapeRenderer
{
[TestClass, Ignore("Some small differences in the asserts when running in Github actions, investigation needed.")]
[TestClass]
public class SvgStandAloneTests : TestBase
{

Expand Down Expand Up @@ -123,13 +123,19 @@ private void GenerateTextBodyFile(string fileName, GroupRenderItem baseGroup, Sv

private SvgTextBodyRenderItem GenerateTextBody(GroupRenderItem baseGroup)
{
var engine = new OpenTypeFontEngine(x => x.SearchSystemDirectories = false);
if (engine.GetFontAvailability("Archivo Narrow") == FontAvailability.NotFound)
var engine = new OpenTypeFontEngine(x =>
{
x.SearchSystemDirectories = true;
});
if (engine.GetFontAvailability("Aptos Narrow") == FontAvailability.NotFound)
{
Assert.Inconclusive("Font not found. This is expected behaviour on web.");
}

var renderContext = new RenderContext(() => engine);
var textBody = new SvgTextBodyRenderItem(renderContext, baseGroup.Bounds, true);
//Aptos Narrow is Default font for a text that does not define its own font'
//As we do not have it, this fallbacks to archivo narrow and then to Old Metrics for Aptos
var paragraph = textBody.AddParagraph("Hello");

paragraph.AddText(" There");
Expand Down Expand Up @@ -242,9 +248,17 @@ public void SvgTextBodyVerticalAlignmentGenerated()

double delta = 0.001;

Assert.AreEqual(180.04052829742432d, textBody.Bounds.Top, delta);

GenerateSvgFile("textBodyAlignVCenter", baseGroup.Bounds, baseGroup);

//This appears to be entirely accurate when comparing to excel
Assert.AreEqual(215.02026414871216, textBody.Bounds.Top, delta);
//This is our old expected value.
//Assert.AreEqual(180.04052829742432d, textBody.Bounds.Top, delta);
//Interestingly 500/2 = 250
//and 250 - 35 = 215
//And 215 - 35 = 180
//Seems we may have been adjusting for something by taking the full height of the text rather than just half.
//Possibly this is now handled by the y of the first tSpan
}

[TestMethod]
Expand Down Expand Up @@ -279,9 +293,16 @@ private RenderTextbox GenerateTextBox(out GroupRenderItem group)
group = GenerateGroupRenderItem();

var textbox = new RenderTextbox(group.Bounds, 500d, 500d);
var engine = new OpenTypeFontEngine(x => x.SearchSystemDirectories = false);
var engine = new OpenTypeFontEngine(x => x.SearchSystemDirectories = true);
var rc = new RenderContext(() => engine);

if (engine.GetFontAvailability("Aptos Narrow") == FontAvailability.NotFound)
{
Assert.Inconclusive("Font not found. This is expected behaviour on web.");
}

textbox.TextBody = new SvgTextBodyRenderItem(rc, group.Bounds, true);

var paragraph = textbox.TextBody.AddParagraph("Hello");

paragraph.AddText(" There");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace TestProject1
{
[TestClass]
public sealed class PresetShapeDefinitionTests
public sealed class PresetShapeDefinitionTest : TestBase
{
[TestMethod]
public async Task LoadPreset()
Expand All @@ -21,7 +21,7 @@ public async Task LoadPreset()
var shape = ws.Drawings.AddShape("Rect1", OfficeOpenXml.Drawing.eShapeStyle.Rect);

PresetShapeDefinitions.ShapeDefinitions[(ShapeStyle)shape.Style].Calculate(shape._width, shape._height, shape.TextBody.TextAutofit == eTextAutofit.ShapeAutofit, null, null);
await p.SaveAsAsync("c:\\temp\\rect.xlsx");
await SaveWorkbookAsync("rect.xlsx", p);
}
}

Expand Down
46 changes: 35 additions & 11 deletions src/EPPlus.DrawingRenderer.Tests/Shape/ShapeToSvgTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using EPPlus.Fonts.OpenType;
using EPPlus.DrawingRenderer;
using EPPlus.Fonts.OpenType;
using OfficeOpenXml;
using OfficeOpenXml.Drawing;
using OfficeOpenXml.Drawing.Chart;
Expand Down Expand Up @@ -399,26 +400,49 @@ public void CustomPath()
}


[TestMethod]
public void OpenReadAndHTMLExportTextbox()
{
using(var p = OpenTemplatePackage("HtmlExportwithCharts.xlsx"))
{
var ws = p.Workbook.Worksheets[0];
var shape = ws.Drawings["InfoBox"];
var svg = shape.ToSvg();
SaveTextFileToWorkbook($"svg\\{shape.Name}.svg", svg);
}
}


[TestMethod]
public void GenerateAllShapes()
public void GenerateSpecificShape()
{
using (var p = new ExcelPackage())
{
var ws = p.Workbook.Worksheets.Add("Shapes");
int y = 100, i = 1;
int y = 100;

var shapeStyle = eShapeStyle.Pie;

var shape = ws.Drawings.AddShape(shapeStyle.ToString(), shapeStyle);
shape.Text = shapeStyle.ToString();
Assert.AreEqual(eDrawingType.Shape, shape.DrawingType);
shape.SetPosition(y, 100);
shape.SetSize(600, 600);
y += 700;

var shapeSvg = shape.ToSvg();
SaveTextFileToWorkbook($"svg\\{shape.Name}.svg", shapeSvg);
}
}

//var shape = ws.Drawings.AddShape(eShapeStyle.Gear6.ToString(), eShapeStyle.Gear6);
//shape.Text = eShapeStyle.Gear9.ToString();
//Assert.AreEqual(eDrawingType.Shape, shape.DrawingType);
//shape.SetPosition(y, 100);
//shape.SetSize(600, 600);
//y += 700;

//var shapeSvg = shape.ToSvg();
//SaveTextFileToWorkbook($"svg\\{shape.Name}.svg", shapeSvg);
[TestMethod]
public void GenerateAllShapes()
{
using (var p = new ExcelPackage())
{
var ws = p.Workbook.Worksheets.Add("Shapes");
int y = 100, i = 1;

foreach (eShapeStyle style in Enum.GetValues(typeof(eShapeStyle)))
{
Expand Down
10 changes: 6 additions & 4 deletions src/EPPlus.DrawingRenderer.Tests/TestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -316,12 +316,14 @@ protected static void SaveWorkbook(string name, ExcelPackage pck)
{
if (pck.Workbook.Worksheets.Count == 0) return;
var fi = new FileInfo(_worksheetPath + name);
if (fi.Exists)
{
//fi.Delete();
}
pck.SaveAs(fi);
}
protected static async Task SaveWorkbookAsync(string name, ExcelPackage pck)
{
if (pck.Workbook.Worksheets.Count == 0) return;
var fi = new FileInfo(_worksheetPath + name);
await pck.SaveAsAsync(fi);
}
protected static readonly DateTime _loadDataStartDate = new DateTime(2022, 11, 1);
/// <summary>
/// Loads 4 columns of {date, numeric, string, numeric}
Expand Down
31 changes: 31 additions & 0 deletions src/EPPlus.DrawingRenderer/RenderItems/RenderItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,35 @@ public void AddChildItem(RenderItem item)
Bounds.Width = item.Bounds.Right > Bounds.Width ? item.Bounds.Right : Bounds.Width;
Bounds.Height = item.Bounds.Bottom > Bounds.Height ? item.Bounds.Bottom : Bounds.Height;
}

/// <summary>
/// Create a subGroup beneath the ParentGroup
/// (Or beneath altOverrideBounds but add the renderitems to the parentGroup) This is strange and due to legacy
/// </summary>
/// <typeparam name="T">Some RenderItem type</typeparam>
/// <param name="subGroupName">Class name of the subgroup for easier debugging</param>
/// <param name="Items">The RenderItems to place within the group</param>
/// <param name="parentGroup">The parent group of this item</param>
public void AddSubGroupingOfRenderItems<T>(string subGroupName, List<T> Items) where T : RenderItem
{
if (Items != null)
{
//Create subGroup
var subGroup = new GroupRenderItem(this.Bounds);
subGroup.Bounds.Name = subGroupName;

//Add items to subGroup
foreach (var renderItem in Items)
{
subGroup.RenderItems.Add(renderItem);
}

//Add subGroup to parent group
this.RenderItems.Add(subGroup);
}
}


public override RenderItem Clone()
{
var item = new GroupRenderItem(Bounds)
Expand All @@ -254,6 +283,8 @@ public override RenderItem Clone()
}
return item;
}


}
public class PathRenderItem : RenderItem
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ public double GetAlignmentVertical()
case TextAnchoringType.Center:
if(AutoSize == false)
{
alignmentY = (Bounds.Height) / 2 - ContentBounds.Height;
alignmentY = (Bounds.Height - ContentBounds.Height) / 2d;
}
break;
case TextAnchoringType.Bottom:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ public RenderTextbox(BoundingBox parent, double maxWidth, double maxHeight)
Init(parent, maxWidth, maxHeight);
}

public string Name
{
get { return _group.Bounds.Name; }
set { _group.Bounds.Name = value; }
}

//The origin point of the entire textbox itself (its outermost left and top point)
protected GroupRenderItem _group;
//The origin point of the textbody after applied margins
Expand Down
20 changes: 15 additions & 5 deletions src/EPPlus.DrawingRenderer/ShapeDefinitions/ShapeDefinitionBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,22 @@ public void Calculate(double width, double height, bool textAutofit, List<string

if (TextBoxRect != null)
{
//if (textAutofit != eTextAutofit.ShapeAutofit)
if (textAutofit == false)
{
TextBoxRect.LeftValue = GetValue(TextBoxRect.LeftName) / Constants.EMU_PER_PIXEL;
TextBoxRect.RightValue = GetValue(TextBoxRect.RightName) / Constants.EMU_PER_PIXEL;
TextBoxRect.TopValue = GetValue(TextBoxRect.TopName) / Constants.EMU_PER_PIXEL;
TextBoxRect.BottomValue = GetValue(TextBoxRect.BottomName) / Constants.EMU_PER_PIXEL;
TextBoxRect.LeftValue = GetValue(TextBoxRect.LeftName) / (double)Constants.EMU_PER_PIXEL;

//The offical Preset file appears to be faulty for Pie. They have mixed up Top and Right attributes.
if(Style == ShapeStyle.Pie)
{
TextBoxRect.RightValue = GetValue(TextBoxRect.TopName) / (double)Constants.EMU_PER_PIXEL;
TextBoxRect.TopValue = GetValue(TextBoxRect.RightName) / (double)Constants.EMU_PER_PIXEL;
}
else
{
TextBoxRect.RightValue = GetValue(TextBoxRect.RightName) / (double)Constants.EMU_PER_PIXEL;
TextBoxRect.TopValue = GetValue(TextBoxRect.TopName) / (double)Constants.EMU_PER_PIXEL;
}
TextBoxRect.BottomValue = GetValue(TextBoxRect.BottomName) / (double)Constants.EMU_PER_PIXEL;
}
else
{
Expand Down Expand Up @@ -400,6 +409,7 @@ internal double CalculateFormula(string formula)
return Math.Sqrt(Math.Pow((double)GetValue(tokens[1]), 2d) + Math.Pow((double)GetValue(tokens[2]), 2) + Math.Pow((double)GetValue(tokens[3]), 2));
case "pin":
//if (y < x), then x = value of this guide else if (y > z), then z
//Else y
double x = GetValue(tokens[1]);
double y = GetValue(tokens[2]);
double z = GetValue(tokens[3]);
Expand Down
2 changes: 1 addition & 1 deletion src/EPPlus.DrawingRenderer/Svg/Core/SvgBaseRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ protected void RenderBaseToSpecified(T item, StringBuilder sb)
{
if (item.Bounds.Name != null)
{
sb.Append($" id=\"{item.Bounds.Name}\" ");
sb.Append($" class=\"{item.Bounds.Name}\" ");
}

if (string.IsNullOrEmpty(item.DefId) == false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public override void Render(GroupRenderItem item)
fillPropery = $" fill=\"{item.FillColor}\" ";
}

OutputStream.Append($"<g {GetTransformOrigin(item)} transform=\"{combinedTransform}\"{fillPropery}>");
OutputStream.Append($"<g class=\"{item.Bounds.Name}\" {GetTransformOrigin(item)} transform=\"{combinedTransform}\"{fillPropery}>");

foreach (var childItem in item.RenderItems)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public override void Render(ParagraphRenderItem item)
var sb = OutputStream;
var fontSize = item.DefaultParagraphFont.Size.PointToPixel().ToString(CultureInfo.InvariantCulture);

sb.AppendLine($"<g transform=\"translate({item.Bounds.Left.PointToPixelString()},{item.Bounds.Top.PointToPixelString()})\" >");
sb.AppendLine($"<g class=\"{item.Bounds.Name}\" transform=\"translate({item.Bounds.Left.PointToPixelString()},{item.Bounds.Top.PointToPixelString()})\" >");

sb.AppendLine("<title>paragraph</title> ");

Expand Down
Loading
Loading