Skip to content

Repository files navigation


Your Stars or Donations can make MiniPDF better

A minimal, lightweight .NET library for converting office files to PDF.

MiniPdf Demo — Excel/Word/PowerPoint to PDF conversion

👉 Online Demo — Try it in your browser, no install required.

⚠️ Due to limited fonts available in the browser, the rendering results may not be optimal. For the best experience, please test locally on your machine.

Features

  • Excel-to-PDF — Convert .xlsx files to PDF
  • Word-to-PDF — Convert .docx files to PDF
  • PowerPoint-to-PDF — Convert .pptx files to PDF
  • LLM-friendly extraction — Convert .xlsx, .docx, and .pptx content to Markdown, JSON, or a semantic .NET model
  • PDF merge with bookmarks — Merge PDFs and add top-level bookmarks to the result
  • Minimal dependencies — Lightweight; relies almost entirely on built-in .NET APIs
  • Serverless-ready — No COM, no Office installation, no Adobe Acrobat — runs anywhere .NET runs
  • Native AOT — Pre-compiled standalone binaries for Windows / Linux / macOS; no .NET runtime required
  • Valid PDF 1.4 output
  • 100% open-source & free — Apache 2.0 licensed, commercial use welcome; just keep the attribution. PRs & contributions are even better!
  • Chart — Not currently supported well

Note: MiniPdf currently only handles basic conversions. Complex or highly customized Office documents may not convert perfectly. If you encounter compatibility issues, please open an Issue or submit a Pull Request — contributions are very welcome!

Reference

  • Trained small LLM by Apache POI + LibreOffice
  • AI development by GitHub Copilot + Claude Code

Getting Started

Install via NuGet

dotnet add package MiniPdf

Usage

usingMiniSoftware;// Excel to PDFMiniPdf.ConvertToPdf("data.xlsx","output.pdf");// Word to PDFMiniPdf.ConvertToPdf("report.docx","output.pdf");// PowerPoint to PDFMiniPdf.ConvertToPdf("slides.pptx","output.pdf");// File to byte arraybyte[]pdfBytes=MiniPdf.ConvertToPdf("data.xlsx");// Render selected Excel sheets by name or 1-based index (null renders all sheets)MiniPdf.ConvertToPdf("data.xlsx","selected.pdf",sheets:new[]{"Summary","Details"});MiniPdf.ConvertToPdf("data.xlsx","selected.pdf",sheetIndexes:new[]{1,3});// Compress and adjust Excel layout for large or wide sheetsMiniPdf.ConvertToPdf("data.xlsx","compact.pdf",newMiniPdfConversionOptions{Compress=true,FitToPage=true,Landscape=true,PrintScale=70,RowsPerPage=80,});// Stream to byte arrayusingvarstream=File.OpenRead("data.xlsx");byte[]pdfBytes=MiniPdf.ConvertToPdf(stream);// Merge PDFs and add bookmarksMiniPdf.MergePdf(new[]{"cover.pdf","body.pdf"},"merged.pdf",newPdfMergeOptions{BookmarkTitles=new[]{"Cover","Body"},Bookmarks=new[]{newPdfBookmark("Body page 2",2)},});

LLM-Friendly Content Extraction

Extract source-ordered content without generating or parsing an intermediate PDF:

usingMiniSoftware;MiniPdfDocumentContentcontent=MiniPdf.ExtractContent("report.docx");stringmarkdown=MiniPdf.ConvertToMarkdown("report.docx");stringjson=MiniPdf.ConvertToJson("report.docx");MiniPdf.ConvertToMarkdown("slides.pptx","slides.md");MiniPdf.ConvertToJson("data.xlsx","data.json",newMiniPdfContentOptions{Sheets=new[]{"Summary"},MaxRows=200,MaxColumns=20,});

DOCX content becomes a document section, XLSX worksheets become worksheet sections, and PPTX slides become slide sections. The schema preserves headings, paragraphs, lists, tables, worksheet cell addresses, hyperlinks, DOCX footnotes, and image/chart metadata. JSON output uses deterministic schema version 1.

Images are represented as metadata placeholders and are not written as sidecar files or processed with OCR. Comments, tracked changes, threaded comments, and PowerPoint speaker notes are not yet extracted.

PDF Merge Usage

Merge Files

usingMiniSoftware;MiniPdf.MergePdf(new[]{"cover.pdf","chapter-1.pdf","chapter-2.pdf"},"book.pdf");

Input order is preserved, so pages from cover.pdf appear first, followed by chapter-1.pdf, then chapter-2.pdf.

Add One Bookmark Per Source PDF

Use BookmarkTitles when each input PDF should become a top-level bookmark. The number of titles must match the number of input PDFs.

MiniPdf.MergePdf(new[]{"cover.pdf","chapter-1.pdf","chapter-2.pdf"},"book-with-bookmarks.pdf",newPdfMergeOptions{BookmarkTitles=new[]{"Cover","Chapter 1","Chapter 2"},});

Add Bookmarks To Specific Pages

Use PdfBookmark for explicit page targets. PageIndex is zero-based and refers to the final merged PDF.

MiniPdf.MergePdf(new[]{"cover.pdf","chapter-1.pdf","chapter-2.pdf"},"book-with-custom-bookmarks.pdf",newPdfMergeOptions{Bookmarks=new[]{newPdfBookmark("Start",0),newPdfBookmark("Chapter 2 - page 3",8),},});

Return A Byte Array

byte[]mergedPdf=MiniPdf.MergePdf(new[]{"cover.pdf","chapter-1.pdf"},newPdfMergeOptions{BookmarkTitles=new[]{"Cover","Chapter 1"},});

Supported inputs are unencrypted PDFs that use classic xref tables. Encrypted PDFs and xref-stream-only PDFs throw NotSupportedException.

Visual PDF Merge Test

To generate a sample merged PDF with bookmarks for manual inspection:

./scripts/Test-PdfMergeVisual.ps1

The script writes artifacts/issue62-merge-visual/merged-bookmarks.pdf. Open it in a PDF viewer and check that the bookmark pane contains Source A, Source B, and Source B - page 2. Add -Open to launch the generated PDF after creation.

Custom Fonts

If your environment has limited system fonts (for example, containers or Blazor WASM), register fonts before conversion.

usingMiniSoftware;// Register one or more fonts at app startup.MiniPdf.RegisterFont("NotoSansSC",File.ReadAllBytes("Fonts/NotoSansSC-Regular.ttf"));MiniPdf.RegisterFont("NotoColorEmoji",File.ReadAllBytes("Fonts/NotoColorEmoji.ttf"));MiniPdf.ConvertToPdf("report.docx","report.pdf");

Notes:

  • Supported input bytes are TrueType .ttf and TrueType Collection .ttc.
  • Register fonts once during startup to avoid duplicate registrations.
  • Registered fonts are prioritized before system fonts.

CLI Tool

MiniPdf also provides a command-line tool — MiniPdf.Cli — for quick conversion without writing code.

Experimental Rust Version

An experimental Rust rewrite is available under minipdf-rs. It contains a minipdf library crate and a Rust CLI with the same basic command shape as the .NET tool. The Rust version currently supports basic .xlsx and .docx text extraction and PDF generation, and is not yet feature-equivalent with the .NET implementation.

Install

dotnet tool install --global MiniPdf.Cli

Usage

# Convert Excel to PDF (output: data.pdf)
minipdf data.xlsx
# Convert Word to PDF
minipdf report.docx
# Convert PowerPoint to PDF
minipdf slides.pptx
# Specify output path
minipdf report.docx -o /path/to/output.pdf
# Register custom fonts (for containers / headless environments)
minipdf report.docx --fonts ./Fonts
# Render selected Excel sheets by name or 1-based index
minipdf data.xlsx --sheets Summary,2
# Compress PDF content streams for large outputs
minipdf data.xlsx --compress
# Render a bounded Excel preview
minipdf data.xlsx --max-rows 200 --max-columns 20 --compress
# Adjust Excel layout for large or wide sheets
minipdf data.xlsx --fit-to-page --landscape --scale 70
# Target more worksheet rows per PDF page
minipdf data.xlsx --rows-per-page 80 --compress
# Extract LLM-friendly Markdown (output: report.md)
minipdf extract report.docx
# Extract deterministic JSON
minipdf extract data.xlsx --format json --sheets Summary --max-rows 200

Commands

CommandDescription
minipdf <file>Convert .xlsx / .docx / .pptx to PDF
minipdf convert <file> -o <out>Convert with explicit output path
minipdf convert <file> --compressCompress PDF content streams
minipdf data.xlsx --max-rows <n> --max-columns <n>Render a bounded Excel preview
minipdf data.xlsx --fit-to-page --landscape --scale <n>Fit and scale Excel layout
minipdf data.xlsx --rows-per-page <n>Target more Excel rows per PDF page
minipdf extract <file>Extract LLM-friendly Markdown
minipdf extract <file> --format jsonExtract semantic JSON schema version 1
minipdf --versionShow version
minipdf --helpShow help

Native AOT Standalone Binaries

MiniPdf.Cli supports Native AOT (Ahead-of-Time) compilation — C# code is compiled directly into native machine code at build time, just like C/C++, producing a standalone executable. No .NET runtime or JIT compiler is needed at run time.

Advantages:

  • Zero dependencies — no .NET SDK or runtime needed on the target machine
  • Instant startup — native machine code, no JIT warm-up
  • Small footprint — single-file binary, easy to distribute and deploy
  • CI/CD friendly — download and run in any pipeline without installing .NET

Download: grab the binary for your platform from the GitHub Releases page.

PlatformFile
Windows x64minipdf-win-x64.zip
Windows ARM64minipdf-win-arm64.zip
Linux x64minipdf-linux-x64.tar.gz
Linux ARM64minipdf-linux-arm64.tar.gz
macOS x64minipdf-osx-x64.tar.gz
macOS ARM64 (Apple Silicon)minipdf-osx-arm64.tar.gz

Usage (example on Linux / macOS):

# Download & extract
tar -xzf minipdf-linux-x64.tar.gz
# Convert
./minipdf report.docx -o report.pdf

Usage (example on Windows):

# Extract the zip, then run
.\minipdf.exe report.docx -o report.pdf

Benchmark

MiniPdf output is compared against MiniExcel and Office 365 as the reference renderers across 373 test cases.

ReportCases🟢 Excellent (≥90%)🟡 Acceptable (70%–90%)🔴 Needs Improvement (<70%)Average Score
XLSX to PDF19117516096.9%
DOCX to PDF1801782097.6%
Issue XLSX Files211083.8%
Total37335419097.2%

Scoring: text similarity 40% + visual similarity 40% + page count 20%

Detailed Comparison Reports

Visual Comparison

All test cases comparing MiniPdf output vs MiniExcel / Office 365 reference. Page 1 shown for multi-page results.

MiniPdfMiniExcel / Office 365 (Reference)
classic01Basic table with headers 🟢 99.9%
classic02Multiple worksheets 🟢 99.8%
classic03Empty workbook 🟢 100.0%
classic04Single cell 🟢 100.0%
classic05Wide table 🟢 99.8%
classic06Tall table 🟢 97.8%
classic07Numbers only 🟢 100.0%
classic08Mixed text and numbers 🟢 99.9%
classic09Long text 🟢 98.4%
classic10Special xml characters 🟢 99.9%
classic11Sparse rows 🟢 100.0%
classic12Sparse columns 🟢 99.9%
classic13Date strings 🟢 99.9%
classic14Decimal numbers 🟢 99.9%
classic15Negative numbers 🟢 99.9%
classic16Percentage strings 🟢 99.4%
classic17Currency strings 🟢 99.9%
classic18Large dataset 🟢 95.7%
classic19Single column list 🟢 99.9%
classic20All empty cells 🟢 100.0%
classic21Header only 🟢 99.9%
classic22Long sheet name 🟢 99.9%
classic23Unicode text 🟢 91.3%
classic24Red text 🟢 99.9%
classic25Multiple colors 🟢 99.8%
classic26Inline strings 🟢 99.9%
classic27Single row 🟢 99.9%
classic28Duplicate values 🟢 99.9%
classic29Formula results 🟢 99.9%
classic30Mixed empty and filled sheets 🟢 100.0%
classic31Bold header row 🟢 99.9%
classic32Right aligned numbers 🟢 99.9%
classic33Centered text 🟢 99.9%
classic34Explicit column widths 🟢 99.9%
classic35Explicit row heights 🟢 99.5%
classic36Merged cells 🟢 99.9%
classic37Freeze panes 🟢 99.6%
classic38Hyperlink cell 🟢 99.9%
classic39Financial table 🟢 99.8%
classic40Scientific notation 🟢 99.9%
classic41Integer vs float 🟢 99.9%
classic42Boolean values 🟢 99.6%
classic43Inventory report 🟢 99.5%
classic44Employee roster 🟢 98.0%
classic45Sales by region 🟢 99.9%
classic46Grade book 🟢 99.6%
classic47Time series 🟢 99.3%
classic48Survey results 🟢 99.6%
classic49Contact list 🟢 98.5%
classic50Budget vs actuals 🟢 99.6%
classic51Product catalog 🟢 98.5%
classic52Pivot summary 🟢 99.6%
classic53Invoice 🟢 99.5%
classic54Multi level header 🟢 99.8%
classic55Error values 🟢 99.8%
classic56Alternating row colors 🟢 99.6%
classic57Cjk only 🟢 91.1%
classic58Mixed numeric formats 🟢 99.5%
classic59Multi sheet summary 🟢 99.9%
classic60Large wide table 🟢 97.4%
classic61Product card with image 🟢 99.9%
classic62Company logo header 🟢 99.6%
classic63Two products side by side 🟢 99.8%
classic64Employee directory with photo 🟢 99.1%
classic65Inventory with product photos 🟢 99.4%
classic66Invoice with logo 🟢 99.2%
classic67Real estate listing 🟢 99.6%
classic68Restaurant menu 🟢 98.6%
classic69Image only sheet 🟢 100.0%
classic70Product catalog with images 🟢 99.2%
classic71Multi sheet with images 🟢 99.8%
classic72Bar chart image with data 🟢 99.5%
classic73Event flyer with banner 🟢 99.6%
classic74Dashboard with kpi image 🟢 97.9%
classic75Certificate with seal 🟢 99.5%
classic76Product image grid 🟢 99.7%
classic77News article with hero image 🟢 99.6%
classic78Small icon per row 🟢 99.2%
classic79Wide panoramic banner 🟢 99.8%
classic80Portrait tall image 🟢 99.8%
classic81Step by step with images 🟢 99.7%
classic82Before after images 🟢 99.4%
classic83Color swatch palette 🟢 99.4%
classic84Travel destination cards 🟢 99.6%
classic85Lab results with image 🟢 99.2%
classic86Software screenshot features 🟢 98.7%
classic87Sports results with logos 🟢 99.8%
classic88Image after data 🟢 99.7%
classic89Nutrition label with image 🟢 99.5%
classic90Project status with milestones 🟢 99.0%
classic91Simple bar chart 🟢 96.6%
classic92Horizontal bar chart 🟢 96.9%
classic93Line chart 🟢 93.2%
classic94Pie chart 🟢 97.2%
classic95Area chart 🟡 76.4%
classic96Scatter chart 🟢 94.8%
classic97Doughnut chart 🟢 97.5%
classic98Radar chart 🟢 95.1%
classic99Bubble chart 🟢 92.0%
classic100Stacked bar chart 🟢 95.0%
classic101Percent stacked bar 🟢 93.6%
classic102Line chart with markers 🟢 93.0%
classic103Pie chart with labels 🟡 86.9%
classic104Combo bar line chart 🟡 81.6%
classic1053d bar chart 🟡 85.8%
classic1063d pie chart 🟢 96.7%
classic107Multi series line 🟡 80.6%
classic108Stacked area chart 🟢 94.4%
classic109Scatter with trendline 🟢 92.3%
classic110Chart with legend 🟡 84.7%
classic111Chart with axis labels 🟢 92.1%
classic112Multiple charts 🟡 85.4%
classic113Chart sheet 🟡 86.4%
classic114Chart large dataset 🟢 91.6%
classic115Chart negative values 🟢 92.1%
classic116Percent stacked area 🟢 93.8%
classic117Stock ohlc chart 🟡 80.9%
classic118Bar chart custom colors 🟢 95.5%
classic119Dashboard multi charts 🟢 92.1%
classic120Chart with date axis 🟡 76.1%
classic121Thin borders 🟢 99.7%
classic122Thick outer thin inner 🟢 99.6%
classic123Dashed borders 🟢 99.1%
classic124Colored borders 🟢 99.7%
classic125Solid fills 🟢 99.2%
classic126Dark header 🟢 99.5%
classic127Font styles 🟢 99.6%
classic128Font sizes 🟢 99.0%
classic129Alignment combos 🟢 99.8%
classic130Wrap and indent 🟢 99.5%
classic131Number formats 🟢 99.6%
classic132Striped table 🟢 99.0%
classic133Gradient rows 🟢 99.6%
classic134Heatmap 🟢 98.8%
classic135Bottom border only 🟢 99.8%
classic136Financial report styled 🟢 99.3%
classic137Checkerboard 🟢 98.4%
classic138Color grid 🟢 99.4%
classic139Pattern fills 🟢 99.2%
classic140Rotated text 🟢 98.1%
classic141Mixed edge borders 🟢 99.7%
classic142Styled invoice 🟢 98.3%
classic143Colored tabs 🟢 100.0%
classic144Note style cells 🟢 99.6%
classic145Status badges 🟢 99.1%
classic146Double border table 🟢 99.6%
classic147Multi sheet styled 🟢 99.7%
classic148Frozen styled grid 🟢 97.3%
classic149Merged styled sections 🟢 98.7%
classic150Kitchen sink styles 🟢 97.5%
classic151Multilingual greetings 🟢 93.5%
classic152Emoji sampler 🟢 91.1%
classic153Currency symbols 🟢 98.5%
classic154Math symbols 🟢 95.7%
classic155Diacritical marks 🟢 99.8%
classic156Rtl bidi text 🟡 84.0%
classic157Cjk extended 🟢 91.3%
classic158Emoji skin tones 🟢 99.3%
classic159Zwj emoji 🟢 90.6%
classic160Punctuation marks 🟢 94.4%
classic161Box drawing 🟢 95.0%
classic162Cjk emoji styled 🟡 86.5%
classic163Cyrillic alphabets 🟢 99.6%
classic164Indic scripts 🟡 87.4%
classic165Southeast asian 🟢 96.0%
classic166Emoji progress 🟢 98.6%
classic167Musical symbols 🟢 90.0%
classic168Mixed ltr rtl styled 🟢 94.5%
classic169Korean invoice 🟡 88.4%
classic170Emoji dashboard 🟢 96.3%
classic171Ipa phonetic 🟢 97.6%
classic172Emoji timeline 🟢 95.3%
classic173African languages 🟢 90.8%
classic174Technical symbols 🟢 94.4%
classic175Multiscript catalog 🟢 92.6%
classic176Combining characters 🟢 94.5%
classic177Emoji calendar 🟡 88.4%
classic178Caucasus ethiopic 🟢 96.9%
classic179Emoji inventory 🟢 91.0%
classic180Polyglot paragraph 🟢 93.6%
classic181Feedback tracker with images 🟢 99.4%
classic182Dense long text columns 🟢 96.5%
classic183Mixed content grid 🟢 99.4%
classic184Wide narrow columns 🟢 98.4%
classic185Tall rows vertical align 🟢 99.7%
classic186Multi sheet image report 🟢 99.6%
classic187Bug report with screenshots 🟢 98.2%
classic188Merged header with images 🟢 99.5%
classic189Alternating image text rows 🟢 95.3%
classic190Dashboard kpi images 🟢 99.5%
classic191Payroll calculator 🟡 89.5%

License

This project is licensed under the Apache License 2.0.

About

[Beta] A minimal .NET library convert Word, Excel, PPT to PDF.

Topics

Resources

Stars

369 stars

Watchers

2 watching

Forks

Releases

Sponsor this project

Contributors

Languages