Evan Lee
Evan Lee

Reputation: 1

Accessing Dictionary of Tab Groups

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()

GUI

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

Answers (1)

Mike from PSG
Mike from PSG

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()

enter image description here

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:

enter image description here

Upvotes: 0

Related Questions