Home > Software design >  Python docx module to modify multiple files
Python docx module to modify multiple files

Time:07-15

I am trying to use small, nested for-loops to iterate through a list of values, replace items in a Word doc with the docx module, changing one value each loop, and saving a new doc each time and naming it as the changed value's name. Everything works except the value I'm trying to change with each loop is not updating on the Word files. The first value in my list is the value that shows up on every Word doc. When I output/save the files, the filename is correctly updating - but the content of the value on the document is always the same. Here's the code:

def makeWord(ident): #'ident' is a list of alphanumeric I.D. numbers
    wordpath = path   'Word_Template.docx'
    outpath = path   'Word Files\\'
    wordfile = Document(wordpath)
    
    for cn in ident:     
        myvars = {'$MO':datamonth, '$YEAR':datayear, '$idnum', cn} #data month/year are constants
        for key, val in myvars.items():
            for para in wordfile.paragraphs:
                replace_text_in_paragraph(para, key, val)
        saveword(wordfile, cn, outpath)
                 
def replace_text_in_paragraph(paragraph, key, value):
    if key in paragraph.text:
        inline = paragraph.runs
        for item in inline:
            if key in item.text:
                item.text = item.text.replace(key, value)

def saveword(wordfile, idnum, outp):
    wordfile.save(outp   idnum   '_'   datamonth   '_'   datayear   '.docx')

My list of values is in the "ident" list. If the first value in the list is "B25", that value is placed in all of my Word docs, though the filename of the Word docs appropriately changes as the loop runs. I have been stuck for two days on this. Any help is greatly appreciated!

CodePudding user response:

If your goal is to replace words in docx files with variables then my advice would be to use the docxtpl library.

You can open the file you want to edit, then use a dictionary to replace values, it's much cleaner-

Heres an example that gives you an idea of how powerful this is:

# If you have multiple forms to do in a list
for form in forms:
        
    # Document
    doc = DocxTemplate(form[0])

    # Feed variables in as a Docx Jinga2 will convert on-page

    context = { 
        'text_in_doc' : "something",
        'text_in_doc2' :  "something",
        'text_in_doc3':  "something",
        }

    # Render new Doc with Jinga2 swapped
    doc.render(context)

    # Save new Doc after Jinga2 conversion 
    doc.save("/save/to/directory/sample.docx")

GL

  • Related