Possible to insert row at specific position with python-docx?

Viewed 7932

I'd like to insert a couple of rows in the middle of the table using python-docx. Is there any way to do it? I've tried to use a similar to inserting pictures approach but it didn't work.

If not, I'd appreciate any hint on which module is a better fit for this task. Thanks.

Here is my attempt to mimic the idea for inserting a picture. It's WRONG. 'Run' object has no attribute 'add_row'.

from docx import Document
doc = Document('your docx file')
tables = doc.tables
p = tables[1].rows[4].cells[0].add_paragraph()
r = p.add_run()
r.add_row()
doc.save('test.docx')
6 Answers

You can insert row to the end of the table and then move it in another position as follows:

from docx import Document
doc = Document('your docx file')
t = doc.tables[0]
row0 = t.rows[0] # for example
row1 = t.rows[-1]
row0._tr.addnext(row1._tr)

Though there isn't a directly usable api to achieve this according to the python-docx documentation, there is a simple solution without using any other libs such as lxml, just use the underlying data structure provided by python-docx, which are CT_Tbl, CT_Row, etc. These classes do have common methods like addnext, addprevious which can conveniently add element as siblings right after/before current element. So the problem can be solved as below, (tested on python-docx v0.8.10)


    from docx import Document
    doc = Document('your docx file')
    tables = doc.tables
    row = tables[1].rows[4]
    tr = row._tr # this is a CT_Row element
    for new_tr in build_rows(): # build_rows should return list/iterator of CT_Row instance
        tr.addnext(new_tr)
    doc.save('test.docx')

this should solve the problem

addnext() in lxml.etree seems like will be the better option to use and its working fine, and the only thing is, i cannot set the height of the row, so please provide some answers, if you know!

current_row = table.rows[row_index] 
table.rows[row_index].height_rule = WD_ROW_HEIGHT_RULE.AUTO
tbl = table._tbl
border_copied = copy.deepcopy(current_row._tr)
tr = border_copied
current_row._tr.addnext(tr)

I created a video here to demonstrate how to do this because it threw me for a loop the first time. https://www.youtube.com/watch?v=nhReq_0qqVM

    document=Document("MyDocument.docx")
    Table = document.table[0]
    Table.add_row()
    
    for cells in Table.rows[-1].cells:
         cells.text = "test text"
    
    insertion_row = Table.rows[4]._tr
    insertion_row.add_next(Table.rows[-1]._tr)
    
    document.save("MyDocument.docx")

The python-docx module doesn't have a method for this, So the best workaround Ive found is to create a new row at the bottom of the table and then use methods from the xml elements to place it in the position it is suppose to be.

This will create a new row with every cell in the row having the value "test text" and we then add that row underneath of our insertion_row.

Related