1

I am having problems

select_item = tree_frame.selection()[0]

IndexError: tuple index out of range

I have an employee table, I am trying to delete a record from the table, but when I select a record for 1st time it is working fine but while I'm trying to delete another record then it is throwing an error.

import tkinter as tk
from tkinter import ttk
from datetime import datetime,date
from tkinter import messagebox as msg
from tkinter import *
import sys
import time
from tkcalendar import DateEntry
from PIL import ImageTk,Image
import mysql.connector

def show_all_emp():
    delete_page()
    emp_data_frame = Frame(main_frame, width=1450, height=720, highlightbackground='black', highlightthickness=1)
    emp_data_frame.place(x=1, y=30)

    # update button
    update_selected_button = Button(main_frame, text="Update Selected Row", bg="#bb44db", fg="white", width=30,font=('Times', 10, 'bold'), command=lambda: update_data(tree_frame))
    update_selected_button.place(x=50, y=1)

    # Delete button
    delete_selected_button = Button(main_frame, text="Delete Selected Row", bg="#bb44db", fg="white", width=30,  font=('Times', 10, 'bold'),command= lambda : delete_data(tree_frame))
    delete_selected_button.place(x=300, y=1)

    # searching part according to degination choose
    filter_enter = ttk.Combobox(main_frame, state="readonly", textvariable=filter_var)
    filter_enter['values'] = ('all_emp', 'Director', 'Manager', 'Employee')
    filter_enter.current(0)
    filter_enter.place(x=1220, y=4)
    filter_var.trace('w', filter_match_show)
    #__________________________________________________
    tree_frame = ttk.Treeview(emp_data_frame)
    tree_frame.place(x=1, y=1, width=1350, height=670)
    s.configure('Treeview', rowheight=40)

    # remove unwanted parameter
    tree_frame['show'] = 'headings'
    # define number of columns
    tree_frame["columns"] = ('Employee Name','user_id', 'password', 'emp. type','report to','doj','start_date','end_date','dob','email', 'Address','Action')
    # assigning the width for column

    tree_frame.column('Employee Name', anchor=tk.CENTER)
    tree_frame.column('user_id', anchor=tk.CENTER)
    tree_frame.column('password', anchor=tk.CENTER)
    tree_frame.column('emp. type', anchor=tk.CENTER)
    tree_frame.column('report to', anchor=tk.CENTER)
    tree_frame.column('doj', anchor=tk.CENTER)
    tree_frame.column('start_date', anchor=tk.CENTER)
    tree_frame.column('end_date', anchor=tk.CENTER)
    tree_frame.column('dob', anchor=tk.CENTER)
    tree_frame.column('email', anchor=tk.CENTER)
    tree_frame.column('Address', anchor=tk.CENTER)
    tree_frame.column('Action', anchor=tk.CENTER)

    # assigning heading name representive column

    tree_frame.heading('Employee Name', text="EMPLOYEE NAME", anchor=tk.CENTER)
    tree_frame.heading('user_id', text="USER_ID", anchor=tk.CENTER)
    tree_frame.heading('password', text="PASSWORD", anchor=tk.CENTER)
    tree_frame.heading('emp. type', text="EMP. TYPE", anchor=tk.CENTER)
    tree_frame.heading('report to', text="REPORT TO", anchor=tk.CENTER)
    tree_frame.heading('doj', text="DOJ", anchor=tk.CENTER)
    tree_frame.heading('start_date', text="START DATE", anchor=tk.CENTER)
    tree_frame.heading('end_date', text="END DATE", anchor=tk.CENTER)
    tree_frame.heading('dob', text="DOB", anchor=tk.CENTER)
    tree_frame.heading('email', text="EMAIL", anchor=tk.CENTER)
    tree_frame.heading('Address', text="ADDRESS", anchor=tk.CENTER)
    tree_frame.heading('Action', text="ACTION", anchor=tk.CENTER)

    tree_frame.tag_configure('grey', background='yellow')
    tree_frame.tag_configure('black', background='white')

    my_tag = 'yellow'  # first row
    cn = mysql.connector.connect(database="HRMS_PROJECT", user="root", password="root", host="localhost")
    cur = cn.cursor()
    q = 'SELECT * FROM  Director_table UNION SELECT * FROM manager_table UNION SELECT * FROM emp_table;'
    cur.execute(q)
    records = cur.fetchall()
    for i, (emp_name,user_id,password, emp_type,report_to, doj,start_date,end_date,dob, email,address) in enumerate(records, start=1):
        my_tag = 'grey' if my_tag == 'yellow' else 'yellow'  # condition for row color
        tree_frame.insert("", "end", values=(emp_name,user_id , password, emp_type,report_to, doj,start_date,end_date,dob, email,address ),tags=(my_tag))
    cn.close()

    # creating vertical scrollbar
    vsb = ttk.Scrollbar(emp_data_frame, orient="vertical")
    vsb.configure(command=tree_frame.yview)
    tree_frame.configure(yscrollcommand=vsb.set)
    vsb.place(x=1353, y=1, height=670)

    # creating horizontal scrollbar
    hsb = ttk.Scrollbar(emp_data_frame, orient="horizontal")
    hsb.configure(command=tree_frame.xview)
    tree_frame.configure(xscrollcommand=hsb.set)
    hsb.place(x=1, y=672, width=1350)


    def delete_data(tree_frame):
        # select_item= tree_frame.selection()[0]
        # print(select_item,type(select_item))

        select_item=tree_frame.selection()[0]
        print(len(select_item),(select_item),type(select_item))
        uid=tree_frame.item(select_item)['values'][1]
        print(uid)
        tbl=''
        type_of_emp=tree_frame.item(select_item)['values'][3]
        print(type_of_emp)
        if type_of_emp == 'Employee':
            tbl='emp_table'
        elif type_of_emp == 'Manager':
            tbl='manager_table'
        elif type_of_emp =='Director':
            tbl='director_table'

        del_query=f'delete from {tbl} where user_id=%s'
        sel_data=(user_id,)
        print(sel_data)
        cn = mysql.connector.connect(database="HRMS_PROJECT", user="root", password="root", host='localhost')
        cur = cn.cursor()

        def del_data():
            ans=msg.askyesno('Delete Record',' Are you sure!!!')
            if ans == True :
                cur.execute(del_query, sel_data)
                cur.close()
                cn.commit()
                tree_frame.delete(select_item)
                msg.showinfo('Deleted', 'Employee has been Deleted Sucessfully!!!')
                cn.close()
                show_all_emp()
            elif ans== False:
                show_all_emp()
                print(select_item)
        del_data()
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • As the error says, `tree_frame.selection()` returns a empty tuple, so before accessing its content, you need to check whether the returned tuple is empty or not. – acw1668 Apr 18 '23 at 15:17
  • I have already checked that , In selection function I write the code – Trupti Ranjan Lenka Apr 18 '23 at 19:56
  • No you didn't, otherwise you will not get the exception. – acw1668 Apr 18 '23 at 22:44
  • in my selection function for checking purpose i wrote the code : def delete_data(tree_frame): select_item= tree_frame.selection()[0] print(select_item)). for print on my console at that time whenever i select different record in multiple time it will be take Id like 1001,1008 like this – Trupti Ranjan Lenka Apr 19 '23 at 05:13
  • Read the error carefully. `tree_frame.selection()[0]` will raise the exception when `tree_frame.selection()` return empty tuple because you try to access the first item in the tuple which does not exist. You should use something like `selection = tree_frame.selection()`, `if selection: ...`. – acw1668 Apr 19 '23 at 05:23

2 Answers2

1
def delete_data(tree_frame):
    # select_item= tree_frame.selection()
    # print(select_item,type(select_item))
    selection=tree_frame.selection()
    print(selection)
    if selection:
        select_item=selection[0]
        print(select_item)
        # print(len(select_item),(select_item),type(select_item))
        uid=tree_frame.item(select_item)['values'][1]
        print(uid)
        tbl=''
        type_of_emp=tree_frame.item(select_item)['values'][3]
        print(type_of_emp)
        if type_of_emp == 'Employee':
            tbl='emp_table'
        elif type_of_emp == 'Manager':
            tbl='manager_table'
        elif type_of_emp =='Director':
            tbl='director_table'

        del_query=f'delete from {tbl} where user_id=%s'
        sel_data=(uid,)
        print(sel_data)
        cn = mysql.connector.connect(database="HRMS_PROJECT", user="root", password="root", host='localhost')
        cur = cn.cursor()

        def del_data():
            ans=msg.askyesno('Delete Record',' Are you sure!!!')
            if ans == True :
                cur.execute(del_query, sel_data)
                cur.close()
                cn.commit()
                tree_frame.delete(select_item)
                msg.showinfo('Deleted', 'Employee has been Deleted Sucessfully!!!')
                cn.close()
        del_data()
    else:
        msg.showinfo('Select Item', 'Please Select Item!!!')
  • This is the right answer. Before I did one mistake like when my confirmation message come that time I manually call my main function but it call automatically that's why it's not work second time when I select any other data. – Trupti Ranjan Lenka Apr 20 '23 at 06:02
0

As the error says, you try to access the first item in an empty tuple which is returned by tree_frame.selection() when there is no item is selected in the treeview.

You need to check whether the tuple is empty or not before proceeding:

def delete_data(tree_frame):
    selection = tree_frame.selection()
    if selection:
        # there is item selected
        select_item = selection[0]
        ...
acw1668
  • 40,144
  • 5
  • 22
  • 34
  • yes.. exactly after 1st selection when i select another record it select empty tuple () . As for my requirement whenever i choose any record it's need to select a tuple like this ('I006',) . Can you please say how to achieve this? – Trupti Ranjan Lenka Apr 19 '23 at 06:19
  • If you have selected an item, you should not get an empty tuple. So I don't get what you said. – acw1668 Apr 19 '23 at 06:22
  • What do you want to say actually? You just copy my suggested code. – acw1668 Apr 19 '23 at 06:34
  • def delete_data(tree_frame): selection=tree_frame.selection() if selection: select_item=selection[0] print(select_item) I try this logic as for my 1st select my tuple element comes like I005 but when i select 2nd record that time i got empty tuple that's why my if block is not working for this reason I can't proceed my delete operation again. Please say me how to achieve this ? – Trupti Ranjan Lenka Apr 19 '23 at 06:54
  • Cannot reproduce your issue, I will not get empty tuple if record is selected. – acw1668 Apr 19 '23 at 07:23
  • def delete_data(tree_frame): selection=tree_frame.selection() print(selection) if selection: select_item=selection[0] print(select_item) when i select item for first time then my output is like ('I004',) I004, but when i try second time then my output is () () , I did't understood why second time my selection function not pick any data. That's the problem – Trupti Ranjan Lenka Apr 19 '23 at 09:33
  • `print(select_item)` will not be executed if `selection` is `()` because the code inside the `if` block will not be executed. So how can you get `() ()`? Also you should not get `()` from `print(select_item)` because `select_item` is not a tuple. – acw1668 Apr 19 '23 at 09:41
  • I just add else part for understanding propose like else: print(selection) for 2nd time empty () tuple comes then my else part print this values – Trupti Ranjan Lenka Apr 19 '23 at 10:29
  • simply I just added else part:- else: print(selection,type(selection)) this is my else part and when i select data for 2nd time this block is execute and this results comes: () – Trupti Ranjan Lenka Apr 19 '23 at 10:32
  • Thank you!! acw1668 for your help and patience. – Trupti Ranjan Lenka Apr 20 '23 at 06:05