[reportlab-users] Table entries with VALIGN=MIDDLE are not correct
Tim Roberts
reportlab-users@reportlab.com
Mon, 04 Oct 2004 12:49:45 -0700
There is a bug in the Platypus table handling when VALIGN is set to
MIDDLE. The text is offset way too high, so much so that it will
overlap cell boundaries if they are drawn. You can see this in this
stripped-down version of test_platypus_tables.py:
from reportlab.platypus import Spacer, SimpleDocTemplate, Table, TableStyle
from reportlab.lib.units import inch
from reportlab.lib import colors
style = TableStyle([
('ALIGN', (1,1), (-1,-1), 'RIGHT'),
('ALIGN', (0,0), (-1,0), 'CENTRE'),
('VALIGN',(0,0), (0,-1), 'TOP'),
('VALIGN',(1,0), (1,-1), 'MIDDLE'),
('VALIGN',(2,0), (2,-1), 'BOTTOM'),
('GRID', (0,0), (-1,-1), 0.25, colors.black)
])
doc = SimpleDocTemplate(
'test_platypus_tables.pdf',
pagesize=(8.5*inch, 11*inch),
showBoundary=1
)
txt = 'Line 1\nLine 2'
doc.build(
[
Table(
(
('','North','South','East','West'),
('Quarter 1',txt,txt,txt,txt),
('Quarter 2',txt,txt,txt,txt),
('Total',300,600,900,'1,200')
),
style = style,
rowHeights = (72,)*4
)
]
)
Here is the code from reportlab\platypus\tables.py that implements the
vertical positioning, at line 965:
if valign=='BOTTOM':
y = rowpos + cellstyle.bottomPadding+n*leading-fontsize
elif valign=='TOP':
y = rowpos + rowheight - cellstyle.topPadding - fontsize
elif valign=='MIDDLE':
y = rowpos + (cellstyle.bottomPadding +
rowheight-cellstyle.topPadding+(n-1)*leading)/2.0
else:
raise ValueError, "Bad valign: '%s'" % str(valign)
The problem is in the 'MIDDLE' case. It it computing the center
position of the text block, but it is not properly compensating for the
baseline position of the first line of text. I've played with about a
dozen solutions and drawn charts on my whiteboard for 30 minutes, and I
have come up with two solutions. The first is the one that
theoretically SHOULD be correct:
elif valign=='MIDDLE':
y = rowpos + (cellstyle.bottomPadding +
rowheight-cellstyle.topPadding+(n-1)*leading - fontsize)/2.0
The second is the one that actually gives the most pleasing results, and
is the one that I'm now using:
elif valign=='MIDDLE':
y = rowpos + (cellstyle.bottomPadding +
rowheight-cellstyle.topPadding+n*leading)/2.0 - fontsize
--
- Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.