Last active
September 26, 2023 02:21
-
-
Save RamonWill/f5e9fbc9df2bdceaa176448512e16eea 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 hidden or 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
alright i solved like this :