'"NameError: name 'add' is not defined" - I did define it though
NOTE: (This is just a part of the code @furas)
I was told by my father to create a timesheet so that his employees working hours would be recorded 24/7. I am trying to make a button, a button that adds a new employee. As you can see in the code, father presses the add/"+" button which opens a new window, this window is has an entry widget so that father could enter the name of the new employee. Then father would press the submit button and it is supposed to add all of the details there should be like: the name, the time in and time out buttons, for the new employee, by using the .get() function, anyways that is not the problem, I know how to do that.
The problem is: I want to make the code look look like this, but obviously I cant becuase add wouldn't be defined. How can I get the same outcome, but different code, any ideas?
WHY = I want to take the new name and make a new employee section with it. Hopefully you understand? The new employee section will add another row designated for the new employeeLets say the new name is josh, so a new row, with designated for josh will appear
# ADD EMPLOYEE BUTTON
add_employee_button = ttk.Button(root, text="+", command=add_employee)
add_employee_button.grid(column=6, row=1)
def submit():
global new_employee_name
global add_entry
new_employee_name = add_entry.get()
print(new_employee_name)
# SUBMIT BUTTON FOR ADD EMPLOYEE
submit_employee_entry_button = Button(add, text="SUBMIT", command=submit)
submit_employee_entry_button.pack()
Solution 1:[1]
You should put this button inside functon add_employee and it will create it after creating window.
It has no sense to create it outside this function. GUIs work in different way than input() - widgets don't wait for user data but they only inform mainloop what it has to display in window. Mainloop starts GUI - it creates window and displays all widgets.
Here code which creates button inside function add_employee and it adds new employee to window. It doesn't have to be outside this function.
The only problem is that you use unique names for buttons and functions for every employee. You should use the same name for buttons TIME IN and TIME OUT and use string (ie employee's name) to keep them in dictionary.
The same problem is with function for buttons TIME IN and TIME OUT - it should be one function for time in and one for time out and they should get employee's name and row's number as parameter - you can use lambda to assign to command= function with parameters.
I didn't check rest of code but I think you could use for-loop to reduce some elements.
It may need also button which runs function which create excel file - at this moment it creates it before mainloop shows window.
import tkinter as tk
from tkinter import ttk
from tkinter import *
from openpyxl.styles import alignment, Alignment, Font
from openpyxl.styles.borders import Border, Side
import time as tm
from openpyxl import Workbook
# --- functions ---
def function_start(name, number):
current_time = tm.strftime("%H:%M")
label = Label(root, text=current_time)
label.grid(column=5, row=3+number)
start_button = data[name][0]
start_button['state'] = 'disabled'
print(f"{name}'S TIME IN: {current_time}")
def function_stop(name, number):
current_time = tm.strftime("%H:%M")
label = Label(root, text=current_time)
label.grid(column=6, row=3+number)
stop_button = data[name][1]
stop_button['state'] = 'disabled'
print(f"{name}'S TIME OUT: {current_time}")
def set_border(ws, cell_range, style):
side = Side(border_style=style, color="000000")
for row in ws[cell_range]:
for cell in row:
cell.border = Border(top=side, left=side, right=side, bottom=side)
def submit():
global window_add
global add_entry
global new_employee_name
name = add_entry.get()
print(name)
number = len(data) + 1
name_label = Label(root, text=name)
start_button = ttk.Button(root, text="TIME IN", command=lambda n=name,i=number:function_start(n, i))
stop_button = ttk.Button(root, text="TIME OUT", command=lambda n=name,i=number:function_stop(n, i))
name_label.grid(column=0, row=3+number)
start_button.grid(column=1, row=3+number, padx=10)
stop_button.grid( column=2, row=3+number, padx=10)
data[name] = [start_button, stop_button, name_label]
window_add.destroy()
def add_employee():
global window_add
global add_entry
window_add = Toplevel()
window_add.title("ADD EMPLOYEE")
add_entry = ttk.Entry(window_add)
add_entry.pack()
button = Button(window_add, text="SUBMIT", command=submit)
button.pack()
# --- main ---
data = {} # to keep buttons
wb = Workbook()
ws = wb.active
root = tk.Tk()
root.title("BFREE AUTOMATED TIMESHEET")
#root.geometry("10000x10000")
#root.iconbitmap("BFREE.png")
for number, name in enumerate(['JIMENA', 'GAGAN', 'CLAUDIA', 'MIRANDA']):
name_label = Label(root, text=name)
start_button = ttk.Button(root, text="TIME IN", command=lambda n=name,i=number:function_start(n, i))
stop_button = ttk.Button(root, text="TIME OUT", command=lambda n=name,i=number:function_stop(n, i))
name_label.grid(column=0, row=3+number)
start_button.grid(column=1, row=3+number, padx=10)
stop_button.grid( column=2, row=3+number, padx=10)
data[name] = [start_button, stop_button, name_label]
# ADD EMPLOYEE BUTTON
add_employee_button = ttk.Button(root, text="+", command=add_employee)
add_employee_button.grid(column=6, row=1)
set_border(ws, 'A1:U1', 'thin')
set_border(ws, 'A1:v6', "medium")
thin_border = Border(left=Side(style='thin'),
right=Side(style='thin'),
top=Side(style='thin'),
bottom=Side(style='thin'))
# EMPLOYEE NAMES
ws['A3'] = "GAGAN"
ws["a3"].font = Font(bold=True)
ws['a4'] = "CLAUDIA"
ws["a4"].font = Font(bold=True)
ws['a5'] = "MIRANDA"
ws["a5"].font = Font(bold=True)
ws['A6'] = "JIMENA"
ws["a6"].font = Font(bold=True)
# DAYS OF THE WEEK
ws.merge_cells("b1:c1")
currentCell = ws["B1"]
currentCell.alignment = Alignment(horizontal="center")
ws["b1"] = "MON"
ws["b1"].font = Font(bold=True)
ws.merge_cells("d1:e1")
currentCell = ws["d1"]
currentCell.alignment = Alignment(horizontal="center")
ws["d1"] = "TUES"
ws["d1"].font = Font(bold=True)
ws.merge_cells("f1:g1")
currentCell = ws["f1"]
currentCell.alignment = Alignment(horizontal="center")
ws["f1"] = "WED"
ws["f1"].font = Font(bold=True)
ws.merge_cells("h1:i1")
currentCell = ws["h1"]
currentCell.alignment = Alignment(horizontal="center")
ws["h1"] = "THUR"
ws["h1"].font = Font(bold=True)
ws.merge_cells("j1:k1")
currentCell = ws["j1"]
currentCell.alignment = Alignment(horizontal="center")
ws["j1"] = "FRI"
ws["j1"].font = Font(bold=True)
ws.merge_cells("l1:m1")
currentCell = ws["l1"]
currentCell.alignment = Alignment(horizontal="center")
ws["l1"] = "MON"
ws["l1"].font = Font(bold=True)
ws.merge_cells("n1:o1")
currentCell = ws["n1"]
currentCell.alignment = Alignment(horizontal="center")
ws["n1"] = "TUES"
ws["n1"].font = Font(bold=True)
ws.merge_cells("p1:q1")
currentCell = ws["p1"]
currentCell.alignment = Alignment(horizontal="center")
ws["p1"] = "WED"
ws["p1"].font = Font(bold=True)
ws.merge_cells("r1:s1")
currentCell = ws["r1"]
currentCell.alignment = Alignment(horizontal="center")
ws["r1"] = "THUR"
ws["r1"].font = Font(bold=True)
ws.merge_cells("t1:u1")
currentCell = ws["t1"]
currentCell.alignment = Alignment(horizontal="center")
ws["t1"] = "FRI"
ws["t1"].font = Font(bold=True)
ws.merge_cells("v1:v2")
currentCell = ws["v1"]
currentCell.alignment = Alignment(vertical="center")
ws["V1"] = "TOTAL:"
ws["V1"].font = Font(bold=True)
# TIME IN AND TIME OUT CELLS
ws["b2"] = "TIME IN"
ws["B2"].font = Font(bold=True)
ws["c2"] = "TIME OUT"
ws["c2"].font = Font(bold=True)
ws["d2"] = "TIME IN"
ws["d2"].font = Font(bold=True)
ws["e2"] = "TIME OUT"
ws["e2"].font = Font(bold=True)
ws["f2"] = "TIME IN"
ws["f2"].font = Font(bold=True)
ws["g2"] = "TIME OUT"
ws["g2"].font = Font(bold=True)
ws["h2"] = "TIME IN"
ws["h2"].font = Font(bold=True)
ws["i2"] = "TIME OUT"
ws["i2"].font = Font(bold=True)
ws["j2"] = "TIME IN"
ws["j2"].font = Font(bold=True)
ws["k2"] = "TIME OUT"
ws["k2"].font = Font(bold=True)
ws["l2"] = "TIME IN"
ws["l2"].font = Font(bold=True)
ws["m2"] = "TIME OUT"
ws["m2"].font = Font(bold=True)
ws["n2"] = "TIME IN"
ws["n2"].font = Font(bold=True)
ws["o2"] = "TIME OUT"
ws["o2"].font = Font(bold=True)
ws["p2"] = "TIME IN"
ws["p2"].font = Font(bold=True)
ws["q2"] = "TIME OUT"
ws["q2"].font = Font(bold=True)
ws["r2"] = "TIME IN"
ws["r2"].font = Font(bold=True)
ws["s2"] = "TIME OUT"
ws["s2"].font = Font(bold=True)
ws["T2"] = "TIME IN"
ws["t2"].font = Font(bold=True)
ws["U2"] = "TIME OUT"
ws["u2"].font = Font(bold=True)
wb.save("BFREE.xlsx")
mainloop()
EDIT:
Version which uses for-loops to generate EXCEL.
It also adds values from buttons TIME IN and TIME OUT to column MON.
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
from openpyxl.styles import alignment, Alignment, Font
from openpyxl.styles.borders import Border, Side
import time as tm
from openpyxl import Workbook
# --- functions ---
def function_start(name, number):
current_time = tm.strftime("%H:%M")
label = tk.Label(root, text=current_time)
label.grid(column=5, row=3+number)
start_button = data[name]['start']
start_button['state'] = 'disabled'
print(f"{name}'S TIME IN: {current_time}")
data[name]['time_in'] = current_time
def function_stop(name, number):
current_time = tm.strftime("%H:%M")
label = tk.Label(root, text=current_time)
label.grid(column=6, row=3+number)
stop_button = data[name]['stop']
stop_button['state'] = 'disabled'
print(f"{name}'S TIME OUT: {current_time}")
data[name]['time_out'] = current_time
def set_border(ws, cell_range, style):
side = Side(border_style=style, color="000000")
for row in ws[cell_range]:
for cell in row:
cell.border = Border(top=side, left=side, right=side, bottom=side)
def submit():
global window_add
global add_entry
global new_employee_name
name = add_entry.get()
print(name)
number = len(data) + 1
name_label = tk.Label(root, text=name)
start_button = ttk.Button(root, text="TIME IN", command=lambda n=name,i=number:function_start(n, i))
stop_button = ttk.Button(root, text="TIME OUT", command=lambda n=name,i=number:function_stop(n, i))
name_label.grid(column=0, row=3+number)
start_button.grid(column=1, row=3+number, padx=10)
stop_button.grid( column=2, row=3+number, padx=10)
data[name] = {"start": start_button, "stop": stop_button, 'time_in': '', 'time_out': ''}
window_add.destroy()
def add_employee():
global window_add
global add_entry
window_add = tk.Toplevel()
window_add.title("ADD EMPLOYEE")
add_entry = ttk.Entry(window_add)
add_entry.pack()
button = ttk.Button(window_add, text="SUBMIT", command=submit)
button.pack()
def generate_workbook():
wb = Workbook()
ws = wb.active
number = len(data)
set_border(ws, 'A1:U1', 'thin')
set_border(ws, f'A1:v{2+number}', "medium")
thin_border = Border(left=Side(style='thin'),
right=Side(style='thin'),
top=Side(style='thin'),
bottom=Side(style='thin'))
# EMPLOYEE NAMES
for number, name in enumerate(data.keys()):
ws[f'A{3+number}'] = name
ws[f'A{3+number}'].font = Font(bold=True)
# DAYS OF THE WEEK
days = [
('B','C','MON'),
('D','E','TUES'),
('F','G','WED'),
('H','I','THUR'),
('J','K','FRI'),
('L','M','MON'),
('N','O','TUES'),
('P','Q','WED'),
('R','S','THUR'),
('T','U','FRI'),
]
for x, y, name in days:
ws.merge_cells(f"{x}1:{y}1")
currentCell = ws[f"{x}1"]
currentCell.alignment = Alignment(horizontal="center")
ws[f"{x}1"] = name
ws[f"{x}1"].font = Font(bold=True)
for number, (name, item) in enumerate(data.items()):
ws[f"B{3+number}"] = item['time_in']
ws[f"C{3+number}"] = item['time_out']
ws.merge_cells("v1:v2")
currentCell = ws["v1"]
currentCell.alignment = Alignment(vertical="center")
ws["V1"] = "TOTAL:"
ws["V1"].font = Font(bold=True)
# TIME IN AND TIME OUT CELLS
for col in ['B', 'D', 'F', 'H', 'J', 'L', 'N', 'P', 'R', 'T']:
ws[f"{col}2"] = "TIME IN"
ws[f"{col}2"].font = Font(bold=True)
for col in ['C', 'E', 'G', 'I', 'K', 'M', 'O', 'Q', 'S', 'U']:
ws[f"{col}2"] = "TIME OUT"
ws[f"{col}2"].font = Font(bold=True)
wb.save("BFREE.xlsx")
messagebox.showinfo('Info', 'File generated')
# --- main ---
data = {} # to keep buttons and values
root = tk.Tk()
root.title("BFREE AUTOMATED TIMESHEET")
#root.geometry("10000x10000")
#root.iconbitmap("BFREE.png")
for number, name in enumerate(['JIMENA', 'GAGAN', 'CLAUDIA', 'MIRANDA']):
name_label = tk.Label(root, text=name)
start_button = ttk.Button(root, text="TIME IN", command=lambda n=name,i=number:function_start(n, i))
stop_button = ttk.Button(root, text="TIME OUT", command=lambda n=name,i=number:function_stop(n, i))
name_label.grid(column=0, row=3+number)
start_button.grid(column=1, row=3+number, padx=10)
stop_button.grid( column=2, row=3+number, padx=10)
data[name] = {"start": start_button, "stop": stop_button, 'time_in': '', 'time_out': ''}
# ADD EMPLOYEE BUTTON
add_employee_button = ttk.Button(root, text="+", command=add_employee)
add_employee_button.grid(column=6, row=1)
# GENERATE EXCEL BUTTON
generate_button = ttk.Button(root, text="To Excel", command=generate_workbook)
generate_button.grid(column=7, row=1)
tk.mainloop()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |

