Search code examples
pythontkintersoftware-design

Making program with Tkinter's entry widget that substitute placeholders in a word document


Can anyone help, im new to coding, im trying to create a document generator program that replaces placeholder words(words in curly braces,eg :{{NAME}}) in existing word documents(via path) by using tkinter entry widgets which then generates a new word document with the new changes,but i cant get the entry widget to work with the the dictionary(it uses the dictionary to swap the keys for the values using docxtemplate).simply put i want the value in the dictionary to be dynamic and changes based on a user's entry input so it can be swapped with its key,if that makes sense.i was inspired by this video on youtube https://youtu.be/fziZXbeaegc.here is a basic code(Note:i dont get any errors):


from pathlib import Path
from docxtpl import DocxTemplate
from tkinter import *  

document_path = Path(__file__).parent / (r"C:\Users\Acer\Desktop\python\My name is.docx")
doc = DocxTemplate(document_path)

#define submit 
def submit():
    doc.render(swap)
    doc.save(Path(__file__).parent / "generated_doc.docx")

#The app window 
root = Tk()

#input field properties
entry=Entry(root,
font=("Arial",15))
entry.pack(side=LEFT)

swap={"NAME" : "Joe"}

#document generation button propeties
generate_button=Button(root,text="Generate",command=submit)
generate_button.pack(side=RIGHT)

root.mainloop()


Solution

  • Two things.

    First, this is probably a bug, since the second part is already a full path.

    document_path = Path(__file__).parent / (r"C:\Users\Acer\Desktop\python\My name is.docx")
    

    That should be:

    document_path = Path(r"C:\Users\Acer\Desktop\python\My name is.docx")
    

    Second, you need to modify the dictionary with the contents of the Entry before the conversion.

    def submit():
        # The following line updates the dictionary.
        swap["NAME"] = entry.get()
        doc.render(swap)
        doc.save(Path(__file__).parent / "generated_doc.docx")
    

    And a suggestion. Instead of hardcoding a filename, use filedialog.askopenfilename() from a button callback to get the name of the file to process, like this:

    fn = filedialog.askopenfilename(
        title='Word file to open',
        parent=root,
        defaultextension='.docx',
        filetypes=(('Word files', '*.doc*'), ('all files', '*.*')),
    )
    

    After this returns, fn contains the path of the selected file.