Reputation: 1
I am trying to use PySimpleGUI and docxtpl to create a GUI which will render user defined inputs into a Word Document.
I would like to use TabGroup to organize the GUI, however it seems this is causing an error on doc.render(values)
Traceback (most recent call last): File "C:\Users\SESA484891\Desktop\doc render practice\DP-docrenderpractice.py", line 27, in doc.render(values) TypeError: keywords must be strings
Does each tab have its own dictionary? How do I access it?
I have tried simplifying my code to remove TabGroup and was able to successfully render values from GUI to a Word document.
from pathlib import Path
import PySimpleGUI as sg
from docxtpl import DocxTemplate
document_path = Path(__file__).parent / "DP-docrenderpractice.docx"
doc = DocxTemplate(document_path)
# TAB
tab1 = [
[sg.Text("Proposal Name:"),sg.Input(key="PROPOSAL_NAME",size=(30,0))]
]
# LAYOUT
layout = [[sg.TabGroup([
[sg.Tab('Tab', tab1)]])],
[sg.Button("Create Template"), sg.Exit()],
]
##########################
window = sg.Window("Doc Render Practice", layout)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == "Exit":
break
if event == "Create Template":
# Render the template, save new word document & inform user
doc.render(values)
output_path = Path(__file__).parent / f"DP-{values['PROPOSAL_NAME']}.docx"
doc.save(output_path)
sg.popup("File saved", f"File has been saved here: {output_path}")
window.close()
Full Traceback
=============================================================================RESTART: C:\Users\SESA484891\Desktop\doc render practice\DP-docrenderpractice.py==================================================
Traceback (most recent call last):
File "C:\Users\ SESA484891\Desktop\doc render practice\DP-docrenderpractice.py", line 27, in <module>
doc.render (values)
File "C:\Users\ SESA484891\AppData\Local\Packages\Python Software Foundation. Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\docxtpl\template.py", line 368, in render
xml src= self.build_xml (context, jinja_env)
File "C:\Users\ SESA484891\AppData\Local\Packages\Python Software Foundation. Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\docxtpl\template.py", line 315, in build_xml
xml = self.render_xml_part (xml, self.docx._part, context, jinja_env)
File "C:\Users\ SESA484891\AppData\Local\Packages\Python Software Foundation. Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\docxtpl\template.py", line 239, in render_xml_part
dst_xml = template.render (context)
File "C:\Users\ SESA484891\AppData\Local\Packages\PythonSoftware Foundation. Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\jinja2\environment.py", line 1296, in render
ctx = self.new_context (dict (*args, **kwargs))
File "C:\Users\ SESA484891\AppData\Local\Packages\PythonSoftware Foundation. Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\jinja2\environment.py", line 1388, in new_context
return new context
File "C:\Users\SESA484891\AppData\Local\Packages\PythonSoftware Foundation. Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\jinja2\runtime.py", line 106, in new_context
parent = dict (globals or (), **vars)
TypeError: keywords must be strings
EDIT:Solved!!!
As others have suggested, I printed out the values dictionary after window.read() to get a better understanding.
PymSimpleGUI adds a key “0” as the index of the currently selected Tab under TabGroup. This conflicts with docxtpl as render requires all keys to be str. The simple fix is to dict.popitem() after the window.read() to delete the last element I.e. the Tab key.
Upvotes: 0
Views: 111
Reputation: 5764
Adding a print(event, values)
immediately following your call to window.read()
will tell you a lot about the values input and the format of the values dictionary.
I've commented out the docxtpl portion of your code and added a print.
from pathlib import Path
import PySimpleGUI as sg
# from docxtpl import DocxTemplate
document_path = Path(__file__).parent / "DP-docrenderpractice.docx"
# doc = DocxTemplate(document_path)
# TAB
tab1 = [
[sg.Text("Proposal Name:"),sg.Input(key="PROPOSAL_NAME",size=(30,0))]
]
# LAYOUT
layout = [[sg.TabGroup([
[sg.Tab('Tab', tab1)]])],
[sg.Button("Create Template"), sg.Exit()],
]
##########################
window = sg.Window("Doc Render Practice", layout)
while True:
event, values = window.read()
print(event, values)
if event == sg.WIN_CLOSED or event == "Exit":
break
if event == "Create Template":
# Render the template, save new word document & inform user
# doc.render(values)
output_path = Path(__file__).parent / f"DP-{values['PROPOSAL_NAME']}.docx"
# doc.save(output_path)
sg.popup("File saved", f"File has been saved here: {output_path}")
window.close()
Entering test
into the Input
element and clicking the Create Template
button, I see this printed:
Create Template {'PROPOSAL_NAME': 'test', 0: 'Tab'}
The TabGroup
element has a key that has defaulted to 0
because one wasn't in the layout.
I get this popup as well:
Upvotes: 0