Search code examples
pythonms-worddocxpython-docx

Setting the background color of a table cell in Word [docx] [Python 3.8.2]


I'm having problems understanding how to set the background color of a table cell.

I tried many combinations, but the only thing I managed to do was the to set the paragraph style.

import docx    

doc = docx.Document()

records = (
    (3, '101', 'Spam'),
    (7, '422', 'Eggs'),
    (4, '631', 'Spam, spam, eggs, and spam')
    )

table = doc.add_table(rows=1, cols=3)

hdr_cells = table.rows[0].cells
hdr_cells[0].text = 'Qty'
hdr_cells[1].text = 'Id'
hdr_cells[2].text = 'Desc'
for qty, id, desc in records:
    row_cells = table.add_row().cells
    row_cells[0].add_paragraph(str(qty), "Title 1")
    row_cells[0].text_frame.paragraph[0].font.size = Pt(12)
    row_cells[1].text = id
    row_cells[2].text = desc

doc.save("Testing.docx")

I would like to set row_cells[0] to have a red background, but I'm unable to do it.

How can I do it?


Solution

  • That option is still not supported by the official python-docx library. However, you can try implementing it yourself. The property you're looking for is called cell shading located under cell properties.

    Solution: Add the shading element(w:shd) to the cell properties(w:tcPr).

    Wrote the simple function that does exactly that:

    def _set_cell_background(cell, fill, color=None, val=None):
        """
        @fill: Specifies the color to be used for the background
        @color: Specifies the color to be used for any foreground
        pattern specified with the val attribute
        @val: Specifies the pattern to be used to lay the pattern
        color over the background color.
        """
        from docx.oxml import qn  # feel free to move these out
        from docx.oxml import OxmlElement
    
        cell_properties = cell._element.tcPr
        try:
            cell_shading = cell_properties.xpath('w:shd')[0]  # in case there's already shading
        except IndexError:
            cell_shading = OxmlElement('w:shd') # add new w:shd element to it
        if fill:
            cell_shading.set(qn('w:fill'), fill)  # set fill property, respecting namespace
        if color:
            pass # TODO
        if val:
            pass # TODO
        cell_properties.append(cell_shading)  # finally extend cell props with shading element
    

    Feel free to extend other properties if you need em.

    So based on your example, once you have your table, before saving the doc, add this line:

    .
    .
    _set_cell_background(table.rows[0].cells[0], 'FF0000')
    doc.save("Testing.docx")
    

    Also, feel free to contribute to the official library by registering this new element here: https://github.com/python-openxml/python-docx/blob/master/docx/oxml/table.py#L753. :)

    Hope this helps,