diff --git a/src/EPPlus.Export.Pdf.Tests/PdfTests.cs b/src/EPPlus.Export.Pdf.Tests/PdfTests.cs index 8ab741f0c..0ec6442dc 100644 --- a/src/EPPlus.Export.Pdf.Tests/PdfTests.cs +++ b/src/EPPlus.Export.Pdf.Tests/PdfTests.cs @@ -12,10 +12,15 @@ Date Author Change *************************************************************************************************/ using EPPlus.Export.Pdf.Settings; using EPPlus.Export.Pdf.Tests; +using EPPlus.Export.Pdf.Settings.PdfPageSizes; using OfficeOpenXml; using OfficeOpenXml.Export.PdfExport; +using OfficeOpenXml.Export.PdfExport.Settings; using OfficeOpenXml.Style; +using System.Diagnostics; +using System.Globalization; using System.Text; +using System.Text.RegularExpressions; namespace EPPlusTest.PDF { @@ -637,5 +642,122 @@ public void EPPlusToPdf() p.Workbook.SaveAsPdf(_pdfPath + "Snake.Pdf"); p.SaveAs(_pdfPath + "Snake.xlsx"); } + + [TestMethod] + public void Testing() + { + using var p = OpenTemplatePackage("PDFTestKarl.xlsx"); + var wb = p.Workbook; + string path = _pdfPath + "WorksheetTest1.pdf"; + wb.SaveAsPdf(path); + AssertLooksLikePdf(File.ReadAllBytes(path)); + } + + [TestMethod] + public void EachWorksheetUsesItsOwnOrientation() + { + using (var package = OpenTemplatePackage("PDFTestKarl.xlsx")) + { + package.Workbook.Worksheets[0].PrinterSettings.Orientation = eOrientation.Portrait; + package.Workbook.Worksheets[1].PrinterSettings.Orientation = eOrientation.Landscape; + + var settings = GetPdfSettings.GetPdfSettingsFromPrinterSettings( + package.Workbook, + package.Workbook.Worksheets[0].PrinterSettings); + + byte[] pdf; + using (var ms = new MemoryStream()) + { + new PdfCatalog(ms, settings, package.Workbook); + pdf = ms.ToArray(); + } + + var matches = Regex.Matches( + Encoding.ASCII.GetString(pdf), + @"/MediaBox\s*\[\s*0\s+0\s+(?[\d.]+)\s+(?[\d.]+)\s*\]"); + + Assert.AreEqual(2, matches.Count, "Expected one page per worksheet."); + + var ci = CultureInfo.InvariantCulture; + double w1 = double.Parse(matches[0].Groups["w"].Value, ci); + double h1 = double.Parse(matches[0].Groups["h"].Value, ci); + double w2 = double.Parse(matches[1].Groups["w"].Value, ci); + double h2 = double.Parse(matches[1].Groups["h"].Value, ci); + + Assert.IsTrue(h1 > w1, "Page 1 should be portrait."); + Assert.IsTrue(w2 > h2, "Page 2 should be landscape."); + // Landscape is the same paper transposed, not a different paper size. + Assert.AreEqual(w1, h2, 0.01d); + Assert.AreEqual(h1, w2, 0.01d); + } + } + + [TestMethod] + public void EachWorksheetUsesItsOwnShowGridLines() + { + using (var package = OpenTemplatePackage("PDFTestKarl.xlsx")) + { + package.Workbook.Worksheets[0].PrinterSettings.ShowGridLines = false; + package.Workbook.Worksheets[1].PrinterSettings.ShowGridLines = true; + + var baseSettings = GetPdfSettings.GetPdfSettingsFromPrinterSettings( + package.Workbook, + package.Workbook.Worksheets[0].PrinterSettings); + + var s0 = GetPdfSettings.GetPdfSettingsForSheet( + baseSettings, package.Workbook.Worksheets[0].PrinterSettings); + var s1 = GetPdfSettings.GetPdfSettingsForSheet( + baseSettings, package.Workbook.Worksheets[1].PrinterSettings); + + Assert.IsFalse(s0.ShowGridLines, "Sheet 1 did not ask for gridlines."); + Assert.IsTrue(s1.ShowGridLines, "Sheet 2 asked for gridlines."); + Assert.IsFalse(baseSettings.ShowGridLines, "The base object must not be mutated."); + } + } + + [TestMethod] + public void EachWorksheetUsesItsOwnPaperSize() + { + using (var package = OpenTemplatePackage("PDFTestKarl.xlsx")) + { + // Orientation is set explicitly so a transposed page size cannot be + // mistaken for a different paper size. + package.Workbook.Worksheets[0].PrinterSettings.Orientation = eOrientation.Portrait; + package.Workbook.Worksheets[1].PrinterSettings.Orientation = eOrientation.Portrait; + package.Workbook.Worksheets[0].PrinterSettings.PaperSize = ePaperSize.A4; + package.Workbook.Worksheets[1].PrinterSettings.PaperSize = ePaperSize.A3; + + var settings = GetPdfSettings.GetPdfSettingsFromPrinterSettings( + package.Workbook, + package.Workbook.Worksheets[0].PrinterSettings); + + byte[] pdf; + using (var ms = new MemoryStream()) + { + new PdfCatalog(ms, settings, package.Workbook); + pdf = ms.ToArray(); + } + + var matches = Regex.Matches( + Encoding.ASCII.GetString(pdf), + @"/MediaBox\s*\[\s*0\s+0\s+(?[\d.]+)\s+(?[\d.]+)\s*\]"); + + Assert.AreEqual(2, matches.Count, "Expected one page per worksheet."); + + var ci = CultureInfo.InvariantCulture; + double w1 = double.Parse(matches[0].Groups["w"].Value, ci); + double h1 = double.Parse(matches[0].Groups["h"].Value, ci); + double w2 = double.Parse(matches[1].Groups["w"].Value, ci); + double h2 = double.Parse(matches[1].Groups["h"].Value, ci); + + // Compare against the source of truth rather than literal point values. + // PdfPageSize rounds mm to whole points, so 210x297 mm becomes 595x842. + Assert.AreEqual(PdfPageSize.A4.WidthPu, w1, "Page 1 should be A4."); + Assert.AreEqual(PdfPageSize.A4.HeightPu, h1, "Page 1 should be A4."); + Assert.AreEqual(PdfPageSize.A3.WidthPu, w2, "Page 2 should be A3, not sheet 1's A4."); + Assert.AreEqual(PdfPageSize.A3.HeightPu, h2, "Page 2 should be A3, not sheet 1's A4."); + } + } + } } diff --git a/src/EPPlus.Export.Pdf/ExcelPdf.cs b/src/EPPlus.Export.Pdf/ExcelPdf.cs index 95b5627be..64e96421e 100644 --- a/src/EPPlus.Export.Pdf/ExcelPdf.cs +++ b/src/EPPlus.Export.Pdf/ExcelPdf.cs @@ -30,6 +30,7 @@ namespace EPPlus.Export.Pdf internal class ExcelPdf { private PdfPageSettings _pageSettings; + private PdfDocumentSettings _documentSettings; private PdfDictionaries _dictionaries; internal List _document = new List(); private string _debugString; @@ -69,8 +70,8 @@ private string GetPatternLabel(PdfCellLayout layout) //Add Fonts //Need to update this method a bit. We should check for all default fonts and not only courier new? Also need to check if we are allowed to embedd the font. internal void AddFontData() - { - if (_pageSettings.EmbeddFonts) + { + if (_documentSettings.EmbeddFonts) { foreach (var font in _dictionaries.Fonts) { @@ -144,8 +145,10 @@ private PdfCatalog AddCatalog(int pagesObjectNumber) } //Create Content - private void AddContent(Transform pageLayout, PdfPage page) + private void AddContent(PdfPageLayout pageLayout, PdfPage page) { + var pageSettings = pageLayout.Settings; + var cells = pageLayout.ChildObjects.Where(t => (t is PdfCellLayout || t is PdfCellContentLayout || t is PdfCellBorderLayout) && !(t is PdfCellLayout cc && (cc.IsHeading || cc.IsPrintTitle)) && @@ -160,7 +163,7 @@ private void AddContent(Transform pageLayout, PdfPage page) //Add clipping rectangle around page content. contentStream.AddCommand("q"); contentStream.AddMarginClipping((PdfPageLayout)pageLayout); - if (_pageSettings.ShowGridLines) + if (pageSettings.ShowGridLines) { contentStream.AddInnerGridLines(pageLayout); } @@ -172,7 +175,7 @@ private void AddContent(Transform pageLayout, PdfPage page) foreach (PdfCellContentLayout content in cells.OfType()) { contentStream.AddCommand($"% CELL TEXT : {content.Name}"); - contentStream.AddCellContentLayout(content, _dictionaries, _pageSettings); + contentStream.AddCellContentLayout(content, _dictionaries, pageSettings); } foreach (PdfCellBorderLayout border in cells.OfType()) { @@ -191,12 +194,12 @@ private void AddContent(Transform pageLayout, PdfPage page) case PdfCellLayout layout: contentStream.AddCellLayout(layout, GetPatternLabel(layout)); break; case PdfCellContentLayout contentLayout: - contentStream.AddCellContentLayout(contentLayout, _dictionaries, _pageSettings); break; + contentStream.AddCellContentLayout(contentLayout, _dictionaries, pageSettings); break; case PdfCellBorderLayout borderLayout: contentStream.AddBorderLayout(borderLayout); break; } } - if (_pageSettings.ShowGridLines || _pageSettings.ShowHeadings) + if (pageSettings.ShowGridLines || pageSettings.ShowHeadings) { contentStream.AddOuterGridBorder(pageLayout); contentStream.AddPrintTitleGridLines(pageLayout); @@ -204,7 +207,7 @@ private void AddContent(Transform pageLayout, PdfPage page) //Add header and footer. foreach (var hf in headerFooterLayouts) { - contentStream.AddCellContentLayout(hf, _dictionaries, _pageSettings); + contentStream.AddCellContentLayout(hf, _dictionaries, pageSettings); } foreach (var titleCell in printTitleLayouts) { @@ -214,7 +217,7 @@ private void AddContent(Transform pageLayout, PdfPage page) case PdfCellLayout layout: contentStream.AddCellLayout(layout, GetPatternLabel(layout)); break; case PdfCellContentLayout contentLayout: - contentStream.AddCellContentLayout(contentLayout, _dictionaries, _pageSettings); break; + contentStream.AddCellContentLayout(contentLayout, _dictionaries, pageSettings); break; case PdfCellBorderLayout borderLayout: contentStream.AddBorderLayout(borderLayout); break; } @@ -232,16 +235,16 @@ private PdfInfoObject AddInfoObject(string workBookName = "") return info; } - internal void CreatePdf(PdfPageSettings pageSettings, PdfDictionaries dictionaries, Transform layout, string fileName) + internal void CreatePdf(PdfDocumentSettings documentSettings, PdfDictionaries dictionaries, Transform layout, string fileName) { //Write the PDF to the file. The Stream overload does the actual work and //populates _debugString. using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) { - CreatePdf(pageSettings, dictionaries, layout, fs); + CreatePdf(documentSettings, dictionaries, layout, fs); } //Write pdf as txt for debug. - if (_pageSettings.Debug && _pageSettings.PrintAsText) + if (_documentSettings.Debug && _documentSettings.PrintAsText) { using (var fs = new FileStream(fileName + ".txt", FileMode.Create, FileAccess.Write)) { @@ -253,7 +256,7 @@ internal void CreatePdf(PdfPageSettings pageSettings, PdfDictionaries dictionari } } - internal void CreatePdf(PdfPageSettings pageSettings, PdfDictionaries dictionaries, Transform layout, Stream stream) + internal void CreatePdf(PdfDocumentSettings documentSettings, PdfDictionaries dictionaries, Transform layout, Stream stream) { if (stream == null) throw new ArgumentNullException(nameof(stream)); if (!stream.CanWrite) throw new ArgumentException("The stream must be writable.", nameof(stream)); @@ -261,7 +264,8 @@ internal void CreatePdf(PdfPageSettings pageSettings, PdfDictionaries dictionari //seek to each object, so the target stream has to support querying its position. if (!stream.CanSeek) throw new ArgumentException("The stream must be seekable, because the PDF cross-reference table requires byte offsets.", nameof(stream)); - _pageSettings = pageSettings; + //_pageSettings = pageSettings; + _documentSettings = documentSettings; _dictionaries = dictionaries; var catalog = AddCatalog(2); //Create Pages @@ -276,8 +280,8 @@ internal void CreatePdf(PdfPageSettings pageSettings, PdfDictionaries dictionari //Create Page and Content for (int i = 0; i < layout.ChildObjects.Count; i++) { - var pageLayout = layout.ChildObjects[i]; - var page = AddPage(2, new List(), _pageSettings); + var pageLayout = (PdfPageLayout)layout.ChildObjects[i]; + var page = AddPage(2, new List(), pageLayout.Settings); AddContent(pageLayout, page); pages.pageObjectNumbers.Add(page.objectNumber); } diff --git a/src/EPPlus.Export.Pdf/Layout/PdfPageLayout.cs b/src/EPPlus.Export.Pdf/Layout/PdfPageLayout.cs index 2a1d0d9a8..b30789030 100644 --- a/src/EPPlus.Export.Pdf/Layout/PdfPageLayout.cs +++ b/src/EPPlus.Export.Pdf/Layout/PdfPageLayout.cs @@ -10,6 +10,7 @@ Date Author Change ************************************************************************************************* 27/11/2025 EPPlus Software AB EPPlus 9 *************************************************************************************************/ +using EPPlus.Export.Pdf.Settings; using EPPlus.Graphics; using System.Collections.Generic; using System.Diagnostics; @@ -27,7 +28,11 @@ internal class PdfPageLayout : Transform public double PrintTitleWidth; public double PrintTitleHeight; public bool isCommentsPage = false; - + /// + /// The settings of the worksheet this page belongs to. + /// Set in PdfLayout.GetCatalog, read in ExcelPdf when writing the page. + /// + internal PdfPageSettings Settings; public PdfPageLayout(double x, double y, double width, double height) : base(x, y, width, height) { } diff --git a/src/EPPlus.Export.Pdf/Settings/PdfDocumentSettings.cs b/src/EPPlus.Export.Pdf/Settings/PdfDocumentSettings.cs new file mode 100644 index 000000000..9217ddef6 --- /dev/null +++ b/src/EPPlus.Export.Pdf/Settings/PdfDocumentSettings.cs @@ -0,0 +1,37 @@ +using EPPlus.Fonts.OpenType; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EPPlus.Export.Pdf.Settings +{ + internal class PdfDocumentSettings + { + internal OpenTypeFontEngine FontEngine; + internal List FontDirectories; + internal bool SearchSystemDirectories; + internal bool EmbeddFonts; + internal string defaultFontName; + internal int FirstPageNumber; + internal bool Debug; + internal bool PrintAsText; + + internal static PdfDocumentSettings From(PdfPageSettings s) + { + return new PdfDocumentSettings + { + FontEngine = s.FontEngine, + FontDirectories = s.FontDirectories, + SearchSystemDirectories = s.SearchSystemDirectories, + EmbeddFonts = s.EmbeddFonts, + defaultFontName = s.defaultFontName, + FirstPageNumber = s.FirstPageNumber, + Debug = s.Debug, + PrintAsText = s.PrintAsText, + }; + } + + } +} diff --git a/src/EPPlus.Export.Pdf/Settings/PdfPageSettings.cs b/src/EPPlus.Export.Pdf/Settings/PdfPageSettings.cs index 5416f1887..76287e5a1 100644 --- a/src/EPPlus.Export.Pdf/Settings/PdfPageSettings.cs +++ b/src/EPPlus.Export.Pdf/Settings/PdfPageSettings.cs @@ -147,7 +147,7 @@ public PdfPageSize PageSize private Orientations _orientation = Orientations.Portrait; /// /// Set the orientation of the pages. - /// + /// public Orientations Orientation { get @@ -216,6 +216,18 @@ private static PdfPageSize ApplyOrientation(PdfPageSize size, Orientations orien ? size : new PdfPageSize(size.Height, size.Width); // swap (ctor is width, height) } + + internal PdfPageSettings CloneForSheet() + { + var c = new PdfPageSettings(_fontEngine); + c.FontDirectories = FontDirectories; + c.SearchSystemDirectories = SearchSystemDirectories; + c.EmbeddFonts = EmbeddFonts; + c.defaultFontName = defaultFontName; + c.Debug = Debug; + c.PrintAsText = PrintAsText; + return c; + } } /// diff --git a/src/EPPlus/Export/PdfExport/Data/PageData.cs b/src/EPPlus/Export/PdfExport/Data/PageData.cs index 6a7d8c510..458d1bb62 100644 --- a/src/EPPlus/Export/PdfExport/Data/PageData.cs +++ b/src/EPPlus/Export/PdfExport/Data/PageData.cs @@ -10,11 +10,12 @@ Date Author Change ************************************************************************************************* 27/11/2025 EPPlus Software AB EPPlus 9 *************************************************************************************************/ +using EPPlus.Export.Pdf.Layout; +using EPPlus.Export.Pdf.Settings; +using OfficeOpenXml.Export.PdfExport.Layout; using OfficeOpenXml.Export.PdfExport.TextMapping; using OfficeOpenXml.Style; using System.Collections.Generic; -using EPPlus.Export.Pdf.Layout; -using OfficeOpenXml.Export.PdfExport.Layout; namespace OfficeOpenXml.Export.PdfExport.Data @@ -50,6 +51,11 @@ internal struct Pages public string HeadingFontName; public float HeadingFontSize; public ExcelFill HeadingFill; + /// + /// The settings of the worksheet these pages belong to. + /// Set in PdfLayout.GetPages, read in PdfLayout.GetCatalog. + /// + public PdfPageSettings Settings; public int Count { get { return Width * Height; } diff --git a/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs b/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs index f4c4f1a9a..e6fe821c3 100644 --- a/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs +++ b/src/EPPlus/Export/PdfExport/Layout/PdfLayout.cs @@ -63,25 +63,30 @@ internal class PdfLayout { private const double rowHeadingWith1CharWidth = 18d; - public static Transform GetLayout(PdfPageSettings pageSettings, PdfDictionaries dictionaries, PdfWorksheet[] pdfSheets) + public static Transform GetLayout(PdfPageSettings[] sheetSettings, PdfDictionaries dictionaries, PdfWorksheet[] pdfSheets) { - var PagesCollection = GetPages(pageSettings, pdfSheets); - var Catalog = GetCatalog(pageSettings, dictionaries, PagesCollection); + var PagesCollection = GetPages(sheetSettings, pdfSheets); + // Page numbering is document-global; sheet 1 supplies it, as before. + var Catalog = GetCatalog(sheetSettings[0].FirstPageNumber, dictionaries, PagesCollection); return Catalog; } - internal static Transform GetCatalog(PdfPageSettings pageSettings, PdfDictionaries dictionaries, List pdfPages) + internal static Transform GetCatalog(int firstPageNumber, PdfDictionaries dictionaries, List pdfPages) { Transform Catalog = new Transform(0d, 0d, 0d, 0d); int totalPages = GetTotalPages(pdfPages); for (int i = 0; i < pdfPages.Count; i++) { + var pageSettings = pdfPages[i].Settings; + + var pages = pdfPages[i].Page; int pageNumber = pageSettings.FirstPageNumber; for (int j = 0; j < pages.Length; j++) { var page = pages[j]; PdfPageLayout pageLayout = new PdfPageLayout(0d, 0d, 0d, 0d); + pageLayout.Settings = pageSettings; pageLayout.isCommentsPage = pdfPages[i].IsCommentsPage; pageLayout.HeadingWidth = page.HeadingWidth; pageLayout.HeadingHeight = page.HeadingHeight; @@ -646,11 +651,14 @@ private static int GetTotalPages(List pdfPages) return totalPages; } - internal static List GetPages(PdfPageSettings pageSettings, PdfWorksheet[] pdfSheets) + internal static List GetPages(PdfPageSettings[] sheetSettings, PdfWorksheet[] pdfSheets) { List PagesCollection = new List(); - foreach (var pdfSheet in pdfSheets) + for (int si = 0; si < pdfSheets.Length; si++) { + var pdfSheet= pdfSheets[si]; + var pageSettings = sheetSettings[si]; + for (int ri = 0; ri < pdfSheet.Ranges.Count; ri++) { var range = pdfSheet.Ranges[ri]; @@ -664,6 +672,7 @@ internal static List GetPages(PdfPageSettings pageSettings, PdfWorksheet[ pages.HeadingFontName = pdfSheet.NormalStyle.Style.Font.Name; pages.HeadingFontSize = pdfSheet.NormalStyle.Style.Font.Size; pages.HeadingFill = pdfSheet.NormalStyle.Style.Fill; + pages.Settings = pageSettings; PagesCollection.Add(pages); } if (pdfSheet.CommentsAndNotes.Range != null) @@ -675,6 +684,7 @@ internal static List GetPages(PdfPageSettings pageSettings, PdfWorksheet[ pages = MapPage(pdfSheet.CommentsAndNotes, pages); pageSettings.ShowHeadings = savedShowHeadings; pages.IsCommentsPage = true; + pages.Settings = pageSettings; PagesCollection.Add(pages); } } diff --git a/src/EPPlus/Export/PdfExport/PdfCatalog.cs b/src/EPPlus/Export/PdfExport/PdfCatalog.cs index f82db724f..0cca173b4 100644 --- a/src/EPPlus/Export/PdfExport/PdfCatalog.cs +++ b/src/EPPlus/Export/PdfExport/PdfCatalog.cs @@ -11,24 +11,25 @@ Date Author Change 27/11/2025 EPPlus Software AB EPPlus 9 *************************************************************************************************/ using EPPlus.Export.Pdf; +using EPPlus.Export.Pdf; +using EPPlus.Export.Pdf.Resources; using EPPlus.Export.Pdf.Resources; using EPPlus.Export.Pdf.Settings; +using EPPlus.Export.Pdf.Settings; using EPPlus.Graphics; using EPPlus.Graphics; -using EPPlus.Export.Pdf; -using EPPlus.Export.Pdf.Settings; -using EPPlus.Export.Pdf.Resources; using OfficeOpenXml.Export.PdfExport.Data; using OfficeOpenXml.Export.PdfExport.Layout; using OfficeOpenXml.Export.PdfExport.RowResize; +using OfficeOpenXml.Export.PdfExport.Settings; using OfficeOpenXml.Export.PdfExport.TextMapping; using OfficeOpenXml.Export.PdfExport.TextShaping; using System; using System.Collections.Generic; -using System.Diagnostics; -using System.IO; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics; +using System.IO; using System.Linq; namespace OfficeOpenXml.Export.PdfExport @@ -80,21 +81,28 @@ private void HandleWorksheetCollection(PdfPageSettings pageSettings, ExcelWorksh // Match the single-worksheet path: resolve the default font before building. pageSettings.defaultFontName = worksheets[0].Workbook.ThemeManager.GetOrCreateTheme().FontScheme.MinorFont[0].Typeface; + // One settings object per worksheet, each from its own printer settings. + var sheetSettings = new PdfPageSettings[worksheets.Length]; + for (int i = 0; i < worksheets.Length; i++) + { + sheetSettings[i] = GetPdfSettings.GetPdfSettingsForSheet(pageSettings, worksheets[i].PrinterSettings); + } + PdfWorksheet[] pdfSheets = null; try { - // Collect text for every worksheet. - pdfSheets = GetPdfWorksheets(pageSettings, worksheets); + //// Collect text for every worksheet. + pdfSheets = GetPdfWorksheets(sheetSettings, worksheets); - // Shape text and auto-fit rows per sheet. - foreach (var pdfSheet in pdfSheets) + //// Shape text and auto-fit rows per sheet. + for (int i = 0; i < pdfSheets.Length; i++) { - ShapeTextInPdfWorksheet(pageSettings, pdfSheet); - PdfCalculateRowHeight.ResizeRowHeights(pdfSheet); + ShapeTextInPdfWorksheet(sheetSettings[i], pdfSheets[i]); + PdfCalculateRowHeight.ResizeRowHeights(pdfSheets[i]); } // One layout spanning all sheets and their ranges. - var layout = GetLayout(pageSettings, pdfSheets); + var layout = GetLayout(sheetSettings, pdfSheets); // Write the PDF document. writePdf(layout); @@ -259,8 +267,13 @@ private void HandleRangeCollection(PdfPageSettings pageSettings, ExcelRangeBase[ ShapeTextInPdfWorksheet(pageSettings, pdfSheet); PdfCalculateRowHeight.ResizeRowHeights(pdfSheet); } - - var layout = GetLayout(pageSettings, pdfSheets); + var sheetSettings = new PdfPageSettings[pdfSheets.Length]; + for (int i = 0; i < sheetSettings.Length; i++) + { + // Ranges within one export share the same printer settings today. + sheetSettings[i] = pageSettings; + } + var layout = GetLayout(sheetSettings, pdfSheets); writePdf(layout); } @@ -291,27 +304,29 @@ internal PdfCellCollection GetCellCollectionFromRange(PdfPageSettings pageSettin //Private Methods private Action WriteToFile(PdfPageSettings pageSettings, string fileName) - { - return layout => new ExcelPdf().CreatePdf(pageSettings, _dictionaries, layout, fileName); + { + return layout => new ExcelPdf().CreatePdf( + PdfDocumentSettings.From(pageSettings), _dictionaries, layout, fileName); } private Action WriteToStream(PdfPageSettings pageSettings, Stream stream) - { - return layout => new ExcelPdf().CreatePdf(pageSettings, _dictionaries, layout, stream); + { + return layout => new ExcelPdf().CreatePdf( + PdfDocumentSettings.From(pageSettings), _dictionaries, layout, stream); } //Create Layout Methods - private Transform GetLayout(PdfPageSettings pageSettings, PdfWorksheet[] pdfSheets) + private Transform GetLayout(PdfPageSettings[] sheetSettings, PdfWorksheet[] pdfSheets) { - var Layout = PdfLayout.GetLayout(pageSettings, _dictionaries, pdfSheets); + var Layout = PdfLayout.GetLayout(sheetSettings, _dictionaries, pdfSheets); return Layout; } private Transform GetLayout(PdfPageSettings pageSettings, PdfWorksheet pdfSheet) { - PdfWorksheet[] pdfSheets = new PdfWorksheet[1] { pdfSheet }; - var Layout = PdfLayout.GetLayout(pageSettings, _dictionaries, pdfSheets); + // Single sheet: one settings object, one sheet. + var Layout = PdfLayout.GetLayout(new[] { pageSettings }, _dictionaries, new[] { pdfSheet }); return Layout; } @@ -435,8 +450,10 @@ private PdfWorksheet GetPdfWorksheet(PdfPageSettings pageSettings, ExcelWorkshee } if (pageSettings.ShowHeadings && _addTextForHeadings) + { _dictionaries.AddFont(pageSettings, pdfSheet.NormalStyle.Style.Font.Name, pdfSheet.GetSubFamilyFromNormalStyle, "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"); - _addTextForHeadings = false; + _addTextForHeadings = false; + } GetMaps(pageSettings, pdfSheet, pdfSheet.Ranges); GetPrintTitles(pageSettings, pdfSheet); @@ -445,6 +462,16 @@ private PdfWorksheet GetPdfWorksheet(PdfPageSettings pageSettings, ExcelWorkshee return pdfSheet; } + private PdfWorksheet[] GetPdfWorksheets(PdfPageSettings[] sheetSettings, ExcelWorksheet[] worksheets) + { + PdfWorksheet[] pdfSheets = new PdfWorksheet[worksheets.Length]; + for (int i = 0; i < pdfSheets.Length; i++) + { + pdfSheets[i] = GetPdfWorksheet(sheetSettings[i], worksheets[i]); + } + return pdfSheets; + } + private List GetRanges(ExcelWorksheet worksheet) { List ranges = new List(); diff --git a/src/EPPlus/Export/PdfExport/Settings/GetPdfSettings.cs b/src/EPPlus/Export/PdfExport/Settings/GetPdfSettings.cs index 571ee41e0..fb78ad66b 100644 --- a/src/EPPlus/Export/PdfExport/Settings/GetPdfSettings.cs +++ b/src/EPPlus/Export/PdfExport/Settings/GetPdfSettings.cs @@ -22,6 +22,21 @@ internal static class GetPdfSettings internal static PdfPageSettings GetPdfSettingsFromPrinterSettings(ExcelWorkbook workbook, ExcelPrinterSettings eps) { var settings = new PdfPageSettings(workbook.RenderContext.FontEngine); + ApplyPrinterSettings(settings, eps); + return settings; + } + + internal static PdfPageSettings GetPdfSettingsForSheet( + PdfPageSettings baseSettings, ExcelPrinterSettings eps) + { + var s = baseSettings.CloneForSheet(); + ApplyPrinterSettings(s, eps); + return s; + } + + private static void ApplyPrinterSettings(PdfPageSettings settings, ExcelPrinterSettings eps) + { + var leftMargin = UnitConversion.ToMillimeters(eps.LeftMargin); var rightMargin = UnitConversion.ToMillimeters(eps.RightMargin); var topMargin = UnitConversion.ToMillimeters(eps.TopMargin); @@ -50,7 +65,6 @@ internal static PdfPageSettings GetPdfSettingsFromPrinterSettings(ExcelWorkbook settings.CommentsAndNotes = (CommentsAndNotes)eps.CellComments; settings.CellErrors = (CellErrors)eps.Errors; settings.FirstPageNumber = eps.FirstPageNumber; - return settings; } private static PdfPageSize GetPageSize(ePaperSize PaperSize)