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

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

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?

File not landing in new directory created by askdirectory in tkinter

Firstly, thanks Carl_M! I will try to ask this question with more simple code. Using tkinker-
the user is asked to select the directory and new subfolder. That works.
Then browse for an exel file that will be modified as a df and sent to the new subfolder. That sort of works (thanks to Carl), but file doesn't go to the new subfolder. It goes to the selectPath. How can I add the path to the folder?
Used 'dirs = os.path.join(path.get(), folder.get())' to assign location, but it's not landing there.
def selectPath():
path_ = askdirectory()
path.set(path_)
def create_subfolder():
print("folder_name: ", folder.get())
print("path_name: ", path.get())
dirs = os.path.join(path.get(), folder.get())
def openFile():
filename = filedialog.askopenfilename(initialdir = r'L:\folder\My_file', filetypes=[("Excel Files", "*.xlsx")])
os.startfile(filename)
df = pd.read_excel(filename, sheet_name = 'Order Details')
df.to_excel(((dirs) + 'Intelliscan.xlsx'),index=False)
Try
def openFile():
filename = filedialog.askopenfilename(initialdir = r'L:\folder\My_file', filetypes=[("Excel Files", "*.xlsx")])
os.startfile(filename)
df = pd.read_excel(filename, sheet_name = 'Order Details')
destination = os.path.join(path.get(), folder.get(),'Intelliscan.xlsx')
df.to_excel(destination,index=False)

UnboundLocalError: local variable 'file1' referenced before assignment please help to fix

I need that when the button is clicked, the file_name variable is saved to a file. Please tell me how to fix my code:
window = tk.Tk()
window.title("Open")
window.geometry("600x400")
window.resizable(False, False)
file_name = ""
def openu():
global file_name
if file_name == "":
file_name = tfd.askopenfilename()
with open("Filen.json", "w") as file1:
json.dump(file_name, file1, indent=2, ensure_ascii=False)
os.startfile(file_name)
else:
with open("Filen.json", "r") as file1:
json.load(file1)
os.startfile(file_name)
if btn1["text"] == "":
btn1["text"] = file_name
btn1 = tk.Button(window, text="", command=openu)
btn1.place(x = 20, y = 25)
window.mainloop()
UPD:
When you click on the button, the program opens a dialog box that opens the file. A File.json is created. Everything is displayed, but one thing does not work. I need that when restarting the program, the buttons are not empty. I changed the code, putting the full one.
Here is the code. When the user opens the window, it loads the file path from the json file and automatically sets the button's text. When the user presses the button, it asks for a new file path name. More detailed explanations can be found in the comments in the code.
import tkinter as tk
import tkinter.filedialog as tfd
import json
import os
window = tk.Tk()
window.title("Open")
window.geometry("600x400")
window.resizable(False, False)
file_name = ""
def load_json():
global file_name
# Load the json file if it exists
if os.path.exists("Filen.json"):
with open("Filen.json") as file1:
contents = json.load(file1)
# If the json has a path in it, load the path to file_name
# Otherwise, set file_name to an empty string ""
if len(contents) > 0:
if contents[0] != "":
file_name = contents[0]
else:
file_name = ""
else:
file_name = ""
# Create the json file if it does not exist
else:
with open("Filen.json", "w") as file1:
json.dump([file_name], file1, indent=2, ensure_ascii=False)
def openu():
global file_name
# Load the json file
load_json()
# If file_name is still "", ask the user to input a file path
path = tfd.askopenfilename()
# If the user gave a path (did not hit Cancel), save path to file_name
# and set the button's label
if path != ():
file_name = path
btn1.config(text=file_name)
# Save file_name to the json file
with open("Filen.json", "w") as file1:
json.dump([file_name], file1, indent=2, ensure_ascii=False)
# Load the json file, and put the file name into the button's text
load_json()
btn1 = tk.Button(window, text=file_name, command=openu)
btn1.place(x = 20, y = 25)
window.mainloop()

How to add buttons in 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!

Python pass variable values in functions

So this is my full code. All I want is append excel files to one excel by sheets from a specific folder. It's GUI and has 3 buttons browse, append, and quit. How do i get path value from browsed folder(filename) ? thanks
from tkinter import *
from tkinter.filedialog import askdirectory
import tkinter as tk
import glob
import pandas as pd
import xlrd
root = Tk()
def browsefunc():
filename = askdirectory()
pathlabel.config(text=filename)
return filename
def new_window():
all_data = pd.DataFrame()
all_data1 = pd.DataFrame()
path = browsefunc()+"/*.xlsx"
for f in glob.glob(path):
df = pd.read_excel(f,sheetname='Scoring',header=0)
df1 = pd.read_excel(f,sheetname='Sheet1',header=0)
all_data = all_data.append(df,ignore_index=False)
all_data1 = all_data1.append(df1,ignore_index=True)
writer = pd.ExcelWriter('pandas_simple.xlsx', engine='xlsxwriter')
all_data.to_excel(writer, sheet_name='Scoring')
all_data1.to_excel(writer, sheet_name='Sheet1')
writer.save()
browsebutton = Button(root, text="Browse", command=browsefunc).pack()
Button(root, text='Append', command=new_window).pack()
Button(root, text='quit', command=root.destroy).pack()
pathlabel = Label(root)
pathlabel.pack()
mainloop()
It is not entirely clear what you are asking, so can you edit the question to be more specific?
I think you are trying to get the local variable filename (from inside the function browsefunc) able to be accessed outside the function as a global variable. Use return. This tutorial explains it nicely.
At the end of browsefunc you add
return filename
and when you call browsefunc you run
path = browsefunc()
That assigns the variable fdback to whatever you return from browsefunc. It can be an integer, float, string, or list etc.
So, final code is:
def browsefunc():
filename = askdirectory()
pathlabel.config(text=filename)
return filename
def new_window():
path = browsefunc()
I would recommend using more explicit variable and function names.

Categories