Files
gh-k-dense-ai-claude-scient…/skills/reportlab/references/tables_reference.md
2025-11-30 08:30:10 +08:00

443 lines
10 KiB
Markdown

# Tables Reference
Comprehensive guide to creating and styling tables in ReportLab.
## Basic Table Creation
```python
from reportlab.platypus import Table, TableStyle
from reportlab.lib import colors
# Simple data (list of lists or tuples)
data = [
['Header 1', 'Header 2', 'Header 3'],
['Row 1, Col 1', 'Row 1, Col 2', 'Row 1, Col 3'],
['Row 2, Col 1', 'Row 2, Col 2', 'Row 2, Col 3'],
]
# Create table
table = Table(data)
# Add to story
story.append(table)
```
## Table Constructor
```python
table = Table(
data, # Required: list of lists/tuples
colWidths=None, # List of column widths or single value
rowHeights=None, # List of row heights or single value
style=None, # TableStyle object
splitByRow=1, # Split across pages by rows (not columns)
repeatRows=0, # Number of header rows to repeat
repeatCols=0, # Number of header columns to repeat
rowSplitRange=None, # Tuple (start, end) of splittable rows
spaceBefore=None, # Space before table
spaceAfter=None, # Space after table
cornerRadii=None, # [TL, TR, BL, BR] for rounded corners
)
```
### Column Widths
```python
from reportlab.lib.units import inch
# Equal widths
table = Table(data, colWidths=2*inch)
# Different widths per column
table = Table(data, colWidths=[1.5*inch, 2*inch, 1*inch])
# Auto-calculate widths (default)
table = Table(data)
# Percentage-based (of available width)
table = Table(data, colWidths=[None, None, None]) # Equal auto-sizing
```
## Cell Content Types
### Text and Newlines
```python
# Newlines work in cells
data = [
['Line 1\nLine 2', 'Single line'],
['Another\nmulti-line\ncell', 'Text'],
]
```
### Paragraph Objects
```python
from reportlab.platypus import Paragraph
from reportlab.lib.styles import getSampleStyleSheet
styles = getSampleStyleSheet()
data = [
[Paragraph("Formatted <b>bold</b> text", styles['Normal']),
Paragraph("More <i>italic</i> text", styles['Normal'])],
]
table = Table(data)
```
### Images
```python
from reportlab.platypus import Image
data = [
['Description', Image('logo.png', width=1*inch, height=1*inch)],
['Product', Image('product.jpg', width=2*inch, height=1.5*inch)],
]
table = Table(data)
```
### Nested Tables
```python
# Create inner table
inner_data = [['A', 'B'], ['C', 'D']]
inner_table = Table(inner_data)
# Use in outer table
outer_data = [
['Label', inner_table],
['Other', 'Content'],
]
outer_table = Table(outer_data)
```
## TableStyle
Styles are applied using command lists:
```python
from reportlab.platypus import TableStyle
from reportlab.lib import colors
style = TableStyle([
# Command format: ('COMMAND', (startcol, startrow), (endcol, endrow), *args)
('GRID', (0, 0), (-1, -1), 1, colors.black), # Grid over all cells
('BACKGROUND', (0, 0), (-1, 0), colors.grey), # Header background
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke), # Header text color
])
table = Table(data)
table.setStyle(style)
```
### Cell Coordinate System
- Columns and rows are 0-indexed: `(col, row)`
- Negative indices count from end: `-1` is last column/row
- `(0, 0)` is top-left cell
- `(-1, -1)` is bottom-right cell
```python
# Examples:
(0, 0), (2, 0) # First three cells of header row
(0, 1), (-1, -1) # All cells except header
(0, 0), (-1, -1) # Entire table
```
## Styling Commands
### Text Formatting
```python
style = TableStyle([
# Font name
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
# Font size
('FONTSIZE', (0, 0), (-1, -1), 10),
# Text color
('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
('TEXTCOLOR', (0, 1), (-1, -1), colors.black),
# Combined font command
('FONT', (0, 0), (-1, 0), 'Helvetica-Bold', 12), # name, size
])
```
### Alignment
```python
style = TableStyle([
# Horizontal alignment: LEFT, CENTER, RIGHT, DECIMAL
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('ALIGN', (0, 1), (0, -1), 'LEFT'), # First column left
('ALIGN', (1, 1), (-1, -1), 'RIGHT'), # Other columns right
# Vertical alignment: TOP, MIDDLE, BOTTOM
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
('VALIGN', (0, 0), (-1, 0), 'BOTTOM'), # Header bottom-aligned
])
```
### Cell Padding
```python
style = TableStyle([
# Individual padding
('LEFTPADDING', (0, 0), (-1, -1), 12),
('RIGHTPADDING', (0, 0), (-1, -1), 12),
('TOPPADDING', (0, 0), (-1, -1), 6),
('BOTTOMPADDING', (0, 0), (-1, -1), 6),
# Or set all at once by setting each
])
```
### Background Colors
```python
style = TableStyle([
# Solid background
('BACKGROUND', (0, 0), (-1, 0), colors.blue),
('BACKGROUND', (0, 1), (-1, -1), colors.lightgrey),
# Alternating row colors
('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.white, colors.lightblue]),
# Alternating column colors
('COLBACKGROUNDS', (0, 0), (-1, -1), [colors.white, colors.lightgrey]),
])
```
### Gradient Backgrounds
```python
from reportlab.lib.colors import Color
style = TableStyle([
# Vertical gradient (top to bottom)
('BACKGROUND', (0, 0), (-1, 0), colors.blue),
('VERTICALGRADIENT', (0, 0), (-1, 0),
[colors.blue, colors.lightblue]),
# Horizontal gradient (left to right)
('HORIZONTALGRADIENT', (0, 1), (-1, 1),
[colors.red, colors.yellow]),
])
```
### Lines and Borders
```python
style = TableStyle([
# Complete grid
('GRID', (0, 0), (-1, -1), 1, colors.black),
# Box/outline only
('BOX', (0, 0), (-1, -1), 2, colors.black),
('OUTLINE', (0, 0), (-1, -1), 2, colors.black), # Same as BOX
# Inner grid only
('INNERGRID', (0, 0), (-1, -1), 0.5, colors.grey),
# Directional lines
('LINEABOVE', (0, 0), (-1, 0), 2, colors.black), # Header border
('LINEBELOW', (0, 0), (-1, 0), 1, colors.black), # Header bottom
('LINEBEFORE', (0, 0), (0, -1), 1, colors.black), # Left border
('LINEAFTER', (-1, 0), (-1, -1), 1, colors.black), # Right border
# Thickness and color
('LINEABOVE', (0, 1), (-1, 1), 0.5, colors.grey), # Thin grey line
])
```
### Cell Spanning
```python
data = [
['Spanning Header', '', ''], # Span will merge these
['A', 'B', 'C'],
['D', 'E', 'F'],
]
style = TableStyle([
# Span 3 columns in first row
('SPAN', (0, 0), (2, 0)),
# Center the spanning cell
('ALIGN', (0, 0), (2, 0), 'CENTER'),
])
table = Table(data)
table.setStyle(style)
```
**Important:** Cells that are spanned over must contain empty strings `''`.
### Advanced Spanning Examples
```python
# Span multiple rows and columns
data = [
['A', 'B', 'B', 'C'],
['A', 'D', 'E', 'F'],
['A', 'G', 'H', 'I'],
]
style = TableStyle([
# Span rows in column 0
('SPAN', (0, 0), (0, 2)), # Merge A cells vertically
# Span columns in row 0
('SPAN', (1, 0), (2, 0)), # Merge B cells horizontally
('GRID', (0, 0), (-1, -1), 1, colors.black),
])
```
## Special Commands
### Rounded Corners
```python
table = Table(data, cornerRadii=[5, 5, 5, 5]) # [TL, TR, BL, BR]
# Or in style
style = TableStyle([
('ROUNDEDCORNERS', [10, 10, 0, 0]), # Rounded top corners only
])
```
### No Split
Prevent table from splitting at specific locations:
```python
style = TableStyle([
# Don't split between rows 0 and 2
('NOSPLIT', (0, 0), (-1, 2)),
])
```
### Split-Specific Styling
Apply styles only to first or last part when table splits:
```python
style = TableStyle([
# Style for first part after split
('LINEBELOW', (0, 'splitfirst'), (-1, 'splitfirst'), 2, colors.red),
# Style for last part after split
('LINEABOVE', (0, 'splitlast'), (-1, 'splitlast'), 2, colors.blue),
])
```
## Repeating Headers
```python
# Repeat first row on each page
table = Table(data, repeatRows=1)
# Repeat first 2 rows
table = Table(data, repeatRows=2)
```
## Complete Examples
### Styled Report Table
```python
from reportlab.platypus import Table, TableStyle
from reportlab.lib import colors
from reportlab.lib.units import inch
data = [
['Product', 'Quantity', 'Unit Price', 'Total'],
['Widget A', '10', '$5.00', '$50.00'],
['Widget B', '5', '$12.00', '$60.00'],
['Widget C', '20', '$3.00', '$60.00'],
['', '', 'Subtotal:', '$170.00'],
]
table = Table(data, colWidths=[2.5*inch, 1*inch, 1*inch, 1*inch])
style = TableStyle([
# Header row
('BACKGROUND', (0, 0), (-1, 0), colors.darkblue),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, 0), 12),
('ALIGN', (0, 0), (-1, 0), 'CENTER'),
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
# Data rows
('BACKGROUND', (0, 1), (-1, -2), colors.beige),
('GRID', (0, 0), (-1, -2), 0.5, colors.grey),
('ALIGN', (1, 1), (-1, -1), 'RIGHT'),
('ALIGN', (0, 1), (0, -1), 'LEFT'),
# Total row
('BACKGROUND', (0, -1), (-1, -1), colors.lightgrey),
('LINEABOVE', (0, -1), (-1, -1), 2, colors.black),
('FONTNAME', (2, -1), (-1, -1), 'Helvetica-Bold'),
])
table.setStyle(style)
```
### Alternating Row Colors
```python
data = [
['Name', 'Age', 'City'],
['Alice', '30', 'New York'],
['Bob', '25', 'Boston'],
['Charlie', '35', 'Chicago'],
['Diana', '28', 'Denver'],
]
table = Table(data, colWidths=[2*inch, 1*inch, 1.5*inch])
style = TableStyle([
# Header
('BACKGROUND', (0, 0), (-1, 0), colors.darkslategray),
('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
# Alternating rows (zebra striping)
('ROWBACKGROUNDS', (0, 1), (-1, -1),
[colors.white, colors.lightgrey]),
# Borders
('BOX', (0, 0), (-1, -1), 2, colors.black),
('LINEBELOW', (0, 0), (-1, 0), 2, colors.black),
# Padding
('LEFTPADDING', (0, 0), (-1, -1), 12),
('RIGHTPADDING', (0, 0), (-1, -1), 12),
('TOPPADDING', (0, 0), (-1, -1), 6),
('BOTTOMPADDING', (0, 0), (-1, -1), 6),
])
table.setStyle(style)
```
## Best Practices
1. **Set colWidths explicitly** for consistent layout
2. **Use repeatRows** for multi-page tables with headers
3. **Apply padding** for better readability (especially LEFTPADDING and RIGHTPADDING)
4. **Use ROWBACKGROUNDS** for alternating colors instead of styling each row
5. **Put empty strings** in cells that will be spanned
6. **Test page breaks** early with realistic data amounts
7. **Use Paragraph objects** in cells for complex formatted text
8. **Set VALIGN to MIDDLE** for better appearance with varying row heights
9. **Keep tables simple** - complex nested tables are hard to maintain
10. **Use consistent styling** - define once, apply to all tables