elcade
elcade

Reputation: 11

Python-PPTX Text Formatting Process

pptx** Community!

Could you please guide me if the method below is the right approach to format text?

In other words, do I have to add: p, run, and all font properties in every text I add to the PPTX?

Thank you so much for your help!

from pptx import Presentation
from pptx.dml.color import RGBColor
from pptx.enum.dml import MSO_THEME_COLOR
from pptx.enum.shapes import MSO_SHAPE
from pptx.enum.text import MSO_ANCHOR, MSO_AUTO_SIZE
from pptx.util import Inches, Pt

prs = Presentation('./data/template.pptx')

cover = prs.slides.add_slide(prs.slide_layouts[0])

pptTitle_Shape = cover.shapes.add_textbox(Inches(0.31), Inches(0.54), 0.61, 9.38)
pptTitle_TextFrame = pptTitle_Shape.text_frame
p = pptTitle_TextFrame.paragraphs[0]
run = p.add_run()
run.text = 'Cover Page Title Name'
font = run.font
font.name = 'Arial'
font.size = Pt(40)
font.bold = False
font.color.rgb = RGBColor(255, 255, 255)

pptCustomerName_Shape = cover.shapes.add_textbox(Inches(0.31), Inches(2.03), 4.5, 0.4)
pptCustomerName_TextFrame = pptCustomerName_Shape.text_frame
p = pptCustomerName_TextFrame.paragraphs[0]
run = p.add_run()
run.text = 'Customer Name'
font = run.font
font.name = 'Arial'
font.size = Pt(28)
font.bold = False
font.color.rgb = RGBColor(255, 255, 255)

pptSEName_Shape = cover.shapes.add_textbox(Inches(0.31), Inches(2.51), 4.5, 0.4)
pptSEName_TextFrame = pptSEName_Shape.text_frame
p = pptSEName_TextFrame.paragraphs[0]
run = p.add_run()
run.text = 'FirstName LName'
font = run.font
font.name = 'Arial'
font.size = Pt(20)
font.bold = False
font.color.rgb = RGBColor(255, 255, 255)

Upvotes: 1

Views: 5964

Answers (2)

Fred
Fred

Reputation: 502

To compliment Scanny's response, I have created a set of functions to apply formatting to several different objects in python-pptx. The functions are quite long as they implement all types of formatting like font alignment, border colours, transparency, margins etc. But you can find them in the following gist: https://gist.github.com/Fredericco72/c21505ebfb354461bc4b7b857764d5d2

They directly map to the logic provided by Scanny but it allows you to do the following:

slide = prs.slides.add_slide(prs.slide_layouts[0])

shape = slide.shapes.add_shape(
    MSO_SHAPE.RECTANGLE,
    left=Cm(1),
    top=Cm(1),
    width=Cm(10),
    height=Cm(3)
)

format_shape(
    shape,
    fill_color="BLUE",
    border_color="RED"
)

format_text_frame(
    shape.text_frame,
    font_size=15,
    font_color="WHITE",
    font_align=PP_ALIGN.RIGHT
)

To allow you to use friendly names for colours like BLUE and RED you need to have a mapping file set up or you can just pass fill_color=RGBColor(255, 255, 255).

Upvotes: 2

scanny
scanny

Reputation: 28863

No, typically not. There are some shortcuts and the defaults should work fine most of the time.

A typical shape-add operation is like this:

shape = shapes.add_shape(...)
shape.text = "foobar"

There is no need to explicitly access the text-frame to add text, a shape that accepts text has a writable .text property.

In general, the default font (character formatting) is going to work fine. This includes you doing work in your starting "template" .pptx file to set the defaults to what you want for most of the text. These defaults would be set at the theme and presentation-defaults level, as well as in placeholders on slide-layouts. You would typically do this by hand using PowerPoint since it's once-per-template rather than once-per-generated-presentation.

Perhaps the most common "customization" would be to change the font size for a particular shape. That would be:

shape.text_frame.paragraphs[0].font.size = Pt(12)

If you find yourself doing that more than occasionally, you can whip up some utility functions:

def shape_set_font_size(shape, points):
    for paragraph in shape.text_frame.paragraphs:
        paragraph.font.size = Pt(points)

shape_set_font_size(shape, 12)
shape_set_font_size(shape_2, 18)

Each _Run object has a font and a certain contiguous span ("run") of characters, including possibly zero characters (""). All characters in a run share the same font and any settings you make at that level override any settings at higher levels that might otherwise be "inherited".

Each _Paragraph object also has a .font property, but this one is the default font for runs inside that paragraph. These font characteristics will apply except where the run overrides them with a setting at its level.

So the right thing to do depends somewhat on the situation. If you used the following, for example, you'll be sure to set the font for all text currently in the paragraph, but not for new text (which gets new runs) that is added:

def shape_set_font_size(shape, points):
    for paragraph in shape.text_frame.paragraphs:
        for run in paragraph.runs:
            run.font.size = Pt(points)

I recommend you avoid the _Run-level font except when you want to emphasize some particular word or phrase, say by making it bold or italic. Otherwise the _Paragraph-level works fine and is more flexible.

Upvotes: 4

Related Questions