-
-
Save Yousuf28/5210ed8fb0317a0ff4ff2c6b1615b054 to your computer and use it in GitHub Desktop.
The code from my tutorial series on how to create a CSV/Dataframe viewer in Tkinter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Tutorial playlist https://www.youtube.com/playlist?list=PLCQT7jmSF-LrwYppkB3Xdbe6QC81-ozmT | |
import tkinter as tk | |
from pathlib import Path | |
from tkinter import ttk | |
from TkinterDnD2 import DND_FILES, TkinterDnD | |
import pandas as pd | |
class Application(TkinterDnD.Tk): | |
def __init__(self): | |
super().__init__() | |
self.title("CSV Viewer") | |
self.main_frame = tk.Frame(self) | |
self.main_frame.pack(fill="both", expand="true") | |
self.geometry("900x500") | |
self.search_page = SearchPage(parent=self.main_frame) | |
class DataTable(ttk.Treeview): | |
def __init__(self, parent): | |
super().__init__(parent) | |
scroll_Y = tk.Scrollbar(self, orient="vertical", command=self.yview) | |
scroll_X = tk.Scrollbar(self, orient="horizontal", command=self.xview) | |
self.configure(yscrollcommand=scroll_Y.set, xscrollcommand=scroll_X.set) | |
scroll_Y.pack(side="right", fill="y") | |
scroll_X.pack(side="bottom", fill="x") | |
self.stored_dataframe = pd.DataFrame() | |
def set_datatable(self, dataframe): | |
self.stored_dataframe = dataframe | |
self._draw_table(dataframe) | |
def _draw_table(self, dataframe): | |
self.delete(*self.get_children()) | |
columns = list(dataframe.columns) | |
self.__setitem__("column", columns) | |
self.__setitem__("show", "headings") | |
for col in columns: | |
self.heading(col, text=col) | |
df_rows = dataframe.to_numpy().tolist() | |
for row in df_rows: | |
self.insert("", "end", values=row) | |
return None | |
def find_value(self, pairs): | |
# pairs is a dictionary | |
new_df = self.stored_dataframe | |
for col, value in pairs.items(): | |
query_string = f"{col}.str.contains('{value}')" | |
new_df = new_df.query(query_string, engine="python") | |
self._draw_table(new_df) | |
def reset_table(self): | |
self._draw_table(self.stored_dataframe) | |
class SearchPage(tk.Frame): | |
def __init__(self, parent): | |
super().__init__(parent) | |
self.file_names_listbox = tk.Listbox(parent, selectmode=tk.SINGLE, background="darkgray") | |
self.file_names_listbox.place(relheight=1, relwidth=0.25) | |
self.file_names_listbox.drop_target_register(DND_FILES) | |
self.file_names_listbox.dnd_bind("<<Drop>>", self.drop_inside_list_box) | |
self.file_names_listbox.bind("<Double-1>", self._display_file) | |
self.search_entrybox = tk.Entry(parent) | |
self.search_entrybox.place(relx=0.25, relwidth=0.75) | |
self.search_entrybox.bind("<Return>", self.search_table) | |
# Treeview | |
self.data_table = DataTable(parent) | |
self.data_table.place(rely=0.05, relx=0.25, relwidth=0.75, relheight=0.95) | |
self.path_map = {} | |
def drop_inside_list_box(self, event): | |
file_paths = self._parse_drop_files(event.data) | |
current_listbox_items = set(self.file_names_listbox.get(0, "end")) | |
for file_path in file_paths: | |
if file_path.endswith(".csv"): | |
path_object = Path(file_path) | |
file_name = path_object.name | |
if file_name not in current_listbox_items: | |
self.file_names_listbox.insert("end", file_name) | |
self.path_map[file_name] = file_path | |
def _display_file(self, event): | |
file_name = self.file_names_listbox.get(self.file_names_listbox.curselection()) | |
path = self.path_map[file_name] | |
df = pd.read_csv(path) | |
self.data_table.set_datatable(dataframe=df) | |
def _parse_drop_files(self, filename): | |
# 'C:/Users/Owner/Downloads/RandomStock Tickers.csv C:/Users/Owner/Downloads/RandomStockTickers.csv' | |
size = len(filename) | |
res = [] # list of file paths | |
name = "" | |
idx = 0 | |
while idx < size: | |
if filename[idx] == "{": | |
j = idx + 1 | |
while filename[j] != "}": | |
name += filename[j] | |
j += 1 | |
res.append(name) | |
name = "" | |
idx = j | |
elif filename[idx] == " " and name != "": | |
res.append(name) | |
name = "" | |
elif filename[idx] != " ": | |
name += filename[idx] | |
idx += 1 | |
if name != "": | |
res.append(name) | |
return res | |
def search_table(self, event): | |
# column value. [[column,value],column2=value2].... | |
entry = self.search_entrybox.get() | |
if entry == "": | |
self.data_table.reset_table() | |
else: | |
entry_split = entry.split(",") | |
column_value_pairs = {} | |
for pair in entry_split: | |
pair_split = pair.split("=") | |
if len(pair_split) == 2: | |
col = pair_split[0] | |
lookup_value = pair_split[1] | |
column_value_pairs[col] = lookup_value | |
self.data_table.find_value(pairs=column_value_pairs) | |
if __name__ == "__main__": | |
root = Application() | |
root.mainloop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment