or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

accessibility-features.mdattachments.mdcolor-management.mddocument-management.mdfont-management.mdimage-handling.mdindex.mdinteractive-elements.mdoutline.mdtables.mdtext-rendering.mdvector-graphics.md

tables.mddocs/

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

```