0
# Tables
1
2
Structured table creation with comprehensive layout and styling options for professional document formatting.
3
4
## Capabilities
5
6
### Table Creation
7
8
Create structured tables with flexible data input and extensive styling options.
9
10
```javascript { .api }
11
/**
12
* Create a new table
13
* @param options - Table configuration options
14
* @returns PDFTable instance for adding rows
15
*/
16
table(options?: TableOptions): PDFTable;
17
18
interface TableOptions {
19
/** Table data as array of arrays or objects */
20
data?: any[][];
21
/** Column headers */
22
headers?: string[];
23
/** Column widths (points or percentages) */
24
columnWidths?: (number | string)[];
25
/** Table width */
26
width?: number;
27
/** Table position */
28
x?: number;
29
y?: number;
30
/** Cell padding */
31
padding?: number | [number, number] | [number, number, number, number];
32
/** Row height */
33
rowHeight?: number;
34
/** Header row styling */
35
headerStyle?: CellStyle;
36
/** Data row styling */
37
rowStyle?: CellStyle;
38
/** Alternating row styling */
39
alternatingRowStyle?: CellStyle;
40
/** Border styling */
41
borderStyle?: BorderStyle;
42
/** Text alignment */
43
align?: 'left' | 'center' | 'right';
44
/** Vertical alignment */
45
valign?: 'top' | 'center' | 'bottom';
46
}
47
48
interface CellStyle {
49
fontSize?: number;
50
font?: string;
51
fillColor?: ColorValue;
52
textColor?: ColorValue;
53
padding?: number | [number, number] | [number, number, number, number];
54
}
55
56
interface BorderStyle {
57
width?: number;
58
color?: ColorValue;
59
style?: 'solid' | 'dashed' | 'dotted';
60
}
61
```
62
63
**Usage Examples:**
64
65
```javascript
66
// Basic table creation
67
const table = doc.table({
68
headers: ['Name', 'Age', 'City'],
69
data: [
70
['Alice', '25', 'New York'],
71
['Bob', '30', 'Los Angeles'],
72
['Charlie', '35', 'Chicago']
73
]
74
});
75
76
// Table with custom styling
77
const styledTable = doc.table({
78
headers: ['Product', 'Price', 'Quantity', 'Total'],
79
columnWidths: [200, 80, 80, 100],
80
headerStyle: {
81
fontSize: 12,
82
font: 'Helvetica-Bold',
83
fillColor: '#f0f0f0',
84
textColor: '#000000'
85
},
86
rowStyle: {
87
fontSize: 10,
88
padding: 5
89
},
90
borderStyle: {
91
width: 1,
92
color: '#cccccc'
93
}
94
});
95
```
96
97
### Table Instance Methods
98
99
Build tables row by row with fine control over content and styling.
100
101
```javascript { .api }
102
interface PDFTable {
103
/**
104
* Add a row to the table
105
* @param data - Row data as array
106
* @param isLastRow - Whether this is the last row
107
* @returns Table instance for chaining, or document if last row
108
*/
109
row(data: any[], isLastRow?: boolean): PDFTable | PDFDocument;
110
111
/**
112
* End table construction
113
* @returns Document instance for chaining
114
*/
115
end(): PDFDocument;
116
117
/** Current table position */
118
x: number;
119
y: number;
120
121
/** Table dimensions */
122
width: number;
123
height: number;
124
}
125
```
126
127
**Usage Examples:**
128
129
```javascript
130
// Build table row by row
131
const table = doc.table({
132
headers: ['Item', 'Description', 'Amount'],
133
columnWidths: [100, 250, 100]
134
});
135
136
// Add data rows
137
table.row(['Item 1', 'First item description', '$10.00']);
138
table.row(['Item 2', 'Second item description', '$15.50']);
139
table.row(['Item 3', 'Third item description', '$8.75']);
140
141
// Add total row with different styling
142
table.row(['', 'Total:', '$34.25'], true);
143
144
// End table construction
145
table.end();
146
```
147
148
### Advanced Table Features
149
150
Create complex tables with merged cells, nested content, and conditional formatting.
151
152
```javascript { .api }
153
interface AdvancedTableOptions extends TableOptions {
154
/** Enable automatic page breaks */
155
pageBreak?: boolean;
156
/** Header repetition on new pages */
157
repeatHeader?: boolean;
158
/** Cell merging specifications */
159
mergedCells?: MergedCell[];
160
/** Conditional row formatting */
161
conditionalFormatting?: ConditionalFormat[];
162
}
163
164
interface MergedCell {
165
startRow: number;
166
endRow: number;
167
startCol: number;
168
endCol: number;
169
content: string;
170
style?: CellStyle;
171
}
172
173
interface ConditionalFormat {
174
condition: (rowData: any[], rowIndex: number) => boolean;
175
style: CellStyle;
176
}
177
```
178
179
**Usage Examples:**
180
181
```javascript
182
// Table with page breaks and header repetition
183
const reportTable = doc.table({
184
headers: ['Date', 'Transaction', 'Debit', 'Credit', 'Balance'],
185
pageBreak: true,
186
repeatHeader: true,
187
headerStyle: {
188
fontSize: 10,
189
font: 'Helvetica-Bold',
190
fillColor: '#d0d0d0'
191
},
192
conditionalFormatting: [
193
{
194
condition: (rowData) => parseFloat(rowData[4]) < 0,
195
style: { textColor: 'red' }
196
}
197
]
198
});
199
200
// Add many rows (will break across pages)
201
for (let i = 0; i < 100; i++) {
202
reportTable.row([
203
`2024-01-${String(i + 1).padStart(2, '0')}`,
204
`Transaction ${i + 1}`,
205
i % 3 === 0 ? '$100.00' : '',
206
i % 3 !== 0 ? '$50.00' : '',
207
`$${(1000 + i * 25).toFixed(2)}`
208
]);
209
}
210
211
reportTable.end();
212
```
213
214
### Data-Driven Tables
215
216
Create tables from structured data sources with automatic formatting.
217
218
**Usage Examples:**
219
220
```javascript
221
// Table from object array
222
const salesData = [
223
{ product: 'Laptop', region: 'North', sales: 1250, target: 1000 },
224
{ product: 'Mouse', region: 'South', sales: 890, target: 900 },
225
{ product: 'Keyboard', region: 'East', sales: 1100, target: 1200 },
226
{ product: 'Monitor', region: 'West', sales: 750, target: 800 }
227
];
228
229
const salesTable = doc.table({
230
headers: ['Product', 'Region', 'Sales', 'Target', 'Performance'],
231
columnWidths: [100, 80, 80, 80, 100],
232
data: salesData.map(item => [
233
item.product,
234
item.region,
235
`$${item.sales}`,
236
`$${item.target}`,
237
`${((item.sales / item.target) * 100).toFixed(1)}%`
238
]),
239
conditionalFormatting: [
240
{
241
condition: (rowData) => {
242
const performance = parseFloat(rowData[4]);
243
return performance >= 100;
244
},
245
style: { fillColor: '#e8f5e8', textColor: '#2e7d32' }
246
},
247
{
248
condition: (rowData) => {
249
const performance = parseFloat(rowData[4]);
250
return performance < 90;
251
},
252
style: { fillColor: '#ffebee', textColor: '#c62828' }
253
}
254
]
255
});
256
```
257
258
### Financial Tables
259
260
Specialized formatting for financial and numerical data.
261
262
**Usage Examples:**
263
264
```javascript
265
// Financial report table
266
const financialTable = doc.table({
267
headers: ['Account', 'Q1', 'Q2', 'Q3', 'Q4', 'Total'],
268
columnWidths: [150, 80, 80, 80, 80, 100],
269
headerStyle: {
270
fontSize: 11,
271
font: 'Helvetica-Bold',
272
fillColor: '#f5f5f5',
273
textColor: '#333333'
274
},
275
rowStyle: {
276
fontSize: 10,
277
padding: [3, 8, 3, 8]
278
},
279
align: 'right' // Right-align numbers
280
});
281
282
const accounts = [
283
['Revenue', 125000, 132000, 145000, 155000, 557000],
284
['Cost of Goods', -45000, -48000, -52000, -55000, -200000],
285
['Gross Profit', 80000, 84000, 93000, 100000, 357000],
286
['Operating Expenses', -35000, -37000, -40000, -42000, -154000],
287
['Net Income', 45000, 47000, 53000, 58000, 203000]
288
];
289
290
accounts.forEach((account, index) => {
291
const isTotal = account[0] === 'Net Income';
292
const formattedRow = [
293
account[0],
294
...account.slice(1).map(val =>
295
val < 0 ? `(${Math.abs(val).toLocaleString()})` : val.toLocaleString()
296
)
297
];
298
299
financialTable.row(formattedRow, index === accounts.length - 1);
300
});
301
```
302
303
## Table Layout Patterns
304
305
### Multi-Section Reports
306
307
```javascript
308
// Create report with multiple table sections
309
doc.fontSize(16).text('Quarterly Sales Report', 100, 100);
310
311
// Summary table
312
doc.fontSize(12).text('Executive Summary', 100, 150);
313
const summaryTable = doc.table({
314
x: 100,
315
y: 170,
316
headers: ['Metric', 'Q4 2023', 'Q1 2024', 'Change'],
317
data: [
318
['Total Sales', '$2.1M', '$2.3M', '+9.5%'],
319
['New Customers', '1,250', '1,420', '+13.6%'],
320
['Retention Rate', '89%', '92%', '+3%']
321
]
322
});
323
summaryTable.end();
324
325
// Detailed breakdown
326
doc.fontSize(12).text('Regional Breakdown', 100, 280);
327
const regionalTable = doc.table({
328
x: 100,
329
y: 300,
330
headers: ['Region', 'Sales', 'Growth', 'Market Share'],
331
data: [
332
['North America', '$1.2M', '+12%', '52%'],
333
['Europe', '$750K', '+8%', '33%'],
334
['Asia Pacific', '$350K', '+15%', '15%']
335
]
336
});
337
regionalTable.end();
338
```
339
340
### Invoice Tables
341
342
```javascript
343
// Invoice line items table
344
const invoiceTable = doc.table({
345
headers: ['Description', 'Qty', 'Rate', 'Amount'],
346
columnWidths: [250, 60, 80, 100],
347
headerStyle: {
348
fontSize: 11,
349
font: 'Helvetica-Bold',
350
fillColor: '#f8f9fa'
351
}
352
});
353
354
const lineItems = [
355
['Web Development Services', '40', '$125.00', '$5,000.00'],
356
['UI/UX Design', '20', '$100.00', '$2,000.00'],
357
['Project Management', '10', '$150.00', '$1,500.00']
358
];
359
360
lineItems.forEach(item => {
361
invoiceTable.row(item);
362
});
363
364
// Totals section
365
invoiceTable.row(['', '', 'Subtotal:', '$8,500.00']);
366
invoiceTable.row(['', '', 'Tax (8.5%):', '$722.50']);
367
invoiceTable.row(['', '', 'Total:', '$9,222.50'], true);
368
```
369
370
## Best Practices
371
372
### Performance Optimization
373
374
```javascript
375
// Pre-calculate table dimensions
376
const tableWidth = 500;
377
const columnCount = 4;
378
const columnWidth = tableWidth / columnCount;
379
380
// Use consistent column widths
381
const optimizedTable = doc.table({
382
columnWidths: Array(columnCount).fill(columnWidth),
383
width: tableWidth
384
});
385
```
386
387
### Responsive Design
388
389
```javascript
390
// Adjust table based on page size
391
const pageWidth = doc.page.width - doc.page.margins.left - doc.page.margins.right;
392
const table = doc.table({
393
width: Math.min(pageWidth, 600), // Don't exceed page width
394
columnWidths: ['30%', '40%', '30%'] // Use percentages for flexibility
395
});
396
```
397
398
### Data Validation
399
400
```javascript
401
// Validate data before table creation
402
function createSafeTable(data, headers) {
403
// Ensure all rows have same column count
404
const columnCount = headers.length;
405
const validatedData = data.map(row => {
406
const paddedRow = [...row];
407
while (paddedRow.length < columnCount) {
408
paddedRow.push('');
409
}
410
return paddedRow.slice(0, columnCount);
411
});
412
413
return doc.table({
414
headers,
415
data: validatedData
416
});
417
}
418
```