Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python-docx: Is it possible to add a new run to paragraph in a specific place (not at the end)

I want to set a style to a corrected word in MS Word text. Since it's not possible to change text style inside a run, I want to insert a new run with new style into the existing paragraph...

for p in document.paragraphs: 
   for run in p.runs: 
       if 'text' in run.text:      
            new_run= Run()
            new_run.text='some new text' 
            # insert this run into paragraph
            # smth like:
            p.insert(new_run) 

How to do it?

p.add_run() adds run to the end of paragraph, doesn't it?

Update

The best would be to be able to clone run (and insert it after a certain run). This way we reproduce the original run's style attributes in the new/cloned one.

Update 2

I could manage that insertion code:

if 'text' in run.text:
    new_run_element = CT_R() #._new() 
    run._element.addnext(new_run_element)
    new_run = Run(new_run_element, run._parent)
    ...

But after that:

  1. the paragraph runs number is left the same: len(p.runs)
  2. as I save that doc in file, the MS Word fails to open it: enter image description here
like image 796
Igor Savinkin Avatar asked Oct 10 '18 12:10

Igor Savinkin


1 Answers

There's no API support for this, but it can be readily accomplished at the oxml/lxml level:

from docx.text.run import Run
from docx.oxml.text.run import CT_R
# ...
for run in p.runs:
    if 'text' in run.text:
        new_run_element = p._element._new_r()
        run._element.addnext(new_run_element)
        new_run = Run(new_run_element, run._parent)
        # ---do things with new_run, e.g.---
        new_run.text = 'Foobar'
        new_run.bold = True

If you want to insert the new run prior to the existing run, use run._element.addprevious(new_run_element). These two are methods on the lxml.etree._Element class which all python-docx elements subclass.
https://lxml.de/api/lxml.etree._Element-class.html

like image 158
scanny Avatar answered Nov 15 '22 05:11

scanny