tksheet
tksheet copied to clipboard
Issue on Selected rows when Displaying Rows
import pandas as pd
from customtkinter import CTk, CTkEntry, CTkButton
from tksheet import Sheet
from tkinter import TOP, BOTH, X
# Sample data
Check = pd.DataFrame([' '])
sample_data = pd.DataFrame([
['Apple', 'Banana','Late'],
['REMARK', 'MARKING','Early'],
['Apps','Thousand','Very Late']
])
data = pd.concat([Check, sample_data], axis=1).fillna('')
# Dictionary to keep track of checkbox states
checkbox_states = {i: False for i in range(len(data))}
def update_checkbox_states(sheet):
for row_idx in range(sheet.total_rows()):
if sheet.get_cell_data(row_idx, 0) == True:
checkbox_states[row_idx] = True
else:
checkbox_states[row_idx] = False
print('DONE UPDATE')
def apply_checkbox_states(sheet):
for row_idx, state in checkbox_states.items():
if state:
sheet.set_cell_data(row_idx, 0, True)
else:
sheet.set_cell_data(row_idx, 0, False)
print('DONE APPLY')
def selected_row(event=None):
global row_edit, rearrange
row_edit = []
for box in sheet.get_all_selection_boxes():
sheet[box].dehighlight()
data = sheet[box].data
for row in data:
row_edit.append(row)
def searching(entry, sheet):
global rows_to_show, isALL
key = entry.get().lower()
if not key:
sheet.display_rows('all', all_displayed=False)
isALL = 'all'
else:
words = key.split()
fill = data.values.tolist()
matching_indices = set(range(len(fill)))
for word in words:
matching_indices = {idx for idx in matching_indices if any(word in str(cell).lower() for cell in fill[idx])}
print(matching_indices)
rows_to_show = list(matching_indices)
sheet.display_rows(rows_to_show, all_displayed=False, redraw=True, reset_row_positions=True)
isALL = 'Not-all'
print('DONE SEARCH')
def custom_sheet():
global sheet
tkEntry = CTkEntry(app, fg_color='white', bg_color='white', text_color='black')
tkEntry.pack(side=TOP, fill=X, expand=True)
sheet = Sheet(app, data=data.values.tolist())
sheet.pack(side=TOP, fill=BOTH, expand=True)
sheet.enable_bindings()
sheet.checkbox('A', checked=False, redraw=False)
tkButton = CTkButton(app, text='Search', command=lambda: [update_checkbox_states(sheet), searching(tkEntry, sheet), apply_checkbox_states(sheet)])
tkButton.pack(side=TOP)
sheet.extra_bindings(bindings="row_select", func= selected_row)
app = CTk()
app.config(background='white')
custom_sheet()
app.mainloop()
First step:
Second step:
Third step:
Output:
[False, 'REMARK', 'MARKING', 'Early']
When I search 'app' in Entry, it hide rows that are not related to search key. When I select the supposedly the 3rd rows. it printed the hidden rows 2.
I think I have the same issues. Depending on options I created, I hide rows using
sheet_obj.display_rows(rows=rows_to_show, all_displayed = False)
where rows_to_show is a list of indexes I want to display, others are not shown.
Likewise I hide columns using
sheet_obj.display_columns(columns=[0,3,4], all_columns_displayed=False)
When I call get_currently_selected, both current_selection.row and current_selection.column are incorrect. Is there a workaround?
@AnonymousVibrate Hello, I am struggling to determine an issue when using the following code to test displaying rows:
from tksheet import Sheet
import tkinter as tk
from itertools import islice
class demo(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.data = [
["Apple", "Banana", "Late"],
["REMARK", "MARKING", "Early"],
["Apps", "Thousand", "Very Late"],
]
self.search_bar = tk.Entry(self)
self.search_bar.pack(side="top", fill="x", expand=True)
self.search_bar.bind("<Return>", self.search_for)
self.sheet = Sheet(self, data=self.data)
self.sheet.pack(side="top", fill="both", expand=True)
self.sheet.enable_bindings()
self.sheet.insert_column(idx=0)
self.sheet.checkbox("A", checked=False, redraw=False)
self.search_button = tk.Button(self, text="Search", command=self.search_for)
self.search_button.pack(side="top")
def search_for(self, event=None):
key = self.search_bar.get().lower()
if not key:
self.sheet.display_rows("all", all_displayed=False, redraw=True, reset_row_positions=True)
else:
words = key.split()
matching_indices = set(
ind
for word in words
for ind, row in enumerate(self.data)
if any(word in f"{cell}".lower() for cell in islice(row, 1, None))
)
if not matching_indices:
matching_indices = list(range(len(self.data)))
self.sheet.display_rows(
matching_indices,
all_displayed=False,
redraw=True,
reset_row_positions=True,
)
app = demo()
app.mainloop()
Is it possible the issue is related to your example?
@agregory999 Hello, get_currently_selected returns the displayed index of the row/column, use:
- https://github.com/ragardner/tksheet/wiki/Version-7#displayed-row-index-to-data
- https://github.com/ragardner/tksheet/wiki/Version-7#displayed-column-index-to-data
to convert the integers in the currently selected tuple
@AnonymousVibrate Hello, I am struggling to determine an issue when using the following code to test displaying rows:
from tksheet import Sheet import tkinter as tk from itertools import islice class demo(tk.Tk): def __init__(self): tk.Tk.__init__(self) self.data = [ ["Apple", "Banana", "Late"], ["REMARK", "MARKING", "Early"], ["Apps", "Thousand", "Very Late"], ] self.search_bar = tk.Entry(self) self.search_bar.pack(side="top", fill="x", expand=True) self.search_bar.bind("<Return>", self.search_for) self.sheet = Sheet(self, data=self.data) self.sheet.pack(side="top", fill="both", expand=True) self.sheet.enable_bindings() self.sheet.insert_column(idx=0) self.sheet.checkbox("A", checked=False, redraw=False) self.search_button = tk.Button(self, text="Search", command=self.search_for) self.search_button.pack(side="top") def search_for(self, event=None): key = self.search_bar.get().lower() if not key: self.sheet.display_rows("all", all_displayed=False, redraw=True, reset_row_positions=True) else: words = key.split() matching_indices = set( ind for word in words for ind, row in enumerate(self.data) if any(word in f"{cell}".lower() for cell in islice(row, 1, None)) ) if not matching_indices: matching_indices = list(range(len(self.data))) self.sheet.display_rows( matching_indices, all_displayed=False, redraw=True, reset_row_positions=True, ) app = demo() app.mainloop()Is it possible the issue is related to your example?
from tksheet import Sheet
import tkinter as tk
from itertools import islice
class demo(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.data = [
["Apple", "Banana", "Late"],
["REMARK", "MARKING", "Early"],
["Apps", "Thousand", "Very Late"],
]
self.search_bar = tk.Entry(self)
self.search_bar.pack(side="top", fill="x", expand=True)
self.search_bar.bind("<Return>", self.search_for)
self.sheet = Sheet(self, data=self.data)
self.sheet.pack(side="top", fill="both", expand=True)
self.sheet.enable_bindings()
self.sheet.insert_column(idx=0)
self.sheet.checkbox("A", checked=False, redraw=False)
self.search_button = tk.Button(self, text="Search", command=self.search_for)
self.search_button.pack(side="top")
self.sheet.extra_bindings(bindings="row_select", func= self.selected_row)
def search_for(self, event=None):
key = self.search_bar.get().lower()
if not key:
self.sheet.display_rows("all", all_displayed=False, redraw=True, reset_row_positions=True)
else:
words = key.split()
matching_indices = set(
ind
for word in words
for ind, row in enumerate(self.data)
if any(word in f"{cell}".lower() for cell in islice(row, 1, None))
)
if not matching_indices:
matching_indices = list(range(len(self.data)))
self.sheet.display_rows(
matching_indices,
all_displayed=False,
redraw=True,
reset_row_positions=True,
)
def selected_row(self ,event=None):
global row_edit, rearrange
row_edit = []
for box in self.sheet.get_all_selection_boxes():
self.sheet[box].dehighlight()
data = self.sheet[box].data
for row in data:
row_edit.append(row)
print(row_edit)
app = demo()
app.mainloop()
Please try this updated code. It will print [False, 'REMARK', 'MARKING', 'Early'] after you select the 3rd row.
Thank you for the update,
My apologies, there is not enough documentation on this,
I think the above issue will be fixed if you change the displayed row of the box to a data row integer,
def selected_row(self ,event=None):
global row_edit, rearrange
row_edit = []
for box in self.sheet.get_all_selection_boxes():
row_number = self.sheet.datarn(box.from_r)
row = self.sheet[row_number].data
for cell in row:
row_edit.append(cell)
print(row_edit)
I will add more documentation on the topic but basically:
- Displayed cell coordinates ignore hidden rows/columns when indexing cells.
- Data cell coordinates include hidden rows/columns in indexing cells.