simple way to modify a tkFileDialog - python

I would like to modify the tkFileDialog to include a Checkbutton for "open this file after saving."
The boolean value of this Checkbutton would determine whether os.startfile() gets called on the file name returned from the dialog, or not.
Example: how could I set the variable openMeNow in:
import tkinter as tk
from os import path, startfile
import pandas as pd
def getOutputFileName(initDir,title="Save Output as",initFile="the_output",defaultExt=''):
root = tk.Tk()
root.lift()
root.attributes("-topmost", True)
root.withdraw()
fOut = tk.filedialog.asksaveasfilename(title=title,
initialdir=initDir,
initialfile=initFile,
defaultextension=defaultExt)
return fOut
outExcel = path.normpath( getOutputFileName(
title="Save Workbook as",
initDir='~/Documents',
initFile='the_workbook.xlsx',
defaultExt='.xlsx'
) )
# do some stuff that returns some results
results = pd.DataFrame({'a':[1,2],'b':[10,100],'c':[0,50]})
xlWriter = pd.ExcelWriter(outExcel, engine='xlsxwriter')
results.to_excel(xlWriter, sheet_name = 'The Results', index=False)
xlWriter.save()
if openMeNow: startfile(outExcel)
The question is sort of similar to this one, with the difference being that I'm trying to modify the filedialog class rather than add another dialog box.

Related

How to apply selecting a file button in python

I learned how to create a select file button but I don't know how to apply it to the code as you can see below.
from openpyxl import Workbook
# import copy
wb = Workbook()
with open('chat_20220222152420.txt', encoding='utf-8') as sherr:
row = 1
column = 1
ws = wb.active
for line in sherr:
if column == 1:
## split the line and rejoin
value = " ".join(line.strip().split(' ')[2:])
else:
value = line.strip()
ws.cell(row=row, column=column, value=value)
if (column := column + 1) > 3:
row += 1
column = 1
wb.save('Chatchatchat.xlsx')
Instead of using the with open(), I wanted to use a button to choose the file I wanted to open. Below is the code I tried for selecting a file. I just don't know how to apply it in the above code :'(
from ipywidgets import Button
from tkinter import Tk, filedialog
from IPython.display import clear_output, display
def select_files(b):
root = Tk()
root.withdraw() # Hide the main window.
root.call('wm', 'attributes', '.', '-topmost', True) # Raise the root to the top of all windows.
b.files = filedialog.askopenfilename(multiple=False) # List of selected files will be set button's file attribute.
print(b.files) # Print the list of files selected.
fileselect = Button(description="File select")
fileselect.on_click(select_files)
display(fileselect)
One way to do this is to move the first block of code into a function that takes a filename to read:
from openpyxl import Workbook
def write_spreadsheet(filename):
wb = Workbook()
with open(filename, encoding='utf-8') as sherr:
row = 1
# ...
Then call it from select_files (note that filedialog.askopenfilename returns a single filename, not a list):
def select_files(b):
root = Tk()
root.withdraw() # Hide the main window.
root.call('wm', 'attributes', '.', '-topmost', True) # Raise the root to the top of all windows.
file = filedialog.askopenfilename(multiple=False) # Ask the user to select a file.
print(file) # Print the file selected.
write_spreadsheet(file) # Process the file.

How to make a dropdown list from an existing list in python (pandas and tkinter)

I want the user to submit their csv excel file and choose the columns from a dropdown menu he wants for analysis.
import pandas as pd
import os
import sys
from tkinter import *
root = Tk()
root.title('Eng3')
filepath = input('Enter filepath: ')
assert os.path.exists(filepath), "I did not find the file at, " + str(filepath)
f = open(filepath, 'r+')
print("Hooray we found your file!")
f.close()
file = pd.read_csv(filepath, encoding='latin1', delimiter=',')
column_list = file.columns.tolist()
print(column_list)
So I made the columns names from the excel file into a list. How can I make a dropdown menu from this list(column_list) to show all column names? When I tried:
tkvar = StringVar(column_list)
menu = OptionMenu(root, tvkar, column_list)
I get this error:
AttributeError: 'list' object has no attribute '_root'
I looked around and found this post How can I create a dropdown menu from a List in Tkinter?. Very useful
file = pd.read_csv(filepath, encoding='latin1', delimiter=',')
column_list = file.columns.tolist() #convert pandas dataframe to simple python list
OPTIONS = column_list #this is what solved my problem
master = Tk()
master.title('Eng3')
variable = StringVar(master)
variable.set(OPTIONS[0]) # default value
w = OptionMenu(master, variable, *OPTIONS)
w.pack()
def ok():
print ("value is:" + variable.get())
button = Button(master, text="OK", command=ok)
button.pack()

Using .split with tkinter

Quite a beginner here. I have a command line script that works fine for what I do and I'm looking to move it into a GUI.
os.chdir(ImageDirST)
for f in sorted(os.listdir(ImageDirST)):
f_name,f_ext = (os.path.splitext(f))
f_sku = (f_name.split(' ')[0])
f_num = (f_name[-2:])
n_name = ('{}_{}{}'.format(f_sku,f_num,f_ext))
print(f, "-->", n_name)
I would like this to display in the same fashion within a message window in tkinter.
With some help from here, I managed to print the filenames in the directory when a button is pushed with:
filenames = sorted(os.listdir(ImageDirBT))
text = "\n".join(filenames)
print_filename_test.set(text)
I have tried to use my split code to setup a list of what the new filenames would look like, prior to setting the variable, with the following, where print_filenames() is the function triggered by the press of a button.
def print_filenames():
filenames = sorted(os.listdir(ImageDirBT))
for filenames in sorted(os.listdir(ImageDirBT)):
f_name,f_ext = (os.path.splitext(filenames))
f_sku = (f_name.split('_')[0])
f_num = (f_name[-2:])
n_name = ('{}_{}{}'.format(f_sku,f_num,f_ext))
newlist = "\n".join(n_name)
print_filename_test.set(newlist)
I don't get any errors with this code for print_filenames(), however what is displayed in the message panel is the last filename in the list, vertically, one character wide:
eg:
F
I
L
E
_
1
1
.
e
x
t
I would like to display the output as:
oldfilename_01.ext --> newfilename_csvdata_01.ext
oldfilename_02.ext --> newfilename_csvdata_02.ext
oldfilename_03.ext --> newfilename_csvdata_03.ext
oldfilename_04.ext --> newfilename_csvdata_04.ext
The command line program I have written uses numbers to chose menu options for what needs to be done, confirming before any renaming is done, hence printing the file name comparisons. My struggle is manipulating the strings in the list to be able to do the same thing.
Using messagebox:
import os
import tkinter as tk
from tkinter import messagebox
ImageDirST = r"your_path"
os.chdir(ImageDirST)
root = tk.Tk()
names = []
for f in sorted(os.listdir(ImageDirST)):
f_name,f_ext = (os.path.splitext(f))
f_sku = (f_name.split(' ')[0])
f_num = (f_name[-2:])
n_name = ('{}_{}{}'.format(f_sku,f_num,f_ext))
names.append(f"{f} --> {n_name}\n")
messagebox.showinfo(title="Something", message="".join(names))
root.mainloop()
Or using Text widget with scrollbar:
import os
import tkinter as tk
from tkinter.scrolledtext import ScrolledText
ImageDirST = r"your_path"
os.chdir(ImageDirST)
root = tk.Tk()
txt = ScrolledText(root, font="Arial 8")
txt.pack()
for f in sorted(os.listdir(ImageDirST)):
f_name,f_ext = (os.path.splitext(f))
f_sku = (f_name.split(' ')[0])
f_num = (f_name[-2:])
n_name = ('{}_{}{}'.format(f_sku,f_num,f_ext))
txt.insert("end",f"{f} --> {n_name}\n")
root.mainloop()

How do I call a file imported through tkinter filedialog?

I am trying to create a very simple GUI that will import a file, run it through some data formatting code, and export it as an .xlsx file
The file would be an excel file. An example would be:
col1
a
b
c
and my current python script does this:
df = read_excel('file.xlsx')
mapping = {'a':'apple','b':'banana','c':'carrot'}
df = df.replace({"col1":mapping}, regex=True)
and it returns:
col1
apple
banana
carrot
but now I am trying to create a GUI that will run it instead (:
This is the code I have so far (I get the error ValueError: DataFrame constructor not properly called!):
import tkinter as tk
from tkinter import filedialog
import pandas as pd
from datetime import datetime, date
def UploadAction(event=None):
filename = filedialog.askopenfilename()
print('Selected:', filename)
df = pd.DataFrame(eval(data=filename))
mmapping = {'a':'apple','b':'banana','c':'carrot'}
df = df.replace({"col1":mapping}, regex=True)
print(df['col1'])
root = tk.Tk()
button = tk.Button(root, text='Open', command=UploadAction)
button.pack()
root.mainloop()
For the excel export, I know the code should be:
writer = pd.ExcelWriter("newfile.xlsx",
engine='xlsxwriter',
datetime_format='yyyymmdd',
date_format='yyyymmdd')
df.to_excel(writer, sheet_name = ('Sheet1'))
workbook = writer.book
worksheet = writer.sheets['Sheet1']
worksheet.set_column('B:C', 20)
writer.save()
but I am not sure of how to include it in the GUI program.
So what would you suggest?
There you go:
=^..^=
import pandas as pd
import tkinter as tk
from tkinter import filedialog
def open_file():
# open file
filename = filedialog.askopenfilename()
# load data into data frame
data = pd.read_csv(filename, sep=" ", header=None)
return data
root = tk.Tk()
button = tk.Button(root, text='Open', command=open_file)
button.pack()
# do something with data
df_data = open_file()
df = df_data.drop(0, axis=1)
# save data to excel
df.to_excel("output.xlsx")
root.mainloop()

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