Search code examples
pythonxmldocxpython-docx

How to wrap cell text in tables via docx library or xml?


I have been using python docx library and oxml to automate some changes to my tables in my word document. Unfortunately, no matter what I do, I cannot wrap the text in the table cells.

I managed to successfully manipulate 'autofit' and 'fit-text' properties of my table, but non of them contribute to the wrapping of the text in the cells. I can see that there is a "w:noWrap" in the xml version of my word document and no matter what I do I cannot manipulate and remove it. I believe it is responsible for the word wrapping in my table.

for example in this case I am adding a table. I can fit text in cell and set autofit to 'true' but cannot for life of me wrap the text:

from docx import Document
from docx.oxml import OxmlElement
from docx.oxml.ns import qn

doc = Document()
table = doc.add_table(5,5)
table.autofit = True # Does Autofit but not wrapping

tc = table.cell(0,0)._tc     # As a test, fit text to cell 0,0
tcPr = tc.get_or_add_tcPr()

tcFitText = OxmlElement('w:tcFitText')
tcFitText.set(qn('w:val'),"true")
tcPr.append(tcFitText)      #Does fitting but no wrapping

doc.save('demo.docx')

I would appreciate any help or hints.


Solution

  • The <w:noWrap> element appears to be a child of <w:tcPr>, the element that controls table cell properties.

    You should be able to access it from the table cell element using XPath:

    tc = table.cell(0, 0)._tc
    noWraps = tc.xpath(".//w:noWrap")
    

    The noWraps variable here will then be a list containing zero or more <w:noWrap> elements, in your case probably one.

    Deleting it is probably the simplest approach, which you can accomplish like this:

    if noWraps:  # ---skip following code if list is empty---
        noWrap = noWraps[0]
        noWrap.getparent().remove(noWrap)
    

    You can also take the approach of setting the value of the w:val attribute of the w:noWrap element, but then you have to get into specifying the Clark name of the attribute namespace, which adds some extra fuss and doesn't really produce a different outcome unless for some reason you want to keep that element around.