python-pptx
python-pptx copied to clipboard
Replace text with formatting
Dear scanny,Thank you very much for your reply When I do a function, I encounter a problem. First of all, I scan the text in PPT, and then replace some text. In this process, I find that the font has become the default font. How can I keep the font style unchanged
def fill_text(prs, text_format, data):
for i in text_format:
idx, sh_idx, text = i['sl_idx'], i['sh_idx'], i['text']
p = i['paragraph']
pgh = prs.slides[idx].shapes[sh_idx].text_frame.paragraphs[p]
for id, elm in enumerate(pgh._element.content_children):
if id == 0:
continue
pgh._element.remove(elm)
prs.slides[idx].shapes[sh_idx].text_frame.paragraphs[p].runs[
0].text = SFormatter().vformat(text, [], data)
return prs
I scanned out the text to be replaced in text_format, and the text in data
Originally posted by @cxin-william in https://github.com/scanny/python-pptx/issues/683#issuecomment-773724457
I am also facing the same challenge when I am replacing text in a shape.
I am also facing the same challenge when I am replacing text in a shape.
Did you solve it?
I might not be understanding the code but the method remove
suggests to me you are replacing the whole object. What you replace it with probably has the default font. How about just updating the text of the object rather than removing and replacing it?
I might not be understanding the code but the method
remove
suggests to me you are replacing the whole object. What you replace it with probably has the default font. How about just updating the text of the object rather than removing and replacing it?
Do you have a good way to replace only text?
In case anyone in future needs this, this seems to work for me. Reverses the strings while keeping formatting.
presentation = pptx.Presentation("test.pptx")
for slide_count,slide in enumerate(presentation.slides):
print("Slide: {}".format(slide_count))
for shape_count,shape in enumerate(slide.shapes):
print("Shape: {}".format(shape_count))
if shape.has_text_frame and shape.text:
for para_count,pgh in enumerate(shape.text_frame.paragraphs):
#print(para_count)
#print(pgh.runs)
if pgh.runs:
for i in range(len(pgh.runs)):
#print(pgh.runs[i].font.size)
#print(pgh.runs[i].text)
pgh.runs[i].text = pgh.runs[i].text[::-1]
#print(pgh.runs[i].font.size)
presentation.save("test_out.pptx")
Inspired by @sharkykittens, maybe we can try the following code to replace the text without changing the format.
presentation = pptx.Presentation("test.pptx")
for slide_count,slide in enumerate(presentation.slides):
print("Slide: {}".format(slide_count))
for shape_count,shape in enumerate(slide.shapes):
print("Shape: {}".format(shape_count))
if shape.has_text_frame and shape.text:
for para_count,pgh in enumerate(shape.text_frame.paragraphs):
if pgh.runs:
for i in range(len(pgh.runs)):
pgh.runs[i].text = pgh.runs[i].text[:0] + "The text that you want to replace with."
presentation.save("test_out.pptx")
For anyone who stumbles upon this thread, here is handy function to replace text at the paragraph level while keeping the format. It assumes that the format is the same for all runs.
from copy import deepcopy
def replace_paragraph_text_retaining_initial_formatting(paragraph, new_text):
font = deepcopy(paragraph.runs[0].font)
paragraph.text = new_text
for run in paragraph.runs:
run._r.insert(0, deepcopy(font._rPr))
Inspired by scanny and sedrew.
I could not figure out a proper way to handle '\v'
at the run level and this solved it.
Can refer to this stackoverflow answer: https://stackoverflow.com/questions/45247042/how-to-keep-original-text-formatting-of-text-with-python-powerpoint?newreg=75b9ab8c12e747f596e2f0be1d66314e
So the basic idea is: Instead of replacing the "text" of the shape, replace the "text" in the run.