Reputation: 1116
I read this documentation on python-docx-template
but I'm pretty confused on the table section. Let's say I have a docx template called Template.docx
. Inside the docx file i have a table that only has headers for it's title.
How can I use python-docx-template
to dynamically populate the table (add rows and values)?
Upvotes: 11
Views: 29478
Reputation: 344
You have a working example here (https://chowdera.com/2022/02/202202101239322085.html) with text and images in dynamically populated rows
The template docx file shall have a merged row with the "for" instruction, then a regular row with the desired columns filled with templates, then a merged row with the "endfor" instruction.
----------------------------------
| {%tr for f in frameworks %} |
----------------------------------
| {{ f.title }} | {{ f.desc }} |
----------------------------------
| {%tr endfor %} |
----------------------------------
and the python code :
from docxtpl import DocxTemplate
import jinja2
tpl = DocxTemplate('test-tpl.docx')
context = {
'frameworks': [
{
'title': 'this is line # 1',
'desc': 'Lorem ipsum dolor sit amet.',
},
{
'title': 'this is line # 2',
'desc': 'Rem nemo ipsam id facilis molestias et enim in pariatur voluptas sed temporibus illo dolor quibusdam.',
},
{
'title': 'this is line # 3',
'desc': 'A cupiditate esse et dolores temporibus sed sequi nisi cum voluptatem praesentium et odit voluptatem.',
},
],
}
jinja_env = jinja2.Environment(autoescape=True)
tpl.render(context, jinja_env)
tpl.save('test-result.docx')
A more complete example (in french) : https://sysgenre.it/automatisation-de-template-docx/
Upvotes: 5
Reputation: 5119
In general, you unlease the power of jinja2
with python-docx-template
.
Filling individual variables
Imagine you make a template.docx
file with a table:
**table 1** **table 2**
{{some_content1}} {{some_content2}}
Then you can fill it using
from docxtpl import DocxTemplate
import jinja2
doc = DocxTemplate("template.docx")
context = { 'some_content1' : "test", "some_content_2": "other"} # Where the magic happens
doc.render(context)
doc.save("generated_doc.docx")
If you have the data available as a pd.DataFrame
then you can also generate the context
dictionary. For example:
import itertools
context = {}
for row, col in itertools.product(df.index, df.columns):
context[f'{row}_{col}'] = df.loc[row, col]
Dynamic table
You can also generate tables dynamically, which I guess you maybe don't want to do (if you are talking about specifying "table headers" in the docx). It's worth looking into though. Use this template with this example from the git tests:
from docxtpl import DocxTemplate
tpl = DocxTemplate('templates/dynamic_table_tpl.docx')
context = {
'col_labels' : ['fruit', 'vegetable', 'stone', 'thing'],
'tbl_contents': [
{'label': 'yellow', 'cols': ['banana', 'capsicum', 'pyrite', 'taxi']},
{'label': 'red', 'cols': ['apple', 'tomato', 'cinnabar', 'doubledecker']},
{'label': 'green', 'cols': ['guava', 'cucumber', 'aventurine', 'card']},
]
}
tpl.render(context)
tpl.save('output/dynamic_table.docx')
Upvotes: 22