Goal:
I am trying to have the script look through a directory named 'data' that is in the working directory of the script for excel workbooks. The script will then have a options menu of the different workbooks to choose from which will then give a selection of column names to choose from in a combo box above.
Results:
I was able to get it to read the default excel workbook upon start up but when I choose a different workbook the combo box does not update the column names.
I've tried to incorporate some sort of update function but I keep having trouble even running it because one or more things don't really line up. I am still new to python and tkinter so I would like some advice and suggestions to solve this problem.
import tkinter
from tkinter import ttk
from tkinter import *
import pandas as pd
def _quit():
root.quit()
root.destroy()
root = Tk()
root.title('BLURG')
root.geometry("1280x720")
path = os.chdir('Data')
filenames = os.listdir(path)
data_as_list = []
for filename in filenames:
if filename.endswith('.xlsx') or filename.endswith('.xls'):
data_as_list.append(filename)
clicked = StringVar()
options = data_as_list
clicked.set(options[0])
drop = OptionMenu(root, clicked, *options)
drop.pack(side="right")
data = pd.read_excel(clicked.get())
df = pd.DataFrame(data)
col_name = list(df.columns)
labelx = tkinter.Label(root, text="x-axis: ")
combox = ttk.Combobox(root, values=col_name)
labelx.pack(side="top")
combox.pack(side="top")
button = tkinter.Button(master=root, text="Quit", command=_quit)
button.pack(side=tkinter.BOTTOM)
root.mainloop()
Using an update function with a postcommand fixed the problem.
...
def update_list():
data = pd.read_excel(clicked.get())
df = pd.DataFrame(data)
col_name = list(df.columns)
combox['values'] = col_name
labelx = tkinter.Label(root, text="x-axis: ")
combox = ttk.Combobox(root, postcommand=update_list)
...
Related
I would like to know if anyone could help me with this problem. Im a beginner at Python, and im trying to create a program. The problem is that i want to search for a person in a stats database, and then get the result of the 5 most similar players based on stats. Now i only get one name, and cannot figure out what I am doing wrong.
This is the code that i have used, but it only displays 1 player, instead of the 5 players that are most similar.
import tkinter as tk
import pandas as pd
import os
from tkinter import filedialog
from tkinter import messagebox
from tkinter import ttk
def compare_players(player_name, data):
player = data[data['Player'] == player_name]
player_stats = player.select_dtypes(include=['float64'])
player_stats = (player_stats - player_stats.mean()) / player_stats.std()
data_stats = data.select_dtypes(include=['float64'])
data_stats = (data_stats - data_stats.mean()) / data_stats.std()
similarity = data_stats.dot(player_stats.T)
top_5 = data.iloc[similarity.iloc[0,:].sort_values(ascending=False).index[:5]]
return top_5
def run_search(folder_path, player_name, data):
result = compare_players(player_name, data)
for i, row in result[['Player', 'Team', 'Age']].iterrows():
tree.insert("", "end", values=(row['Player'], row['Team'], row['Age']))
def on_search():
player_name = entry.get()
run_search(folder_path, player_name, data)
def load_data():
global data
data = pd.DataFrame()
for file in os.listdir(folder_path):
if file.endswith(".xlsx"):
file_path = os.path.join(folder_path, file)
temp_data = pd.read_excel(file_path)
data = pd.concat([data, temp_data], axis=0)
root = tk.Tk()
root.withdraw()
folder_path = filedialog.askdirectory(initialdir = *Here i put the folder which contains many excel files*,
title = "Select folder")
load_data()
root = tk.Tk()
root.title("Player Comparison")
root.geometry("600x400")
label = tk.Label(root, text="Enter player name:")
entry = tk.Entry(root)
search_button = tk.Button(root, text="Search", command=on_search)
label.pack()
entry.pack()
search_button.pack()
tree = ttk.Treeview(root, columns=("Player", "Team", "Age"), show="headings")
tree.heading("Player", text="Player Name")
tree.heading("Team", text="Team")
tree.heading("Age", text="Age")
tree.pack(side="left", fill="y")
root.mainloop()
The code is most likely all over the place, but i try :D
Thanks for all answers in advance.
I am trying to build a simple application using Tkinter wherein I should be able to search files in my local folders and display them. For example, if I am searching a 'test.txt' file, it will return me that file plus all txt files. Now the second part of the problem is, I have to merge all the files that was returned to me in my search into one single file (I know it sounds absurd but please forgive me). I have successfully achieved the first part but not able to implement the second part. Quite new to functions and OOPs concepts. Pasting my code below in the hope for some guidance. Please forgive me for the code quality as I am quite new.
import pandas as pd
from tkinter import *
import os
from docx import Document
doc1 = Document()
def search_file():
file_entry_name = entry.get()
answer.delete(1.0,END)
extension = file_entry_name.split('.')[1]
file_name = file_entry_name.split('.')[0]
file_entry_name = file_entry_name.lower()
for r,d,f in os.walk('/Users/kausthab/Documents/Documents – Kausthab’s MacBook Air/DSBA'):
for file in f:
file.split()
if file.startswith(file_entry_name) or file.endswith(extension):
answer.insert(INSERT,file + '\n')
def merge_file():
# files = os.listdir('/Users/kausthab/Documents/Documents – Kausthab’s MacBook Air/DSBA')
# global answer
# for i in answer:
# if i != '.DS_Store': # i kept getting an error for a hidden file. So excluded it
# doc1.add_heading(i, 2)
# doc2 = Document(i)
# for para in doc2.paragraphs:
# para_in_doc = doc1.add_paragraph(para.text)
# doc1.add_page_break()
# doc1.save('search.docx')
return
root = Tk()
root.title('Docu Search')
topframe = Frame(root)
entry = Entry(topframe)
entry.pack()
button = Button(topframe, text="search",command =search_file)
button.pack()
topframe.pack(side = TOP)
bottomframe = Frame(root)
scroll = Scrollbar(bottomframe)
scroll.pack(side=RIGHT, fill=Y)
answer = Text(bottomframe, width=80, height=50, yscrollcommand = scroll.set,wrap= WORD)
scroll.config(command=answer.yview)
merge_button = Button(bottomframe, text="merge",command =merge_file)
merge_button.pack()
answer.pack()
bottomframe.pack()
root.mainloop()
I'm struggling again to figure out a way to update my tkinter listbox from a combobox selection.
What I want to happen is the user imports an excel file, the file is then read and all the sheets available on that workbook is displayed for the user to select (this part works - Combobox), once its selected it suppose to display all the headers in that excel sheet in a listbox so the user can select multiple headers. The headers changes depending on the sheet selected, so the listbox would have to update and display the new headers.
I figured out how to display it as a ComboBox and it'll update as different sheets are selected, but I need the ability to select multiple headers - hence why I'm trying to use a listbox.
I've pasted what I've got right now.
import pandas as pd
import os
import xlrd
from tkinter import *
from tkinter.filedialog import askopenfilename, asksaveasfilename
from tkinter.ttk import Combobox
import tkinter as tk
import re
import numpy as np
class myApp:
importedSheets = []
headers = []
reports = ['A','B','C','D']
# rb_select = IntVar()
def UploadAction(self):
self.filename = askopenfilename()
def SaveAction(self):
self.savelocation = asksaveasfilename()
def sheetnames(self):
self.xlssheets = xlrd.open_workbook(self.filename,on_demand=True)
importedSheets = self.xlssheets.sheet_names()
self.cbox_sheets.config(value=importedSheets) #updating the value of the combobox
return importedSheets
def headernames(self):
if self.reporttype.get(self.reporttype.curselection()) == self.reports[0]:
self.df = pd.read_excel(self.filename,sheet_name = self.cbox_sheets.get(),header = 1, index_col=0)
headers = list(self.df.columns)
self.headerselectors.config(values=headers)
def __init__(self,master):
self.filename = None
self.master = master
#---------------------------------------------------------------------#
# Creating Basic Frame Structure
#---------------------------------------------------------------------#
self.frame1 = Frame(master=master,relief=RAISED,borderwidth=1)
self.frame1.pack(padx=10,pady=10)
self.frame2 = Frame(master=master,relief=RAISED,borderwidth=1)
self.frame2.pack(padx=10,pady=10)
self.frame3 = Frame(master=master,relief=RAISED,borderwidth=1)
self.frame3.pack(padx=10,pady=10)
#---------------------------------------------------------------------#
# Frame 2 - Selecting Sheet and Header To Work with
#---------------------------------------------------------------------#
self.frame2a = Frame(master = self.frame2)
self.frame2b = Frame(master = self.frame2)
self.frame2r = Frame(master = self.frame2)
self.frame2a.pack(side=TOP)
self.frame2b.pack(side=LEFT)
self.frame2r.pack(side=RIGHT)
self.uploadLabel = Label(master = self.frame2a,text = '1) Select the file you want to import',font=(None,12,)).pack()
self.uploadButton = Button(master = self.frame2a,text = 'Import', command =lambda:self.UploadAction()).pack(padx=5,pady=5)
self.reporttype = Listbox(master=self.frame2a,height=4,selectmode=SINGLE,exportselection = False)
for x,reports in enumerate(self.reports):
self.reporttype.insert(x,reports)
self.reporttype.pack(padx=5,pady=5)
#---------------------------------------------------------------------#
# Selecting Sheets to work with:
#---------------------------------------------------------------------#
self.sheetLabel = Label(master = self.frame2b,text = '2) Select the sheet to extract',font=(None,12)).pack(padx=15)
self.cbox_sheets = Combobox(master = self.frame2b,values = self.importedSheets,postcommand = self.sheetnames)
self.cbox_sheets.pack(padx=5,pady=5)
#---------------------------------------------------------------------#
# Selecting Headers to Work with:
#---------------------------------------------------------------------#
self.headerLabel = Label(master = self.frame2r,text = '3) Select the header with data',font=(None,12)).pack(padx=15)
self.headerselectors = Combobox(master = self.frame2r,values = self.headers,postcommand = self.headernames)
self.headerselectors.pack(padx=5,pady=5)
if __name__ == '__main__':
root = Tk()
my_gui = myApp(root)
root.mainloop()
EDIT: The section that needs to be worked on is in: Selecting Headers to Work with (I don't know how to highlight on stackoverflow)
To create a dynamic listbox I had to bind it to a button:
self.headerLabel = Label(master = self.frame2r,
text = '3) Select the header with data',
font=(None,12)).pack(padx=15)
self.headers_button = Button(master = self.frame2r, text = 'Show Headers',command = self.headernames).pack()
self.headers_select = Listbox (master = self.frame2r,exportselection = False,selectmode=MULTIPLE)
self.headers_select.pack()
Once I created the basic listbox and button I added to my function def headernames(self):
def headernames(self):
if self.reporttype.get(self.reporttype.curselection()) == self.reports[0]:
self.df = pd.read_excel(self.filename,sheet_name = self.cbox_sheets.get(),header = 1, index_col=0)
headers = list(self.df.columns)
self.headers_select.delete(0,'end')
for x,header in enumerate(headers):
self.headers_select.insert(x,header)
Now everytime I click on the button "Show Headers" it'll clear the list and then add the new headers for the selected sheet.
I'm trying to adjust the size of tkinter Treeview window but it's not working. Below I will attach the code which I'm working with.
from tkinter import *
import pandas as pd
from tkinter import ttk, filedialog
from tkinter import font
root = Tk()
root.title('Excel To Treeview')
root.geometry("2800x1600")
# Create frame
my_frame = Frame(root)
#my_frame.config(width = 100)
my_frame.pack(pady=20)
# Create treeview
my_tree = ttk.Treeview(my_frame)
my_tree.config()
# File open function
def file_open():
filename = filedialog.askopenfilename(
initialdir="/home/ashanglenn",
title = "Open A File",
filetypes=(("xlsx files", "*.xlsx"), ("All Files", "*.*"))
)
if filename:
try:
filename = r"{}".format(filename)
df = pd.read_excel(filename)
except ValueError:
my_label.config(text="File Couldn't Be Opened...try again!")
except FileNotFoundError:
my_label.config(text="File Couldn't Be Found...try again!")
# Clear old treeview
clear_tree()
# Set up new treeview
my_tree["column"] = list(df.columns)
my_tree["show"] = "headings"
# Loop thru column list for headers
for column in my_tree["column"]:
my_tree.heading(column, text=column)
# Put data in treeview
df_rows = df.to_numpy().tolist()
for row in df_rows:
my_tree.insert("", "end", values=row)
# Pack the treeview finally
my_tree.pack()
def clear_tree():
my_tree.delete(*my_tree.get_children())
# Add a menu
my_menu = Menu(root)
root.config(menu=my_menu)
# Add menu dropdown
file_menu = Menu(my_menu, tearoff=False)
my_menu.add_cascade(label="Spreadsheets", menu=file_menu)
file_menu.add_command(label="Open", command=file_open)
my_label = Label(root, text='')
my_label.pack(pady=20)
root.mainloop()
so as I mentioned when I open the excel file via the menu "Spreadsheets -> Open" it will open the Treeview window for a fixed size, no matter what size of columns and rows the excel file contains it open up to a fixed size. So I want to extend the size of this Treeview to the full screen size of the window. For better understanding I have attached a picture of this program with this google drive link.
https://drive.google.com/file/d/12pzYW1G6-GNN0eO03zMK2U1sglaY6SBz/view?usp=sharing
I'm pretty new to Python and still learning basics. I would really appreciate your valuable help. Hope the question is clear! Thank You.
I'm not quite sure the best way to ask this (I've tried searching and can't find what I'm looking for). I have a GUI that uploads an excel sheet that has base information, cleans it up, adds in relevant information, and exports out a new excel.
What I'm looking to do is to be able to copy/paste the relevant data directly into the GUI rather than uploading an excel sheet. The data is on a different application that currently has to be pasted into an into an excel sheet to be able to be uploaded.
For reference the data would be 3 columns and up to 100 rows in length.
Let me know if more information is needed or if I can explain something better! I'm very new to programming so I'm not always sure what verbiage to use.
Update: This is my script currently. I was looking to replace def getExcel1 () with being able to paste the information over rather than having to paste into an excel then upload the excel.
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
import pandas as pd
import xlwt
window = tk.Tk()
canvas1 = tk.Canvas(window, width = 400, height = 250, bg = 'lightsteelblue2', relief = 'raised')
canvas1.pack()
label1 = tk.Label(window, text = 'Store Name', width = 20)
entry1 = tk.Entry()
canvas1.create_window(250, 100, window = entry1)
canvas1.create_window(100, 100, window = label1)
def getExcel1 ():
global df1
import_file_path = filedialog.askopenfilename()
df1 = pd.read_excel (import_file_path)
browseButton_CSV1 = tk.Button(text=" Import TC56 Information ", command=getExcel1, bg='green', fg='white', font=('bookman old style', 12, 'bold'))
canvas1.create_window(200, 50, window=browseButton_CSV1)
def getInput1 ():
global df2
df2 = entry1.get()
submit_button1 = tk.Button(text = 'Submit Store Name', command = getInput1, bg = 'green', fg = 'white', font= ('bookman old style', 12, 'bold'))
canvas1.create_window(200, 150, window = submit_button1)
def CreateExcel ():
Serial = df1['DSN'].str.split('S').str[1]
Asset = df1['Asset']
DevNum = df1['Device #']
Friendly = df2 + ' ' + '#' + DevNum.astype(str) + ' ' + Serial.astype(str)
df = pd.DataFrame({'Serial': Serial, 'FriendlyName': Friendly, 'Asset': Asset, 'ProdOG': df2 + 'AD'})
export_file_path = filedialog.asksaveasfilename(defaultextension='.xls')
df.to_excel (export_file_path, index = None, header=True)
browseButton_CSV1 = tk.Button(text=" Create Input File ", command=CreateExcel, bg='green', fg='white', font=('bookman old style', 12, 'bold'))
canvas1.create_window(200, 200, window=browseButton_CSV1)
window.mainloop()
The in_() function reads and stores text from the clipboard. It also assumes there's no tk.Tk() object so it's not really needed here. It's the from_grid function that arranges the text into nested lists. You may prefer to arrange for it to return a dataframe rather than a list of lists.
I've trimmed your code to just show the reading part. I've no real pandas experience. I think there may be ways to read into a pandas dataframe from the clipboard but I've never done it.
To use: copy a region in an excel spreadsheet before clicking "Import TC56 Information" The resulting dataframe will print in the console. It can then processed as required.
import tkinter as tk
import pandas as pd
import numpy as np
window = tk.Tk()
def from_grid(parent, delimit_row="\n", delimit_cell="\t"):
"""
Returns a list of lists copied from the clipboard.
Usage: grid=from_grid(delimit_row="\t", delimit_cell="\n")
grid is a list of lists
[ [ r00, r01, r02, ... ],
[ r10, r11, r12, ... ],
....
]
by defaut: the row delimiter is a newline, "\n"
the cell delimiter is a tab character, "\t"
This will paste a copied region of a spreadsheet into a list of lists.
"""
txt = parent.selection_get(selection="CLIPBOARD") # Replaces the in_() function.
rows=txt.split(delimit_row)
ret=[]
for row in rows:
temp=row.split(delimit_cell)
ret.append(temp)
return ret[:-1] # A final empty last row is appended.
# This loses it.
canvas1 = tk.Canvas(window, width = 400, height = 250, bg = 'lightsteelblue2', relief = 'raised')
canvas1.pack()
df1 = 0 # Result store
def do_paste():
global df1
temp=from_grid( window )
df1 = pd.DataFrame( np.array( temp[1:] ), columns= temp[0] ) # Assumed column headers from Excel
print(df1) # To see what's happening remove once it's working
browseButton_CSV1 = tk.Button(text=" Import TC56 Information ", command=do_paste )
canvas1.create_window(200, 50, window=browseButton_CSV1)
window.mainloop()