Dynamically update Tkinter ComboBox from an empty list

Viewed 152

I'm struggling to find a solution to this tkinter application I'm trying to build.

What I'm trying to build is a tool to pull out sheets and headers for an excel file. I want to enable the user to select the sheet and headers they want to pull from.

class myApp:
importedSheets = []
us_sheets = None
headers = []
us_headers = None

def UploadAction(self):
    self.filename = askopenfilename()
    print(self.filename)

def sheetnames(self):
    global importedSheets
    self.xlssheets = xlrd.open_workbook(self.filename,on_demand=True)
    importedSheets = self.xlssheets.sheet_names()
    #print (importedSheets)
    return importedSheets

I'm able to have the user select the file they want to pull information from, and populate the empty list importedSheets = [ ] with the correct sheet names.

What I can't seem to find out is how to display this list on a Tkinter Combobox. Everytime I try it, it just shows a blank combobox.

    def __init__(self,master):
       self.filename = None
       self.master = master
       self.cbox_sheets = Combobox(master = master,values = myApp.importedSheets,postcommand = self.sheetnames).pack()

import pandas as pd
import os
import xlrd
from tkinter import *
from tkinter.filedialog import askopenfilename
from tkinter.ttk import Combobox
import tkinter as tk
import re
import numpy as np

class myApp:
    importedSheets = []
    us_sheets = None
    headers = []
    us_headers = None
    
    def UploadAction(self):
        self.filename = askopenfilename()
        print(self.filename)
    
    def sheetnames(self):
        global importedSheets
        self.xlssheets = xlrd.open_workbook(self.filename,on_demand=True)
        importedSheets = self.xlssheets.sheet_names()
        #print (importedSheets)
        return importedSheets
        
    def showsheets(self):
        return myApp.importedSheets()
    
    def __init__(self,master):
        self.filename = None
        self.master = master
    
        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)
        
        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 = 'Select the file you want to import',font=(None,12)).pack()
        self.uploadButton = Button(master = self.frame2a,text = 'Import',command = lambda:self.UploadAction()).pack()
       
        self.sheetLabel = Label(master = self.frame2b,text = 'Select the sheet to extract',font=(None,12)).pack(padx=15)
        
        self.cbox_sheets = Combobox(master = self.frame2b,values = myApp.importedSheets,postcommand = self.sheetnames).pack()
       
        self.headerLabel = Label(master = self.frame2r,text = 'Select the header with data',font=(None,12)).pack(padx=15)
        
        
if __name__ == '__main__':
    root = Tk()
    my_gui = myApp(root)
    root.mainloop()
1 Answers

Weird enough, the code still is a mystery to me, but as far as this question is concerned, this is how you should edit your declaration of combobox:

self.cbox_sheets = Combobox(master = self.frame2b,values = self.importedSheets,postcommand = self.sheetnames)
self.cbox_sheets.pack()

Perhaps you should do this for all your other widgets too. Now just change your function to such:

 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

Perhaps there should be a change made in showsheet() too:

def showsheets(self):
    return self.importedSheets # because its is not a callable object so remove ()

Also wherever you say myApp.whatever you can change it to self.whatever, I think its more accurate to say so. There might be more improvements to be done on this code, but for now, this should get you running and answer your question.

Related