0

I am trying to replicate the excel workbook functionality of filtering multiple columns as needed and use the filtered dataframe for further task using tkinter and pandas. I have 100+ columns to select from and Like excel, it also has reset/clear filter option.

the code works well although i am encountering 2 issues:

  1. When i filter dataframe, it does not preserve the historical filtered dataframe. for example if select Col A - item 1 and then select Col B item 2. the cascading filtering does not work and it is saving the filtered dataframe either by Col A - item 1 or Col B item 2 not preserve the historical filtered data
  2. I do not get any Column headers on the treeview display, some issue in below lines. I did try all possible ways
for col in columns:
    treeview.heading("#0", text=col,command=lambda col=col:print(col))

Any suggestion or help please?

from win32com.shell import shell, shellcon
import pandas as pd
import openpyxl
from openpyxl import load_workbook
import numpy as np
import time
from tkinter import *
from tkinter import ttk,filedialog
import tkinter as tk

def apply_filter():
    selected_column = column_var.get()
    selected_item = item_var.get()

    if selected_column and selected_item:
        filtered_df = df[df[selected_column] == selected_item]
        filter_history.append(filtered_df)
        display_filtered_dataframe(filter_history)
        
def update_items(event):
    selected_column = column_var.get()
    if selected_column:
        items = df[selected_column].unique()  # Clean the items
        item_var.set('')  # Reset the item selection
        item_dropdown['values'] = list(map(str,items))
        
def reset_filter():
    filter_history.clear()
    display_filtered_dataframe([df])
    column_var.set('')  # Reset column selection
    item_var.set('')    # Reset item selection

def display_filtered_dataframe(dataframe):
    for row in treeview.get_children():
        treeview.delete(row)
    if dataframe:
        current_df = dataframe[-1]  # Get the most recent filtered DataFrame
        # Display the filtered DataFrame using Treeview
        columns = current_df.columns
        treeview["columns"] = ["#0"]+columns
        treeview.heading("#0", text="Index")
        for col in columns:
            treeview.heading("#0", text=col,command=lambda col=col:print(col))
            treeview.column("#0", width=100)  

        for i, row in current_df.iterrows():
            treeview.insert('', 'end', values=[i] + list(row))
            
# Create the main application window
root = tk.Tk()
root.title("Excel Data Filter")

# Create a vertical scrollbar for column selection
column_var = tk.StringVar()
column_label = tk.Label(root, text="Select Column:")
column_label.pack()

column_listbox = tk.Listbox(root, selectmode=tk.SINGLE)
column_listbox.pack()

for column in df.columns:
    column_listbox.insert(tk.END, column)
    
# Create a Combobox for item selection
item_var = tk.StringVar()
item_label = tk.Label(root, text="Select Item:")
item_label.pack()

item_dropdown = ttk.Combobox(root, textvariable=item_var, state='readonly')
item_dropdown.pack()

# Create a filter button to apply the filter
filter_button = tk.Button(root, text="Apply Filter", command=apply_filter)
filter_button.pack()

# Create a reset button to clear the filter
reset_button = tk.Button(root, text="Reset Filter", command=reset_filter)
reset_button.pack()

# Create a Treeview widget for displaying the filtered DataFrame as a table
columns = df.columns
treeview = ttk.Treeview(root, columns=["#0"] + columns, show='headings')
for col in columns:
    treeview.heading("#0", text=col,command=lambda col=col:print(col))
    treeview.column("#0", width=100,anchor='e')  #<---adjustable width of Display df

#Display df scrollbar    
tree_scroll_y = ttk.Scrollbar(root, orient='vertical', command=treeview.yview)
tree_scroll_x = ttk.Scrollbar(root, orient='horizontal', command=treeview.xview)
treeview.configure(yscrollcommand=tree_scroll_y.set, xscrollcommand=tree_scroll_x.set)
treeview.pack()
tree_scroll_y.pack(side='right', fill='y')
tree_scroll_x.pack(side='bottom', fill='x')

# List to store the history of filtered DataFrames
filter_history = []

# Link the Listbox selection to the column variable and item selection
def on_select(event):
    selected_index = column_listbox.curselection()
    if selected_index:
        selected = column_listbox.get(selected_index[0])  # Extract the first item from the tuple
        column_var.set(selected)
        update_items(None)

column_listbox.bind("<<ListboxSelect>>", on_select)

# Display the initial DataFrame
display_filtered_dataframe([df])
#pt.updateModel(Table(model=df))

root.mainloop()

4
  • 1
    What is df? It isn't defined and trying to run your code will give errors. Your code seems complicated enough that it would be hard to see what is wrong just by looking at the code. Can you provide an example? Commented Oct 25, 2023 at 14:13
  • '''df''' is the input 'dataframe df=pd.read_excel("example.xlsx")'. I have solved the 1st issue though, still unable to display the column header in the display table of tkinter
    – Biplab1985
    Commented Oct 25, 2023 at 14:19
  • For item 2, it is because you have used the same column name "#0" for all the columns.
    – acw1668
    Commented Oct 25, 2023 at 23:03
  • Note also that you have used show='headings' when creating the treeview widget, so the tree column (i.e. "#0") is not visible. So it is not necessary to set the column properties on that column.
    – acw1668
    Commented Oct 26, 2023 at 1:54

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.