Convert Excel (XLSX) to PDF in Node.js: Why Spreadsheet Parsers Can't Do It, and What Actually Works

ExcelJS reads and writes XLSX beautifully but has no PDF export — a gap documented in GitHub issues 1562 and 1806. After workbook.xlsx.writeBuffer(), you have…

ExcelJS reads and writes XLSX beautifully but has no PDF export — a gap documented in GitHub issues 1562 and 1806 [1][2]. After workbook.xlsx.writeBuffer(), you have a buffer going nowhere. The community's reflex is to shell out to headless LibreOffice in Docker, inheriting a second class of production problems: font substitution, broken column widths, conversions failing under concurrent requests, and broken characters in Alpine images [3][4][5][6].

Why there is no clean XLSX-to-PDF path in Node.js

ExcelJS issue 1562 asks directly whether Excel files created with the library can convert to PDF, and issue 1806 proposes adding PDF or HTML export as a native feature [1][2]. Neither has shipped. On Stack Overflow, developers hit the same wall after workbook.xlsx.writeBuffer() in Angular — the buffer has no rendering target [7]. Reddit's r/node threads show the same pattern: users with styled spreadsheets unable to find any standalone JS library that handles XLSX-to-PDF properly, with answers pointing to paid external APIs or manual HTML table rendering [8][9].

The default community answer is LibreOffice headless. It reads the format, but the results are never perfect and sometimes unacceptable [10]. Font substitution is immediate: Arial and Times New Roman become LiberationSerif throughout the document [3]. Column widths break, with some columns wrapping onto the next line in the PDF instead of displaying as a single table [4]. Under concurrent requests, the conversion stops working entirely — a bug tracked in LibreOffice Bugzilla 124798 [5]. In Alpine Docker images, missing font packages produce broken characters, worked around by manual installation of msttcorefonts-installer, fontconfig, and Google fonts [6].

Nutrient offers a Node.js SDK that claims no external dependencies, serverless readiness, and PDF/A support, unlike the libreoffice-convert wrapper it also documents. By default, PDFs carry a Nutrient watermark removed only with a license key. PDF4.dev notes there is no free public API for this conversion and suggests self-hosting LibreOffice behind Gotenberg. The remaining option — parsing XLSX yourself with a library like ExcelJS, then rebuilding layout, pagination, and styling in PDFKit or Puppeteer — means reimplementing a spreadsheet renderer from scratch.

Convert XLSX to PDF with the MarkupGo Node client

MarkupGo's Office to PDF API handles over 130 formats including .xlsx, currently in beta [11]. The official markupgo-node client exposes the same OfficeProperties options [12].

Install the client:

npm install markupgo-node

Read your XLSX file and convert:

import { MarkupGoClient } from 'markupgo-node';
import fs from 'fs';

const client = new MarkupGoClient({
  apiKey: process.env.MARKUPGO_API_KEY
});

const fileBuffer = fs.readFileSync('./report.xlsx');

const pdfBuffer = await client.officeToPdf({
  files: [fileBuffer],
  properties: {
    landscape: true,
    singlePageSheets: false
  }
});

fs.writeFileSync('./report.pdf', pdfBuffer);

The files array accepts buffers or streams. The client handles the multipart/form-data encoding the API requires [11]. If you want the PDF as a buffer rather than a task object, the API supports that — just append /buffer to the conversion URL [11]. For a financial report with wide columns, landscape: true suits wide tables [11]. Keeping singlePageSheets: false preserves normal pagination across multiple pages rather than compressing each sheet to one page [11].

Spreadsheet-specific options to tune the output

The properties object controls how spreadsheet structure maps to PDF pages.

  • landscape: rotate to landscape orientation for wide tables, financial models, or dashboards with many columns [11]
  • singlePageSheets: fit each sheet onto a single PDF page, useful for summary dashboards you intend to screenshot or thumbnail; hidden sheets are included [11]
  • merge: combine multiple uploaded workbooks into one PDF, ordered alphanumerically [11]
  • quality and maxImageResolution: control compression for charts and embedded images — default quality is 90, with optional resolution reduction to 75, 150, 300, 600, or 1200 DPI [11]

For a monthly finance package with three workbook files, set merge: true and receive one combined PDF. For a board presentation with embedded charts, raise quality and leave resolution untouched.

What to know before going to production

The Office to PDF API is in beta, so monitor conversion results for edge cases in your specific spreadsheets [11]. Each document is limited to 5MB and 10 files per request; contact MarkupGo for higher limits [11]. The upload uses multipart/form-data, not JSON, but the Node client abstracts this [11].

Each conversion consumes credits from your plan. The free trial includes 100 credits per month with no credit card required, enough to validate the pipeline before committing.

Next steps

Sources

  1. [Q] How can I convert Excel to pdf? (github.com)
  2. [F] Add the feature to convert the excel file to pdf. (github.com)
  3. stackoverflow.com
  4. stackoverflow.com
  5. stackoverflow.com
  6. stackoverflow.com
  7. convert an excel generated with exceljs to pdf (stackoverflow.com)
  8. r/node on Reddit: Convert Excel (xls) to PDF in node (reddit.com)
  9. How do I automate xlsx to pdf conversion in Node? (reddit.com)
  10. stackoverflow.com
  11. markupgo.com
  12. markupgo.com