python-docx Bilingual Document RTL and LTR - python

I want to create a bilingual MS word document; containing English and Arabic text.
As you may know, Arabic is an RTL language (written from right to left).
My most difficult problem was solved, Arabic text renders from right-to-left; yet the paragraph alignment stays Left, and I want it right (while keeping English left as it's the default).
Here is my working:
from docx import Document, enum
from docx.shared import Inches
from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_PARAGRAPH_ALIGNMENT
document = Document()
document.add_heading('Document Title', 0)
p = document.add_paragraph('English text renders correctly; left to right; with default Left Alignment ')
p.add_run('bold').bold = True
p.add_run(' and some ')
p.add_run('italic.').italic = True
mystyle = document.styles.add_style('mystyle', enum.style.WD_STYLE_TYPE.CHARACTER)
paragraph = document.add_paragraph()
paragraph.alignment = WD_ALIGN_PARAGRAPH.RIGHT
p = document.add_paragraph().add_run('هذه فقرة باللغة العربية يجب أن تكتب من اليمين إلى اليسار.')
p.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
font = p.font
font.rtl = True
p.style = mystyle
document.save('demo8.docx')
This is how it should be

Related

TableStyle is overwritten by document style

Because the original project seems inactive I have to replicate my Issue here at StackOverflow.
It seems to me that the global document style does overwrite lower styles e.g. TableStyle. I assume I misunderstand the concept here.
See this code as an example
#!/usr/bin/env python3
import os
import docx
document = docx.Document()
document.styles['Normal'].font.name = 'Fira Mono'
document.styles['Normal'].font.size = docx.shared.Pt(8)
my_tab_style = document.styles.add_style('MyTab', docx.enum.style.WD_STYLE_TYPE.TABLE)
my_tab_style.font.name = 'Fira Sans'
my_tab_style.font.size = docx.shared.Pt(20)
p = document.add_paragraph('Should be Fira Mono 8pt')
tab = document.add_table(rows=1, cols=1, style='MyTab')
tab.rows[0].cells[0].text = 'Should be Fira Sans 20pt'
document.save('test.docx')
os.system('start test.docx')
I would expect the document text in "Fira Mono 8pt" and the table content in "Fira Sans 20pt". But it isn't.
When you outcomment the document style lines
# document.styles['Normal'].font.name = 'Fira Mono'
# document.styles['Normal'].font.size = docx.shared.Pt(8)
the table style is taken into account.

cannot make text rtl with python-docx

yes i know many questions about this issue exists but i couldn't make any of them work.
i have python 3.7 and python-docx 0.8.11.
i have tried many solutions including this one
from docx import Document, enum
document = Document()
mystyle = document.styles.add_style('mystyle', enum.style.WD_STYLE_TYPE.CHARACTER)
run = document.add_paragraph().add_run(text)
run.style = mystyle
font = run.font
font.rtl = True
document.save('test.docx')
also
from docx import Document, enum
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
doc = Document()
rtlstyle = doc.styles.add_style('rtl', enum.style.WD_STYLE_TYPE.PARAGRAPH)
rtlstyle.font.rtl = True
p = doc.add_paragraph(text)
p.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
p.style = rtlstyle
doc.save('test.docx')
nothing worked so far
see this : https://stackoverflow.com/posts/73133074/revisions
also as mensiond here put this before your text: u'\u202B' + "your text"
or u'\u202E' if didn't work

How to change the font size of an python pptx object

I would like to change the font size of the title and of the body of my pptx-presentation. I tried to set it via title_shape.font = Pt(15) and body_shape.font = Pt(10), which does not work.
Here is my code:
from pptx import Presentation, util, text
from pptx.util import Cm, Pt
import fnmatch
import os
import contentOf_pptx as contOfPres
# ..............
# Generate presentation
# ..............
prs = Presentation()
#blank_slide_layout = prs.slide_layouts[6] #blank layout, see slide layout in powerpoint
title_only = prs.slide_layouts[5] #title only, see slide layout in powerpoint
# ..............
# set layout
# ..............
bullet_slide_layout = prs.slide_layouts[1]
slide = prs.slides.add_slide(bullet_slide_layout)
shapes = slide.shapes
title_shape = shapes.title
title_shape.font = Pt(15)
body_shape = shapes.placeholders[1]
body_shape.font = Pt(10)
# ..............
# set relevant text objects
# ..............
title_shape.text = 'Test Title'
tf = body_shape.text_frame
tf.text = 'Test SubText'
# ----------------------------------
# Store pptx
# ----------------------------------
prs.save('C:\\tests\\test_pptx_python.pptx')
A Shape object does not have a .font attribute (at least it didn't until you added one by assigning to that name :)
Font is characteristic of a Run object; a run is a sequence of characters that all share the same character formatting, also loosely known as a font.
A Paragraph object also has a .font property which is used the same way, but which specifies the default font for the runs in a paragraph. Individual runs in that paragraph can override that default by setting the attributes of their own font object.
If you only want one font for the shape (which is common), probably the fastest way is:
shape.text_frame.paragraphs[0].font.size = Pt(15)
which works because most shapes only contain a single paragraph (and all must contain at least one).
More thorough would be:
for paragraph in shape.text_frame.paragraphs:
paragraph.font.size = Pt(15)
and more thorough still would be:
for paragraph in shape.text_frame.paragraphs:
for run in paragraph.runs:
run.font.size = Pt(15)
More details on this are in the documentation here:
https://python-pptx.readthedocs.io/en/latest/user/text.html
Here is a simple approach that worked for me:
slide = prs.slides.add_slide(blank_slide_layout)
slide.shapes.title.text = "The Title of My Slide"
slide.shapes.title.text_frame.paragraphs[0].font.size = Pt(15)

Creating a table in python docx and use small_caps (python-docx)

This is what I have tried:
from docx import Document
from docx.shared import Inches
from docx.shared import Pt
table = document.add_table(rows= 3, cols = 1)
row = table.rows[0]
runner = row.cells[0].paragraphs[0].add_run('Summary')
runner.bold = True
runner.small_caps = True
document.save('demo.docx')
I am trying to create a table and small caps the text but cannot get the syntax right
I have figured how to use small caps for text.
runner_font = runner.font
runner_font.size = Pt(14)
runner_font.small_caps = True
runner_font.bold = True
I believe bold and italic are properties that built in under both add_run and font. But for small_caps, all_caps, color can be called under font only.

Python Reportlab PDF - Centering Text on page

I am using ReportLab to generate a pdf dynamically with python.
I would like a line of text to be centered on a page. Here is the specific code I currently have, but do not know how to center the text horizontally.
header = p.beginText(190, 740)
header.textOut("Title of Page Here")
# I know i can use TextLine etc in place of textOut
p.drawText(header)
The text displays and I can manually move the left position so the text looks centered, but I need this to be centered programmatically since the text will be dynamic and I don't know how much text there will be.
The reportlab canvas has a drawCentredString method. And yes, they spell it like that.
We’re British, dammit, and proud of
our spelling!
Edit:
As for text objects, I'm afraid you don't. You can do something along those lines, though:
from reportlab.pdfbase.pdfmetrics import stringWidth
from reportlab.rl_config import defaultPageSize
PAGE_WIDTH = defaultPageSize[0]
PAGE_HEIGHT = defaultPageSize[1]
text = "foobar foobar foobar"
text_width = stringWidth(text)
y = 1050 # wherever you want your text to appear
pdf_text_object = canvas.beginText((PAGE_WIDTH - text_width) / 2.0, y)
pdf_text_object.textOut(text) # or: pdf_text_object.textLine(text) etc.
You can use other page sizes, obviously.
I just needed this too, and wrote this:
def createTextObject(canv, x, y, text, style, centered=False):
font = (style.fontName, style.fontSize, style.leading)
lines = text.split("\n")
offsets = []
if centered:
maxwidth = 0
for line in lines:
offsets.append(canv.stringWidth(line, *font[:2]))
maxwidth = max(*offsets)
offsets = [(maxwidth - i)/2 for i in offsets]
else:
offsets = [0] * len(lines)
tx = canv.beginText(x, y)
tx.setFont(*font)
for offset, line in zip(offsets, lines):
tx.setXPos(offset)
tx.textLine(line)
tx.setXPos(-offset)
return tx
You can use Flowable object like Paragraph and assign alignment value to 1:
styles = getSampleStyleSheet()
title_style = styles['Heading1']
title_style.alignment = 1
title = Paragraph("Hello Reportlab", title_style)
story.append(title)
This example will create a pdf document with centered text:
from flask import make_response
import io
from reportlab.platypus import SimpleDocTemplate, Paragraph
from reportlab.lib.styles import getSampleStyleSheet
story=[]
pdf_doc = io.BytesIO()
doc = SimpleDocTemplate(pdf_doc)
styles = getSampleStyleSheet()
title_style = styles['Heading1']
title_style.alignment = 1
title = Paragraph("Hello Reportlab", title_style)
story.append(title)
doc.build(story)
content = pdf_doc.getvalue()
#output to browser
response = make_response(content)
response.mimetype = 'application/pdf'
return response
If you want the text to be floaten to the left, you need to change alignment to 0:
title_style.alignment = 0
If you want the text to be floaten to the right, you need to change alignment to 2:
title_style.alignment = 2
Try:
<para alignment="center">
As Per Reference : http://two.pairlist.net/pipermail/reportlab-users/2006-June/005092.html
In your case:
header.textOut("<"para alignment='center'>"Title of Page Here")
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
doc = SimpleDocTemplate("form_letter.pdf",pagesize=letter,
rightMargin=72,leftMargin=72,
topMargin=72,bottomMargin=18)
Story = []
styles = getSampleStyleSheet()
title_style = styles['Heading1']
title_style.alignment = 1
title = Paragraph("Welcome to india", title_style)
Story.append(title)
doc.build(Story)

Categories

Resources