How I created the simplest GUI using Python’s appJar library

Botir Rakhimov
3 min readFeb 3, 2021

In my previous article I talked about how one of extremely time-consuming manual process was automated using two simple Python functions. We had split multi-page PDF file into separate ‘one-pagers’ and rename each based on instructions given. For those who want to revisit , you can read it here.

For all this time our finance department was running those functions in IDE until I finally made some time to wrap the code in a simple GUI — the result is a nice small app with user interface and very easy to use.

Most folks out there make use of Tkinter library for such GUI’s but I this time I tried using appJar and sharing the code below:

Let’s install our library first:

pip3 install appJar

And import all the library packages we will be using including appJar and built-in pathlib . The latter is an object API tool for working with files and directories.

from appJar import gui
from pathlib import Path

I will copy and paste the functions mentioned in previous article for our reference:

def split_pdf_pages(root_directory, extract_folder):
for root, dirs, files in os.walk(root_directory):
for filename in files:
basename, extension = os.path.splitext(filename)
if extension == ".pdf":
path = root + "\\" + basename + extension
open_pdf = PyPDF2.PdfFileReader(open(path, "rb"))
for i in range(open_pdf.numPages):
output = PyPDF2.PdfFileWriter()
output.addPage(open_pdf.getPage(i))
with open(extract_to+ "\\" + basename + "-%s.pdf" % i, "wb") as output_pdf:
output.write(output_pdf)
def rename_pdfs(root_directory, extract_folder):
for root, dirs, files in os.walk(root_directory):
for filename in files:
basename, extension = os.path.splitext(filename)
if extension == ".pdf":
path = root + "\\" + basename + extension output_string = StringIO()
pdf_file = open(path, "rb")
parser = PDFParser(pdf_file)
doc = PDFDocument(parser)
rsrcmgr = PDFResourceManager()
device = TextConverter(rsrcmgr, output_string, laparams=LAParams())
interpreter = PDFPageInterpreter(rsrcmgr, device) for page in PDFPage.create_pages(doc):
interpreter.process_page(page)
num = output_string.getvalue()

for cust_name in re.findall("CV.\s[A-Za-z]+",num):
cust = cust_name[0:50]
for inv in re.findall("#[0-9]+", num):
inv_num = inv[:8]
for month in re.findall("January", num) or re.findall("February", num) or re.findall("March",
num) or re.findall(
"April", num) or re.findall("May", num) or re.findall("June", num) or re.findall("July",
num) or re.findall(
"August", num) or re.findall("September", num) or re.findall("October", num) or re.findall(
"November", num) or re.findall("December", num):
date = month year=datetime.date.today().year
pdf_file.close()

os.rename(path, rename_to + "//" + f"{cust} { inv_num} { date} { year} .pdf")

Next, we need a function to validate the inputs:

def validate_inputs(input_file, output_dir,rename_dir):
errors = False
error_msgs = []
if Path(input_file).suffix.upper() != ".PDF":
errors = True
error_msgs.append("Please select a PDF input file")
if not (Path(output_dir)).exists():
errors = True
error_msgs.append("Please Select a valid output directory")
if not (Path(rename_dir)).exists():
errors = True
error_msgs.append("Please Select a valid output directory")
return (errors, error_msgs)

The above basically says:

  1. If user chooses any other file except PDF, the app will give user an error screen asking the user to choose PDF files only.

2 & 3. Check if the directories stated are valid and have existing path. We have two directories — one for splitting and second for renaming the files

Let’s work on our main button function which gives the instruction to Split and Rename where we link our above functions of validate_inputs, split_pdf_pages and rename_pdfs:

def press(button):
if button == "Split&Rename":
src_file = app.getEntry("Input_File")
dest_dir = app.getEntry("Output_Directory")
rename_to=app.getEntry("Rename to folder")
errors, error_msg = validate_inputs(src_file,dest_dir,rename_to)
if errors:
app.errorBox("Error", "\n".join(error_msg), parent=None)
else:
split_pdf_pages(src_file, dest_dir)
rename_pdfs(dest_dir, rename_to)
else:
app.stop()

We are done with functions and now it’s time to play around with our GUI . I usually prefer seeing light-blueish colors in my GUI — but of course you can play around with any available color and see how it looks.

app = gui("Split&Rename", useTtk=True)
app.setTtkTheme("alt")
app.setSize(500, 300)
app.addLabel("title", "Welcome to our Split&Rename! app")
app.setFg("Teal")
app.setBg("PowderBlue")

Last but not least, let’s add the labels:

app.addLabel("Choose PDF File")
app.addFileEntry("Input_File")

app.addLabel("Select folder to split")
app.addDirectoryEntry("Output_Directory")

app.addLabel("Select folder to rename")
app.addDirectoryEntry("Rename to folder")

app.addButtons(["Split&Rename", "Quit"], press)
app.go()

At the end, we can package/wrap the whole thing with pyinstaller where users will be able run the program with a simple click like any other app:

pip3 install pyinstaller#To package run the below in your terminal
pyinstaller -F -w main.py

--

--

Botir Rakhimov

Implementing Python to give automated solutions in Finance