The template approach works and its major advantage is that it is a truly cross-platform solution. However, it requires that a style has already been applied once in the document.
Let's consider a (simplified) version of the toy example from the python-docx
documentation page.
The first step involves creating the template document:
from docx import Document
document = Document()
document.add_heading('Document Title', 0)
p = document.add_paragraph('A plain paragraph having some ')
p.add_run('bold').bold = True
p.add_run(' and some ')
p.add_run('italic.').italic = True
document.add_heading('Heading, level 1', level=1)
document.add_paragraph('Intense quote', style='IntenseQuote')
document.add_paragraph(
'first item in unordered list', style='ListBullet'
)
document.add_paragraph(
'first item in ordered list', style='ListNumber'
)
document.save('demo.docx')
(Note that you can also apply the styles manually in this first step without using python-docx
, that is from within Word.)
Next, you open this demo.docx
in Microsoft Word where you:
- add the desired header
- insert the page numbers from the menu
- save the document
Once you have done the above, you simply delete the main contents of the demo.docx
document (but not the content of the header and footer!) and save the file again.
In the second step, you call demo.docx
using python-docx
to make the changes you need:
from docx import Document
document = Document('demo.docx')
document.add_heading('A New Title for my Document', 0)
p = document.add_paragraph('A new paragraph having some plain ')
p.add_run('bold').bold = True
p.add_run(' and some ')
p.add_run('italic.').italic = True
document.add_heading('New Heading, level 1', level=1)
document.add_paragraph('Intense quote', style='IntenseQuote')
document.add_paragraph(
'first new item in unordered list', style='ListBullet'
)
document.add_paragraph(
'first new item in ordered list', style='ListNumber'
)
document.save('demo.docx')
You can even make further content additions, such as a table with an existing table style:
from docx import Document
document = Document('demo.docx')
document.add_page_break()
recordset = [ [1, "101", "Spam"], [2, "42", "Eggs"], [3, "631", "Spam, spam, eggs, and spam"]]
table = document.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 item in recordset:
row_cells = table.add_row().cells
row_cells[0].text = str(item[0])
row_cells[1].text = str(item[1])
row_cells[2].text = item[2]
table.style = 'ColorfulShading'
document.save('demo.docx')
Of course, one can avoid repeating the first step all the time, by copying the customized file and then making the necessary changes there (e.g. demo_copy.docx
) without affecting the template:
import shutil
shutil.copyfile('demo.docx', 'demo_copy.docx')
Finally, it is worth mentioning that you can also use customized styles! For an example of how to do this using python-docx
and table styles see here.