diff --git a/src/EPPlus.Export.Pdf.Tests/PdfTests.cs b/src/EPPlus.Export.Pdf.Tests/PdfTests.cs index a566064de..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; @@ -761,5 +762,13 @@ public void EachWorksheetUsesItsOwnPaperSize() } } + [TestMethod] + public void GetClampedCellWidth_CellFitsWithinPage_ReturnsCellWidthUnchanged() + { + 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/DocumentObjects/PdfContentStream.cs b/src/EPPlus.Export.Pdf/DocumentObjects/PdfContentStream.cs index cdddc3a9d..9f897bfb9 100644 --- a/src/EPPlus.Export.Pdf/DocumentObjects/PdfContentStream.cs +++ b/src/EPPlus.Export.Pdf/DocumentObjects/PdfContentStream.cs @@ -362,11 +362,12 @@ 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; 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 +382,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, 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.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 e6fe821c3..2131c5bbb 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); } } @@ -1348,6 +1350,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; @@ -1623,5 +1632,10 @@ private static void EmitBandFrameV(List target, PdfRange range, double } if (rs != null) target.Add(new GridLine(x, rs.Value, x, re)); } + + internal static double GetClampedCellWidth(PdfPageSettings pageSettings, double cellX, double cellWidth) + { + return System.Math.Min(cellWidth, pageSettings.PageSize.WidthPu - cellX); + } } }