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:
- 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
- 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()
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?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.