python wrap text and reportlab - python

I have a little code and I would like to wrap my long string in every 10th character and then add it into a PDF using reportlab:
This is how I try:
text = '*long_text_long_text_long_text_long_text*'
text = "\n".join(wrap(text, 10))
canvas.drawString(5,227, text)
My pdf was created but where I want to break the lines I can only see black rectangles. You can see the attached picture:
Can you help me? Thank you!

drawString draws a single line. so you will need to adjust the coordinate for each line in a loop.
y = 227
for line in wrap(text, 10):
canvas.drawString(5, y, line)
y += 15

An alternative to placing each line individually is using Paragraph:
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A5
from reportlab.platypus import Paragraph
text = "long text<br />long text<br />long text<br />"
text_width=A5[0] / 2
text_height=A5[1] / 2
x = A5[0]/4
y = A5[1]/4
pdf = canvas.Canvas(filename="test.pdf", pagesize=A5)
styles = getSampleStyleSheet()
p = Paragraph(text, styles["Normal"])
p.wrapOn(pdf, text_width, text_height)
p.drawOn(pdf, x, y)
pdf.save()
In addition to supporting manually put line breaks, the Paragraph also supports automatic line breaks.

Related

Highlighting substrings in print statements

I have been trying to write a short script to be run directly in jupyter notebook. It simply scrolls through texts (400 words on avg.) in pandas df and asks user for a label.
I am struggling with finding an elegant solution that would highlight all substrings 'eu' in the text to be printed out.
In an other thread, I have found this printmd function that I use to highlight the "eu" substring. However, this only works for the first appearance and breaks the lines as well.
import sys
from IPython.display import clear_output
from IPython.display import Markdown, display
def printmd(string):
display(Markdown(string))
printmd('**bold**')
labels = []
for i in range(0,len(SampleDf)):
clear_output() # clear the output before displaying another article
print(SampleDf.loc[i]['article_title'])
lc = SampleDf.loc[i]['article_body'].lower() # the search is case sensitive
pos = lc.find('eu') # where is the 'eu' mentioned
print(SampleDf.loc[i]['article_body'][:pos])
printmd('**eu**')
print(SampleDf.loc[i]['article_body'][pos+2:])
var = input("press y if the text is irrelevant" )
if var == 'y':
label = 0 # 0 for thrash
else:
label = 1 # 1 for relevant
labels.append(label)
I would love to get rid of the line breaks introduced by the separate print statements and highlight all mentions of the "eu".
Look at this as string processing, not an output problem. If I'm understanding your needs properly, this is a simple replace usage:
new_text = old_text.replace("eu", "**eu**")
If you still need your single-token mode, then
suppressing a line feed is a simple matter of using the print parameter for that purpose:
print('**eu**', end='')

Python docx library text align

I am using python docx library to manipulate a word document. However I can't find how to align a line to the center in the documents page of that library. I can't find by google either.
from docx import Document
document = Document()
p = document.add_paragraph('A plain paragraph having some ')
p.add_run('bold').bold = True
p.add_run(' and some ')
p.add_run('italic.').italic = True
How can I align the text in docx?
With the new version of python-docx 0.7 https://github.com/python-openxml/python-docx/commit/158f2121bcd2c58b258dec1b83f8fef15316de19
Add feature #51: Paragraph.alignment (read/write)
Now it is possible to align a paragraph as here: http://python-docx.readthedocs.org/en/latest/dev/analysis/features/par-alignment.html
paragraph = document.add_paragraph("This is a text")
paragraph.alignment = 0 # for left, 1 for center, 2 right, 3 justify ....
edit from comments
actually it is 0 for left, 1 for center, 2 for right
edit 2 from comments
You shouldn't hard code magic numbers like this. Use WD_ALIGN_PARAGRAPH.CENTER to get the correct value for centering, etc. To do this use the following import
from docx.enum.text import WD_ALIGN_PARAGRAPH
p = document.add_paragraph('A plain paragraph having some ',style='BodyText', breakbefore=False, jc='left')# #param string jc: Paragraph alignment, possible values:left, center, right, both (justified), ...
for reference see this reference at def paragraph read the documentation

ReportLab: Text with large font size is crammed within paragraph

Using ReportLab, I want to render a block of text with a large font size. Right now, my code places the text within a Paragraph so it can be word wrapped. However, the text turns out crammed together when rendered.
It seems like the height I specified for the Paragraph object is not being taken into account. Is there an attribute for Paragraph that I can add to fix this?
My Code Below:
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
from reportlab.platypus import Paragraph
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER
doc = canvas.Canvas('test.pdf')
p = ParagraphStyle('test')
p.textColor = 'black'
p.borderColor = 'black'
p.borderWidth = 1
p.alignment = TA_CENTER
p.fontSize = 100
para = Paragraph("THIS IS A REALLY LONG AND BIG STRING OF TEXT RIGHT HERE!!!!!", p)
para.wrapOn(doc,1200,1000)
para.drawOn(doc, 0.5*inch, 6*inch)
doc.save()
The answer is to set the leading attribute to 120:
p.leading = 120
By default, a style has a fontSize of 10 with a leading value of 12. The leading parameter specifies the distance down to move when advancing from one text line to the next.

How to add space between lines within a single paragraph with Reportlab

I have a block of text that is dynamically pulled from a database and is placed in a PDF before being served to a user. The text is being placed onto a lined background, much like notepad paper. I want to space the text so that only one line of text is between each background line.
I was able to use the following code to create a vertical spacing between paragraphs (used to generate another part of the PDF).
style = getSampleStyleSheet()['Normal']
style.fontName = 'Helvetica'
style.spaceAfter = 15
style.alignment = TA_JUSTIFY
story = [Paragraph(choice.value,style) for choice in chain(context['question1'].itervalues(),context['question2'].itervalues())]
generated_file = StringIO()
frame1 = Frame(50,100,245,240, showBoundary=0)
frame2 = Frame(320,100,245,240, showBoundary=0)
page_template = PageTemplate(frames=[frame1,frame2])
doc = BaseDocTemplate(generated_file,pageTemplates=[page_template])
doc.build(story)
However, this won't work here because I have only a single, large paragraph.
Pretty sure what yo u want to change is the leading. From the user manual in chapter 6.
To get double-spaced text, use a high
leading. If you set
autoLeading(default "off") to
"min"(use observed leading even if
smaller than specified) or "max"(use
the larger of observed and specified)
then an attempt is made to determine
the leading on a line by line basis.
This may be useful if the lines
contain different font sizes etc.
Leading is defined earlier in chapter 2:
Interline spacing (Leading)
The vertical offset between the point
at which one line starts and where the
next starts is called the leading
offset.
So try different values of leading, for example:
style = getSampleStyleSheet()['Normal']
style.leading = 24
Add leading to ParagraphStyle
orden = ParagraphStyle('orden')
orden.leading = 14
orden.borderPadding = 10
orden.backColor=colors.gray
orden.fontSize = 14
Generate PDF
buffer = BytesIO()
p = canvas.Canvas(buffer, pagesize=letter)
text = Paragraph("TEXT Nro 0001", orden)
text.wrapOn(p,500,10)
text.drawOn(p, 45, 200)
p.showPage()
p.save()
pdf = buffer.getvalue()
buffer.close()
The result

Word wrap on report lab PDF table

I'm using the Table of Report Lab library to print a table on a PDF report. I would like to know if it's possible to configure the table to perform an automatic wrapping of the content of a cell.
For example, I have a text that doesn't fit on a cell inside a column. I would like that the table performs the wrap automatically adjusting the content of the cells to fit on the columns width. Is it possible?
You can put any flowable in a table element. It is probably good practice to have all table elements as flowables, so they can be styled the same. For your case you will most likely need a Paragraph flowable. eg.
styles = getSampleStyleSheet()
text = Paragraph("long line",
styles['Normal'])
You can put `text' into the data you feed to a table and it will automatically wrap.
My solution, force newline in the string:
def __chopLine(line, maxline):
cant = len(line) / maxline
cant += 1
strline = ""
index = maxline
for i in range(1,cant):
index = maxline * i
strline += "%s\n" %(line[(index-maxline):index])
strline += "%s\n" %(line[index:])
return strline
*whole code of word wrap
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import Paragraph, Table, TableStyle
from reportlab.lib.enums import TA_JUSTIFY, TA_LEFT, TA_CENTER
from reportlab.lib import colors
# bodytext style used for wrapping data on flowables
styles = getSampleStyleSheet()
styleN = styles["BodyText"]
#used alignment if required
styleN.alignment = TA_LEFT
styleBH = styles["Normal"]
styleBH.alignment = TA_CENTER
hdescrpcion = Paragraph('''<b>descrpcion</b>''', styleBH)
hpartida = Paragraph('''<b>partida</b>''', styleBH)
descrpcion = Paragraph('long long long long long long long long long long long long long long long long long long long long line ', styleN)
partida = Paragraph('1', styleN)
data= [[hdescrpcion, hpartida],
[partida ,descrpcion]]
table = Table(data)
table.setStyle(TableStyle([
('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
('BOX', (0,0), (-1,-1), 0.25, colors.black),
]))
c = canvas.Canvas("a.pdf", pagesize=A4)
table.wrapOn(c, 50, 50)
table.drawOn(c, 100,600)
c.save()

Categories