Documentation

Installation

npm install pdf-lib-table pdf-lib

pdf-lib is a peer dependency.

Basic usage

import { PDFDocument, StandardFonts, rgb } from 'pdf-lib';
import { createPDFTables } from 'pdf-lib-table';

const pdfDoc = await PDFDocument.create();
const page = pdfDoc.addPage([792, 612]);

const timesRoman = await pdfDoc.embedFont(StandardFonts.TimesRoman);
const timesRomanBold = await pdfDoc.embedFont(StandardFonts.TimesRomanBold);

// column definitions - columnId keys into each row's data object
const columns = [
    { columnId: 'serial', header: 'Serial' },
    { columnId: 'product', header: 'Product', wrapText: false }, // truncate with an ellipsis instead of wrapping
    { columnId: 'price', header: 'Price', width: 60, align: 'right' }, // fixed width in points, right-aligned
];

// each entry is { type: 'row' | 'subheading', data: {...} }
const data = [
    { type: 'row', data: { serial: '0-646-50584-X', product: 'Gloves', price: '701.00' } },
    { type: 'row', data: { serial: '0-10-349834-6', product: 'Boots', price: '87.00' } },
];

const document = await createPDFTables(data, page, pdfDoc, columns, StandardFonts, rgb, {
    tableStartingX: 50,     // 50pt from the left edge of the page
    tableStartingY: 50,     // 50pt down from the top of the page
    headerFont: timesRomanBold,
    cellFont: timesRoman,
    cellLineHeight: 12,
    continuationFont: timesRoman,
    subHeadingFont: timesRoman,
});

document.drawVerticalTables();

const pdfBytes = await pdfDoc.save();

createPDFTables(data, page, pdfDoc, columns, fonts, colors, options) builds the table (adding pages as needed) and returns a document object; call drawVerticalTables() on it to draw. All seven arguments are required - fonts is the StandardFonts import and colors is the rgb function, both from pdf-lib.

Coordinates and sizing

  • tableStartingX is the table's left edge, measured from the left edge of the page.
  • tableStartingY is the table's top edge, measured down from the top of the page, so tableStartingX: 0, tableStartingY: 0 puts the table in the top-left corner.
  • tableMaxWidth defaults to the space between tableStartingX and the right edge of the page, and an explicit value is clamped so the table can never run off the page.
  • Column widths are computed automatically from the content within tableMaxWidth; row heights are computed from the wrapped text.
  • A column definition may pin its width with width (in points). Fixed widths are honored exactly and override tableMaxWidth: when they total more than tableMaxWidth the table simply grows to fit them, like an HTML table. Auto columns share whatever space remains.
  • Values that leave no drawable room (a negative offset, a tableStartingY below the space reserved for the continuation footer, a tableStartingX past the page edge) throw a descriptive error.

Multi-page tables

Rows that don't fit are carried onto automatically appended pages, with the header repeated and a continuation footer (default 'Continues on Next Page') drawn on every page except the last. continuationFillerHeight reserves the space for that footer below the table.

The appendedTableStartingX/Y and appendedTableMaxWidth options position the table on pages 2+ and default to the initial-page values. Appended pages are created with the same dimensions as the initial page, so portrait, landscape, or any custom page size carries through the whole table.

Options

Columns

Each column definition supports:

PropertyDefaultDescription
columnIdRequiredKeys into each row's data object.
headerRequiredHeader text for the column.
widthautoFixed column width in points (see Coordinates and sizing).
align'left'Cell text alignment: 'left', 'center' or 'right'. Header text follows headerTextAlignment.
wrapTexttrueWhen false, cell text stays on one line and is truncated with an ellipsis when it doesn't fit.

Subheading column definitions (subHeadingColumns) also accept align.

Table

OptionDefaultDescription
tableType'vertical'Only 'vertical' is currently supported.
tableStartingX0Left edge of the table, from the left edge of the page.
tableStartingY0Top edge of the table, measured down from the top of the page.
tableMaxWidthpage width - tableStartingXMaximum table width; clamped to the page edge.
appendedTableStartingXtableStartingXLeft edge on appended pages.
appendedTableStartingYtableStartingYTop edge on appended pages.
appendedTableMaxWidthtableMaxWidthMaximum width on appended pages; clamped to the page edge.
tableBordertrueDraw a border around the table.
tableBorderThickness1Border thickness.
tableBorderColorblackAny pdf-lib rgb value.
tableBorderRadius0Rounded table corners - table content is clipped to the rounded shape.
tableDividedXtrueDraw horizontal divider lines between rows.
tableDividedYtrueDraw vertical divider lines between columns.
tableDividerXColorblackRow divider color.
tableDividerYColorblackColumn divider color.
tableDividerXThickness1Row divider thickness.
tableDividerYThickness1Column divider thickness.
OptionDefaultDescription
continuationFontRequiredFont for the continuation text.
continuationText'Continues on Next Page'Text drawn below the table when it continues.
continuationFontSize15Continuation text size.
continuationTextXcenteredX position of the continuation text.
continuationTextY10Y position of the continuation text from the page bottom.
continuationFillerHeight20Vertical space reserved below the table for the footer.
OptionDefaultDescription
headerFontRequiredAny pdf-lib font.
headerHeighttext heightMinimum header height - gives headerTextJustification room to work; the header still grows to fit wrapped text.
headerTextSize12Header text size.
headerTextColorblackAny pdf-lib rgb value.
headerBackgroundColornoneHeader fill color.
headerBackgroundOpacity0.25Opacity of the header fill (0-1).
headerWrapTexttrueWrap header text within the column (wrapped lines are spaced at headerTextSize).
headerTextAlignment'left''left', 'center' or 'right'.
headerTextJustification'center''top', 'center' or 'bottom'.
headerDividedXtrueDraw the line under the header.
headerDividedYtrueDraw vertical dividers between header cells.
headerDividerXColorblackDivider color.
headerDividerYColorblackDivider color.
headerDividerXThickness1Divider thickness.
headerDividerYThickness1Divider thickness.

Rows

OptionDefaultDescription
rowBackgroundColornoneBackground color for every row.
rowBackgroundOpacity0.25Opacity of row backgrounds, including the alternate color (0-1).
rowAlternateColorfalseAlternate the background color of every other row.
rowAlternateColorValuenoneThe alternate color (used when rowAlternateColor is true).

Cells

OptionDefaultDescription
cellFontRequiredAny pdf-lib font.
cellTextSize10Cell text size.
cellLineHeightcellTextSizeCell line height - drives row height and text placement.
cellTextColorblackAny pdf-lib rgb value.
cellPaddingX2Horizontal padding between cell text and its dividers/border.
cellPaddingY1Vertical padding between cell text and its dividers/border.
additionalWrapCharactersnoneExtra characters (beyond whitespace) that text may wrap on, e.g. ['-', '/'].

Divider and border strokes are centered on cell boundaries, so half of each line's thickness intrudes into the cell; the effective padding grows automatically so text stays clear of the lines at any thickness.

Subheadings

Subheading rows span the table and print values under specific parent columns. Define which columns a subheading uses with subHeadingColumns, then add { type: 'subheading', data: {...} } entries keyed by the subheading columnId:

const subHeadingColumns = [
    { columnId: 'type', parentId: 'product' }, // value lines up under the product column
    { columnId: 'total', parentId: 'price' },
];

const data = [
    { type: 'subheading', data: { type: 'Winter gear', total: '788.00' } },
    { type: 'row', data: { serial: '0-646-50584-X', product: 'Gloves', price: '701.00' } },
];
OptionDefaultDescription
subHeadingFontRequiredFont for subheading text.
subHeadingColumnsnoneSubheading column definitions (see above).
subHeadingTextSize10Subheading text size.
subHeadingLineHeightsubHeadingTextSizeSubheading line height - drives subheading row height.
subHeadingHeighttext heightMinimum subheading row height - the row still grows to fit wrapped text.
subHeadingTextColorcellTextColorAny pdf-lib rgb value.
subHeadingBackgroundColornoneBackground color for subheading rows.
subHeadingBackgroundOpacity0.25Opacity of subheading backgrounds (0-1).
subHeadingWrapTextfalseWrap subheading text within its column.
subHeadingDividedXfalseDraw the line under subheading rows.
subHeadingDividedYfollows tableDividedYDraw vertical dividers between subheading cells.
subHeadingDividerYColortableDividerYColorDivider color.
subHeadingDividerYThicknesstableDividerYThicknessDivider thickness.
subHeadingDividerXColorblackDivider color.
subHeadingDividerXThickness1Divider thickness.

Roadmap

  • tableType: 'horizontal' and '2way' - only 'vertical' tables are currently supported