Convert
June 27, 2026 · View on GitHub
A minimal, lightweight .NET library for converting office files to PDF.
👉 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
.xlsxfiles to PDF - Word-to-PDF — Convert
.docxfiles to PDF - PowerPoint-to-PDF — Convert
.pptxfiles to PDF - 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
using MiniSoftware;
// Excel to PDF
MiniPdf.ConvertToPdf("data.xlsx", "output.pdf");
// Word to PDF
MiniPdf.ConvertToPdf("report.docx", "output.pdf");
// PowerPoint to PDF
MiniPdf.ConvertToPdf("slides.pptx", "output.pdf");
// File to byte array
byte[] 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 });
// Stream to byte array
using var stream = File.OpenRead("data.xlsx");
byte[] pdfBytes = MiniPdf.ConvertToPdf(stream);
Custom Fonts
If your environment has limited system fonts (for example, containers or Blazor WASM), register fonts before conversion.
using MiniSoftware;
// 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
.ttfand 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
Commands
| Command | Description |
|---|---|
minipdf <file> | Convert .xlsx / .docx / .pptx to PDF |
minipdf convert <file> -o <out> | Convert with explicit output path |
minipdf --version | Show version |
minipdf --help | Show 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.
| Platform | File |
|---|---|
| Windows x64 | minipdf-win-x64.zip |
| Windows ARM64 | minipdf-win-arm64.zip |
| Linux x64 | minipdf-linux-x64.tar.gz |
| Linux ARM64 | minipdf-linux-arm64.tar.gz |
| macOS x64 | minipdf-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.
| Report | Cases | 🟢 Excellent (≥90%) | 🟡 Acceptable (70%–90%) | 🔴 Needs Improvement (<70%) | Average Score |
|---|---|---|---|---|---|
| XLSX to PDF | 191 | 175 | 16 | 0 | 96.9% |
| DOCX to PDF | 180 | 178 | 2 | 0 | 97.6% |
| Issue XLSX Files | 2 | 1 | 1 | 0 | 83.8% |
| Total | 373 | 354 | 19 | 0 | 97.2% |
Scoring: text similarity 40% + visual similarity 40% + page count 20%
Detailed Comparison Reports
- XLSX Benchmark Report — XLSX conversion test cases
- DOCX Benchmark Report — DOCX conversion test cases
- Issue Files Xlsx Report — Real-world issue file test cases
- Issue Files Docx Report — Real-world issue file test cases
Visual Comparison
All test cases comparing MiniPdf output vs MiniExcel / Office 365 reference. Page 1 shown for multi-page results.
| MiniPdf | MiniExcel / Office 365 (Reference) |
|---|---|
| classic01 | Basic table with headers 🟢 99.9% |
![]() |
![]() |
| classic02 | Multiple worksheets 🟢 99.8% |
![]() |
![]() |
| classic03 | Empty workbook 🟢 100.0% |
![]() |
![]() |
| classic04 | Single cell 🟢 100.0% |
![]() |
![]() |
| classic05 | Wide table 🟢 99.8% |
![]() |
![]() |
| classic06 | Tall table 🟢 97.8% |
![]() |
![]() |
| classic07 | Numbers only 🟢 100.0% |
![]() |
![]() |
| classic08 | Mixed text and numbers 🟢 99.9% |
![]() |
![]() |
| classic09 | Long text 🟢 98.4% |
![]() |
![]() |
| classic10 | Special xml characters 🟢 99.9% |
![]() |
![]() |
| classic11 | Sparse rows 🟢 100.0% |
![]() |
![]() |
| classic12 | Sparse columns 🟢 99.9% |
![]() |
![]() |
| classic13 | Date strings 🟢 99.9% |
![]() |
![]() |
| classic14 | Decimal numbers 🟢 99.9% |
![]() |
![]() |
| classic15 | Negative numbers 🟢 99.9% |
![]() |
![]() |
| classic16 | Percentage strings 🟢 99.4% |
![]() |
![]() |
| classic17 | Currency strings 🟢 99.9% |
![]() |
![]() |
| classic18 | Large dataset 🟢 95.7% |
![]() |
![]() |
| classic19 | Single column list 🟢 99.9% |
![]() |
![]() |
| classic20 | All empty cells 🟢 100.0% |
![]() |
![]() |
| classic21 | Header only 🟢 99.9% |
![]() |
![]() |
| classic22 | Long sheet name 🟢 99.9% |
![]() |
![]() |
| classic23 | Unicode text 🟢 91.3% |
![]() |
![]() |
| classic24 | Red text 🟢 99.9% |
![]() |
![]() |
| classic25 | Multiple colors 🟢 99.8% |
![]() |
![]() |
| classic26 | Inline strings 🟢 99.9% |
![]() |
![]() |
| classic27 | Single row 🟢 99.9% |
![]() |
![]() |
| classic28 | Duplicate values 🟢 99.9% |
![]() |
![]() |
| classic29 | Formula results 🟢 99.9% |
![]() |
![]() |
| classic30 | Mixed empty and filled sheets 🟢 100.0% |
![]() |
![]() |
| classic31 | Bold header row 🟢 99.9% |
![]() |
![]() |
| classic32 | Right aligned numbers 🟢 99.9% |
![]() |
![]() |
| classic33 | Centered text 🟢 99.9% |
![]() |
![]() |
| classic34 | Explicit column widths 🟢 99.9% |
![]() |
![]() |
| classic35 | Explicit row heights 🟢 99.5% |
![]() |
![]() |
| classic36 | Merged cells 🟢 99.9% |
![]() |
![]() |
| classic37 | Freeze panes 🟢 99.6% |
![]() |
![]() |
| classic38 | Hyperlink cell 🟢 99.9% |
![]() |
![]() |
| classic39 | Financial table 🟢 99.8% |
![]() |
![]() |
| classic40 | Scientific notation 🟢 99.9% |
![]() |
![]() |
| classic41 | Integer vs float 🟢 99.9% |
![]() |
![]() |
| classic42 | Boolean values 🟢 99.6% |
![]() |
![]() |
| classic43 | Inventory report 🟢 99.5% |
![]() |
![]() |
| classic44 | Employee roster 🟢 98.0% |
![]() |
![]() |
| classic45 | Sales by region 🟢 99.9% |
![]() |
![]() |
| classic46 | Grade book 🟢 99.6% |
![]() |
![]() |
| classic47 | Time series 🟢 99.3% |
![]() |
![]() |
| classic48 | Survey results 🟢 99.6% |
![]() |
![]() |
| classic49 | Contact list 🟢 98.5% |
![]() |
![]() |
| classic50 | Budget vs actuals 🟢 99.6% |
![]() |
![]() |
| classic51 | Product catalog 🟢 98.5% |
![]() |
![]() |
| classic52 | Pivot summary 🟢 99.6% |
![]() |
![]() |
| classic53 | Invoice 🟢 99.5% |
![]() |
![]() |
| classic54 | Multi level header 🟢 99.8% |
![]() |
![]() |
| classic55 | Error values 🟢 99.8% |
![]() |
![]() |
| classic56 | Alternating row colors 🟢 99.6% |
![]() |
![]() |
| classic57 | Cjk only 🟢 91.1% |
![]() |
![]() |
| classic58 | Mixed numeric formats 🟢 99.5% |
![]() |
![]() |
| classic59 | Multi sheet summary 🟢 99.9% |
![]() |
![]() |
| classic60 | Large wide table 🟢 97.4% |
![]() |
![]() |
| classic61 | Product card with image 🟢 99.9% |
![]() |
![]() |
| classic62 | Company logo header 🟢 99.6% |
![]() |
![]() |
| classic63 | Two products side by side 🟢 99.8% |
![]() |
![]() |
| classic64 | Employee directory with photo 🟢 99.1% |
![]() |
![]() |
| classic65 | Inventory with product photos 🟢 99.4% |
![]() |
![]() |
| classic66 | Invoice with logo 🟢 99.2% |
![]() |
![]() |
| classic67 | Real estate listing 🟢 99.8% |
![]() |
![]() |
| classic68 | Restaurant menu 🟢 98.6% |
![]() |
![]() |
| classic69 | Image only sheet 🟢 100.0% |
![]() |
![]() |
| classic70 | Product catalog with images 🟢 99.2% |
![]() |
![]() |
| classic71 | Multi sheet with images 🟢 99.8% |
![]() |
![]() |
| classic72 | Bar chart image with data 🟢 99.5% |
![]() |
![]() |
| classic73 | Event flyer with banner 🟢 99.6% |
![]() |
![]() |
| classic74 | Dashboard with kpi image 🟢 97.9% |
![]() |
![]() |
| classic75 | Certificate with seal 🟢 99.5% |
![]() |
![]() |
| classic76 | Product image grid 🟢 99.7% |
![]() |
![]() |
| classic77 | News article with hero image 🟢 99.6% |
![]() |
![]() |
| classic78 | Small icon per row 🟢 99.2% |
| classic79 | Wide panoramic banner 🟢 99.8% |
![]() |
![]() |
| classic80 | Portrait tall image 🟢 99.8% |
![]() |
![]() |
| classic81 | Step by step with images 🟢 99.7% |
![]() |
![]() |
| classic82 | Before after images 🟢 99.4% |
![]() |
![]() |
| classic83 | Color swatch palette 🟢 99.4% |
![]() |
![]() |
| classic84 | Travel destination cards 🟢 99.6% |
![]() |
![]() |
| classic85 | Lab results with image 🟢 99.2% |
![]() |
![]() |
| classic86 | Software screenshot features 🟢 98.7% |
![]() |
![]() |
| classic87 | Sports results with logos 🟢 99.8% |
![]() |
![]() |
| classic88 | Image after data 🟢 99.7% |
![]() |
![]() |
| classic89 | Nutrition label with image 🟢 99.5% |
![]() |
![]() |
| classic90 | Project status with milestones 🟢 99.0% |
![]() |
![]() |
| classic91 | Simple bar chart 🟢 96.6% |
![]() |
![]() |
| classic92 | Horizontal bar chart 🟢 96.9% |
![]() |
![]() |
| classic93 | Line chart 🟢 93.2% |
![]() |
![]() |
| classic94 | Pie chart 🟢 97.2% |
![]() |
![]() |
| classic95 | Area chart 🟡 76.4% |
![]() |
![]() |
| classic96 | Scatter chart 🟢 94.8% |
![]() |
![]() |
| classic97 | Doughnut chart 🟢 97.5% |
![]() |
![]() |
| classic98 | Radar chart 🟢 95.1% |
![]() |
![]() |
| classic99 | Bubble chart 🟢 92.0% |
![]() |
![]() |
| classic100 | Stacked bar chart 🟢 95.0% |
![]() |
![]() |
| classic101 | Percent stacked bar 🟢 93.6% |
![]() |
![]() |
| classic102 | Line chart with markers 🟢 93.0% |
![]() |
![]() |
| classic103 | Pie chart with labels 🟡 86.9% |
![]() |
![]() |
| classic104 | Combo bar line chart 🟡 81.6% |
![]() |
![]() |
| classic105 | 3d bar chart 🟡 85.8% |
![]() |
![]() |
| classic106 | 3d pie chart 🟢 96.7% |
![]() |
![]() |
| classic107 | Multi series line 🟡 80.6% |
![]() |
![]() |
| classic108 | Stacked area chart 🟢 94.4% |
![]() |
![]() |
| classic109 | Scatter with trendline 🟢 92.3% |
![]() |
![]() |
| classic110 | Chart with legend 🟡 84.7% |
![]() |
![]() |
| classic111 | Chart with axis labels 🟢 92.1% |
![]() |
![]() |
| classic112 | Multiple charts 🟡 85.4% |
![]() |
![]() |
| classic113 | Chart sheet 🟡 86.4% |
![]() |
![]() |
| classic114 | Chart large dataset 🟢 91.6% |
![]() |
![]() |
| classic115 | Chart negative values 🟢 92.1% |
![]() |
![]() |
| classic116 | Percent stacked area 🟢 93.8% |
![]() |
![]() |
| classic117 | Stock ohlc chart 🟡 80.9% |
![]() |
![]() |
| classic118 | Bar chart custom colors 🟢 95.5% |
![]() |
![]() |
| classic119 | Dashboard multi charts 🟢 92.1% |
![]() |
![]() |
| classic120 | Chart with date axis 🟡 76.1% |
![]() |
![]() |
| classic121 | Thin borders 🟢 99.7% |
![]() |
![]() |
| classic122 | Thick outer thin inner 🟢 99.6% |
![]() |
![]() |
| classic123 | Dashed borders 🟢 99.1% |
![]() |
![]() |
| classic124 | Colored borders 🟢 99.7% |
![]() |
![]() |
| classic125 | Solid fills 🟢 99.2% |
![]() |
![]() |
| classic126 | Dark header 🟢 99.5% |
![]() |
![]() |
| classic127 | Font styles 🟢 99.6% |
![]() |
![]() |
| classic128 | Font sizes 🟢 99.0% |
![]() |
![]() |
| classic129 | Alignment combos 🟢 99.8% |
![]() |
![]() |
| classic130 | Wrap and indent 🟢 99.5% |
![]() |
![]() |
| classic131 | Number formats 🟢 99.6% |
![]() |
![]() |
| classic132 | Striped table 🟢 99.0% |
![]() |
![]() |
| classic133 | Gradient rows 🟢 99.6% |
![]() |
![]() |
| classic134 | Heatmap 🟢 98.8% |
![]() |
![]() |
| classic135 | Bottom border only 🟢 99.8% |
![]() |
![]() |
| classic136 | Financial report styled 🟢 99.3% |
![]() |
![]() |
| classic137 | Checkerboard 🟢 98.4% |
![]() |
![]() |
| classic138 | Color grid 🟢 99.4% |
![]() |
![]() |
| classic139 | Pattern fills 🟢 99.2% |
![]() |
![]() |
| classic140 | Rotated text 🟢 98.1% |
![]() |
![]() |
| classic141 | Mixed edge borders 🟢 99.7% |
![]() |
![]() |
| classic142 | Styled invoice 🟢 98.3% |
![]() |
![]() |
| classic143 | Colored tabs 🟢 100.0% |
![]() |
![]() |
| classic144 | Note style cells 🟢 99.6% |
![]() |
![]() |
| classic145 | Status badges 🟢 99.1% |
![]() |
![]() |
| classic146 | Double border table 🟢 99.6% |
![]() |
![]() |
| classic147 | Multi sheet styled 🟢 99.7% |
![]() |
![]() |
| classic148 | Frozen styled grid 🟢 97.3% |
![]() |
![]() |
| classic149 | Merged styled sections 🟢 98.7% |
![]() |
![]() |
| classic150 | Kitchen sink styles 🟢 97.5% |
![]() |
![]() |
| classic151 | Multilingual greetings 🟢 93.5% |
![]() |
![]() |
| classic152 | Emoji sampler 🟢 91.1% |
![]() |
![]() |
| classic153 | Currency symbols 🟢 98.5% |
![]() |
![]() |
| classic154 | Math symbols 🟢 95.7% |
![]() |
![]() |
| classic155 | Diacritical marks 🟢 99.8% |
![]() |
![]() |
| classic156 | Rtl bidi text 🟡 84.0% |
![]() |
![]() |
| classic157 | Cjk extended 🟢 91.3% |
![]() |
![]() |
| classic158 | Emoji skin tones 🟢 99.3% |
![]() |
![]() |
| classic159 | Zwj emoji 🟢 90.6% |
![]() |
![]() |
| classic160 | Punctuation marks 🟢 94.4% |
![]() |
![]() |
| classic161 | Box drawing 🟢 95.0% |
![]() |
![]() |
| classic162 | Cjk emoji styled 🟡 86.5% |
![]() |
![]() |
| classic163 | Cyrillic alphabets 🟢 99.6% |
![]() |
![]() |
| classic164 | Indic scripts 🟡 87.4% |
![]() |
![]() |
| classic165 | Southeast asian 🟢 96.0% |
![]() |
![]() |
| classic166 | Emoji progress 🟢 98.6% |
![]() |
![]() |
| classic167 | Musical symbols 🟢 90.0% |
![]() |
![]() |
| classic168 | Mixed ltr rtl styled 🟢 94.5% |
![]() |
![]() |
| classic169 | Korean invoice 🟡 88.4% |
![]() |
![]() |
| classic170 | Emoji dashboard 🟢 96.3% |
![]() |
![]() |
| classic171 | Ipa phonetic 🟢 97.6% |
![]() |
![]() |
| classic172 | Emoji timeline 🟢 95.3% |
![]() |
![]() |
| classic173 | African languages 🟢 90.8% |
![]() |
![]() |
| classic174 | Technical symbols 🟢 94.4% |
![]() |
![]() |
| classic175 | Multiscript catalog 🟢 92.6% |
![]() |
![]() |
| classic176 | Combining characters 🟢 94.5% |
![]() |
![]() |
| classic177 | Emoji calendar 🟡 88.4% |
![]() |
![]() |
| classic178 | Caucasus ethiopic 🟢 96.9% |
![]() |
![]() |
| classic179 | Emoji inventory 🟢 91.0% |
![]() |
![]() |
| classic180 | Polyglot paragraph 🟢 93.6% |
![]() |
![]() |
| classic181 | Feedback tracker with images 🟢 99.4% |
| classic182 | Dense long text columns 🟢 96.5% |
![]() |
![]() |
| classic183 | Mixed content grid 🟢 99.4% |
![]() |
![]() |
| classic184 | Wide narrow columns 🟢 98.4% |
![]() |
![]() |
| classic185 | Tall rows vertical align 🟢 99.7% |
![]() |
![]() |
| classic186 | Multi sheet image report 🟢 99.6% |
![]() |
![]() |
| classic187 | Bug report with screenshots 🟢 98.2% |
![]() |
![]() |
| classic188 | Merged header with images 🟢 99.5% |
![]() |
![]() |
| classic189 | Alternating image text rows 🟢 95.3% |
![]() |
![]() |
| classic190 | Dashboard kpi images 🟢 99.5% |
![]() |
![]() |
| classic191 | Payroll calculator 🟡 89.5% |
![]() |
![]() |
License
This project is licensed under the Apache License 2.0.

























































































































































































































































































































































































