I am using python-docx to programmatically generate a very large and messy table inside of word document.
How, as part of beautification process I need to merge together all cells in specific rows or columns.
When I know how many cells are there in a row or column in advance merge is trivial. MVP below:
from docx import Document
doc = Document()
#adding table of details with 4 columns
tableOverview = doc.add_table(rows=1, cols=4)
tableOverview.style = 'Table Grid'
#add some text in a first cell of a row
row = tableOverview.row_cells(0)
row[0].text = "Job details"
#merge all 4 cells in a row into one
merge1 = row[0].merge(row[1]).merge(row[2]).merge(row[3])
However:
- This looks really ugly and un-pythonic to specify chain of merges
- It gets tricky if I don’t know in advance how many cells are there in a row (or in a column). This becomes a problem as I am generating this tables based on inputs hence number of cells per row and column is dynamic – so I can’t hardcode such merge chain
Quick check of documentation didn’t yield any good examples, it is always the case that there are just two cells being merged at a time. Is there some reasonable way to merge together a whole list of cells?
Thanks!
Advertisement
Answer
All you need provide to _Cell.merge()
is the cell at the opposite diagonal of the rectangle you want to merge.
So, for example, if you wanted to merge the top-left 3 x 3 cell area in a 9 x 9 table, you could use:
table.cell(0, 0).merge(table.cell(2, 2))
or, more verbose but perhaps more instructive:
top_left = table.cell(0, 0)
bottom_right = table.cell(2, 2)
top_left.merge(bottom_right)
So all you need do is get a reference to any two diagonal corners. Note that:
bottom_right.merge(top_left)
works just as well as the other direction. For that matter:
top_right = table.cell(0, 2)
bottom_left = table.cell(2, 0)
bottom_left.merge(top_right)
works just as well too. Any two diagonal “corner” cells can be used to define a merged cell.