After updating OptionMenu, Optionmenu's function does not work - python

def kayit_ekle_update(): ##
kayit_listesiVar.set('') # remove default selection only, not the full list
kayit_listesiOM['menu'].delete(0, 'end') # remove full list
kayitlilarOM = os.listdir("allin1/data_records")
for opt in kayitlilarOM:
kayit_listesiOM['menu'].add_command(label=opt, command=tk._setit(kayit_listesiVar, opt))
kayit_listesiVar.set(kayitlilarOM[0]) # default value set
def entri_doldur(se):
## get data from excel and append them to a new list(veri_al_list)
veri_al_list = []
om_deger = "allin1/data_records/" + kayit_listesiVar.get()
wb_kayit = load_workbook(om_deger)
ws_kayit = wb_kayit.active
for column_data in ws_kayit['1']:
veri_al_list.append(column_data.value)
veri_al_list = [' ' if v is None else v for v in veri_al_list] # None elemanı hata verdiriyor. Burada tüm None olanları "" ile değiştiriyoruz.
print(veri_al_list)
## There are Entry widgets created with for loop.
## en in entry_liste ==> Entries
## ne in veri_al_liste ==> data list from excel
for en, ne in zip(entry_liste, veri_al_list):
en.delete(0,END)
en.insert(END, ne)
wb_kayit.close()
kayitlilarOM = os.listdir("allin1/data_records")
kayit_listesiVar = StringVar()
kayit_listesiVar.set("Kayıt seç")
kayit_listesiOM = OptionMenu(ust, kayit_listesiVar, *kayitlilarOM, command=entri_doldur)
I have entry widgets in my code. The user can enter data and save them. Each time this data is saved, a new excel file is created and the data is saved in it.
The name of each saved excel file is displayed in an optionmenu. When we select a record from the Optionmenu, the entri_doldur() function works and the entries are filled according to the record.
I can delete the selected record with the button. When deleted, both the entries are empty and the option menu is updated.
But the problem occurs when I create a new record. Creating a new excel file. The data is saved in it. Option menu is being updated. But after that, when I select a record in the optionmenu, the entri_doldur() function does not work. The information of the selected record does not fill the entries.

Related

Why am I getting a type error from this function?

I am trying to create a drop down menu in tkinter that allows the user to select a machine, or row # from the excel sheet, and then all the data from that entire row is displayed in tkinter through the display_selected function. I keep getting this error.
This is my error:
TypeError: line_7_window.<locals>.display_selected() takes 0 positional arguments but 1 was given
This is my code:
def get_machine():
for row in sheet.iter_rows(min_row=2, max_col=1, max_row=60):
for cell in row:
if cell.value == inputmachine:
machineindex = cell
return machineindex.row
def get_machineattributes():
for col in sheet.iter_cols(min_row = (get_machine()), max_col = 15, max_row = (get_machine())):
for cell in col:
return (cell.value)
def display_selected():
data = Message(line_7, text=get_machineattributes())
data.pack()
data.place(x=650, y=30)
copy = Button(line_7, text="Copy to Clipboard", command=pyperclip.copy(line7_choice))
copy.pack()
copy.place(x=550, y=45)
return
inputmachine = StringVar(line_7)
inputmachine.set("Click to select a machine")
dropdown = OptionMenu(line_7, inputmachine, *lst, command=display_selected)
dropdown.pack()
dropdown.place(x=670, y=25)
I have tried everything and I cant figure out why this would not work.
Your callback function display_selected, specified when creating the option menu, will receive the actual option chosen from Tk, so you need that parameter when defining it, even if you do nothing with it.
In other words, use something like:
def display_selected(choice):
del choice # not used
# rest of function
As an aside, I suspect you may be better off with an option menu to select the item, and a separate button to act on that selection. That would allow you to confirm the selected item before performing any action, in case you inadvertently choose the wrong one.

How to get the Values from the Entry box in Tkinter?

def in_Vals():
in_win = Tk()
in_win.title("Check In Details")
in_win.geometry("700x700")
in_win.resizable(0,0)
# title
title = Label(in_win,text="Check In Details",font=("Harlow Solid Italic",30,"italic"),fg="black",bg="#fbb08c")
title.pack(anchor="center",pady=5)
#creating label's
_Id_ = Label(in_win,text="Id :",font=("Times New Roman",15,"italic"),fg="black",bg="#fbb08c")
_Name_ = Label(in_win,text="Name :",font=("Times New Roman",15,"italic"),fg="black",bg="#fbb08c")
_Date_ = Label(in_win,text="Date :",font=("Times New Roman",15,"italic"),fg="black",bg="#fbb08c")
_Time_ = Label(in_win,text="Time :",font=("Times New Roman",15,"italic"),fg="black",bg="#fbb08c")
_Number_ = Label(in_win,text="Number :",font=("Times New Roman",15,"italic"),fg="black",bg="#fbb08c")
_Id_.pack(anchor='w',padx=10,pady=20)
_Name_.pack(anchor='w',padx=10,pady=20)
_Date_.pack(anchor='w',padx=10,pady=20)
_Time_.pack(anchor='w',padx=10,pady=20)
_Number_.pack(anchor='w',padx=10,pady=20)
# creating submit function
def submit():
print(f"{in_val_1}\n{in_val_2}\n{in_val_3}\n{in_val_4}\n{in_val_5}")
# creating entries
Id = Entry(in_win,width=25,font=("Courier",15,'bold'))
Name = Entry(in_win,width=25,font=("Courier",15,'bold'))
Date = Entry(in_win,width=25,font=("Courier",15,'bold'))
Time = Entry(in_win,width=25,font=("Courier",15,'bold'))
Number = Entry(in_win,width=25,font=("Courier",15,'bold'))
Id.place(x=100,y=87)
Name.place(x=100,y=157)
Date.place(x=100,y=227)
Time.place(x=100,y=293)
Number.place(x=100,y=360)
#getting values
in_val_1 = Id.get()
in_val_2 = Name.get()
in_val_3 = Date.get()
in_val_4 = Time.get()
in_val_5 = Number.get()
# creating submit button
submit = Button(in_win,text="Submit",font=("Wild Latin",15,"bold"),command=submit)
submit.place(x = 250,y=450)
in_win.config(bg="#fbb08c")
in_win.mainloop()
Here the function in_vals() is a coded to take data from the ID, Name, Date, Time, Number Entries and assign the values of The entries to the variables in_val_1 to in_val_5 ,to get the values from the entry box I have used the .get() Method. but when I try to Print the Variables that I assigned to the .get() method, it prints some white Space's.
The solution for the problem same as mine is
defining the values outside the the button function does not get anything.
here I have defined out side the button function
after defining it inside the button function it gives me the desired output

Setting individual column headers in Python Tkinter's Tksheet widget / rolling back changes in same

I am writing a UI for a simulation program which accepts tabular data.
The basic functionality I need is for the user to be able to enter / change data in cells either by directly typing into them, or by pasting data (usually from an excel sheet). The program checks this data and either accepts or rejects it before running the simulation. I also want to let the user type in their own column headers for the table.
Tksheet is an awesome Tkinter add-on, giving an excel-like "feel" to the input frame, but its documentation leaves much to be desired. (For instance: each event generates a different event-information array--see code for two event-processing routines below--but nowhere is it specified what these parameters are. It is left for the user to discover using trial and error, or trying to read the source code--which is not documented either).
I have two specific questions:
Is there any way to not-commit, or to roll back, changes to the table? If my data-tests fail, how do I prevent potentially harmful user input from being entered into the table?
Obviously I can (and do) add a begin_*** event in which I can keep copies of the original values, and then reset the table values if the data testing at the end_*** event fails, but this is wasteful and inelegant. I have a feeling that the set_data_ref_on_destroy property has something to do with such a capability, but the documentation does not explain what this parameter is or how to use it.
How can I change a single column header at a time? The .headers property seems to work only with a full list of headers starting with column 0 (if I run self.sheet.headers([single_value], index = i) it ignores the index parameter and plugs single_value in column 0)
Again, I can set the column headers to something non-default at init and keep a running list of all headers, so that I can reset all the headers on each change, but this is wasteful and inelegant.
In the following code sample I set up a simple table, and bind three user-generated events: one for typing a value to a cell, one for pasting a block of values, and one for adding an option to the right-click menu of a column header, to allow the user to type a name to the column.
from tksheet import Sheet
import tkinter as tk
import tkinter.messagebox as msg
import tkinter.simpledialog as sd
class demo(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.grid_columnconfigure(0, weight=1) # This configures the window's escalators
self.grid_rowconfigure(0, weight=1)
self.frame = tk.Frame(self)
self.frame.grid_columnconfigure(0, weight=1)
self.frame.grid_rowconfigure(0, weight=1)
self.frame.grid(row=0, column=0, sticky="nswe")
self.sheet = Sheet(self.frame, data=[[]]) # set up empty table
self.sheet.grid(row=0, column=0, sticky="nswe")
self.sheet.enable_bindings(bindings= # enable table behavior
("single_select",
"select_all",
"column_select",
"row_select",
"drag_select",
"arrowkeys",
"column_width_resize",
"double_click_column_resize",
"row_height_resize",
"double_click_row_resize",
"right_click_popup_menu",
"rc_select", # rc = right click
"copy",
"cut",
"paste",
"delete",
"undo",
"edit_cell"
))
# Note that options that change the structure/size of the table (e.g. insert/delete col/row) are disabled
# make sure that pasting data won't change table size
self.sheet.set_options(expand_sheet_if_paste_too_big=False)
# bind specific events to my own functions
self.sheet.extra_bindings("end_edit_cell", func=self.cell_edited)
self.sheet.extra_bindings("end_paste", func=self.cells_pasted)
label = "Change column name" # Add option to the right-click menu for column headers
self.sheet.popup_menu_add_command(label, self.column_header_change, table_menu=False, index_menu=False, header_menu=True)
# Event functions
def cell_edited(self, info_tuple):
r, c, key_pressed, updated_value = info_tuple # break the info about the event to individual variables
if check_input(updated_value):
pass # go do stuff with the updated table
else:
msg.showwarning("Input Error", "'" + updated_value + "' is not a legal value")
pass # what do I do here? How do I make tksheet *not* insert the change to the table?
def cells_pasted(self, info_tuple):
key_pressed, rc_tuple, updated_array = info_tuple # break the info about the event to individual variables
r, c = rc_tuple # row & column where paste begins
if check_input(updated_array):
pass # go do stuff with the updated table
else:
msg.showwarning("Input Error", "pasted array contains illegal values")
pass # what do I do here? How do I make tksheet *not* insert the change to the table?
def column_header_change(self):
r, c = self.sheet.get_currently_selected()
col_name = sd.askstring("User Input", "Enter column name:")
if col_name is not None and col_name != "": # if user cancelled (or didn't enter anything), do nothing
self.sheet.headers([col_name], index=c) # This does not work - it always changes the 1st col
self.sheet.redraw()
# from here down is test code
def check_input(value): # instead of actual data testing we let the tester choose a pass/fail response
return msg.askyesno("Instead of input checking","Did input pass entry checks?")
test = demo()
lst = ["hello", "world"]
test.sheet.insert_column(values=lst)
lst = [0, "hello", "yourself"]
test.sheet.insert_column(values=lst)
test.mainloop()
I realize that the original post is now 5 months old, and I'm a relative n00b, but I hope this helps.
Given a tksheet instance 'sheet' that has already been populated with headers ["A"."B"."C"], the following works to change the header "B" to "NEW":
sheet.headers()[1]="NEW"
Hope this helps.

Python Refresh GUI to create another output

I am very new to Python. I am trying to create an app that printing a number from a Smartsheet sheet then delete it. The problem is I only can print it once, once I click "Create" button again, it gives error message. I believe when I click "Create" button again, it returns the deleted number from the sheet. Thank you!
{"response": {"statusCode": 404, "reason": "Not Found", "content": {"detail": {"ids": [3462338204985220], "type": "row"}, "errorCode": 1006, "message": "Not Found", "refId": "hcuqkioxqz46"}}}
Here is the sheet that stores a series of number:
Here is my code:
#Smartsheet client access token
smartsheet_client = smartsheet.Smartsheet('access token')
#Order Dashboard sheet ID
MySheet=smartsheet_client.Sheets.get_sheet(sheet_id)
def conceptnum():
n=1
for Myrow in MySheet.rows:
while n==1:
for Mycell in Myrow.cells:
row_ids=Myrow.id
label1['text']=int(Mycell.value)
label2['text']="Your concept number is created"
smartsheet_client.Sheets.delete_rows(
sheet_id, # sheet_id
row_ids) # row_ids
n=n-1
Height=100
Width=200
root=tk.Tk()
canvas=tk.Canvas(root, height=Height, width=Width)
canvas.pack()
frame=tk.Frame(root, bg="grey")
frame.place(relx=0.05, rely=0.3, relwidth=0.9, relheight=0.4)
button=tk.Button(root, text="Create",command=conceptnum)
button.pack(side='bottom')
label1=tk.Label(frame,font=15)
label1.place(relx=0.1, rely=0.1,relwidth=0.8, relheight=0.8)
label2=tk.Label(root)
label2.place(relwidth=1,relheight=0.2)
root.mainloop()
As currently written, your conceptnum() function is doing this:
for each row in the sheet ->
for each cell in the current row ->
...
delete the current row
So, if your sheet contains more than one column, your script will:
get the first row of the sheet
get the value of the first cell of the row being processed
delete the row from the sheet
get the value of the second cell of the row being processed
delete the row from the sheet -> this delete row request (and the subsequent request for each additional column/cell in the row being processed) will return the "Not Found" error -- because that row no longer exists in the sheet -- you deleted it after reading the first cell value.
Assuming that your objective is to read the value in the first cell of the first row of the sheet, and then delete that row from the sheet, here's a function that will do so -- please note that I've changed the function name and variable names to follow Python style convention (lowercase with underscores):
def concept_num():
# get sheet
my_sheet = smartsheet_client.Sheets.get_sheet(sheet_id)
# initialize row_id
row_id = None
for row in my_sheet.rows:
# get the ID of the current (first) row
row_id = row.id
# get the Cell object for the first cell of the current (first) row
cell = row.cells[0]
# set labels
label1['text'] = int(cell.value)
label2['text'] = 'Your concept number is created'
# exit the 'for' loop (so that only the first row is processed)
break
# delete the row that was just processed
if row_id != None:
smartsheet_client.Sheets.delete_rows(sheet_id, row_id)
else:
label1['text'] = 'n/a'
label2['text'] = 'Concept number not found.'
EDIT 4/13/2020:
You need to fetch the sheet each time the concept_num function runs -- so that my_sheet reflects the current contents of the sheet (i.e., no longer contains rows that were deleted when the function ran previously). I've updated the code snippet above accordingly (i.e., added the get sheet call at the top of the concept_num function). I've also added code at the end of the snippet (using an else) to update labels accordingly if the sheet contains no more numbers when the Create button is clicked.

Is there a way to get the Column menu updates automatically with the sheet menu?

I am devoloping an app where the user upload his excel file and gets the Sheets and columns. How do I get the Columns drop-down menu (The second one) to update with the Sheets drop-down menu(First one).
I have already tried to make a function 'Update' that gets the new sheet form the Fuction 'GetSheet' and update it. But it does not work as the column drop-down menu get Always stucked in the Default sheet.
master.title('ATT Analytics App')
master.geometry("400x250")
Myfile= filedialog.askopenfile()
wb = load_workbook(filename = str(Myfile.name))
#Sheets = wb.sheetnames
variable = StringVar(master)
variable.set(str(wb.sheetnames[2])) # default value
w = OptionMenu(master, variable, str(wb.sheetnames[0]), str(wb.sheetnames[1]), str(wb.sheetnames[2]), str(wb.sheetnames[3]))
w.pack()
def GetSheet():
FileRead = pd.read_excel(str(Myfile.name),sheet_name= str(variable.get()))
MyHeadres = list(FileRead.columns.values)
return MyHeadres, FileRead
variable1 = StringVar(master)
def Update(TheHeaders):
variable1.set(str(TheHeaders[0]))
wc = OptionMenu(master, variable1, str(TheHeaders[0]), str(TheHeaders[1]), str(TheHeaders[2]), str(TheHeaders[3]), str(TheHeaders[4]), str(TheHeaders[5]))
return wc
def RunAll():
GetMySheet, FileRead = GetSheet()
UpdateMysheet = Update(GetMySheet)
return UpdateMysheet, variable1.get(), FileRead
button = Button(master, text="Run", command=RunAll)
button.pack(side = TOP)
UpdateMysheet, MyColumn, ReadMyFile = RunAll()
UpdateMysheet.pack()
FileRead = ReadMyFile
mainloop()
I want to bring my Code to be able to update the Column Drop-down (Variable1) menu with the drop down menu (Variable), which works fine and also get to store the column you want and move on the choose another one and so on..
I would appreciate your help a lot.
Edit: Now when I choose another sheet, the Default value of the columns updates to the new sheet, but when I look the complete List, I find out that the values are from the old sheet.

Categories