简体   繁体   中英

Populate word table using python-docx

I have a table to populate table to populate , I am quite new to python-docx. I have tried to populate it using render but it's only giving as output one server:

for i in serverJson:
        doc.render(i)

where serverJson is the list of servers entered by the user. for eg:

    for i in appserver: 
        server_1={"component":"Tomcat","comp_version":"7","server":i,
                                         "app_port":"5000","db_sid":" ","db_port":"200"}
    
        server_2={"component":"Apache","comp_version": "2.4","server":i,
                                    "app_port":" ","db_sid":" ","db_port":"200"}
        serverJson.append(server_1)
        serverJson.append(server_2)

My question is how do i populate the table shown in the link with the number of servers entered by user?

So, what you are actually doing with this block of code:

for i in serverJson:
    doc.render(i)

Is to render the same doc multiple times, but only using the single variables you provided. Instead, you need to provide a jinja for statement inside the block itself, to allow it to dynamically create rows and columns. You will have to operate on both your docx file and on the Python code. Firstly, create a table and make your docx file look like:

在此处输入图像描述

Above, we are using some jinja2 for loops to achieve the following:

  • Generate as many columns in the headers as we need
  • Generate as many rows as the servers in the list
  • Generate as many columns containing the data of the server in question

In order to populate the above template with the correct context, take a look at the below code:

from docxtpl import DocxTemplate
import os,sys

#Just change these according to your needs
inputFileName = "i.docx"
outputFileName = "o.docx"

#This is done to obtain the absolute paths to the input and output documents,
#because it is more reliable than using the relative path
basedir = os.path.dirname(sys.argv[0])
path = os.path.join(basedir, "", inputFileName)
outpath = os.path.join(basedir, "", outputFileName)

template = DocxTemplate(path)

#Specify all your headers in the headers column
context = {
'headers' : ['Component', 'Component Version', 'Server FQDN', 'Application port', 'DB SID', 'DB Port', 'Infos'],
'servers': []
}

#Fictious appserver list
appserver = ['a','b']

#Add data to servers 1 and 2 using a list and not a dict, remember to add
#an empty string for the Infos, as well, otherwise the border won't be drawn
for i in appserver: 
    server_1= ["Tomcat",7,i,5000," ",200,""]
    server_2= ["Apache",2.4,i," "," ",200,""]
    context['servers'].append(server_1)
    context['servers'].append(server_2)

template.render(context)
template.save(outpath)

The above, will produce o.docx which will look like:

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM