In this Python Tkinter tutorial, I will walk you through how to create a Word document using a simple GUI application. We will use the tkinter module to build the interface and the python-docx library to generate Word documents with dynamic content.
I will explain the key modules used, show you the complete source code, and demonstrate how the output document is generated.
Let’s get in.
Create a Word Document in Python Tkinter
So we created a complete application using Python Tkinter that will take inputs like below:
| User Inputs | Tkinter Widget |
|---|---|
| Employee ID | Entry widget |
| Employee Name | Entry Widget |
| Designation | Entry Widget |
| Joining Date | Entry Widget |
| End Date | Entry Widget |
| Gender | OptionMenu Widget |
Then, when the user fills the form and clicks on the Generate Word button, it will create an experience certificate (Word document) with the dynamic values provided by the user.
The form looks like below:

The output will come like below:

Check out Display Data in Textboxes using Python Tkinter
Tkinter Module in Python
Using the Tkinter module in Python, we can create a graphical user interface (GUI) for any application. It is a popular and easy-to-use Python module that can help you convert your command-line-based application into an interactive GUI-based program.
| User Inputs | Tkinter Widget |
|---|---|
| Employee ID | Entry widget |
| Employee Name | Entry Widget |
| Designation | Entry Widget |
| Joining Date | Entry Widget |
| End Date | Entry Widget |
| Gender | OptionMenu Widget |
Gender is a tkinter OptionMenu widget; the user can select the gender using the dropdown. This information is used for declaring a subject pronoun. Using gender information, we have specified he, she, him, his, her in the body text of the message.
Read Set a Background Image in Python Tkinter
Python-docx module in Python
Python-docx can be installed using pip and conda package manager with the following command.
# using pip
pip install python-docx
# using anaconda
conda install -c conda-forge python-docxBelow is the picture of a Word document with marked features.

Each feature has a dedicated method in Python-docx. Few widely used methods of python-docx are add_paragraph(), add_picture(), add_heading(), add_page_break(), add_table(), etc.
from docx import Document
doc = Document()Moving forward, we will discuss common methods of the Python-docx module, using which you can create a sample Word document in Python.
Check out Create Window Titles in Python Tkinter
docx.styles()
If you want to save time from manually formatting each row of a Word document, then you can apply a bundle of pre-formatted styles using this feature in the python-docx module.

Other than this, you can modify the style by adding bullet points, changing font weight to bold, italics, underline, etc.
Example:
This example demonstrates how to create a style in the Python docx module also shows how to use the style on a paragraph in the Python docx module.
# style created
new_style = doc.styles['Heading 1']
# style applied
doc.add_paragraph(style=new_style)docx.add_heading()
Heading specifies the short description of the topic or content. A good heading is always short and self-explanatory. In this section, we will learn how to add a heading using Python.
- Every sub-heading is smaller than the parent heading, and this way they form a hierarchy of 1-9 levels, where 1 is the highest level and 9 is the lowest.
doc.add_heading('United States of America', level=1)Change the level value to modify the heading size in Python docx.
Check out Create an OptionMenu in the Python Tkinter
docx.add_paragraph()
The paragraph is a widely used method, as this will require you to add text to the Word document using python Python-docx module.
Example:
In this code, we have added a paragraph: ‘Best Country’, and using the run object, added the country name: the United States of America, and then applied bold formatting on the country name.
# one-liner
doc.add_paragraph('Best Country').add_run('United States of America').bold = True
# same thing in 2 lines to make it look good
nomination = doc.add_paragraph('Best Country')
nomination.add_run('United States of America').bold =True
docx.add_picture()
Using the add_picture() method in Python-docx, you can add an image to the Word document. The picture below shows the column available for uploading images in a Word document.

Python docx add_picture() method provides an option to add a picture to the Word file. You can control the size of the image by defining its height and width of the image.
Syntax:
Height and width are optional to provide, but they will be either in Inches or cm (centimeters). We recommend keeping the image in the same folder where the main project is, but in case it is not possible, then provide the complete path in place of <image_path>.
from docx.shared import Inches
doc = Document()
doc.add_picture(<image_path>, width=Inches(val), height=Inches(val))Example:
The below example demonstrates the use of docx.add_image() in the Python docx module. In this example, we have added an image file to the Word document.
# import modules
from docx import Document
from docx.shared import Inches
# create an instance
doc = Document()
# add image
doc.add_picture('logo.png', height=Inches(0.81), width=Inches(2.52))
# save file
doc.save('word.docx')
Check out Create Layouts with Python Tkinter Frame
Source code of the tkinter application
In this section, we have provided source code for creating an application for generating experience certificates for employees who are leaving the organization.
PermissionError: [Errno 13] Permission denied: 'word.docx'The Word file must be closed before clicking on the ‘Generate Word’ button again. If you are seeing the above permission error, that means the file is open. Close the file and try again to fix this error.
Read Create a Progress Bar in Python Tkinter
Python Tkinter Code (GUI Development)
Here is the source code for creating a Graphical User Interface (GUI) for the Experience Letter generating application in Python.
# modules
from tkinter import *
# clear function
def clear_inputs():
eid.delete(0, 'end')
ename.delete(0, 'end')
desig.delete(0, 'end')
jd.delete(0, 'end')
ed.delete(0, 'end')
ws = Tk()
ws.title('Service Certificate Generator')
ws.geometry('400x300')
ws.config(bg='#456')
f = ('sans-serif', 13)
btn_font = ('sans-serif', 10)
bgcolor = '#BF5517'
genvar = StringVar()
genopt = ['Male', 'Female']
genvar.set('Male')
# frames
frame = Frame(ws, padx=20, pady=20, bg=bgcolor)
frame.pack(expand=True, fill=BOTH)
# label widgets
Label(
frame,
text="Employee ID",
font=f,
bg=bgcolor
).grid(row=0, column=0, sticky='w')
Label(
frame,
text="Employee Name",
font=f,
bg=bgcolor
).grid(row=1, column=0, sticky='w')
Label(
frame,
text="Designation",
font=f,
bg=bgcolor
).grid(row=2, column=0, sticky='w')
Label(
frame,
text="Joining Date",
font=f,
bg=bgcolor
).grid(row=3, column=0, sticky='w')
Label(
frame,
text="End Date",
font=f,
bg=bgcolor
).grid(row=4, column=0, sticky='w')
Label(
frame,
text='Gender',
font=f,
bg=bgcolor
).grid(row=5, column=0, sticky='w')
# entry widgets
eid = Entry(frame, width=20, font=f)
eid.grid(row=0, column=1)
ename = Entry(frame, width=20, font=f)
ename.grid(row=1, column=1)
desig = Entry(frame, width=20, font=f)
desig.grid(row=2, column=1)
jd = Entry(frame, width=20, font=f)
jd.grid(row=3, column=1)
ed = Entry(frame, width=20, font=f)
ed.grid(row=4, column=1)
gender = OptionMenu(
frame,
genvar,
*genopt
)
gender.grid(row=5, column=1, pady=(5,0))
gender.config(width=15, font=f)
btn_frame = Frame(frame, bg=bgcolor)
btn_frame.grid(columnspan=2, pady=(50, 0))
# default inputs for testing
eid.insert(0,'E1008')
ename.insert(0, 'Vineet Singh')
desig.insert(0, 'Python Developer')
jd.insert(0, 'Aug 3rd, 2020')
ed.insert(0, 'July 31st, 2021')
# action buttons
submit_btn = Button(
btn_frame,
text='Generate Word',
command=None, #generate,
font=btn_font,
padx=10,
pady=5
)
submit_btn.pack(side=LEFT, expand=True, padx=(15, 0))
clear_btn = Button(
btn_frame,
text='Clear',
command=clear_inputs,
font=btn_font,
padx=10,
pady=5,
width=7
)
clear_btn.pack(side=LEFT, expand=True, padx=15)
exit_btn = Button(
btn_frame,
text='Exit',
command=lambda:ws.destroy(),
font=btn_font,
padx=10,
pady=5
)
exit_btn.pack(side=LEFT, expand=True)
# mainloop
ws.mainloop()Check out Master the Python Tkinter Canvas
Source Code for Creating a Word File using Python
Here is the fully functional Python source code for creating a Word file using Python.
# modules
from docx import Document
from docx.opc.coreprops import CoreProperties
from docx.enum.style import WD_STYLE_TYPE
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.shared import Inches, Pt
# user inputs
logo = 'files/tsinfo_logo.jpg'
output = 'Experience_letter1.docx'
sign = 'files/signature.png'
ceo_sig_text = '''Adarshnath Singh \nDirector'''
heading = 'Service Certificate'
emp_id = 'E1001' #eid.get()
emp_name = 'Vineet Singh' # ename.get()
designation = 'Software Engineer' #desig.get()
joining_date = 'August 20, 2019' #jd.get()
end_date = 'July 31, 2021' #ed.get()
comp_detail = '''TSInfo Technologies (OPC) Pvt Ltd
Flat G-115, SJR Residency, Devarabeesanahalli, Bellandur, Bangalore, 560103
Email: info@tsinfotechnologies.com, Phone: +91-9916854253
'''
gen = 'He' # who.get()
# subject pronoun
gen2 = 'his' # her
gen3 = 'him' # her
if gen.lower() == 'he':
gen2 = 'his'
gen3 = 'him'
elif gen.lower() == 'she':
gen2 = 'her'
gen3 = 'her'
else:
print('Error: accept He/She only')
# certificate template
body_text = f'''This is to certify that {emp_name} has worked with TSInfo Technologies (OPC) Pvt Ltd from {joining_date} to {end_date}, and was designated as {designation} at the time of {gen2} leaving the organization.
{gen.capitalize()} is hardworking and a good team player.
We wish {gen3} all the success in his future endeavor.
'''
# create instance
doc = Document()
# declare margin
sections = doc.sections
for section in sections:
section.top_margin = Inches(0.04)
section.bottom_margin = Inches(0.19)
section.left_margin = Inches(0.93)
section.right_margin = Inches(0.89)
section = doc.sections[0]
# logo image placement
logo = doc.add_picture(logo, width=Inches(2.52), height=Inches(0.81))
logo_placement = doc.paragraphs[-1]
logo_placement.alignment = WD_ALIGN_PARAGRAPH.CENTER
# line space
for _ in range(1):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style).add_run(' ')
linespace_style.font.size = Pt(10)
# employee Id
empid_style = doc.styles['Normal']
empid = doc.add_paragraph(style=empid_style).add_run(f'{emp_id}')
empid.font.bold = True
# line space
for _ in range(1):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style).add_run()
linespace.font.size = 10
# Header
heading_style = doc.styles['Body Text']
head=doc.add_paragraph(style=heading_style).add_run(f'{heading}')
doc.paragraphs[-1].alignment = WD_ALIGN_PARAGRAPH.CENTER
head.font.size = Pt(20)
head.font.bold = True
# body text
body_style = doc.styles['Body Text']
body = doc.add_paragraph(style=body_style).add_run(f'{body_text}')
body.font.size = Pt(14)
body.font.name = 'Times New Roman'
#line space
for _ in range(2):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style).add_run()
linespace.font.size = 10
# signature image & text
ceo_sign = doc.styles['Body Text']
doc.add_picture(sign, width=Inches(1.57), height=Inches(0.43))
doc.add_paragraph(style=ceo_sign).add_run(f'{ceo_sig_text}')
ceo_sign.font.size = Pt(14)
# line space
for _ in range(4):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style)
# footer text : company description
company_text = doc.styles['Normal']
company_text.paragraph_format.space_before = Pt(12)
doc.add_paragraph(style=company_text).add_run(f'{comp_detail}')
center_align = doc.paragraphs[-1]
center_align.alignment = WD_ALIGN_PARAGRAPH.CENTER
# saving file to word document
doc.save(output)Read Set and Manage Window Size in Python Tkinter
Complete Source code for creating a Word document using Python tkinter
Here is the source code of the complete application that will generate the experience letter of an employee. It accepts the information through a graphical user interface created using the tkinter module in Python.
# modules
from docx import Document
from docx.opc.coreprops import CoreProperties
from docx.enum.style import WD_STYLE_TYPE
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.shared import Inches, Pt
from tkinter import *
from tkinter import messagebox
ws = Tk()
ws.title('Service Certificate Generator')
ws.geometry('400x300')
ws.config(bg='#456')
f = ('sans-serif', 13)
btn_font = ('sans-serif', 10)
bgcolor = '#BF5517'
genvar = StringVar()
genopt = ['Male', 'Female']
genvar.set('Male')
def clear_inputs():
eid.delete(0, 'end')
ename.delete(0, 'end')
desig.delete(0, 'end')
jd.delete(0, 'end')
ed.delete(0, 'end')
def generate():
# data variables
logo = 'files/tsinfo_logo.jpg'
output = 'output/Experience_letter.docx'
sign = 'files/signature.png'
ceo_sig_text = '''Adarshnath Singh \nDirector'''
heading = 'Service Certificate'
emp_id = eid.get()
emp_name = ename.get()
designation = desig.get()
joining_date = jd.get()
end_date = ed.get()
comp_detail = '''
TSInfo Technologies (OPC) Pvt Ltd
Flat G-115, SJR Residency, Devarabeesanahalli, Bellandur, Bangalore, 560103
Email: info@tsinfotechnologies.com, Phone: +91-9916854253
'''
# gender specification
gen1 = 'He' # she
gen2 = 'his' # her
gen3 = 'him' # her
if genvar.get() == 'Male':
gen1 = 'He'
gen2 = 'his'
gen3 = 'him'
elif genvar.get() == 'Female':
gen1 = 'She'
gen2 = 'her'
gen3 = 'her'
else:
messagebox.showerror('Error', 'Incorrect gender Selection!')
# experience certificate template
body_text = f'''
This is to certify that {emp_name} has worked with TSInfo Technologies (OPC) Pvt Ltd from {joining_date} to {end_date}, and was designated as {designation} at the time of {gen2} leaving the organization.
{gen1} is hardworking and a good team player.
We wish {gen3} all the success in {gen2} future endeavor.
'''
# create object(s)
doc = Document()
sections = doc.sections
# declare margin
for section in sections:
section.top_margin = Inches(0.04)
section.bottom_margin = Inches(0.19)
section.left_margin = Inches(0.93)
section.right_margin = Inches(0.89)
section = doc.sections[0]
# logo image placement
logo = doc.add_picture(logo, width=Inches(2.52), height=Inches(0.81))
logo_placement = doc.paragraphs[-1]
logo_placement.alignment = WD_ALIGN_PARAGRAPH.CENTER
# line space
for _ in range(1):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style).add_run(' ')
linespace_style.font.size = Pt(10)
# employee Id
empid_style = doc.styles['Normal']
empid = doc.add_paragraph(style=empid_style).add_run(f'{emp_id}')
empid.font.bold = True
# line space
for _ in range(1):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style).add_run()
linespace.font.size = 10
# Header
heading_style = doc.styles['Body Text']
head = doc.add_paragraph(style=heading_style).add_run(f'{heading}')
doc.paragraphs[-1].alignment = WD_ALIGN_PARAGRAPH.CENTER
head.font.size = Pt(20)
head.font.bold = True
# body text
body_style = doc.styles['Body Text']
body = doc.add_paragraph(style=body_style).add_run(f'{body_text}')
body.font.size = Pt(14)
body.font.name = 'Times New Roman'
#line space
for _ in range(2):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style).add_run()
linespace.font.size = 10
# signature image & text
ceo_sign = doc.styles['Body Text']
doc.add_picture(sign, width=Inches(1.57), height=Inches(0.43))
doc.add_paragraph(style=ceo_sign).add_run(f'{ceo_sig_text}')
ceo_sign.font.size = Pt(14)
# line space
for _ in range(4):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style)
# linespace.font.size = Pt(10)
# footer text : company description
company_text = doc.styles['Normal']
company_text.paragraph_format.space_before = Pt(12)
doc.add_paragraph(style=company_text).add_run(f'{comp_detail}')
center_align = doc.paragraphs[-1]
center_align.alignment = WD_ALIGN_PARAGRAPH.CENTER
doc.save(output)
# frames
frame = Frame(ws, padx=20, pady=20, bg=bgcolor)
frame.pack(expand=True, fill=BOTH)
# label widgets
Label(
frame,
text="Employee ID",
font=f,
bg=bgcolor
).grid(row=0, column=0, sticky='w')
Label(
frame,
text="Employee Name",
font=f,
bg=bgcolor
).grid(row=1, column=0, sticky='w')
Label(
frame,
text="Designation",
font=f,
bg=bgcolor
).grid(row=2, column=0, sticky='w')
Label(
frame,
text="Joining Date",
font=f,
bg=bgcolor
).grid(row=3, column=0, sticky='w')
Label(
frame,
text="End Date",
font=f,
bg=bgcolor
).grid(row=4, column=0, sticky='w')
Label(
frame,
text='Gender',
font=f,
bg=bgcolor
).grid(row=5, column=0, sticky='w')
# entry widgets
eid = Entry(frame, width=20, font=f)
eid.grid(row=0, column=1)
ename = Entry(frame, width=20, font=f)
ename.grid(row=1, column=1)
desig = Entry(frame, width=20, font=f)
desig.grid(row=2, column=1)
jd = Entry(frame, width=20, font=f)
jd.grid(row=3, column=1)
ed = Entry(frame, width=20, font=f)
ed.grid(row=4, column=1)
gender = OptionMenu(
frame,
genvar,
*genopt
)
gender.grid(row=5, column=1, pady=(5,0))
gender.config(width=15, font=f)
btn_frame = Frame(frame, bg=bgcolor)
btn_frame.grid(columnspan=2, pady=(50, 0))
# default inputs for testing
eid.insert(0,'E1008')
ename.insert(0, 'Vineet Singh')
desig.insert(0, 'Python Developer')
jd.insert(0, 'Aug 3rd, 2020')
ed.insert(0, 'July 31st, 2021')
submit_btn = Button(
btn_frame,
text='Generate Word',
command=generate,
font=btn_font,
padx=10,
pady=5
)
submit_btn.pack(side=LEFT, expand=True, padx=(15, 0))
clear_btn = Button(
btn_frame,
text='Clear',
command=clear_inputs,
font=btn_font,
padx=10,
pady=5,
width=7
)
clear_btn.pack(side=LEFT, expand=True, padx=15)
exit_btn = Button(
btn_frame,
text='Exit',
command=lambda:ws.destroy(),
font=btn_font,
padx=10,
pady=5
)
exit_btn.pack(side=LEFT, expand=True)
# mainloop
ws.mainloop()Output of Python Tkinter Application


In this tutorial, I have explained how to create a Word document using a simple GUI application.
You may like to read:
- Use the Tkinter Treeview Widget in Python
- Take User Input and Store It in a Variable Using Python Tkinter
- Cancel Scheduled Functions with after_cancel() in Python Tkinter

Bijay Kumar is an experienced Python and AI professional who enjoys helping developers learn modern technologies through practical tutorials and examples. His expertise includes Python development, Machine Learning, Artificial Intelligence, automation, and data analysis using libraries like Pandas, NumPy, TensorFlow, Matplotlib, SciPy, and Scikit-Learn. At PythonGuides.com, he shares in-depth guides designed for both beginners and experienced developers. More about us.