First of all, I think this module is awesome as there are nearly no other easy options to convert a docx to a pdf using Python. So if this problem could be solved, I'd be very happy.
I created a script that opens a docx, edit some text variables according to a Tkinter Entry input and then saves it as a new docx. I then want to convert it to a pdf so that I don't need to do that manually but that's the part which I can't get to succeed. I'll share with you my code and all the output it gives me:
from docx import Document
from docx.shared import Pt
from tkinter import *
from tkinter import messagebox
from tkinter import font as tkfont
from docx2pdf import convert
import docx2pdf
import os
print(docx2pdf.__version__)
root = Tk()
root.config(background='#009688')
root.wm_withdraw()
root.update()
root.title('Contractmaker')
naamhuurder = StringVar(root)
geboortedatum = StringVar(root)
adreshuurder = StringVar(root)
pchuurder = StringVar(root)
woonplaatshuurder = StringVar(root)
adresapp = StringVar(root)
typekamer = StringVar(root)
einddatumcontract = StringVar(root)
begindatumcontract = StringVar(root)
beginmaand1 = StringVar(root)
eindmaand1 = StringVar(root)
# Make all entries empty
def clear():
entryNames = [naamhuurderr, geboortedatumm, adreshuurderr, pchuurderr, woonplaatshuurderr,
einddatumcontractt, begindatumcontractt,
beginmaand11, eindmaand11]
for i in entryNames:
i.delete(0, END)
# The function that changes the variables and saves it as a pdf in the correct folder
def contractupdater():
global huur
global appwp
global pcapp
# open the document and set the fontsize and style
doc = Document('./Contract.docx')
styles = doc.styles['Normal']
font = styles.font
font.size = Pt(9)
font.name = 'Arial'
# Remove the spaces from the adress line
oldadres = adresapp.get()
nospaceadres = oldadres.replace(' ', '').lower()
# Handle the dropdown menus
if adresapp.get() == 'Slotlaan 73' or adresapp.get() == 'Slotlaan 77':
pcapp = '2902AK'
appwp = 'Capelle aan den IJssel'
elif adresapp.get() == 'Albert Cuypstraat 22':
pcapp = '2902GC'
appwp = 'Capelle aan den IJssel'
if typekamer.get() == 'Grote kamer':
huur = '510'
elif typekamer.get() == 'Kleine kamer':
huur = '435'
elif typekamer.get() == 'Grote kamer gedeeld':
huur = '800'
# Check whether the date has been filled in correctly
try:
einddatum = einddatumcontract.get()
laatstecijferpluseen = str(int(einddatum[-1]) + 1)
verlengentot = str(einddatum[:-1])
verlengentot += laatstecijferpluseen
except:
verlengentot = 'error'
# Replace the variables with the input
Dictionary = {"naam.vv": naamhuurder.get(), "gb.vv": geboortedatum.get(), 'adres.vv': adreshuurder.get(),
'postcode.vv': pchuurder.get(),
'woonplaats.vv': woonplaatshuurder.get(), 'appdres.vv': adresapp.get(), 'apppc.vv': pcapp,
'appwp.vv': appwp, 'typekamer.vv': typekamer.get(), 'enddate.vv': einddatumcontract.get(),
'begindate.vv': begindatumcontract.get(), 'verlengdatum.vv': verlengentot, 'huur.vv': huur,
'begineerstemaand.vv': beginmaand1.get(), 'eindeerstemaand.vv': eindmaand1.get()}
# Check whether all Entry received input
entriesWithInput = []
for key, value in Dictionary.items():
if len(value) > 0:
entriesWithInput.append(value)
# Replace the variables of in the docx to the input if it fullfills the if statements
if len(entriesWithInput) == len(Dictionary):
if verlengentot != 'error':
for i in Dictionary:
for p in doc.paragraphs:
if p.text.find(i) >= 0:
p.text = p.text.replace(i, Dictionary[i])
# Save changed document at the correct place
doc.save('/Users/Jem/Documents/Huurovereenkomsten/Specifiek/{}/contract{}.docx'.format(nospaceadres,
naamhuurder.get()))
path = '/Users/Jem/Documents/Huurovereenkomsten/Specifiek/{}/contract{}.docx'.format(nospaceadres, naamhuurder.get())
os.chmod(path, 0o777)
convert('/Users/Jem/Documents/Huurovereenkomsten/Specifiek/{}/contract{}.docx'.format(nospaceadres,
naamhuurder.get()))
# Show user that the file has succesfully been made
messagebox.showinfo('Succesvol opgeslagen', 'Het contract is gemaakt en opgeslagen in de folder.')
else:
messagebox.showerror('Vul alleen cijfers in bij de datum', 'Vul een datum als volgt in: dd-mm-jjjj')
else:
messagebox.showerror('Er ging iets mis',
'Controleer of alle data correct is ingevuld en probeer opnieuw.')
# GUI stuff that takes care of the scrollbar
def on_configure(event):
canvas.configure(scrollregion=canvas.bbox('all'))
def on_mousewheel(event):
canvas.yview_scroll(int(event.delta), 'units')
# Create some fonts
bold_font = tkfont.Font(weight='bold')
# Create the actual GUI
canvas = Canvas(root, width=450, height=550)
canvas.config(background='#009688')
canvas.pack(side=RIGHT)
scrollbar = Scrollbar(root, command=canvas.yview)
# scrollbar.pack(side=RIGHT, fill='y')
canvas.configure(yscrollcommand=scrollbar.set)
canvas.bind('<Configure>', on_configure)
canvas.bind_all('<MouseWheel>', on_mousewheel)
frame = Frame(canvas)
frame.config(background='#009688')
canvas.create_window((0,0), window=frame)
labelNaamhuurder = Label(frame, text='Naam huurder', bg='#009688', font=bold_font).grid(row=0, column=0, sticky=W, padx=(30, 0), pady=(15, 0))
naamhuurderr = Entry(frame, textvariable=naamhuurder, relief=FLAT, highlightcolor='#9DCCFD')
naamhuurderr.focus_set()
naamhuurderr.grid(row=0, column=2, pady=(15, 0))
labelGeboortedatum = Label(frame, text='Geboortedatum', bg='#009688', font=bold_font).grid(row=1, column=0, pady=(15, 0), sticky=W, padx=(30, 0))
geboortedatumm = Entry(frame, textvariable=geboortedatum, relief=FLAT, highlightcolor='#9DCCFD')
geboortedatumm.grid(row=1, column=2, pady=(15, 0))
labelAdreshuurder = Label(frame, text='Adres huurder', bg='#009688', font=bold_font).grid(row=2, column=0, pady=(15, 0), sticky=W, padx=(30, 0))
adreshuurderr = Entry(frame, textvariable=adreshuurder, relief=FLAT, highlightcolor='#9DCCFD')
adreshuurderr.grid(row=2, column=2, pady=(15, 0))
labelPchuurder = Label(frame, text='Postcode huurder', bg='#009688', font=bold_font).grid(row=3, column=0, pady=(15, 0), sticky=W, padx=(30, 0))
pchuurderr= Entry(frame, textvariable=pchuurder, relief=FLAT, highlightcolor='#9DCCFD')
pchuurderr.grid(row=3, column=2, pady=(15, 0))
labelWoonplaatshuurder = Label(frame, text='Woonplaats huurder', bg='#009688', font=bold_font).grid(row=4, column=0, pady=(15, 0), sticky=W, padx=(30, 0))
woonplaatshuurderr = Entry(frame, textvariable=woonplaatshuurder, relief=FLAT, highlightcolor='#9DCCFD')
woonplaatshuurderr.grid(row=4, column=2, pady=(15, 0))
labelAdresapp = Label(frame, text='Adres appartement', bg='#009688', font=bold_font).grid(row=5, column=0, pady=(15, 0), sticky=W, padx=(30, 0))
appartementen = {'Slotlaan 73', 'Slotlaan 77', 'Albert Cuypstraat 22'}
adresapp.set('Slotlaan 73') # Default option
dropdownMenuhuur = OptionMenu(frame, adresapp, *appartementen)
dropdownMenuhuur.config(width=18)
dropdownMenuhuur.grid(row=5, column=2, pady=(15, 0))
labelTypekamer = Label(frame, text='Type kamer', bg='#009688', font=bold_font).grid(row=6, column=0, pady=(15, 0), sticky=W, padx=(30, 0))
typeKamers = {'Grote kamer', 'Kleine kamer', 'Grote kamer gedeeld'}
typekamer.set('Grote kamer') # Default option
dropdownMenutypekamer = OptionMenu(frame, typekamer, *typeKamers)
dropdownMenutypekamer.config(width=18)
dropdownMenutypekamer.grid(row=6, column=2, pady=(15, 0))
labelEinddatumcontract = Label(frame, text='Eind datum contract', bg='#009688', font=bold_font).grid(row=7, column=0, pady=(15, 0), sticky=W, padx=(30, 0))
einddatumcontractt = Entry(frame, textvariable=einddatumcontract, relief=FLAT, highlightcolor='#9DCCFD')
einddatumcontractt.grid(row=7, column=2, pady=(15, 0))
labelBegindatumcontract = Label(frame, text='Begin datum contract', bg='#009688', font=bold_font).grid(row=8, column=0, pady=(15, 0), sticky=W, padx=(30, 0))
begindatumcontractt = Entry(frame, textvariable=begindatumcontract, relief=FLAT, highlightcolor='#9DCCFD')
begindatumcontractt.grid(row=8, column=2, pady=(15, 0))
labelBeginmaand1 = Label(frame, text='Begin van de eerste maand', bg='#009688', font=bold_font).grid(row=9, column=0, pady=(15, 0), sticky=W, padx=(30, 0))
beginmaand11 = Entry(frame, textvariable=beginmaand1, relief=FLAT, highlightcolor='#9DCCFD')
beginmaand11.grid(row=9, column=2, pady=(15, 0))
labelEindmaand1 = Label(frame, text='Eind van de eerste maand', bg='#009688', font=bold_font).grid(row=10, column=0, pady=(15, 0), sticky=W, padx=(30, 0))
eindmaand11 = Entry(frame, textvariable=eindmaand1, relief=FLAT, highlightcolor='#9DCCFD')
eindmaand11.grid(row=10, column=2, pady=(15, 0))
empty = Button(frame, text='Opnieuw', command=clear, font=bold_font)
empty.config(width=10, fg='#009688', borderwidth=0, relief=RAISED)
empty.configure(highlightbackground='#009688')
empty.grid(row=11, column=0, pady=(25, 0), padx=(80, 0))
converter = Button(frame, text='OK', command=contractupdater, font=bold_font)
converter.config(width=10, fg='#009688', borderwidth=2, relief=RAISED)
converter.configure(highlightbackground='#009688')
converter.grid(row=11, column=2, pady=(25, 0), padx=(0, 80))
root.after(1, root.deiconify)
root.mainloop()
Before I added the os.chmod(path, 0o777), it would ask me for permission. After I added that, it wouldn't ask me for permission anymore but it still didn't work. In this SO question, I've also asked my question. After running the above code, it gives me
0%| | 0/1 [00:02<?, ?it/s]
It then opens the file in MS Word but doesn't do anything in Word and then it gives me:
{'input': '/Users/Jem/Documents/Huurovereenkomsten/Specifiek/slotlaan73/contractabc.docx', 'output': '/Users/Jem/Documents/Huurovereenkomsten/Specifiek/slotlaan73/contractabc.pdf', 'result': 'error', 'error': 'Error: Er heeft zich een fout voorgedaan.'}
'Er heeft zich een fout voorgedaan.' is Dutch for: an error has occurred.
Really hoping you can find a solution for this because, as said, I think this module can be very useful.