the scrollbar for the sidebar shows only up when i set the self.sidebar_width to atleast 600 why is that . Please fix this. Only print the code that needs to be changed. Lets think step by step. Python 3.12 code: import ctypes
import csv
import json
from pathlib import Path
import tkinter as tk
from tkinter import filedialog, messagebox, simpledialog
from tkinter import ttk
from tksheet import Sheet

def set_dpi_awareness():
"""Enable DPI awareness for high DPI settings."""
try:
ctypes.windll.shcore.SetProcessDpiAwareness(1)
except Exception as e:
print(f"Error setting DPI awareness: {e}")

class TableApp:
"""Table Editor application with a sidebar and table management."""

def init(self, root: tk.Tk):
"""Initialize the TableApp."""
self.root = root
self.config_dimensions()
self.config_fonts()
self.config_colors()
self.initialize_data()
self.setup_ui()
self.load_tables()

def config_dimensions(self):
"""Configure application dimensions."""
Window dimensions

self.root.title("Table Editor with Sidebar")
self.root.geometry("1920x1080")
self.root.minsize(1200, 560)
Component dimensions

self.sidebar_width = 400
self.static_frame_width = 100
self.header_height = 190

def config_fonts(self):
"""Configure application fonts."""
font_name, font_size, font_style = "Literata", 12, "normal"
self.default_font = (font_name, font_size, font_style)
self.root.option_add("*Font", f"{font_name} {font_size}")

def config_colors(self):
"""Configure application colors."""
self.text_color = "#333333"
self.background_color = "#FFFFFF"
self.sidebar_color = "#F7F8FC"
self.button_color = "#F7F8FC"
self.button_color_selected = "#EAEDEF"

def setup_ui(self):
"""Set up the user interface components."""
self.create_sidebar()
self.create_main_frame()
self.create_header_frame()
self.create_table_frame()

def create_sidebar(self):
"""Create the sidebar with navigation and actions."""
sidebar = self._create_frame(
parent=self.root,
width=self.sidebar_width,
bg=self.sidebar_color,
side='left',
anchor='nw',
fill='y'
)

self._create_frame(
parent=self.root,
width=self.static_frame_width,
bg=self.background_color,
side='left',
anchor='nw',
fill='y'
)
sidebar.pack_propagate(False)

self._add_normal_buttons(sidebar)
self._add_scrollable_canvas(sidebar)
self._add_delete_table_section(sidebar)

def _create_frame(
self,
parent: tk.Widget,
width: int | None,
bg: str,
side: str,
anchor: str,
fill: str,
expand: bool = False
) -> tk.Frame:
"""Create and pack a frame with specified properties."""
frame = tk.Frame(parent, width=width, bg=bg, bd=0, relief='flat')
frame.pack(side=side, anchor=anchor, fill=fill, expand=expand)
return frame

def _add_normal_buttons(self, sidebar: tk.Frame):
"""Add navigation buttons to the sidebar."""
normal_buttons_frame = self._create_frame(
parent=sidebar,
width=None,
bg=self.sidebar_color,
side='top',
anchor='nw',
fill='x'
)

create_table_label = self._create_clickable_label(
parent=normal_buttons_frame,
text="Create New Table",
command=self.create_new_table
)
create_table_label.pack(fill='x')
self.add_custom_hover(create_table_label)

self._add_separator(normal_buttons_frame)

def _add_scrollable_canvas(self, sidebar: tk.Frame):
"""Add a scrollable canvas to display table labels."""
scrollbar_frame = self._create_frame(
parent=sidebar,
width=None,
bg=self.sidebar_color,
side='top',
anchor='nw',
fill='both',
expand=True
)

canvas = tk.Canvas(scrollbar_frame, bg=self.sidebar_color, highlightthickness=0)
canvas.pack(side="left", fill="both", expand=True)

scrollbar = ttk.Scrollbar(scrollbar_frame, orient="vertical", command=canvas.yview)
scrollbar.pack(side="right", fill="y")

canvas.configure(yscrollcommand=scrollbar.set)

self.table_labels_frame = tk.Frame(canvas, bg=self.sidebar_color)
canvas.create_window((0, 0), window=self.table_labels_frame, anchor="nw")

self._bind_scrollbar_events(canvas, scrollbar, scrollbar_frame)

def _bind_scrollbar_events(self, canvas: tk.Canvas, scrollbar: ttk.Scrollbar, scrollbar_frame: tk.Frame):
"""Manage scrollbar visibility based on content size."""
def configure_scrollbar(event: tk.Event | None = None):
canvas.update_idletasks()
canvas_height = scrollbar_frame.winfo_height()
content_height = self.table_labels_frame.winfo_reqheight()

if content_height > canvas_height:
    scrollbar.pack(side="right", fill="y")
else:
    scrollbar.pack_forget()

canvas.configure(scrollregion=canvas.bbox("all"))

self.table_labels_frame.bind("", configure_scrollbar)
scrollbar_frame.bind("", configure_scrollbar)

def _add_delete_table_section(self, sidebar: tk.Frame):
"""Add the delete table option to the sidebar."""
self._add_separator(sidebar)

delete_table_label = self._create_clickable_label(
parent=sidebar,
text="Delete Selected Table",
command=self.delete_table
)
delete_table_label.pack(fill='x', side='bottom')
self.add_custom_hover(delete_table_label)

def _add_separator(self, parent: tk.Widget):
"""Add a horizontal separator to the parent widget."""
separator = ttk.Separator(parent, orient='horizontal')
separator.pack(fill='x')

def _create_clickable_label(self, parent: tk.Widget, text: str, command, allow_rename: bool = False) -> tk.Label:
"""Create a clickable label with optional rename capability."""
label = tk.Label(
parent,
text=text,
bg=self.button_color,
fg=self.text_color,
cursor="hand2" if not allow_rename else "arrow",
anchor='w',
)
label.bind("", lambda _: command())
if allow_rename:
label.bind("", lambda _: self.begin_rename(text))
return label

def create_main_frame(self):
"""Create the main frame for displaying tables."""
self.main_frame = tk.Frame(self.root)
self.main_frame.pack(expand=True, fill='both', side='right')

def create_header_frame(self):
"""Create the header with filter and action buttons."""
header_frame = tk.Frame(self.main_frame, height=self.header_height, bg=self.background_color)
header_frame.pack(fill='x')
header_frame.pack_propagate(False)

tk.Label(header_frame, text="Filter:", bg=self.background_color, fg=self.text_color).pack(
side='left')

self.filter_entry = tk.Entry(header_frame, fg=self.text_color)
self.filter_entry.pack(side='left')
self.filter_entry.bind("", lambda _: self.apply_filter())

rename_headers = self._create_clickable_label(
parent=header_frame,
text="Rename Headers",
command=self.rename_headers,
allow_rename=False
)
rename_headers.pack(side='left', fill='x')

import_table = self._create_clickable_label(
parent=header_frame,
text="Import Table",
command=self.import_file,
allow_rename=False
)
import_table.pack(side='right', fill='x')

export_table = self._create_clickable_label(
parent=header_frame,
text="Export Table",
command=self.export_table,
allow_rename=False
)
export_table.pack(side='right', fill='x')

def create_table_frame(self):
"""Create the frame to hold the active table."""
self.table_frame = tk.Frame(self.main_frame, bg=self.background_color)
self.table_frame.pack(expand=True, fill='both')

def initialize_data(self):
"""Initialize data structures and directories."""
self.save_file_dir = Path("tables")
self.save_file_dir.mkdir(exist_ok=True)

self.tables: dict[str, Sheet] = {}
self.table_labels: dict[str, tk.Label] = {}
self.original_data: dict[str, list[list[str]]] = {}
self.headers: dict[str, list[str]] = {}
self.current_table_name: str | None = None
self.rename_entry: tk.Entry | None = None
self.selected_table_label: tk.Label | None = None

def create_new_table(self):
"""Create a new table and select it."""
table_name = f"Table {len(self.tables) + 1}"
self.add_table(table_name)
self.load_selected_table(table_name)

def import_file(self):
"""Import a table from a CSV or JSON file."""
file_path = filedialog.askopenfilename(
title="Open File",
filetypes=[("JSON files", ".json"), ("CSV files", ".csv")]
)
if not file_path:
return

try:
if file_path.endswith('.csv'):
with open(file_path, newline='', encoding='utf-8') as csvfile:
data = list(csv.reader(csvfile))
elif file_path.endswith('.json'):
with open(file_path, 'r', encoding='utf-8') as jsonfile:
data = json.load(jsonfile)
else:
raise ValueError("Unsupported file format.")

headers, table_data = data[0], data[1:]
self.add_table_from_data(file_path, headers, table_data)

except Exception as e:
messagebox.showerror("File Import Error", str(e))

def add_table_from_data(self, file_path: str, headers: list[str], table_data: list[list[str]]):
"""Add a table using existing data from a file."""
table_name = Path(file_path).stem
table_name = self.ensure_unique_table_name(table_name)

self.add_table(table_name, table_data)
self.headers[table_name] = headers
self.load_selected_table(table_name)
self.save_data(table_name)

def ensure_unique_table_name(self, table_name: str) -> str:
"""Ensure the table name is unique by appending suffixes if necessary."""
original_name = table_name
counter = 1
while table_name in self.tables:
table_name = f"{original_name} (New {counter})"
counter += 1
return table_name

def export_table(self):
"""Export the current table to a CSV or JSON file."""
if not self.current_table_name:
messagebox.showwarning("No Table Selected", "Please select a table to export.")
return

file_path = filedialog.asksaveasfilename(
title="Save As",
defaultextension=".json",
filetypes=[("JSON files", ".json"), ("CSV files", ".csv")],
initialfile=self.current_table_name
)
if not file_path:
return

try:
data = [self.headers[self.current_table_name]] + self.tables[self.current_table_name].get_sheet_data()
if file_path.endswith('.csv'):
self.save_as_csv(file_path, data)
elif file_path.endswith('.json'):
self.save_as_json(file_path, data)
else:
raise ValueError("Unsupported file format.")

messagebox.showinfo("Export Successful", f"Table '{self.current_table_name}' has been exported successfully.")

except Exception as e:
messagebox.showerror("Export Failed", f"An error occurred during export: {e}")

def save_as_csv(self, file_path: str, data: list[list[str]]):
"""Save table data as a CSV file."""
with open(file_path, 'w', newline='', encoding='utf-8') as csvfile:
csv.writer(csvfile).writerows(data)

def save_as_json(self, file_path: str, data: list[list[str]]):
"""Save table data as a JSON file."""
with open(file_path, 'w', encoding='utf-8') as jsonfile:
json.dump(data, jsonfile, indent=4)

def add_table(self, table_name: str, data: list[list[str]] | None = None):
"""Add a new table to the application."""
default_data = [["" for _ in range(5)] for _ in range(10)]
sheet = Sheet(
self.table_frame,
data=data or default_data,
show_table=True,
headers=None,
font=self.default_font,
header_font=self.default_font,
auto_resize_columns=True
)
sheet.set_options(table_fg=self.text_color, header_fg=self.text_color)
sheet.enable_bindings()
sheet.extra_bindings([("end_edit_cell", lambda _: self.save_data(table_name))])
sheet.pack_forget()

self.tables[table_name] = sheet
self.original_data[table_name] = sheet.get_sheet_data()
self.headers.setdefault(table_name, sheet.headers())

self.create_table_label(table_name)

def create_table_label(self, table_name: str):
"""Create a label for the table in the sidebar."""
label = self._create_clickable_label(
parent=self.table_labels_frame,
text=table_name,
command=lambda: self.load_selected_table(table_name),
allow_rename=True
)
label.pack(fill='x')
self.table_labels[table_name] = label
self.add_custom_hover(label)

def delete_table(self):
"""Delete the currently selected table."""
if not self.current_table_name:
messagebox.showwarning("No Table Selected", "Please select a table to delete.")
return

if messagebox.askyesno("Delete Table", f"Are you sure you want to delete the table '{self.current_table_name}'?"):
self.remove_table(self.current_table_name)

def remove_table(self, table_name: str):
"""Remove a table from the application."""
self.tables[table_name].destroy()
self.table_labels[table_name].destroy()
del self.tables[table_name]
del self.original_data[table_name]
del self.headers[table_name]
del self.table_labels[table_name]
(self.save_file_dir / f"{table_name}.json").unlink(missing_ok=True)
self.current_table_name = None
self.selected_table_label = None

def load_tables(self):
"""Load existing tables from the save directory."""
for file_path in self.save_file_dir.glob("*.json"):
table_name = file_path.stem
with file_path.open('r', encoding='utf-8') as file:
data = json.load(file)

headers, table_data = data.pop(0), data
self.add_table(table_name, table_data)
self.headers[table_name] = headers

def load_selected_table(self, table_name: str):
"""Display the selected table and hide others."""
for name, sheet in self.tables.items():
if name == table_name:
sheet.pack(expand=True, fill='both')
self.current_table_name = name
sheet.headers(self.headers[name])
self.apply_filter()
self.selected_table_label = self.table_labels[name]
self.selected_table_label.config(bg=self.button_color_selected)
else:
sheet.pack_forget()
self.table_labels[name].config(bg=self.button_color)

def save_data(self, table_name: str):
"""Save the current data of a table."""
data = [self.headers[table_name]] + self.tables[table_name].get_sheet_data()
file_path = self.save_file_dir / f"{table_name}.json"
with file_path.open('w', encoding='utf-8') as file:
json.dump(data, file)
print(f"Data for {table_name} saved successfully.")

def apply_filter(self):
"""Filter table data based on the filter entry."""
if not self.current_table_name:
return

term = self.filter_entry.get().lower()
original_data = self.original_data[self.current_table_name]
filtered_data = [
row for row in original_data
if any(term in str(cell).lower() for cell in row)
]
self.tables[self.current_table_name].set_sheet_data(filtered_data)

def rename_headers(self):
"""Rename the headers of the selected table."""
if not self.current_table_name:
messagebox.showwarning("No Table Selected", "Please select a table to rename headers.")
return

current_headers = self.headers[self.current_table_name]
new_headers = simpledialog.askstring(
"Rename Headers",
"Enter new headers (comma-separated):",
initialvalue=", ".join(current_headers)
)
if new_headers:
header_list = [header.strip() for header in new_headers.split(',')]
self.headers[self.current_table_name] = header_list
self.tables[self.current_table_name].headers(header_list)
self.save_data(self.current_table_name)

def begin_rename(self, table_name: str):
"""Start renaming a table by replacing its label with an entry."""
if table_name not in self.table_labels:
messagebox.showerror("Error", f"Table '{table_name}' not found.")
return

label = self.table_labels[table_name]
self.cancel_rename()

self.rename_entry = tk.Entry(
self.table_labels_frame,
bg=label.cget("bg"),
fg=self.text_color,
relief='flat'
)
self.rename_entry.insert(0, table_name)
self.rename_entry.place(
x=label.winfo_x(),
y=label.winfo_y(),
width=label.winfo_width(),
height=label.winfo_height()
)
self.rename_entry.focus()
self.rename_entry.select_range(0, tk.END)
self.rename_entry.bind('', lambda _: self.end_rename(table_name))
self.rename_entry.bind('', lambda _: self.cancel_rename())

def end_rename(self, old_name: str):
"""Finalize the renaming of a table."""
new_name = self.rename_entry.get().strip()

if not new_name:
messagebox.showerror("Invalid Name", "Table name cannot be empty.")
self.rename_entry.focus_set()
return

if new_name in self.tables and new_name != old_name:
messagebox.showerror("Duplicate Name", f"A table named '{new_name}' already exists.")
self.rename_entry.focus_set()
return

if new_name != old_name:
self.update_table_name(old_name, new_name)
self.load_selected_table(new_name)

self.cancel_rename()

def update_table_name(self, old_name: str, new_name: str):
"""Update the table's name and associated resources."""
self.tables[new_name] = self.tables.pop(old_name)
self.original_data[new_name] = self.original_data.pop(old_name)
self.headers[new_name] = self.headers.pop(old_name)

label = self.table_labels.pop(old_name)
label.config(text=new_name)
label.bind("", lambda _: self.load_selected_table(new_name))
label.bind("", lambda _: self.begin_rename(new_name))

self.table_labels[new_name] = label

if self.selected_table_label == label:
label.config(bg=self.button_color_selected)

current_file = self.save_file_dir / f"{old_name}.json"
new_file = self.save_file_dir / f"{new_name}.json"
current_file.rename(new_file)

def cancel_rename(self):
"""Cancel the ongoing rename operation."""
if self.rename_entry:
self.rename_entry.destroy()
self.rename_entry = None

def add_custom_hover(self, label: tk.Label):
"""Add hover effects to a label."""
def on_enter(_: tk.Event):
if label != self.selected_table_label:
label.config(bg=self.button_color_selected)

def on_leave(_: tk.Event):
if label != self.selected_table_label:
label.config(bg=self.button_color)

label.bind("", on_enter)
label.bind("", on_leave)

if name == "main":
set_dpi_awareness()
root = tk.Tk()
app = TableApp(root)
root.mainloop()