Python Docx
If you need to create a word doc on a server I recommend using the python package “docx”.
To install docx run
1 | pip install python-docx |
You can read through the official documentation here:
http://python-docx.readthedocs.io/en/latest/user/install.html
Styling your template
A useful thing to do is to style your template in microsoft word and then save the template and use it as your starting document.
eg
1 | document = Document("document_path.docx", "path_to_template.docx")) |
Some tricks I have learnt while using docx
First you create your document:
1 | document = Document("path/doc.docx") |
Then you add elements to your document using the following
- add_paragraph
- add_picture
- add_page_break
- add_heading
- add_table
- add_row
Examples
1 | document.add_paragraph('Hello World' |
Adding a table
1 2 3 4 | table = document.add_table(rows=1, cols=5) row = table.add_row().cells index = 0 row[index].add_paragraph('Hello World') |
XML
To view the xml of an element use element.xml
Eg
1 2 | p = document.add_paragraph('Hello World') p.xml |
Advanced
I ran into a tricky part where I wanted to add content to the middle of an existing document with existing content.
I added this copy to the document “[BOOKMARK HERE]”
And then I used this code to search for that and then to add elements after that copy.
Add a paragraph after a paragraph, or a heading after a paragraph:
1 2 3 4 5 | def addParagraphAfterParagraph(self, document, paragraph, bookmark = '[BOOKMARK HERE]'): for para in document.paragraphs: if para.text == bookmark: p = para._p p.addnext(paragraph._p) |
To add a table after the copy I had to use something like this:
1 2 3 4 5 | def addTableAfterParagraph(self, document, table, bookmark = '[BOOKMARK HERE]'): for para in document.paragraphs: if para.text == bookmark: p = para._p p.addnext(table._tbl) |
To add an image after that copy I had to use something like this:
1 2 3 4 5 6 7 | def addImageAfterParagraph(self, document, image_path, width, bookmark = '[IMAGE HERE]'): for para in document.paragraphs: if para.text == bookmark: p = para._p para.text = '' run = para.add_run() run.add_picture(image_path, width=width) |
Also remember you have to run these in reverse because you’re adding it after an element, so it will place before the next element each time and immediately after the copy.