Fill tables in a template Word with Python (DocxTemplate, Jinja2)

2.1k Views Asked by At

I am trying to fill with Python a table in Word with DocxTemplate and I have some issues to do it properly. I want to use 2 dictionnaries to fill the data in 1 table, in the figure below.

Table to fill

The 2 dictionnaries are filled in a loop and I write the template document at the end. The input document to create my dictionnaries is an DB extraction written in SQL. My main issue is when I want to fill the table with my data in the 2 different dictionnaries. In the code below I will give as an example the 2 dictionnaries with values in it.

# -*- coding: utf8 -*-
#
#
from docxtpl import DocxTemplate                        
if __name__ == "__main__":
    document = DocxTemplate("template.docx")
    DicoOccuTable = {'`num_carnet_adresses`': '`annuaire_telephonique`\n`carnet_adresses`\n`carnet_adresses_complement', 
    '`num_eleve`': '`CFA_apprentissage_ctrl_coherence`\n`CFA_apprentissage_ctrl_examen`}
    DicoChamp = {'`num_carnet_adresses`': 72, '`num_eleve`': 66}
    template_values = {}
    #
    template_values["keys"] = [[{"name":cle, "occu":val} for cle,val in DicoChamp.items()],
    [{"table":vals} for cles,vals in DicoOccuTable.items()]]
    # 
    document.render(template_values)
    document.save('output/' + nomTable.replace('`','') + '.docx')  

As a result the two lines for the table are created but nothing is written within... I would like to add that it's only been 1 week that I work on Python, so I feel that I don't manage properly the different objects here. If you have any suggestion to help me, I would appreciate it !

I put here the loop to create the dictionnaries, it may help you to understand why I coded it wrong :)

for c in ChampList:
        with open("db_reference.sql", "r") as f:
            listTable = []
            line = f.readlines()
            for l in line:
                if 'CREATE TABLE' in l:
                    begin = True
                    linecreateTable = l
                    x = linecreateTable.split()
                    nomTable = x[2]
                elif c in l and begin == True:
                    listTable.append(nomTable)
                elif ') ENGINE=MyISAM DEFAULT CHARSET=latin1;' in l:    
                    begin = False
            nbreOccu=len(listTable)
            Tables = "\n".join(listTable)
            DicoChamp.update({c:nbreOccu})
            DicoOccuTable.update({c:Tables})
            # DicoChamp = {c:nbreOccu}
            template_values = {}

Thank You very much !

1

There are 1 best solutions below

0
On

Finally I found a solution for this problem. Here it is. Instead of using 2 dictionnaries I created 1 dictionnary with this strucuture :

Dico = { Champ : [Occu , Tables] }

The full code for creating the table is detailed below :

from docxtpl import DocxTemplate 
document = DocxTemplate("template.docx")
template_values = {}
Context = {}
for c in ChampList:
    listTable = []
    nbreOccu = 0
    OccuTables = []
    with open("db_reference.sql", "r") as g:
        listTable = []
        ligne = g.readlines()
        for li in ligne:
            if 'CREATE TABLE' in li:
                begin = True
                linecreateTable2 = li
                y = linecreateTable2.split()
                nomTable2 = y[2]
            elif c in li and begin == True:
                listTable.append(nomTable2)
            elif ') ENGINE=MyISAM DEFAULT CHARSET=latin1;' in li:    
                begin = False
            elif '/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;' in li:
                nbreOccu=len(listTable)
                inter = "\n".join(listTable)
                OccuTables.append(nbreOccu)
                OccuTables.append(inter)
                ChampNumPropre = c.replace('`','')
                Context.update({ChampNumPropre:OccuTables})
            else:
                continue
    template_values["keys"] = [{"label":cle, "cols":val} for cle,val in Context.items()]
# 
document.render(template_values)
document.save('output/' + nomTable.replace('`','') + '.docx') 

And I used a table with the following structure :

enter image description here

I hope you will find your answers here and good luck !