From 9c63117ad5d0ff210a282e35a570b1782b42a95a Mon Sep 17 00:00:00 2001 From: KarlKallman Date: Thu, 27 Aug 2026 16:14:50 +0200 Subject: [PATCH 1/5] Fix for bug #2485 --- src/EPPlus.Export.Pdf.Tests/PdfTests.cs | 10 ++++++++++ src/EPPlus.Export.Pdf/Settings/PdfPageSettings.cs | 4 ++-- src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs | 7 +++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/EPPlus.Export.Pdf.Tests/PdfTests.cs b/src/EPPlus.Export.Pdf.Tests/PdfTests.cs index a566064de..141f00e95 100644 --- a/src/EPPlus.Export.Pdf.Tests/PdfTests.cs +++ b/src/EPPlus.Export.Pdf.Tests/PdfTests.cs @@ -21,6 +21,7 @@ Date Author Change using System.Globalization; using System.Text; using System.Text.RegularExpressions; +using FakeItEasy.Configuration; namespace EPPlusTest.PDF { @@ -761,5 +762,14 @@ public void EachWorksheetUsesItsOwnPaperSize() } } + [TestMethod] + public void ColLargerThanPrintableArea() + { + using(var p = OpenTemplatePackage("CenterOnPagePdf.xlsx")) + { + var ms = p.Workbook; + ms.SaveAsPdf(_pdfPath + "test.pdf") +; } + } } } diff --git a/src/EPPlus.Export.Pdf/Settings/PdfPageSettings.cs b/src/EPPlus.Export.Pdf/Settings/PdfPageSettings.cs index 76287e5a1..fe20194ed 100644 --- a/src/EPPlus.Export.Pdf/Settings/PdfPageSettings.cs +++ b/src/EPPlus.Export.Pdf/Settings/PdfPageSettings.cs @@ -200,8 +200,8 @@ public PdfScaling Scaling internal string defaultFontName = ""; //DEBUG - internal bool Debug = false; - internal bool PrintAsText = false; + internal bool Debug = true; + internal bool PrintAsText = true; public PdfPageSettings(OpenTypeFontEngine fontEngine) { diff --git a/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs b/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs index e6fe821c3..b8edcb35c 100644 --- a/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs +++ b/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs @@ -1348,6 +1348,13 @@ private static List GetColumnSegments(PdfPageSettings pageSettings, // Content-bounds overflow: col doesn't fit, end segment before it and reprocess. if (width + range.ColWidths[col] + effectiveAdded >= pageSettings.ContentBounds.Width) { + if(col == segStartIdx) + { + segments.Add(new PageSegment(range.Map.FromColumn + col, range.Map.FromColumn + col)); + segStartIdx = col + 1; + width = 0d; + continue; + } segments.Add(new PageSegment(range.Map.FromColumn + segStartIdx, range.Map.FromColumn + col - 1)); segStartIdx = col; width = 0d; From 6061b9061ff293cb9fbbc96a3ca136367b4d91ce Mon Sep 17 00:00:00 2001 From: KarlKallman Date: Fri, 28 Aug 2026 13:29:54 +0200 Subject: [PATCH 2/5] Added test --- src/EPPlus.Export.Pdf.Tests/PdfTests.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/EPPlus.Export.Pdf.Tests/PdfTests.cs b/src/EPPlus.Export.Pdf.Tests/PdfTests.cs index 141f00e95..3e700671b 100644 --- a/src/EPPlus.Export.Pdf.Tests/PdfTests.cs +++ b/src/EPPlus.Export.Pdf.Tests/PdfTests.cs @@ -21,7 +21,6 @@ Date Author Change using System.Globalization; using System.Text; using System.Text.RegularExpressions; -using FakeItEasy.Configuration; namespace EPPlusTest.PDF { @@ -761,15 +760,5 @@ public void EachWorksheetUsesItsOwnPaperSize() Assert.AreEqual(PdfPageSize.A3.HeightPu, h2, "Page 2 should be A3, not sheet 1's A4."); } } - - [TestMethod] - public void ColLargerThanPrintableArea() - { - using(var p = OpenTemplatePackage("CenterOnPagePdf.xlsx")) - { - var ms = p.Workbook; - ms.SaveAsPdf(_pdfPath + "test.pdf") -; } - } } } From 1d5af5317e4ed4a2dfcb0e5dc27845242a9725a7 Mon Sep 17 00:00:00 2001 From: KarlKallman Date: Mon, 31 Aug 2026 16:29:59 +0200 Subject: [PATCH 3/5] WIP --- src/EPPlus.Export.Pdf.Tests/PdfTests.cs | 11 +++++++++++ .../DocumentObjects/PdfContentStream.cs | 6 +++++- src/EPPlus.Export.Pdf/ExcelPdf.cs | 2 +- .../Layout/PdfCellContentLayout.cs | 2 +- src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs | 13 ++++++++++--- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/EPPlus.Export.Pdf.Tests/PdfTests.cs b/src/EPPlus.Export.Pdf.Tests/PdfTests.cs index 3e700671b..4cd23487e 100644 --- a/src/EPPlus.Export.Pdf.Tests/PdfTests.cs +++ b/src/EPPlus.Export.Pdf.Tests/PdfTests.cs @@ -760,5 +760,16 @@ public void EachWorksheetUsesItsOwnPaperSize() Assert.AreEqual(PdfPageSize.A3.HeightPu, h2, "Page 2 should be A3, not sheet 1's A4."); } } + + [TestMethod] + public void ClippingWhenCellIsWiderThanPage() + { + using(var package = OpenTemplatePackage("CenterOnPagePdf.xlsx")) + { + var ws = package.Workbook.Worksheets[0]; + string path = _pdfPath + "ClippingWideCellTest.pdf"; + ws.SaveAsPdf(path); + } + } } } diff --git a/src/EPPlus.Export.Pdf/DocumentObjects/PdfContentStream.cs b/src/EPPlus.Export.Pdf/DocumentObjects/PdfContentStream.cs index cdddc3a9d..c1fc73abe 100644 --- a/src/EPPlus.Export.Pdf/DocumentObjects/PdfContentStream.cs +++ b/src/EPPlus.Export.Pdf/DocumentObjects/PdfContentStream.cs @@ -362,11 +362,13 @@ public void AddOuterGridBorder(Transform pageLayout) commands.Add($"% Gridlines Border End"); } - public void AddMarginClipping(PdfPageLayout pageLayout) + //public void AddMarginClipping(PdfPageLayout pageLayout) + public void AddMarginClipping(PdfPageLayout pageLayout, PdfPageSettings pageSettings) { if (pageLayout is not PdfPageLayout pl) return; if (pageLayout.isCommentsPage) return; commands.Add($"% Margin Clip Start"); + if (pl.BorderLines.Count == 0) return; // Derive the tight bounding box directly from BorderLines. // pageLayout is created with all-zero dimensions so ContentTop/Bottom/Left/Height // cannot be used here — they are always 0. @@ -381,6 +383,8 @@ public void AddMarginClipping(PdfPageLayout pageLayout) left = System.Math.Min(left, System.Math.Min(line.X1, line.X2)); right = System.Math.Max(right, System.Math.Max(line.X1, line.X2)); } + right = System.Math.Min(right, left + pageSettings.ContentBounds.Width); + bottom = System.Math.Max(bottom, top - pageSettings.ContentBounds.Height); var pad = GridLine.Width * 4; var x = left + pl.HeadingWidth + pl.PrintTitleWidth - pad; var y = bottom - pad; diff --git a/src/EPPlus.Export.Pdf/ExcelPdf.cs b/src/EPPlus.Export.Pdf/ExcelPdf.cs index 64e96421e..864a47ad6 100644 --- a/src/EPPlus.Export.Pdf/ExcelPdf.cs +++ b/src/EPPlus.Export.Pdf/ExcelPdf.cs @@ -162,7 +162,7 @@ private void AddContent(PdfPageLayout pageLayout, PdfPage page) contentStream.AddCommand($"% {pageLayout.Name} start"); //Add clipping rectangle around page content. contentStream.AddCommand("q"); - contentStream.AddMarginClipping((PdfPageLayout)pageLayout); + contentStream.AddMarginClipping((PdfPageLayout)pageLayout, pageSettings); if (pageSettings.ShowGridLines) { contentStream.AddInnerGridLines(pageLayout); diff --git a/src/EPPlus.Export.Pdf/Layout/PdfCellContentLayout.cs b/src/EPPlus.Export.Pdf/Layout/PdfCellContentLayout.cs index 76d47b756..1d3951ecc 100644 --- a/src/EPPlus.Export.Pdf/Layout/PdfCellContentLayout.cs +++ b/src/EPPlus.Export.Pdf/Layout/PdfCellContentLayout.cs @@ -55,7 +55,7 @@ public PdfCellContentLayout(PdfPageSettings pageSettings, PdfDictionaries dictio } double firstLineAscent = TextLines[0].LargestAscent; double lastLineAscent = TextLines[TextLines.Count - 1].LargestAscent; - LocalPosition = CalculateAlignment(cell.Text, TextLines.LineFragments[0].Width, totalTextHeight, firstLineAscent, lastLineAscent, LocalPosition.X, LocalPosition.Y, cell.Width, height); + LocalPosition = CalculateAlignment(cell.Text, TextLines.LineFragments[0].Width, totalTextHeight, firstLineAscent, lastLineAscent, LocalPosition.X, LocalPosition.Y, width, height); } public PdfCellContentLayout(PdfPageSettings pageSettings, PdfDictionaries dictionaries, PdfHeaderFooter headerFooter, double x, double y, double width, double height, double scaleX = 1, double scaleY = 1, double rotation = 0, Transform parent = null) diff --git a/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs b/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs index b8edcb35c..014299d65 100644 --- a/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs +++ b/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs @@ -163,8 +163,10 @@ internal static Transform GetCatalog(int firstPageNumber, PdfDictionaries dictio } else { + var contentRight = pageSettings.ContentBounds.Left + pageSettings.ContentBounds.Width; + var effectiveWidth = GetClampedCellWidth(pageSettings, x, map.ColumnWidth); //Fill - var fill = new PdfCellLayout(x, y, map.ColumnWidth, rowHeight); + var fill = new PdfCellLayout(x, y, effectiveWidth, rowHeight); SetFill(dictionaries, map.CellStyle, map.Text, fill); fill.UpdateShadingPositionMatrix(pageSettings); fill.Name = map.Name; @@ -172,11 +174,11 @@ internal static Transform GetCatalog(int firstPageNumber, PdfDictionaries dictio //Text if (map.TextLines != null && map.TextLines.Count > 0) { - var text = new PdfCellContentLayout(pageSettings, dictionaries, map, info, x, y, map.ColumnWidth, rowHeight); + var text = new PdfCellContentLayout(pageSettings, dictionaries, map, info, x, y, effectiveWidth, rowHeight); text.Name = map.Name; text.GidsAndCharMap(dictionaries); if (NeedsClipping(map, pages[j], row, col)) - text.SetupClipping(x, y, map.ColumnWidth, rowHeight); + text.SetupClipping(x, y, effectiveWidth, rowHeight); pageLayout.AddChild(text); } } @@ -1630,5 +1632,10 @@ private static void EmitBandFrameV(List target, PdfRange range, double } if (rs != null) target.Add(new GridLine(x, rs.Value, x, re)); } + private static double GetClampedCellWidth(PdfPageSettings pageSettings, double cellX, double cellWidth) + { + var contentRight = pageSettings.ContentBounds.Left + pageSettings.ContentBounds.Width; + return System.Math.Min(cellWidth, contentRight - cellX); + } } } From f4d3c2154d62fd6e253987835589286d8c7ae6fb Mon Sep 17 00:00:00 2001 From: KarlKallman Date: Tue, 1 Sep 2026 08:26:02 +0200 Subject: [PATCH 4/5] WIP --- src/EPPlus.Export.Pdf/DocumentObjects/PdfContentStream.cs | 5 ++--- src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/EPPlus.Export.Pdf/DocumentObjects/PdfContentStream.cs b/src/EPPlus.Export.Pdf/DocumentObjects/PdfContentStream.cs index c1fc73abe..9f897bfb9 100644 --- a/src/EPPlus.Export.Pdf/DocumentObjects/PdfContentStream.cs +++ b/src/EPPlus.Export.Pdf/DocumentObjects/PdfContentStream.cs @@ -362,7 +362,6 @@ public void AddOuterGridBorder(Transform pageLayout) commands.Add($"% Gridlines Border End"); } - //public void AddMarginClipping(PdfPageLayout pageLayout) public void AddMarginClipping(PdfPageLayout pageLayout, PdfPageSettings pageSettings) { if (pageLayout is not PdfPageLayout pl) return; @@ -383,8 +382,8 @@ public void AddMarginClipping(PdfPageLayout pageLayout, PdfPageSettings pageSett left = System.Math.Min(left, System.Math.Min(line.X1, line.X2)); right = System.Math.Max(right, System.Math.Max(line.X1, line.X2)); } - right = System.Math.Min(right, left + pageSettings.ContentBounds.Width); - bottom = System.Math.Max(bottom, top - pageSettings.ContentBounds.Height); + right = System.Math.Min(right, pageSettings.PageSize.WidthPu); + bottom = System.Math.Max(bottom, 0d); var pad = GridLine.Width * 4; var x = left + pl.HeadingWidth + pl.PrintTitleWidth - pad; var y = bottom - pad; diff --git a/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs b/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs index 014299d65..f7cb0c2a8 100644 --- a/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs +++ b/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs @@ -1634,8 +1634,7 @@ private static void EmitBandFrameV(List target, PdfRange range, double } private static double GetClampedCellWidth(PdfPageSettings pageSettings, double cellX, double cellWidth) { - var contentRight = pageSettings.ContentBounds.Left + pageSettings.ContentBounds.Width; - return System.Math.Min(cellWidth, contentRight - cellX); + return System.Math.Min(cellWidth, pageSettings.PageSize.WidthPu - cellX); } } } From c8cafbc0416522dc0a5755284a4e289479743565 Mon Sep 17 00:00:00 2001 From: KarlKallman Date: Tue, 1 Sep 2026 09:11:48 +0200 Subject: [PATCH 5/5] Fix #2845: infinite loop and off-page content for oversized columns --- src/EPPlus.Export.Pdf.Tests/PdfTests.cs | 15 +++++++-------- src/EPPlus.Export.Pdf/Settings/PdfPageSettings.cs | 4 ++-- src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs | 3 ++- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/EPPlus.Export.Pdf.Tests/PdfTests.cs b/src/EPPlus.Export.Pdf.Tests/PdfTests.cs index 4cd23487e..4fa1cf91a 100644 --- a/src/EPPlus.Export.Pdf.Tests/PdfTests.cs +++ b/src/EPPlus.Export.Pdf.Tests/PdfTests.cs @@ -11,10 +11,11 @@ Date Author Change 10/07/2025 EPPlus Software AB EPPlus.Fonts.OpenType 1.0 *************************************************************************************************/ using EPPlus.Export.Pdf.Settings; -using EPPlus.Export.Pdf.Tests; using EPPlus.Export.Pdf.Settings.PdfPageSizes; +using EPPlus.Export.Pdf.Tests; using OfficeOpenXml; using OfficeOpenXml.Export.PdfExport; +using OfficeOpenXml.Export.PdfExport.Layout; using OfficeOpenXml.Export.PdfExport.Settings; using OfficeOpenXml.Style; using System.Diagnostics; @@ -762,14 +763,12 @@ public void EachWorksheetUsesItsOwnPaperSize() } [TestMethod] - public void ClippingWhenCellIsWiderThanPage() + public void GetClampedCellWidth_CellFitsWithinPage_ReturnsCellWidthUnchanged() { - using(var package = OpenTemplatePackage("CenterOnPagePdf.xlsx")) - { - var ws = package.Workbook.Worksheets[0]; - string path = _pdfPath + "ClippingWideCellTest.pdf"; - ws.SaveAsPdf(path); - } + var s = new PdfPageSettings(null); + + Assert.AreEqual(51.71d, PdfLayout.GetClampedCellWidth(s, 126.31d, 51.71d), 0.0001); } + } } diff --git a/src/EPPlus.Export.Pdf/Settings/PdfPageSettings.cs b/src/EPPlus.Export.Pdf/Settings/PdfPageSettings.cs index fe20194ed..76287e5a1 100644 --- a/src/EPPlus.Export.Pdf/Settings/PdfPageSettings.cs +++ b/src/EPPlus.Export.Pdf/Settings/PdfPageSettings.cs @@ -200,8 +200,8 @@ public PdfScaling Scaling internal string defaultFontName = ""; //DEBUG - internal bool Debug = true; - internal bool PrintAsText = true; + internal bool Debug = false; + internal bool PrintAsText = false; public PdfPageSettings(OpenTypeFontEngine fontEngine) { diff --git a/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs b/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs index f7cb0c2a8..2131c5bbb 100644 --- a/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs +++ b/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs @@ -1632,7 +1632,8 @@ private static void EmitBandFrameV(List target, PdfRange range, double } if (rs != null) target.Add(new GridLine(x, rs.Value, x, re)); } - private static double GetClampedCellWidth(PdfPageSettings pageSettings, double cellX, double cellWidth) + + internal static double GetClampedCellWidth(PdfPageSettings pageSettings, double cellX, double cellWidth) { return System.Math.Min(cellWidth, pageSettings.PageSize.WidthPu - cellX); }