Frenesy
Frenesy

Reputation: 13

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?

Upvotes: 1

Views: 4766

Answers (1)

aleksandarbos
aleksandarbos

Reputation: 615

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,

Upvotes: 5

Related Questions