How can I achieve the horizontal align result with a Reportlab table vertically? As seen below, the table correctly aligns horizontally by filling the available space within the frame and then centering the cells within that space. I want the table to fill the frame vertically the same way it does horizontally well and then center the cells accordingly. Or, a possible alternative could be centering the table itself within the frame.
Current code:
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
from reportlab.lib import colors
from reportlab.platypus import (
Frame, Flowable, PageTemplate,
BaseDocTemplate, TableStyle, Table,
NextPageTemplate,
)
class Square(Flowable):
def __init__(self):
super().__init__()
self.width = inch
self.height = inch
def __repr__(self):
return "Square"
def draw(self):
"""
draw the line
"""
self.canv.setFillColorRGB(255, 0, 0)
self.canv.rect(0, 0, self.width, self.height, fill=True)
medium_margin = inch * .5
small_margin = inch * .25
segment_table_width = letter[0] - medium_margin * 2
segment_table_height = inch * 3
segment_table_frame = Frame(
medium_margin,
medium_margin,
segment_table_width,
segment_table_height,
showBoundary=True,
leftPadding=0,
bottomPadding=0,
rightPadding = 0,
topPadding=0
)
segment_cover = PageTemplate(
"segment-cover",
frames=[
segment_table_frame
],
pagesize=letter
)
template = BaseDocTemplate(
filename = "example.pdf",
pageTemplates=[segment_cover],
pageSize = letter
)
story = []
table_data = [[Square() for j in range(5)] for i in range(20)]
table_style = TableStyle([
('ALIGN', (0,0), (-1,-1), 'CENTER'),
("BACKGROUND", (0,0), (-1,-1), colors.green)
])
table = Table(table_data, style=table_style)
parts = table.split(segment_table_width, segment_table_height)
table1, table2 = parts
story.append(NextPageTemplate("segment-cover"))
story.append(table1)
template.build(story)
CodePudding user response:
Ended up creating a custom flowable for vertically centering a flowable within a frame. Only works if there is only one flowable in the frame.
def get_frame_size(frame : Frame):
return (frame._width, frame._height)
class CenterFlowable(Flowable):
"""
center flowable vertically within a frame
frame : the frame it is being centered in
flowable : the floawable that is being centered
"""
def __init__(self, frame : Frame, flowable : Flowable):
super().__init__()
self.frame = frame
self.flowable = flowable
self.width, self.height = get_frame_size(frame)
def draw(self):
table_style = TableStyle([
("ALIGN", (0,0), (-1,-1), "CENTER"),
("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
("BOTTOMPADDING", (0, 0), (-1, -1), 0),
("TOPPADDING", (0, 0), (-1, -1), 0),
])
table = Table(
[[self.flowable]],
colWidths=self.width,
rowHeights=self.height,
style=table_style
)
table.wrapOn(self.canv, 0, 0)
table.drawOn(self.canv, 0, 0)
Can be used by wrapping it around the flowable you want to center:
story = [] #document story
story.append(CenterFlowable(frame, flowable_i_want_to_center_in_frame))