How to add buttons in python? - python

I have a code which manages my file transfers. Now I want to add a tkinter to it so I can actually make a button 'run' which will let me run the code. I don't know where to implement the tkinter code as I don't know where to begin.
This is my current code:
import os
source1 = r'D:FolderX'
location2 = 'c:\data\AM\Desktop\destination'
black_list = ['folder1', 'folder2']
for root, dirs, files in os.walk(source1):
#Exclude the blacklist folders.
dirs[:] = [d for d in dirs if d not in black_list]
for file in files:
file_path = os.path.join(root, file)
if os.path.getsize(file_path) == 0:
continue
if file.endswith(".tdms"):
tdms_path = (os.path.join(root, file))
file_size = os.path.getsize(tdms_path)
if file_size == 0:
continue
else:
continue
metadata = td.read_metadata(tdms_path)
print(metadata)
dfs.append(pd.DataFrame([metadata.properties.values()], columns=metadata.properties.keys()))
df = pd.concat(dfs)
df.to_excel(locatie2 + '\\' + 'final_sheet.xlsx'

Here's an example of how to use buttons with tkinter that I think will help.
import tkinter
import tkMessageBox
top = tkinter.Tk()
def buttonPressed():
# put code for what happens when button pressed here
messagebox.showinfo("Window Title", "The code is now running")
B = tkinter.Button(top, text="Press Me", command=buttonPressed)
B.pack()
top.mainloop()
Hope this helps!

Related

Word file keyword or text importing and save to excel sheet using python gui tkinter

I created a python gui using tkinter, the gui gui is showing but during i need to locate the Microsoft word files containing the .docx and .doc it can't see but empty folder. The importing and extraction will not proceed since it doesn't see the word files.
I install the modules,
as python script shown below. Any idea?
Analyze Python Program Requested
import docx
import openpyxl
import os
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import filedialog
import threading
import win32com.client
Set the default directory and output location
default_directory = '/path/to/default/directory'
output_location = None
Create the GUI
root = tk.Tk()
root.geometry("300x250")
root.title('Data Extractor')
Create a label to display the current directory
label = tk.Label(root, text='Directory: ' + default_directory)
label.pack()
Create a button to select the directory
def select_directory():
global default_directory
directory = filedialog.askdirectory()
if directory:
default_directory = directory
label.config(text='Directory: ' + default_directory)
button = tk.Button(root, text='Set Directory', command=select_directory)
button.pack()
Create a button to select the output location
def select_output_location():
global output_location
output_location = filedialog.asksaveasfilename(defaultextension='.xlsx', filetypes=[("Excel Workbook", "*.xlsx")])
if output_location:
output_label.config(text='Output: ' + output_location)
output_label = tk.Label(root, text='Output: ')
output_label.pack()
output_button = tk.Button(root, text='Set Output Location', command=select_output_location)
output_button.pack()
Create a progress bar
progress = ttk.Progressbar(root, length=200)
progress.pack()
Create a button to start the extraction
def extract_data():
if default_directory and output_location:
thread = threading.Thread(target=extract_data_thread)
thread.start()
else:
tk.messagebox.showerror("Error", "Please select the directory, output location and check if it contain word files")
def extract_data_thread():
# Create a new Excel workbook
workbook = openpyxl.Workbook()
# Create a new sheet
sheet = workbook.create_sheet()
# Set the starting row for the data
row = 1
# Set the directory to the default or selected directory
directory = default_directory
# Get the number of files to process
file_count = 0
for root, dirs, files in os.walk(directory):
file_count += len([f for f in files if f.endswith(('.docx', '.doc'))])
# Set the progress bar maximum value
progress['maximum'] = file_count
progress['value'] = 0
processed_files = 0
# Iterate over the files in the directory
for root, dirs, files in os.walk(directory):
for filename in files:
if filename.endswith(('.docx', '.doc')):
try:
if filename.endswith('.docx'):
doc = docx.Document(os.path.join(root, filename))
tables = doc.tables
elif filename.endswith('.doc'):
word = win32com.client.Dispatch("Word.Application")
doc = word.Documents.Open(os.path.join(root, filename))
tables = doc.Tables
else:
continue
if tables:
table = tables[0]
model_no = table.cell(0,1).text
reference_number = table.cell(0,2).text
date_released = table.cell(1,1).text
else:
continue
except:
print("An error occurred while processing file: " + filename)
continue
# Add the data to the sheet
sheet.cell(row=row, column=1).value = filename
sheet.cell(row=row, column=2).value = model_no
sheet.cell(row=row, column=3).value = reference_number
sheet.cell(row=row, column=4).value = date_released
# Increment the row counter
row += 1
# Update the progress bar
processed_files += 1
progress.set(processed_files)
root.update()
if processed_files == 0:
tk.messagebox.showerror("Error", "No word files or keyword detected")
else:
# Save the workbook
workbook.save(output_location)
progress['value'] = 0
print("Successfully saved data to: " + output_location)
Create the "Extract Data" button
extract_button = tk.Button(root, text='Extract Data', command=extract_data)
extract_button.pack()
root.mainloop()
any idea how solve the issue?

Opening at least two csv files and merging them using tkinter button

I want to open multiple files (at least two) and store them into individual variables so I could then merge them using pandas, but all done by the click of a tkinter button. I have been stuck on this for two days now. I know I should be using Classes(OOP) python, but this isn't my forte as I am still a beginner...any help in the right direction will be appreciated. My code snippets:
importing all libraries
import tkinter
from sys import path
from tkinter import *
from tkinter import ttk, messagebox
from tkinter import filedialog as fd
from tkinter.messagebox import showinfo
from tkinter.messagebox import showerror
from tkinter.filedialog import asksaveasfile
from PIL import ImageTk, Image
import pandas as pd
browse_button = Button(btn_frame, text='Browse File', command=lambda: file_dialog(),
font=('helvetica', 10, 'bold'), bg='#ebdec5')
browse_button.grid(row=0, column=1, padx=10, pady=30)
load_button = Button(btn_frame, text='Load Data', command=lambda: merge_files(),
font=('helvetica', 10, 'bold'), bg='#ebdec5')
load_button.grid(row=0, column=2, padx=10, pady=40)
label_file = Label(btn_frame, text=browse_filetxt, font=('helvetica', 9, 'bold'), bg='#ebdec5')
label_file.place(rely=0, relx=0)
## file dialog to load files,how to load more than one, and and assign variables that can be used...
def file_dialog():
try:
file_name = fd.askopenfilename(initialdir='/',
title='Select a file',
filetypes=(('csv files', '*.csv'), ('All files', '*.*')))
except FileNotFoundError:
tkinter.messagebox.showerror('Information', "File not found")
return None
label_file['text'] = file_name
def merge_files():
global df
file_path = label_file['text']
try:
csv_filename = r'{}'.format(file_path)
df = pd.read_csv(csv_filename, delimiter=',')
# How to place files into variables.....
# what goes here..Please help
except ValueError:
tkinter.messagebox.showerror('Information', 'File is invalid')
return None
except FileNotFoundError:
tkinter.messagebox.showerror('Information', "File not found")
## I want to load two ore more files, put them into different variables, then use the variables,
# to merge both csv files using pandas......
You should use list to keep all selected files. This way you may have any number of files and you can use for-loop to work with all filenames
all_files = []
and when you select file
def file_dialog():
global all_files
try:
file_name = fd.askopenfilename(initialdir='/home/furas/test',
title='Select a file',
filetypes=(('csv files', '*.csv'), ('All files', '*.*')))
except FileNotFoundError:
tkinter.messagebox.showerror('Information', "File not found")
return
# check if not pressed `Cancel`
if file_name:
all_files.append( file_name )
And later you cand merge them
df = pd.DataFrame() # create new empty dataframe
for filename in all_files:
print('filename:', filename)
try:
new_df = pd.read_csv(filename, delimiter=',')
df = df.append(new_df) # <--- inside `try/except`
except ValueError:
tkinter.messagebox.showerror('Information', 'File is invalid')
except FileNotFoundError:
tkinter.messagebox.showerror('Information', "File not found")
print(df.to_string())
Minimal working example:
import tkinter as tk
from tkinter import filedialog as fd
import pandas as pd
# --- functions ---
def file_dialog():
global all_files
print('[file_dialog]')
try:
file_name = fd.askopenfilename(initialdir='/home/furas/test',
title='Select a file',
filetypes=(('csv files', '*.csv'), ('All files', '*.*')))
except FileNotFoundError:
tkinter.messagebox.showerror('Information', "File not found")
return
# check if not pressed `Cancel`
if file_name:
all_files.append( file_name )
def merge_files():
global df
global all_files
print('[merge_files]')
df = pd.DataFrame() # create new empty dataframe
for filename in all_files:
print('filename:', filename)
try:
new_df = pd.read_csv(filename, delimiter=',')
df = df.append(new_df)
except ValueError:
tkinter.messagebox.showerror('Information', 'File is invalid')
except FileNotFoundError:
tkinter.messagebox.showerror('Information', "File not found")
print(df.to_string())
# remove all filenames
all_files = []
# --- main ---
df = pd.DataFrame() # create empty dataframe at start (as default value)
all_files = [] # create empty list at start (as default value)
root = tk.Tk()
browse_button = tk.Button(root, text='Browse File', command=file_dialog)
browse_button.pack(fill='x')
load_button = tk.Button(root, text='Load Data', command=merge_files)
load_button.pack(fill='x')
root.mainloop()
EDIT:
There is also askopenfilenames with char s at the end to select many filenames at once.
It gives list/tuple with all selected filenames which you could assign to global variable (and replace all previous filenames) or use extend() or += to add filenames to existing list
file_names = fd.askopenfilenames(...)
# check if not pressed `Cancel`
if file_names:
#all_files.extend( file_names ) # add to existing list
#all_files += file_names # add to existing list
all_files = file_names # replace previous list

Python function return is none

I have a problem in my project. In my program I have the availability to choose more files if I want. The Problem is, that the return choosen_files has the list of the files but choosen_files which calls the more_files() method is none.
Do you have any suggestion?
Here is my code
import tkinter as tk
from tkinter import filedialog as fd
def get_files(path):
root = tk.Tk()
root.withdraw()
files = fd.askopenfilenames(
parent=root, title='Choose all files you want', initialdir=path)
return list(files)
def more_files(choosen_files, path):
print("choosen files:")
[print(file) for file in choosen_files]
wantMoreFiles = input(
"Do you want to choose more files? [(1) yes, (2) no]").lower()
if wantMoreFiles in ['1', 'y', 'yes']:
new_files = get_files(path)
choosen_files.extend(new_files)
more_files(choosen_files, path)
else:
return choosen_files
#this has the correct list
files = ['path/file1']
path = 'path'
choosen_files = more_files(files, path)
#this is none
Thank you very much!
You don't return anything on the last line.
Just return more_files(files, path)

Folder access permission denied python [Permission: Errno 13]

Hello everyone viewing this question and trying to solve it!
I am making a GUI-based project planner where I need to add oroject name, requirements and steps to achieve which are then saved. I am also adding a feature to add files to it according to relevancy. But when I try to test it I get this: PermissionError: [Errno 13] Permission denied: '<project name>'. I don't know where I am going wrong despite of reading many such question. I have tried chmod but even that is not working. Here is the code:
from tkinter import *
from tkinter import messagebox
from tkinter.filedialog import askopenfilename
import os
WIN = Tk()
files =[]
def copy(src,dest):
os.chmod(dest, 0o777)
with open(src,'r') as f, open(dest,'w+') as f2:
f2.write(f)
def start(name):
os.startfile(name)
#<---Button functions--->
def Addfile():
global files
WIN.filename = askopenfilename(initialdir = "C:",title = "choose your file")
print(WIN.filename)
added_fr = Frame(text_box_files)
added_fr.pack()
f_name = Label(added_fr,text=WIN.filename)
f_name.pack()
#dest = shutil.copyfile(WIN.filename, destination)
files.append(WIN.filename)
f_b = Button(added_fr,text="Open",command=lambda x = WIN.filename: start(x))
f_b.pack()
def submit():
global files
name = name_ent.get()
req = text_box.get("1.0",END)
steps = text_box_step.get("1.0",END)
if name != "" and name not in os.listdir() and req != "" and steps != "":
os.mkdir(name)
with open(f"{name}\\req.txt","w") as f:
f.write(req)
with open(f"{name}\\steps.txt","w") as f2:
f2.write(steps)
os.mkdir(f"{name}\\main")
with open(f"{name}\\main\\main.py","w") as f3:
f3.write(f"#Main .py file of {name} project")
elif name in os.listdir():
messagebox.showerror("Project already exists", "A project with this name already exists! Try something else")
elif name=="" or req=="" or steps=="":
messagebox.showerror("Naming error", "Project name/steps/requirement can't be left blank")
print(files)
for fi in files:
copy(fi, name)
#<----Frames---->
head = Frame(WIN, padx=15,pady=10)
head.pack()
main_frame1 = Frame(WIN)
main_frame1.pack()
main_frame2 = Frame(WIN,highlightbackground="black" , highlightthickness=1)
main_frame2.pack()
name_frame = Frame(main_frame1,highlightbackground="black" , highlightthickness=1,padx=382,pady=3)
name_frame.pack()
requirements_frame = Frame(main_frame2)
requirements_frame.grid(row=0,column=0)
files_frame = Frame(main_frame2,highlightbackground="black", highlightthickness=1)
files_frame.grid(row=0,column=1)
#<----Title---->
title = Label(head, text="Project Planner", font=("Arial bold",18))
title.pack()
#<----Name-Frame---->
name_lb = Label(name_frame,text="Project name: ").grid(row=0,column=0,sticky="e")
name_ent = Entry(name_frame,width=20)
name_ent.grid(row=0,column=1)
#<----Requirements---->
requirements_lb = Label(requirements_frame, text="Requirements: ")
requirements_lb.pack()
text_box = Text(requirements_frame,width=100,height=5)
text_box.pack(side = TOP, expand = True, fill = BOTH)
#<----Step---->
step_lb = Label(requirements_frame,text="Steps/Ideas to solve: ")
step_lb.pack()
text_box_step = Text(requirements_frame,width=100,height=17)
text_box_step.pack(side = TOP, expand = True, fill = BOTH)
#<----Files---->
files_lb = Label(files_frame,text="Add files: ")
files_lb.pack()
text_box_files = Text(files_frame,width=20)
text_box_files.pack()
add = Button(files_frame,text="Add",command=Addfile)
add.pack(ipadx=30)
#<----Submit---->
submit = Button(WIN,text="Submit",command=submit)
submit.pack(ipadx=30,pady=2)
WIN.mainloop()
Also my operating system is Windows,
Please help.

How do I get my tkinter picture viewer working?

I've been trying to teach myself tkinter and wanted to make a program that would find all the pictures in the directory and sub-directories of a folder and then display them one by one with a button to either save the file into the "Yes", "Maybe", or "Skip" folders or simply delete the file.
Here's what I'm trying to get it to look like:
And here is my code which tries to do just that:
# Python 3.4
import os
import tkinter as tk
from tkinter import Frame, Button
from PIL import Image, ImageTk
from send2trash import send2trash
tk_root = tk.Tk()
tk_root.title("Picture Viewer - Do I want to keep this picture?")
file_count = 0
p = path = 'C:\\Users\\MyUserName\\Desktop\\Test\\'
yes = lambda img: os.rename(img, p+'Yes\\Picture_{0}.jpg'.format(file_count))
maybe = lambda img: os.rename(img, p+'Maybe\\Picture_{0}.jpg'.format(file_count))
skip = lambda img: os.rename(img, p+'Skipped\\Picture_{0}.jpg'.format(file_count))
delete = lambda img: send2trash(img) # Note: os.remove('img.jpg') also works
def search(directory):
global file_count
for root, subdirs, files in os.walk(directory):
for file in files:
if os.path.splitext(file)[1].lower() in ('.jpg', '.jpeg'):
img = os.path.join(root, file)
file_count += 1
top_frame = Frame(tk_root)
bottom_frame = Frame(tk_root)
top_frame.pack(side='top')
bottom_frame.pack(side='bottom')
picture = ImageTk.PhotoImage(Image.open(img))
picture = tk.Label(tk_root, image=picture)
picture.pack(side='top')
button_yes = Button(top_frame, text="Yes", command=lambda x=img:yes(x))
button_maybe = Button(top_frame, text="Maybe", command=lambda x=img:maybe(x))
button_skip = Button(top_frame, text="skip", command=lambda x=img:skip(x))
button_delete = Button(bottom_frame, text="Delete", command=lambda x=img:delete(x))
button_yes.pack(side='left')
button_maybe.pack(side='left')
button_skip.pack(side='left')
button_delete.pack(side='bottom')
print('All done!')
search('Test')
However, the problem is after I launch the program it isn't working well at all. It simply moves the first picture, "1.jpg", into whatever folder I pick (or delete) and then giving the following error if I try to sort another image:
FileNotFoundError: [WinError 2] The system cannot find the file
specified: 'Test\Example.jpg' ->
'C:\Users\Vale\Desktop\Test\Maybe\1.jpg'
Perhaps most importantly the images are not displaying and cycling properly. It is just a gray box in the middle each time. How do I get my program to work? I'm aware I need to get the image to appear still and something needs to be done to get the program to move onto the next picture as well (so I don't get FileNotFoundError for trying to sort the same picture twice), but I'm unsure what to do differently after watching tutorials and reading documentation.
As mentioned by BlackJack, your code creates the GUI Widgets over and over. You'll need to move that out from the loop. Also for displaying the image in the Label, you can't use picture as the name for both the ImageTk object and Label object.
Suggestions to changes. You could use a Generator to get the image path/filename. And make regular functions instead of using lambda. I had an interest in seeing how it could work, so I made the program below based on your code. When I tested it I had different paths, working on OSX, so haven't tested it with your Windows paths (that I put into the code here).
import os
import tkinter as tk
from tkinter import Frame, Button
from PIL import Image, ImageTk
tk_root = tk.Tk()
tk_root.title("Picture Viewer - Do I want to keep this picture?")
file_count = 0
p = path = 'C:\\Users\\MyUserName\\Desktop\\Test\\'
def search(directory):
global file_count
for root, subdirs, files in os.walk(directory):
for file in files:
if os.path.splitext(file)[1].lower() in ('.jpg', '.jpeg'):
img = os.path.join(root, file)
file_count += 1
yield img
def next_image():
try:
global photo_path
photo_path = next(path_generator)
photo = ImageTk.PhotoImage(Image.open(photo_path))
picture.configure(image=photo)
picture.image = photo
except StopIteration:
picture.configure(image='', text='All done!')
def move_file(directory):
if not os.path.exists(directory):
os.makedirs(directory)
new_file = directory + 'Picture_{0}.jpg'.format(file_count)
os.rename(photo_path, new_file)
def yes():
move_file(path + 'Yes\\')
next_image()
def maybe():
move_file(path + 'Maybe\\')
next_image()
def skip():
move_file(path + 'Skipped\\')
next_image()
def delete():
# Code for deleting file here
next_image()
top_frame = Frame(tk_root)
bottom_frame = Frame(tk_root)
top_frame.pack(side='top')
bottom_frame.pack(side='bottom')
path_generator = search(p)
photo_path = next(path_generator)
photo = ImageTk.PhotoImage(Image.open(photo_path))
picture = tk.Label(tk_root, image=photo)
picture.image = photo
picture.pack(side='top')
button_yes = Button(top_frame, text="Yes", command=yes)
button_maybe = Button(top_frame, text="Maybe", command=maybe)
button_skip = Button(top_frame, text="skip", command=skip)
button_delete = Button(bottom_frame, text="Delete", command=delete)
button_yes.pack(side='left')
button_maybe.pack(side='left')
button_skip.pack(side='left')
button_delete.pack(side='bottom')
tk_root.mainloop()
EDIT:
One issue with this code seems to be that it runs through the subdirectories (Yes, Maybe, Skipped). So you'll be presented with the images twice if it is in the path and then moved.
If you don't want to traverse the Yes, Maybe and Skipped folders, you can change the search function to:
def search(directory):
global file_count
excludes = ['Yes', 'Maybe', 'Skipped']
for root, subdirs, files in os.walk(directory, topdown=True):
subdirs[:] = [d for d in subdirs if d not in excludes]
for file in files:
if os.path.splitext(file)[1].lower() in ('.jpg', '.jpeg'):
img = os.path.join(root, file)
file_count += 1
yield img

Categories