mirror of
https://github.com/foliojs/pdfkit.git
synced 2025-12-08 20:15:54 +00:00
* Add page size utilities - Added page.contentWidth - Added page.contentHeight * Add table support - Tables support cell customization (including colors) - Tables also support rotatable text (with alignment support) - Tables have accessibility support * chore: fix code generation context - code generation now respects the current document positioning to allow use of page dependent operations * chore: remove comments from build * removed unnecessary config optimisations * Optimize table minification * Performance improvements to tables * Improve font handling in tables
378 lines
10 KiB
Markdown
378 lines
10 KiB
Markdown
# Tables in PDFKit
|
|
|
|
## The basics
|
|
|
|
PDFKit makes adding tables to documents quite simple, and includes many options
|
|
to customize the display of the output.
|
|
|
|
### A simple table
|
|
Basic tables can be defined without configuration:
|
|
|
|
doc.table({
|
|
data: [
|
|
['Column 1', 'Column 2', 'Column 3'],
|
|
['One value goes here', 'Another one here', 'OK?']
|
|
]
|
|
})
|
|
|
|
or the more verbose way
|
|
|
|
doc.table()
|
|
.row(['Column 1', 'Column 2', 'Column 3'])
|
|
.row(['One value goes here', 'Another one here', 'OK?'])
|
|
|
|
![1]()
|
|
|
|
---
|
|
|
|
### Defining column widths
|
|
|
|
Tables allow you to define the widths of columns:
|
|
|
|
* `*` - distributes equally, filling the whole available space (default)
|
|
* `fixed value` - a fixed width based on the document content
|
|
|
|
Example:
|
|
|
|
doc.table({
|
|
columnStyles: [100, "*", 200, "*"],
|
|
data: [
|
|
["width=100", "star-sized", "width=200", "star-sized"],
|
|
[
|
|
"fixed-width cells have exactly the specified width",
|
|
{ text: "nothing interesting here", textColor: "grey" },
|
|
{ text: "nothing interesting here", textColor: "grey" },
|
|
{ text: "nothing interesting here", textColor: "grey" }
|
|
],
|
|
],
|
|
});
|
|
|
|
![2]()
|
|
|
|
---
|
|
|
|
### Defining row heights
|
|
|
|
doc.table({
|
|
rowStyles: [20, 50, 70],
|
|
data: [
|
|
["row 1 with height 20", "column B"],
|
|
["row 2 with height 50", "column B"],
|
|
["row 3 with height 70", "column B"],
|
|
],
|
|
});
|
|
|
|
![3]()
|
|
|
|
With same height:
|
|
|
|
doc.table({
|
|
rowStyles: 40,
|
|
data: [
|
|
["row 1", "column B"],
|
|
["row 2", "column B"],
|
|
["row 3", "column B"],
|
|
],
|
|
});
|
|
|
|
![4]()
|
|
|
|
---
|
|
|
|
With height from function:
|
|
|
|
doc.table({
|
|
rowStyles: (row) => (row + 1) * 25,
|
|
data: [
|
|
["row 1", "column B"],
|
|
["row 2", "column B"],
|
|
["row 3", "column B"],
|
|
],
|
|
});
|
|
|
|
![5]()
|
|
|
|
---
|
|
|
|
### Column/row spans
|
|
|
|
Each cell can set a rowSpan or colSpan
|
|
|
|
doc.table({
|
|
columnStyles: [200, "*", "*"],
|
|
data: [
|
|
[{ colSpan: 2, text: "Header with Colspan = 2" }, "Header 3"],
|
|
["Header 1", "Header 2", "Header 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
[
|
|
{
|
|
rowSpan: 3,
|
|
text: "rowspan set to 3\nLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor",
|
|
},
|
|
"Sample value 2",
|
|
"Sample value 3",
|
|
],
|
|
["Sample value 2", "Sample value 3"],
|
|
["Sample value 2", "Sample value 3"],
|
|
[
|
|
"Sample value 1",
|
|
{
|
|
colSpan: 2,
|
|
rowSpan: 2,
|
|
text: "Both:\nrowspan and colspan\ncan be defined at the same time",
|
|
},
|
|
],
|
|
["Sample value 1"],
|
|
],
|
|
})
|
|
|
|
![6]()
|
|
|
|
---
|
|
|
|
### Styling
|
|
|
|
No borders:
|
|
|
|
doc.table({
|
|
rowStyles: { border: false },
|
|
data: [
|
|
["Header 1", "Header 2", "Header 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
],
|
|
})
|
|
|
|
![7]()
|
|
|
|
Header line only:
|
|
|
|
doc.table({
|
|
rowStyles: (i) => {
|
|
return i < 1 ? { border: [0, 0, 1, 0] } : { border: false };
|
|
},
|
|
data: [
|
|
["Header 1", "Header 2", "Header 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
],
|
|
})
|
|
|
|
![8]()
|
|
|
|
---
|
|
|
|
Light Horizontal lines:
|
|
|
|
doc.table({
|
|
rowStyles: (i) => {
|
|
return i < 1
|
|
? { border: [0, 0, 2, 0], borderColor: "black" }
|
|
: { border: [0, 0, 1, 0], borderColor: "#aaa" };
|
|
},
|
|
data: [
|
|
["Header 1", "Header 2", "Header 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
],
|
|
})
|
|
|
|
![9]()
|
|
|
|
---
|
|
|
|
But you can provide a custom styler as well
|
|
|
|
doc.table({
|
|
// Set the style for all cells
|
|
defaultStyle: { border: 1, borderColor: "gray" },
|
|
// Set the style for cells based on their column
|
|
columnStyles: (i) => {
|
|
if (i === 0) return { border: { left: 2 }, borderColor: { left: "black" } };
|
|
if (i === 2) return { border: { right: 2 }, borderColor: { right: "black" } };
|
|
},
|
|
// Set the style for cells based on their row
|
|
rowStyles: (i) => {
|
|
if (i === 0) return { border: { top: 2 }, borderColor: { top: "black" } };
|
|
if (i === 3) return { border: { bottom: 2 }, borderColor: { bottom: "black" } };
|
|
},
|
|
data: [
|
|
["Header 1", "Header 2", "Header 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
],
|
|
})
|
|
|
|
![10]()
|
|
|
|
---
|
|
|
|
Zebra style
|
|
|
|
doc.table({
|
|
rowStyles: (i) => {
|
|
if (i % 2 === 0) return { backgroundColor: "#ccc" };
|
|
},
|
|
data: [
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
["Sample value 1", "Sample value 2", "Sample value 3"],
|
|
],
|
|
})
|
|
|
|
![11]()
|
|
|
|
---
|
|
|
|
### Optional border
|
|
|
|
doc.table({
|
|
data: [
|
|
[
|
|
{ border: [true, false, false, false], backgroundColor: "#eee", text: "border:\n[true, false, false, false]" },
|
|
{ border: false, backgroundColor: "#ddd", text: "border:\nfalse" },
|
|
{ border: true, backgroundColor: "#eee", text: "border:\ntrue" },
|
|
],
|
|
[
|
|
{ rowSpan: 3, border: true, backgroundColor: "#eef", text: "rowSpan: 3\n\nborder:\ntrue" },
|
|
{ border: undefined, backgroundColor: "#eee", text: "border:\nundefined (default)" },
|
|
{ border: [false, false, false, true], backgroundColor: "#ddd", text: "border:\n[false, false, false, true]" },
|
|
],
|
|
[
|
|
{ colSpan: 2, border: true, backgroundColor: "#efe", text: "colSpan: 2\n\nborder:\ntrue" },
|
|
],
|
|
[
|
|
{ border: 0, backgroundColor: "#eee", text: "border:\n0 (same as false)" },
|
|
{ border: [false, true, true, false], backgroundColor: "#ddd", text: "border:\n[false, true, true, false]" },
|
|
],
|
|
],
|
|
})
|
|
|
|
![12]()
|
|
|
|
---
|
|
|
|
doc.table({
|
|
defaultStyle: { border: false, width: 60 },
|
|
data: [
|
|
["", "column 1", "column 2", "column 3"],
|
|
[
|
|
"row 1",
|
|
{
|
|
rowSpan: 3,
|
|
colSpan: 3,
|
|
border: true,
|
|
backgroundColor: "#ccc",
|
|
text: "rowSpan: 3\ncolSpan: 3\n\nborder:\n[true, true, true, true]",
|
|
},
|
|
],
|
|
["row 2"],
|
|
["row 3"],
|
|
],
|
|
})
|
|
|
|
![13]()
|
|
|
|
---
|
|
|
|
When defining multiple styles, the cells follow the precedence:
|
|
|
|
1. `defaultStyle`
|
|
2. `columnStyles`
|
|
3. `rowStyles`
|
|
4. `cellStyle`
|
|
|
|
so if a table was:
|
|
|
|
doc.table({
|
|
defaultStyle: { border: 1 },
|
|
columnStyles: { border: { right: 2 } },
|
|
rowStyles: { border: { bottom: 3 } },
|
|
data: [
|
|
[{ border: { left: 4 } }]
|
|
]
|
|
})
|
|
|
|
The resulting cell would have a style of:
|
|
|
|
{
|
|
border: {
|
|
top: 1, // From the default
|
|
right: 2, // From the column
|
|
bottom: 3, // From the row
|
|
left: 4 // From the cell
|
|
}
|
|
}
|
|
|
|
|
|
Internally, PDFKit keeps track of the current X and Y position of table as it
|
|
is added to the document. This way, any calls to `text` or `table` will be placed below the table row.
|
|
|
|
doc
|
|
.text('before')
|
|
.table({
|
|
data: [
|
|
['Column 1', 'Column 2', 'Column 3'],
|
|
['One value goes here', 'Another one here', 'OK?']
|
|
]
|
|
})
|
|
.text('after')
|
|
|
|
![16]()
|
|
|
|
## Table options
|
|
|
|
- `position` - The position of the table (default `{x: doc.x, y: doc.y}`)
|
|
- `maxWidth` - The maximum width the table can expand to (defaults to the remaining content width (offset from the tables position))
|
|
- `columnStyles` - Column definitions of the table. (default `auto`)
|
|
- `rowStyles` - Row definitions of the table. (default `*`)
|
|
- `defaultStyle` - Defaults to apply to every cell
|
|
- `data` - The data to render (not required, you can call `.row()`). This can be an iterable (async or sync)
|
|
- `debug` - Whether to show the debug lines for all the cells (default `false`)
|
|
|
|
## Cell options
|
|
|
|
- `text` - The value, will be cast to a string (`null` and `undefined` are not rendered but the cell is still outlined)
|
|
- `rowSpan` - How many rows this cell covers, follows the same logic as HTML `rowspan`
|
|
- `colSpan` - How many columns this cell covers, follows the same logic as HTML `colspan`
|
|
- `padding` - The padding for the cell (default `0.25em`)
|
|
- `border` - The border for the cell (default `1pt`)
|
|
- `borderColor` - The border colors for the cell (default `black`)
|
|
- `font` - Font options for the cell
|
|
- `backgroundColor` - Set the background color of the cell
|
|
- `align` - The alignment of the cell text (default `{x: 'left', y: 'top'}`)
|
|
- `textStroke` - The text stroke (default `0`)
|
|
- `textStrokeColor` - Sets the text stroke color of the cells text (default `black`)
|
|
- `textColor` - Sets the text color of the cells text (default `black`)
|
|
- `type` - Sets the cell type (for accessibility) (default `TD`)
|
|
- `textOptions` - Sets any text options you wish to provide (such as rotation)
|
|
- `debug` - Whether to show the debug lines for the cell (default `false`)
|
|
|
|
## Column options
|
|
|
|
Extends the [cell options](#cell-options) above with:
|
|
|
|
- `width` - The width of the column (default `*`)
|
|
- `minWidth` - The minimum width of the column (default `0`)
|
|
- `maxWidth` - The maximum width of the column (default `Infinity`)
|
|
|
|
## Row options
|
|
|
|
Extends the [cell options](#cell-options) above with:
|
|
|
|
- `height` - The height of the row (default `auto`)
|
|
- `minHeight` - The minimum height of the row (default `0`)
|
|
- `maxHeight` - The maximum height of the row (default `Infinity`)
|