Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

147 Commits

Repository files navigation

Excel.Report.PDF

NuGet Excel.Report.PDFNuGet Excel.Report.PrintDocumentLicense: MIT

A .NET library that converts Excel workbooks into PDF and turns Excel files into reusable, data-driven report templates — without depending on Microsoft Office or COM Interop.

  • Excel → PDF: Pure managed conversion via ClosedXML + PdfSharp.
  • Template engine: Place $symbols and #directives directly in cells and overwrite the workbook with your data at runtime.
  • Multi-page reports: Split long lists across First / Body / Last page templates with automatic page numbering.
  • Built-in renderers: Drop in dynamic images and QR codes from cell directives, or register your own.
  • GDI+ printing: Bind the same rendering pipeline to System.Drawing.Printing.PrintDocument (Windows) for preview / direct printing.
Excel → PDFQuotation template

Table of contents


Install

# Core: Excel → PDF + template engine
PM>Install-Package Excel.Report.PDF
# Optional: Bind to System.Drawing.Printing (Windows only — preview / printer output)
PM>Install-Package Excel.Report.PrintDocument

Excel.Report.PDF targets .NET 6.0 and runs on Windows / Linux / macOS. Excel.Report.PrintDocument is Windows-only because it depends on GDI+ via System.Drawing.Common.


Quick start

1. Set up a font resolver

PdfSharp does not ship with fonts. Implement IFontResolver once at startup and return whichever font bytes you want PdfSharp to embed.

usingPdfSharp.Fonts;publicclassCustomFontResolver:IFontResolver{publicbyte[]GetFont(stringfaceName)=>faceName.EndsWith("#b")?Resources.NotoSansJP_ExtraBold:Resources.NotoSansJP_Regular;publicFontResolverInfoResolveTypeface(stringfamilyName,boolisBold,boolisItalic){varfaceName=familyName;if(isBold)faceName+="#b";returnnewFontResolverInfo(faceName);}}GlobalFontSettings.FontResolver=newCustomFontResolver();

A more sophisticated example that loads fonts directly from the Windows Fonts registry lives in Source/TestWinFormsApp/WindowsInstalledFontResolver.cs.

See docs/getting-started.md for the full setup walkthrough.

2. Convert Excel to PDF

usingExcel.Report.PDF;// Whole workbook → multi-page PDFusingvarpdf=ExcelConverter.ConvertToPdf("report.xlsx");File.WriteAllBytes("report.pdf",pdf.ToArray());// Specific sheet by 1-based positionusingvarpdfSheet1=ExcelConverter.ConvertToPdf("report.xlsx",1);// Specific sheet by nameusingvarpdfNamed=ExcelConverter.ConvertToPdf("report.xlsx","Summary");// Stream overloads are also availableusingvarfs=File.OpenRead("report.xlsx");usingvarpdfFromStream=ExcelConverter.ConvertToPdf(fs);

The renderer respects Excel's page setup (paper size, margins, scaling, page breaks, centering) and reproduces fonts, fills, borders (including Double), text rotation, vertical text, and embedded pictures.

Print scaling — set a fixed zoom percentage (PageSetup.Scale) or fit the sheet to the page width (#FitColumn / PageSetup.PagesWide). See docs/special-directives.md → Print scaling.

3. Overwrite a template, then convert

Drop $symbols and #directives straight into your .xlsx template, then bind a data object at runtime.

usingClosedXML.Excel;usingExcel.Report.PDF;vardata=newQuotation{Title="Banquet ingredients",Client="Excel Consulting Inc.",PersonInCharge="Shoichi Otani",};data.Details.Add(new(){Title="Sea bream",Detail="Fresh",Price=10000,Discount=0});data.Details.Add(new(){Title="Yellowtail",Detail="Fresh",Price=20000,Discount=0});data.Details.Add(new(){Title="Hamachi",Detail="Bargain",Price=30000,Discount=2000});data.Details.Add(new(){Title="Octopus",Detail="Bargain",Price=40000,Discount=1000});usingvarbook=newXLWorkbook("Quotation.xlsx");// Overwrite a single sheetawaitbook.Worksheet(1).OverWrite(newObjectExcelSymbolConverter(data));// ...or overwrite every sheet (and expand multi-page #PagedLoopRows templates)// await book.OverWrite(new ObjectExcelSymbolConverter(data));// Render the populated workbook to PDFusingvarms=newMemoryStream();book.SaveAs(ms);usingvarpdf=ExcelConverter.ConvertToPdf(ms,1);File.WriteAllBytes("Quotation.pdf",pdf.ToArray());

ObjectExcelSymbolConverter resolves symbols against the public properties of the bound object (and supports nested loops). To map symbols to a database row, an API response, or any other source, implement IExcelSymbolConverter — see docs/template-overwrite.md.


Cell directive reference

All directives live in cell text. $ resolves to a value; # invokes a function, loop, or rendering command.

DirectiveWherePurpose
$nameany cellReplace the cell value with converter.GetData("name").
#LoopRow($items, item, n)column AInsert-mode loop. Copies n rows above the current row, once per element of $items.
#LoopRowData($items, item, n)column AData-only loop. Reuses the existing row format and writes values without inserting rows.
#PagedLoopRows(pageType, rowsPerPage, $items, item, blockRowCount)column ADistributes a long list across First / Body / Last template sheets — see docs/multi-page.md.
#Image($bytesOrStream[, widthScale[, heightScale]])any cellInsert a picture from byte[] or Stream.
#QR($text[, pixelsPerModule])any cellInsert a QR code (PNG, ECC level M). Default pixelsPerModule = 10.
#Pageany cell except column ARender the current page number when converting to PDF.
#PageCountany cell except column ARender the total page count (resolved after layout).
#PageOf("/")any cell except column ARender current<separator>total. The separator is the literal in the parentheses.
#Emptyany cellReserve the cell area for layout calculations but draw nothing.
#FitColumnA1 onlyScale the rendered output so the used column width fills the printable page width (see Print scaling).

Multiple cell directives can coexist on the same cell separated by | (for example #Empty | #FitColumn).

Detailed semantics, edge cases, and worked examples are split across the documents below.


Extending with your own #Function

#Image and #QR are themselves implementations of the public IOverWriteFunction interface. You can register additional #YourName(...) directives in two lines of code — there are no internal hooks involved.

usingClosedXML.Excel;usingExcel.Report.PDF;publicsealedclassUpperFunction:IOverWriteFunction{publicstringName=>"Upper";// matched as "#Upper(...)"publicTaskInvokeAsync(IXLWorksheetsheet,introwIndex,intcolIndex,object?[]args){vartext=args.ElementAtOrDefault(0)?.ToString()??string.Empty;sheet.Cell(rowIndex,colIndex).SetValue(XLCellValue.FromObject(text.ToUpperInvariant()));returnTask.CompletedTask;}}// Register once at startupExcelOverWriter.RegisterOverWriteFunction(newUpperFunction());

Then in any cell:

#Upper($Client)

args already has $symbols resolved by your IExcelSymbolConverter. See docs/built-in-functions.md for argument-parsing rules, real-world recipes (barcodes, signature stamps, computed totals, async DB lookups), and the full extensibility contract.


Detailed documentation


Requirements

PackageTargetKey dependencies
Excel.Report.PDFnet6.0ClosedXML 0.105.x, PdfSharp 6.2.x, QRCoder 1.7.x
Excel.Report.PrintDocumentnet6.0 (Windows)Excel.Report.PDF, System.Drawing.Common 8.0.x

Both libraries are pure managed code — no Microsoft Office, no COM, no native interop.


License

MIT © Codeer Software

About

No description, website, or topics provided.

Resources

Stars

16 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages