Rotated document with ReportLab (vertical text)

python, reportlab

Solution

This is the top google result for this question, so I thought I'd post a better solution. My answer comes straight from here

If you are using a doc template, you can use a very lightweight Flowable that will create vertical text in a particular table cell.

# rotatedtext.py
from reportlab.platypus.flowables import Flowable


class verticalText(Flowable):

'''Rotates a text in a table cell.'''

def __init__(self, text):
    Flowable.__init__(self)
    self.text = text

def draw(self):
    canvas = self.canv
    canvas.rotate(90)
    fs = canvas._fontsize
    canvas.translate(1, -fs/1.2)  # canvas._leading?
    canvas.drawString(0, 0, self.text)

def wrap(self, aW, aH):
    canv = self.canv
    fn, fs = canv._fontname, canv._fontsize
    return canv._leading, 1 + canv.stringWidth(self.text, fn, fs)

Then to use it in a doc:

# vertical_text_table.py
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib import colors
from reportlab.lib.colors import HexColor
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import inch
from reportlab.platypus import (
      BaseDocTemplate, Frame, Paragraph, NextPageTemplate,
      PageBreak, PageTemplate, Image, Table, TableStyle, Spacer)
from rotatedtext import verticalText

document = BaseDocTemplate(
    'Vertical.pdf')

Elements = []

titleFrame_1 = Frame(
    0.5*inch, 0.75*inch, 7*inch, 9*inch, id='col1', showBoundary=0)
titleTemplate_1 = PageTemplate(
    id='OneCol', frames=titleFrame_1)
document.addPageTemplates([titleTemplate_1])

cw = [1.2*inch] + [1*inch]*6
rh = [0.25*inch] + [.6*inch] + [0.25*inch]*7

data = [
    ['Some', 'Reporting', '', 'Data', '', 'Here', ''],
    ['', verticalText('Vertical'), verticalText('Text'),
        verticalText('Vertical'), verticalText('Text'),
        verticalText('Vertical'), verticalText('Text')],
    ['Row1', '0', '0', '69', '803', '20751', '11627'],
    ['Row2', '0', '0', '1', '0', '1096', '103'],
    ['Row3', '0', '0', '0', '0', '233', '1'],
    ['Row4', '0', '0', '0', '0', '694', '38'],
    ['Row5', '0', '0', '23', '2', '1319', '2'],
    ['Row6', '0', '0', '0', '0', '0', '0'],
    ['TOTAL', '0', '0', '93', '805', '24093', '11771'],
    ]

ts = [
    ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
    ('SPAN', (1, 0), (2, 0)),
    ('SPAN', (3, 0), (4, 0)),
    ('SPAN', (5, 0), (6, 0)),
    ('SPAN', (0, 0), (0, 1)),
    ('ALIGN', (0, 0), (-1, 1), 'CENTER'),
    ('ALIGN', (0, 2), (-1, -1), 'RIGHT'),
    ('VALIGN', (0, 0), (-1, -2), 'MIDDLE'),
    ('FONT', (0, 0), (-1, 1), 'Helvetica-Bold', 7, 7),
    ('FONT', (0, 2), (0, -2), 'Helvetica-Bold', 7, 7),
    ('FONT', (1, 2), (-1, -2), 'Helvetica', 7, 7),
    ('FONT', (0, -1), (-1, -1), 'Helvetica-Bold', 8, 8),
    ('TEXTCOLOR', (0, -1), (-1, -1), colors.white),
    ('BACKGROUND', (0, -1), (-1, -1), colors.black),
]

t = Table(
    data, style=ts,
    colWidths=cw, rowHeights=rh)

Elements.append(t)
document.build(Elements)

Which gives:

Problem

I'm trying to get something like the following snippet to actually draw this document rotated by 90 degrees. The pagesize is already the way I want it in the end, but the text is still horizontal. How can I rotate the text making it vertical? ``` style = getSampleStyleSheet() normal = style["Normal"] normal.alignment = TA_CENTER normal.fontName = "Helvetica" normal.fontSize = 15 pdf = SimpleDocTemplate("testplatypus.pdf", pagesize = (80, 250), rightMargin=10, leftMargin=10, topMargin=20,bottomMargin=20) story = [] text = "I really need this to be wrapped and vertical!" para = Paragraph(text, normal) story.append(para) pdf.build(story) ```

Original source

Related problems