7

我试图获得类似以下片段的内容,以实际绘制旋转 90 度的文档。页面大小最终已经是我想要的方式,但文本仍然是水平的。如何旋转文本使其垂直?

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)
4

5 回答 5

12

这是这个问题的最高谷歌结果,所以我想我会发布一个更好的解决方案。我的答案直接来自这里

如果您使用的是 doc 模板,则可以使用非常轻量级的 Flowable,它将在特定的表格单元格中创建垂直文本。

# 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)

然后在文档中使用它:

# 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)

这使:

带有垂直文本的表格。

于 2016-10-31T19:15:46.503 回答
2

我找到了一个简单的方法来解决这个 USING canvas.drawString()。它在一个常规的 python 函数中。下面示例中的“WHATEVER TEXT”将在您的 pdf 上垂直渲染文本。阅读代码中的注释以充分了解如何实现这一点。

def lista_privados(request, pk):
    g1 = get_object_or_404(Grupo, pk=pk)
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="{}"'.format(g1)
    buffer = BytesIO()
    c = canvas.Canvas(buffer, pagesize=A4)
    c.setPageSize(landscape(letter))

    #Whatever your other code is

重要的是它只在最后,在你的 showPage() 之前有效

    c.rotate(90)
    c.drawString(16*cm, -14*cm, "WHATEVER TEXT 1")
    c.drawString(16*cm, -14.4*cm, "WHATEVER TEXT 2")
            #c.drawString(x*cm, y*cm, "TEXT YOU WANT TO DISPLAY VERICALLY")
            #Note the '-' is VERY IMPORTANT OR IT WON'T WORK
            #ONLY WRITE THE c.rotate(90) one, you can list as many 'c.drawString(16*cm, -14*cm, "WHATEVER TEXT")' as you wish
            #The font size will be the last one you set on your code, so if for example you do "c.setFont('Helvetica', 5)" just the "c.rotate(90)", "WHATEVER TEXT" will be Helvetica, 5.

    c.showPage() #save page

    c.save()
    pdf = buffer.getvalue()
    buffer.close()
    response.write(pdf)
    template = 'privados/imp_list.html'
    return response
于 2019-01-17T03:32:38.967 回答
1

也许您可以通过添加构建方法来做到这一点。

就是这样。

pdf = SimpleDocTemplate("testplatypus.pdf", pagesize = (80, 250), rightMargin=10,  leftMargin=10, topMargin=20,bottomMargin=20)
pdf.build(Story, onFirstPage = myFirstPage, onLaterPages=myLaterPages)

def myFirstPage(canvas, doc):
            canvas.saveState()
            canvas.rotate(90)
            canvas.restoreState()


def myLaterPages(canvas, doc):
            canvas.saveState()
            canvas.rotate(90)
            canvas.restoreState()
于 2013-01-26T12:54:29.723 回答
1

受 KJYDavis 发布的解决方案的启发,我制作了一个 VerticalParagraph,以便它支持段落所具有的样式功能,例如 ParaghaphStyle、XML 标记标签和段落内标记(Reportlab 文档第 6 章

from reportlab.platypus import Paragraph


class VerticalParagraph(Paragraph):
"""Paragraph that is printed vertically"""

    def __init__(self, args, **kwargs):
        super().__init__(args, **kwargs)
        self.horizontal_position = -self.style.leading

    def draw(self):
        """ Draw text """
        canvas = self.canv
        canvas.rotate(90)
        canvas.translate(1, self.horizontal_position)
        super().draw()

    def wrap(self, available_width, _):
        """ Wrap text in table """
        string_width = self.canv.stringWidth(
            self.getPlainText(), self.style.fontName, self.style.fontSize
        )
        self.horizontal_position = - (available_width + self.style.leading) / 2
        height, _ = super().wrap(availWidth=1 + string_width, availHeight=available_width)
        return self.style.leading, height

它可以像使用 Paragraph flowable 一样使用,尽管我只在表格中尝试过。

stylesheet = getSampleStyleSheet()
text = VerticalParagraph('<para align="CENTER">Some <b>BOLD</b> <i>Text</i></para>', stylesheet['BodyText'])

另一个好处是这个版本不需要直接访问 Canvas 的私有成员,例如_fontname,_fontsize_leading,如果您的项目使用 pylint 或类似的东西,这很好。

于 2021-04-30T20:24:39.523 回答
-1

如果您想将水平文本转换为垂直文本,我找到了一种简单直接的方法。

def your_function_name(request, pk):
    g1 = get_object_or_404(Grupo, pk=pk)
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=Plista2.pdf'
    buffer = BytesIO()
    c = canvas.Canvas(buffer, pagesize=A4)
c.setPageSize(landscape(letter))
于 2019-01-17T03:25:58.807 回答