- About tksheet
- Installation and Requirements
- Basic Initialization
- Initialization Options
- Header and Index
- Setting Table Data
- Getting Table Data
- Bindings and Functionality
- Identifying Bound Event Mouse Position
- Table Colors
- Highlighting Cells
- Text Font and Alignment
- Row Heights and Column Widths
- Getting Selected Cells
- Modifying Selected Cells
- Modifying and Getting Scroll Positions
- Readonly Cells
- Hiding Columns
- Hiding Table Elements
- Cell Text Editor
- Dropdown Boxes
- Check Boxes
- Table Options and Other Functions
- Example Loading Data from Excel
- Example Custom Right Click and Text Editor Functionality
- Example Displaying Selections
- Example List Box
- Example Header Dropdown Boxes and Filtering
- Example ReadMe Screenshot Code
tksheet
is a Python tkinter table widget written in pure python. It is licensed under the MIT license.
It works using tkinter canvases and moves lines, text and highlight rectangles around for only the visible portion of the table.
Cell values can be any class with a str
method.
Some examples of things that are not possible with tksheet:
- Cell merging
- Cell text wrap
- Changing font for individual cells
- Different fonts for index and table
- Mouse drag copy cells
- Hide rows
- Cell highlight borders (except for dropdown boxes)
- Highlighting continuous multiple cells with a single border
If you'd like to buy me a coffee for creating and supporting this library you can do so here: https://www.buymeacoffee.com/ragardner
tksheet
is available through PyPi (Python package index) and can be installed by using Pip through the command line pip install tksheet
Alternatively you can download the source code and (inside the tksheet directory) use the command line python setup.py develop
tksheet
requires a Python version of 3.6
or higher.
Like other tkinter widgets you need only the Sheet()
s parent as an argument to initialize a Sheet()
e.g.
sheet = Sheet(my_frame_widget)
my_frame_widget
would be replaced by whatever widget is yourSheet()
s parent.
As an example, this is a tkinter program involving a Sheet()
widget
from tksheet import Sheet
import tkinter as tk
class demo(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.grid_columnconfigure(0, weight = 1)
self.grid_rowconfigure(0, weight = 1)
self.frame = tk.Frame(self)
self.frame.grid_columnconfigure(0, weight = 1)
self.frame.grid_rowconfigure(0, weight = 1)
self.sheet = Sheet(self.frame,
data = [[f"Row {r}, Column {c}\nnewline1\nnewline2" for c in range(50)] for r in range(500)])
self.sheet.enable_bindings()
self.frame.grid(row = 0, column = 0, sticky = "nswe")
self.sheet.grid(row = 0, column = 0, sticky = "nswe")
app = demo()
app.mainloop()
This is a full list of all the start up arguments, the only required argument is the sheets parent, everything else has default arguments.
Sheet(
parent,
show_table = True,
show_top_left = True,
show_row_index = True,
show_header = True,
show_x_scrollbar = True,
show_y_scrollbar = True,
width = None,
height = None,
headers = None,
default_header = "letters", #letters, numbers or both
default_row_index = "numbers", #letters, numbers or both
show_default_header_for_empty = True,
page_up_down_select_row = True,
expand_sheet_if_paste_too_big = False,
paste_insert_column_limit = None,
paste_insert_row_limit = None,
ctrl_keys_over_dropdowns_enabled = False,
arrow_key_down_right_scroll_page = False,
enable_edit_cell_auto_resize = True,
data_reference = None,
data = None,
startup_select = None,
startup_focus = True,
total_columns = None,
total_rows = None,
column_width = 120,
header_height = "1",
max_colwidth = "inf",
max_rh = "inf",
max_header_height = "inf",
max_row_width = "inf",
row_index = None,
after_redraw_time_ms = 100,
row_index_width = 100,
auto_resize_default_row_index = True,
set_all_heights_and_widths = False,
row_height = "1",
font = get_font(),
header_font = get_heading_font(),
popup_menu_font = get_font(),
align = "w",
header_align = "center",
row_index_align = "center",
displayed_columns = [],
all_columns_displayed = True,
max_undos = 20,
outline_thickness = 0,
outline_color = theme_light_blue['outline_color'],
column_drag_and_drop_perform = True,
row_drag_and_drop_perform = True,
empty_horizontal = 150,
empty_vertical = 100,
selected_rows_to_end_of_window = False,
horizontal_grid_to_end_of_window = False,
vertical_grid_to_end_of_window = False,
show_vertical_grid = True,
show_horizontal_grid = True,
display_selected_fg_over_highlights = False,
show_selected_cells_border = True,
theme = "light blue",
popup_menu_fg = "gray2",
popup_menu_bg = "#f2f2f2",
popup_menu_highlight_bg = "#91c9f7",
popup_menu_highlight_fg = "black",
frame_bg = theme_light_blue['table_bg'],
table_grid_fg = theme_light_blue['table_grid_fg'],
table_bg = theme_light_blue['table_bg'],
table_fg = theme_light_blue['table_fg'],
table_selected_cells_border_fg = theme_light_blue['table_selected_cells_border_fg'],
table_selected_cells_bg = theme_light_blue['table_selected_cells_bg'],
table_selected_cells_fg = theme_light_blue['table_selected_cells_fg'],
table_selected_rows_border_fg = theme_light_blue['table_selected_rows_border_fg'],
table_selected_rows_bg = theme_light_blue['table_selected_rows_bg'],
table_selected_rows_fg = theme_light_blue['table_selected_rows_fg'],
table_selected_columns_border_fg = theme_light_blue['table_selected_columns_border_fg'],
table_selected_columns_bg = theme_light_blue['table_selected_columns_bg'],
table_selected_columns_fg = theme_light_blue['table_selected_columns_fg'],
resizing_line_fg = theme_light_blue['resizing_line_fg'],
drag_and_drop_bg = theme_light_blue['drag_and_drop_bg'],
index_bg = theme_light_blue['index_bg'],
index_border_fg = theme_light_blue['index_border_fg'],
index_grid_fg = theme_light_blue['index_grid_fg'],
index_fg = theme_light_blue['index_fg'],
index_selected_cells_bg = theme_light_blue['index_selected_cells_bg'],
index_selected_cells_fg = theme_light_blue['index_selected_cells_fg'],
index_selected_rows_bg = theme_light_blue['index_selected_rows_bg'],
index_selected_rows_fg = theme_light_blue['index_selected_rows_fg'],
index_hidden_rows_expander_bg = theme_light_blue['index_hidden_rows_expander_bg'],
header_bg = theme_light_blue['header_bg'],
header_border_fg = theme_light_blue['header_border_fg'],
header_grid_fg = theme_light_blue['header_grid_fg'],
header_fg = theme_light_blue['header_fg'],
header_selected_cells_bg = theme_light_blue['header_selected_cells_bg'],
header_selected_cells_fg = theme_light_blue['header_selected_cells_fg'],
header_selected_columns_bg = theme_light_blue['header_selected_columns_bg'],
header_selected_columns_fg = theme_light_blue['header_selected_columns_fg'],
header_hidden_columns_expander_bg = theme_light_blue['header_hidden_columns_expander_bg'],
top_left_bg = theme_light_blue['top_left_bg'],
top_left_fg = theme_light_blue['top_left_fg'],
top_left_fg_highlight = theme_light_blue['top_left_fg_highlight'])
startup_select
selects cells, rows or columns at initialization by using atuple
e.g.(0, 0, "cells")
for cell A0 or(0, 5, "rows")
for rows 0 to 5.data_reference
anddata
are essentially the same
You can change these settings after initialization using the set_options()
function.
Set the header to something non-default (if new header is shorter than total columns then default headers e.g. letters will be used on the end.
headers(newheaders = None, index = None, reset_col_positions = False, show_headers_if_not_sheet = True, redraw = False)
- Using an integer
int
for argumentnewheaders
makes the sheet use that row as a header e.g.headers(0)
means the first row will be used as a header (the first row will not be hidden in the sheet though), this is sort of equivalent to freezing the row. - Leaving
newheaders
asNone
and using theindex
argument returns the existing header value in that index. - Leaving all arguments as default e.g.
headers()
returns existing headers.
Set the index to something non-default (if new index is shorter than total rows then default index e.g. numbers will be used on the end.
row_index(newindex = None, index = None, reset_row_positions = False, show_index_if_not_sheet = True, redraw = False)
- Using an integer
int
for argumentnewindex
makes the sheet use that column as an index e.g.row_index(0)
means the first column will be used as an index (the first column will not be hidden in the sheet though), this is sort of equivalent to freezing the column. - Leaving
newindex
asNone
and using theindex
argument returns the existing row index value in that index. - Leaving all arguments as default e.g.
row_index()
returns the existing row index.
Set sheet data, overwrites any existing data.
set_sheet_data(data = [[]],
reset_col_positions = True,
reset_row_positions = True,
redraw = True,
verify = False,
reset_highlights = False)
data
(list
) has to be a list of lists for full functionality, for display only a list of tuples or a tuple of tuples will work.reset_col_positions
andreset_row_positions
(bool
) whenTrue
will reset column widths and row heights.redraw
(bool
) refreshes the table after setting new data.verify
(bool
) goes throughdata
and checks if it is a list of lists, will raise error if not, disabled by default.reset_highlights
(bool
) resets all table cell highlights.
Set cell data, overwrites any existing data.
set_cell_data(r, c, value = "", set_copy = True, redraw = False)
set_copy
meansstr()
will be used on the value before setting.
Insert a row into the sheet.
insert_row(values = None, idx = "end", height = None, deselect_all = False, add_columns = False,
redraw = False)
- Leaving
values
asNone
inserts an empty row, e.g.insert_row()
will append an empty row to the sheet. height
is the new rows displayed height in pixels, leave asNone
for default.add_columns
checks the rest of the sheets rows are at least the length as the new row, leave asFalse
for better performance.
Set column data, overwrites any existing data.
set_column_data(c, values = tuple(), add_rows = True, redraw = False)
add_rows
adds extra rows to the sheet if the column data doesn't fit within current sheet dimensions.
Insert a column into the sheet.
insert_column(values = None, idx = "end", width = None, deselect_all = False, add_rows = True, equalize_data_row_lengths = True,
mod_column_positions = True,
redraw = False)
Insert multiple columns into the sheet.
insert_columns(columns = 1, idx = "end", widths = None, deselect_all = False, add_rows = True, equalize_data_row_lengths = True,
mod_column_positions = True,
redraw = False)
columns
can be eitherint
or iterable of iterables.
Set row data, overwrites any existing data.
set_row_data(r, values = tuple(), add_columns = True, redraw = False)
Insert multiple rows into the sheet.
insert_rows(rows = 1, idx = "end", heights = None, deselect_all = False, add_columns = True,
redraw = False)
rows
can be eitherint
or iterable of iterables.
sheet_data_dimensions(total_rows = None, total_columns = None)
delete_row(idx = 0, deselect_all = False, redraw = True)
total_rows(number = None, mod_positions = True, mod_data = True)
total_columns(number = None, mod_positions = True, mod_data = True)
set_sheet_data_and_display_dimensions(total_rows = None, total_columns = None)
move_row(row, moveto)
delete_column(idx = 0, deselect_all = False, redraw = True)
move_column(column, moveto)
Make all data rows the same length (same number of columns), goes by longest row. This will only affect the data variable, not visible columns.
equalize_data_row_lengths()
Modify widget height and width in pixels
height_and_width(height = None, width = None)
height
(int
) set a height in pixelswidth
(int
) set a width in pixels If both arguments areNone
then table will reset to default tkinter canvas dimensions.
Get sheet data and, if required, header and index data.
get_sheet_data(return_copy = False, get_header = False, get_index = False)
return_copy
(bool
) will copy all cells ifTrue
, also copies header and index if they areTrue
.get_header
(bool
) will put the header as the first row ifTrue
.get_index
(bool
) will put index items as the first item in every row.
get_cell_data(r, c, return_copy = True)
get_row_data(r, return_copy = True)
get_column_data(c, return_copy = True)
Get number of rows in table data.
get_total_rows()
Enable table functionality and bindings.
enable_bindings(*bindings)
bindings
(str
) options are (rc stands for right click):- "all"
- "single_select"
- "toggle_select"
- "drag_select"
- "select_all"
- "column_drag_and_drop"
- "row_drag_and_drop"
- "column_select"
- "row_select"
- "column_width_resize"
- "double_click_column_resize"
- "row_width_resize"
- "column_height_resize"
- "arrowkeys"
- "row_height_resize"
- "double_click_row_resize"
- "right_click_popup_menu"
- "rc_select"
- "rc_insert_column"
- "rc_delete_column"
- "rc_insert_row"
- "rc_delete_row"
- "hide_columns"
- "copy"
- "cut"
- "paste"
- "delete"
- "undo"
- "edit_cell"
- "edit_header"
Notes:
- Dragging and dropping rows / columns is bound to shift - mouse left click and hold and drag.
"edit_header"
is not enabled bybindings = "all"
and has to be enabled individually, double click on header cells to edit.- To allow table expansion when pasting data which doesn't fit in the table use either:
expand_sheet_if_paste_too_big = True
in sheet initialization arguments orsheet.set_options(expand_sheet_if_paste_too_big = True)
Disable table functionality and bindings, uses the same arguments as enable_bindings()
disable_bindings(*bindings)
Bind various table functionality to your own functions. To unbind a function either set func
argument to None
or leave it as default e.g. extra_bindings("begin_copy")
to unbind "begin_copy"
.
extra_bindings(bindings, func = "None")
Notes:
- Upon an event being triggered the bound function will be sent a namedtuple containing variables relevant to that event, use
print()
or similar to see all the variable names in the event. Each event contains different variable names with the exception ofeventname
e.g.event.eventname
- For most of the
"end_..."
events the bound function is run before the value is set. - The bound function for
"end_edit_cell"
is run before the cell data is set in order that a return value can set the cell instead of the user input. Using the event you can assess the user input and if needed override it with a return value which is notNone
. ifNone
is the return value then the user input will not be overridden.
Arguments:
bindings
(str
) options are:- "begin_copy"
- "end_copy"
- "begin_cut"
- "end_cut"
- "begin_paste"
- "end_paste"
- "begin_undo"
- "end_undo"
- "begin_delete"
- "end_delete"
- "begin_edit_cell"
- "end_edit_cell"
- "begin_row_index_drag_drop"
- "end_row_index_drag_drop"
- "begin_column_header_drag_drop"
- "end_column_header_drag_drop"
- "begin_delete_rows"
- "end_delete_rows"
- "begin_delete_columns"
- "end_delete_columns"
- "begin_insert_columns"
- "end_insert_columns"
- "begin_insert_rows"
- "end_insert_rows"
- "row_height_resize"
- "column_width_resize"
- "cell_select"
- "select_all"
- "row_select"
- "column_select"
- "drag_select_cells"
- "drag_select_rows"
- "drag_select_columns"
- "shift_cell_select"
- "shift_row_select"
- "shift_column_select"
- "deselect"
- "all_select_events"
- "bind_all"
- "unbind_all"
func
argument is the function you want to send the binding event to.
Add commands to the in-built right click popup menu.
popup_menu_add_command(label, func, table_menu = True, index_menu = True, header_menu = True)
Remove the custom commands added using the above function from the in-built right click popup menu, if label
is None
then it removes all.
popup_menu_del_command(label = None)
Disable table functionality and bindings (uses the same options as enable_bindings()
.
disable_bindings(bindings = "all")
Enable or disable mousewheel, left click etc.
basic_bindings(enable = False)
Enable or disable cell edit functionality, including Undo.
edit_bindings(enable = False)
Enable or disable the ability to edit a specific cell.
cell_edit_binding(enable = False, keys = [])
keys
can be used to bind more keys to open a cell edit window
bind(binding, func, add = None)
add
will only work for bindings which are not the following:"<ButtonPress-1>"
,"<ButtonMotion-1>"
,"<ButtonRelease-1>"
,"<Double-Button-1>"
,"<Motion>"
and lastly whichever is your operating systems right mouse click button
unbind(binding)
cut(event = None)
copy(event = None)
paste(event = None)
delete(event = None)
undo(event = None)
The below functions require a mouse click event, for example you could bind right click, example here, and then identify where the user has clicked.
identify_region(event)
identify_row(event, exclude_index = False, allow_end = True)
identify_column(event, exclude_header = False, allow_end = True)
Sheet control actions for binding your own keys to e.g. sheet.bind("<Control-B>", sheet.paste)
cut(self, event = None)
copy(self, event = None)
paste(self, event = None)
delete(self, event = None)
undo(self, event = None)
edit_cell(self, event = None, dropdown = False)
To change the colors of individual cells, rows or columns use the functions listed under highlighting cells.
For the colors of specific parts of the table such as gridlines and backgrounds use the function set_options()
, arguments can be found here. Most of the set_options()
arguments are the same as the sheet initialization arguments.
Otherwise you can change the theme using the below function.
change_theme(theme = "light blue")
theme
(str
) options (themes) arelight blue
,light green
,dark
,dark blue
anddark green
.
bg
andfg
arguments use either a tkinter color or a hexstr
color.- Highlighting cells, rows or columns will also change the colors of dropdown boxes and check boxes.
highlight_cells(row = 0, column = 0, cells = [], canvas = "table", bg = None, fg = None, redraw = False, overwrite = True)
- Setting
overwrite
toFalse
allows a previously setfg
to be kept while setting a newbg
or vice versa.
dehighlight_cells(row = 0, column = 0, cells = [], canvas = "table", all_ = False, redraw = True)
get_highlighted_cells(canvas = "table")
highlight_rows(rows = [], bg = None, fg = None, highlight_index = True, redraw = False, end_of_screen = False, overwrite = True)
end_of_screen
whenTrue
makes the row highlight go past the last column line if there is any room there.- Setting
overwrite
toFalse
allows a previously setfg
to be kept while setting a newbg
or vice versa.
highlight_columns(columns = [], bg = None, fg = None, highlight_header = True, redraw = False, overwrite = True)
- Setting
overwrite
toFalse
allows a previously setfg
to be kept while setting a newbg
or vice versa.
dehighlight_all()
dehighlight_rows(rows = [], redraw = False)
dehighlight_columns(columns = [], redraw = False)
newfont
arguments require a three tuple e.g.("Arial", 12, "normal")
align
arguments (str
) options arew
,e
orcenter
.
font(newfont = None, reset_row_positions = True)
header_font(newfont = None)
align(align = None, redraw = True)
header_align(align = None, redraw = True)
row_index_align(align = None, redraw = True)
Change the text alignment for specific rows, "global"
resets to table setting.
align_rows(rows = [], align = "global", align_index = False, redraw = True)
Change the text alignment for specific columns, "global"
resets to table setting.
align_columns(columns = [], align = "global", align_header = False, redraw = True)
Change the text alignment for specific cells inside the table, "global"
resets to table setting.
align_cells(row = 0, column = 0, cells = [], align = "global", redraw = True)
Change the text alignment for specific cells inside the header, "global"
resets to header setting.
align_header(columns = [], align = "global", redraw = True)
Change the text alignment for specific cells inside the index, "global"
resets to index setting.
align_index(rows = [], align = "global", redraw = True)
Set default column width in pixels.
default_column_width(width = None)
width
(int
).
Set default row height in pixels or lines.
default_row_height(height = None)
height
(int
,str
) use a numericalstr
for number of lines e.g."3"
for a height that fits 3 lines orint
for pixels.
Set default header bar height in pixels or lines.
default_header_height(height = None)
height
(int
,str
) use a numericalstr
for number of lines e.g."3"
for a height that fits 3 lines orint
for pixels.
Set a specific cell size to its text
set_cell_size_to_text(row, column, only_set_if_too_small = False, redraw = True)
Set all row heights and column widths to cell text sizes.
set_all_cell_sizes_to_text(redraw = True)
Get the sheets column widths.
get_column_widths(canvas_positions = False)
canvas_positions
(bool
) gets the actual canvas x coordinates of column lines.
Get the sheets row heights.
get_row_heights(canvas_positions = False)
canvas_positions
(bool
) gets the actual canvas y coordinates of row lines.
Set all column widths to specific width
in pixels (int
) or leave None
to set to cell text sizes for each column.
set_all_column_widths(width = None, only_set_if_too_small = False, redraw = True, recreate_selection_boxes = True)
Set all row heights to specific height
in pixels (int
) or leave None
to set to cell text sizes for each row.
set_all_row_heights(height = None, only_set_if_too_small = False, redraw = True, recreate_selection_boxes = True)
Set a specific column width.
column_width(column = None, width = None, only_set_if_too_small = False, redraw = True)
set_column_widths(column_widths = None, canvas_positions = False, reset = False, verify = False)
set_width_of_index_to_text(recreate = True)
row_height(row = None, height = None, only_set_if_too_small = False, redraw = True)
set_row_heights(row_heights = None, canvas_positions = False, reset = False, verify = False)
delete_row_position(idx, deselect_all = False)
insert_row_position(idx = "end", height = None, deselect_all = False, redraw = False)
insert_row_positions(idx = "end", heights = None, deselect_all = False, redraw = False)
sheet_display_dimensions(total_rows = None, total_columns = None)
move_row_position(row, moveto)
delete_column_position(idx, deselect_all = False)
insert_column_position(idx = "end", width = None, deselect_all = False, redraw = False)
insert_column_positions(idx = "end", widths = None, deselect_all = False, redraw = False)
move_column_position(column, moveto)
get_example_canvas_column_widths(total_cols = None)
get_example_canvas_row_heights(total_rows = None)
verify_row_heights(row_heights, canvas_positions = False)
verify_column_widths(column_widths, canvas_positions = False)
get_currently_selected(get_coords = False, return_nones_if_not = False)
get_selected_rows(get_cells = False, get_cells_as_rows = False, return_tuple = False)
get_selected_columns(get_cells = False, get_cells_as_columns = False, return_tuple = False)
get_selected_cells(get_rows = False, get_columns = False, sort_by_row = False, sort_by_column = False)
get_all_selection_boxes()
get_all_selection_boxes_with_types()
Check if cell is selected, returns bool
.
cell_selected(r, c)
Check if row is selected, returns bool
.
row_selected(r)
Check if column is selected, returns bool
.
column_selected(c)
Check if any cells, rows or columns are selected, there are options for exclusions, returns bool
.
anything_selected(exclude_columns = False, exclude_rows = False, exclude_cells = False)
Check if user has entire table selected, returns bool
.
all_selected()
get_ctrl_x_c_boxes()
get_selected_min_max()
- returns
(min_y, min_x, max_y, max_x)
of any selections including rows/columns.
set_currently_selected(current_tuple_0 = 0, current_tuple_1 = 0, selection_binding = True)
select_row(row, redraw = True)
select_column(column, redraw = True)
select_cell(row, column, redraw = True)
select_all(redraw = True, run_binding_func = True)
move_down()
add_cell_selection(row, column, redraw = True, run_binding_func = True, set_as_current = True)
add_row_selection(row, redraw = True, run_binding_func = True, set_as_current = True)
add_column_selection(column, redraw = True, run_binding_func = True, set_as_current = True)
toggle_select_cell(row, column, add_selection = True, redraw = True, run_binding_func = True, set_as_current = True)
toggle_select_row(row, add_selection = True, redraw = True, run_binding_func = True, set_as_current = True)
toggle_select_column(column, add_selection = True, redraw = True, run_binding_func = True, set_as_current = True)
create_selection_box(r1, c1, r2, c2, type_ = "cells")
recreate_all_selection_boxes()
deselect(row = None, column = None, cell = None, redraw = True)
see(row = 0, column = 0, keep_yscroll = False, keep_xscroll = False, bottom_right_corner = False, check_cell_visibility = True)
set_xview(position, option = "moveto")
set_yview(position, option = "moveto")
get_xview()
get_yview()
set_view(x_args, y_args)
move_down()
readonly_rows(rows = [], readonly = True, redraw = True)
readonly_columns(columns = [], readonly = True, redraw = True)
readonly_cells(row = 0, column = 0, cells = [], readonly = True, redraw = True)
readonly_header(columns = [], readonly = True, redraw = True)
Display only certain columns.
display_columns(indexes = None,
enable = None,
reset_col_positions = True,
set_col_positions = True,
refresh = False,
redraw = False,
deselect_all = True)
- If the chosen indexes are equal to a list of columns as long as the longest row in the sheets data then enable will be set to
False
.
Hide parts of the table or all of it
hide(canvas = "all")
canvas
(str
) options areall
,row_index
,header
,top_left
,x_scrollbar
,y_scrollbar
all
hides the entire table and is the default.
Show parts of the table or all of it
show(canvas = "all")
canvas
(str
) options areall
,row_index
,header
,top_left
,x_scrollbar
,y_scrollbar
all
shows the entire table and is the default.
create_text_editor(row = 0, column = 0, text = None, state = "normal", see = True, set_data_ref_on_destroy = False,
binding = None)
set_text_editor_value(text = "", r = None, c = None)
bind_text_editor_set(func, row, column)
get_text_editor_value(destroy_tup = None, r = None, c = None, set_data_ref_on_destroy = True, event = None, destroy = True, move_down = True, redraw = True, recreate = True)
destroy_text_editor(event = None)
get_text_editor_widget(event = None)
bind_key_text_editor(key, function)
unbind_key_text_editor(key)
Create a dropdown box (only creates the arrow and border and sets it up for usage, does not pop open the box).
def create_dropdown(r = 0,
c = 0,
values = [],
set_value = None,
state = "readonly",
redraw = False,
selection_function = None,
modified_function = None)
def create_header_dropdown(c = 0,
values = [],
set_value = None,
state = "readonly",
redraw = False,
selection_function = None,
modified_function = None)
Notes:
- When a user selects an item from the dropdown box the sheet will set the underlying cells data to the selected item, to bind this event use either the
selection_function
argument or see the functionextra_bindings()
with binding"end_edit_cell"
here.
Arguments:
- Set first argument to
"all"
to create a full column (in the main table) or a full header of dropdown boxes. values
are the values to appear when the dropdown box is popped open.state
determines whether or not there is also an editable text window at the top of the dropdown box when it is open.redraw
refreshes the sheet so the newly created box is visible.selection_function
can be used to trigger a specific function when an item from the dropdown box is selected, if you are using the aboveextra_bindings()
as well it will also be triggered but after this function. e.g.selection_function = my_function_name
modified_function
can be used to trigger a specific function when thestate
of the box is set to"normal"
and there is an editable text window and a change of the text in that window has occurred.
Get chosen dropdown boxes values.
get_dropdown_values(r = 0, c = 0)
get_header_dropdown_values(c = 0)
Set the values and displayed value of a chosen dropdown box.
set_dropdown_values(r = 0, c = 0, set_existing_dropdown = False, values = [], displayed = None)
set_header_dropdown_values(c = 0, set_existing_dropdown = False, values = [], displayed = None)
set_existing_dropdown
ifTrue
takes priority overr
andc
and sets the values of the last popped open dropdown box (if one one is popped open, if not then anException
is raised).values
(list
,tuple
)displayed
(str
,None
) if notNone
will try to set the displayed value of the chosen dropdown box to given argument.
Set and get bound dropdown functions.
dropdown_functions(r, c, selection_function = "", modified_function = "")
header_dropdown_functions(c, selection_function = "", modified_function = "")
Delete dropdown boxes.
delete_dropdown(r = 0, c = 0)
delete_header_dropdown(c = 0)
- Set first argument to
"all"
to delete all dropdown boxes on the sheet.
Get a dictionary of all dropdown boxes; keys: (row int, column int)
and values: (ttk combobox widget, tk canvas window object)
get_dropdowns()
get_header_dropdowns()
Pop open a dropdown box.
open_dropdown(r, c)
open_header_dropdown(c)
Close an already open dropdown box.
close_dropdown(r, c)
close_header_dropdown(c)
- Also destroys any opened text editor windows.
Create a check box.
create_checkbox(r,
c,
checked = False,
state = "normal",
redraw = False,
check_function = None,
text = "")
create_header_checkbox(c,
checked = False,
state = "normal",
redraw = False,
check_function = None,
text = "")
Notes:
- Use
highlight_cells()
or rows or columns to change the color of the checkbox. - Check boxes are always left aligned despite any align settings.
Arguments:
- Set first argument to
"all"
to create a full column (in the main table) or a full header of checkboxes. text
displays text next to the checkbox in the cell, but will not be used as data, data will either beTrue
orFalse
check_function
can be used to trigger a function when the user clicks a checkbox.state
can be"normal"
or"disabled"
. If"disabled"
then color will be same as table grid lines, else it will be the cells text color.
Set or toggle a checkbox.
click_checkbox(r, c, checked = None)
click_header_checkbox(c, checked = None)
Get a dictionary of all check box dictionaries.
get_checkboxes()
get_header_checkboxes()
Delete a checkbox.
delete_checkbox(r = 0, c = 0)
delete_header_checkbox(c = 0)
- Set first argument to
"all"
to delete all check boxes.
Set or get information about a particular checkbox.
checkbox(r,
c,
checked = None,
state = None,
check_function = "",
text = None)
checkbox(c,
checked = None,
state = None,
check_function = "",
text = None)
- If any arguments are not default they will be set for the chosen checkbox.
- If all arguments are default a dictionary of all the checkboxes information will be returned.
def set_options(
show_default_header_for_empty = None,
enable_edit_cell_auto_resize = None,
selected_rows_to_end_of_window = None,
horizontal_grid_to_end_of_window = None,
vertical_grid_to_end_of_window = None,
page_up_down_select_row = None,
expand_sheet_if_paste_too_big = None,
paste_insert_column_limit = None,
paste_insert_row_limit = None,
ctrl_keys_over_dropdowns_enabled = None,
arrow_key_down_right_scroll_page = None,
display_selected_fg_over_highlights = None,
empty_horizontal = None,
empty_vertical = None,
show_horizontal_grid = None,
show_vertical_grid = None,
top_left_fg_highlight = None,
auto_resize_default_row_index = None,
font = None,
default_header = None,
default_row_index = None,
header_font = None,
show_selected_cells_border = None,
theme = None,
max_colwidth = None,
max_row_height = None,
max_header_height = None,
max_row_width = None,
header_height = None,
row_height = None,
column_width = None,
header_bg = None,
header_border_fg = None,
header_grid_fg = None,
header_fg = None,
header_selected_cells_bg = None,
header_selected_cells_fg = None,
header_hidden_columns_expander_bg = None,
index_bg = None,
index_border_fg = None,
index_grid_fg = None,
index_fg = None,
index_selected_cells_bg = None,
index_selected_cells_fg = None,
index_hidden_rows_expander_bg = None,
top_left_bg = None,
top_left_fg = None,
frame_bg = None,
table_bg = None,
table_grid_fg = None,
table_fg = None,
table_selected_cells_border_fg = None,
table_selected_cells_bg = None,
table_selected_cells_fg = None,
resizing_line_fg = None,
drag_and_drop_bg = None,
outline_thickness = None,
outline_color = None,
header_selected_columns_bg = None,
header_selected_columns_fg = None,
index_selected_rows_bg = None,
index_selected_rows_fg = None,
table_selected_rows_border_fg = None,
table_selected_rows_bg = None,
table_selected_rows_fg = None,
table_selected_columns_border_fg = None,
table_selected_columns_bg = None,
table_selected_columns_fg = None,
popup_menu_font = None,
popup_menu_fg = None,
popup_menu_bg = None,
popup_menu_highlight_bg = None,
popup_menu_highlight_fg = None,
row_drag_and_drop_perform = None,
column_drag_and_drop_perform = None,
redraw = True)
Get internal storage dictionary of highlights, readonly cells, dropdowns etc.
get_cell_options(canvas = "table")
get_frame_y(y)
get_frame_x(x)
Flash a dashed box of chosen dimensions.
show_ctrl_outline(canvas = "table", start_cell = (0, 0), end_cell = (1, 1))
Reset table undo storage.
reset_undos()
Refresh the table.
redraw(redraw_header = True, redraw_row_index = True)
Refresh the table.
refresh(redraw_header = True, redraw_row_index = True)
Using pandas
library, requires additional libraries:
pandas
openpyxl
from tksheet import Sheet
import tkinter as tk
import pandas as pd
class demo(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.grid_columnconfigure(0, weight = 1)
self.grid_rowconfigure(0, weight = 1)
self.frame = tk.Frame(self)
self.frame.grid_columnconfigure(0, weight = 1)
self.frame.grid_rowconfigure(0, weight = 1)
self.sheet = Sheet(self.frame,
data = pd.read_excel("excel_file.xlsx", # filepath here
#sheet_name = "sheet1", # optional sheet name here
engine = "openpyxl",
header = None).values.tolist())
self.sheet.enable_bindings()
self.frame.grid(row = 0, column = 0, sticky = "nswe")
self.sheet.grid(row = 0, column = 0, sticky = "nswe")
app = demo()
app.mainloop()
This is to demonstrate adding your own commands to the in-built right click popup menu (or how you might start making your own right click menu functionality) and also creating a cell text editor the manual way.
from tksheet import Sheet
import tkinter as tk
class demo(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.grid_columnconfigure(0, weight = 1)
self.grid_rowconfigure(0, weight = 1)
self.frame = tk.Frame(self)
self.frame.grid_columnconfigure(0, weight = 1)
self.frame.grid_rowconfigure(0, weight = 1)
self.sheet = Sheet(self.frame,
data = [[f"Row {r}, Column {c}\nnewline1\nnewline2" for c in range(50)] for r in range(500)])
self.sheet.enable_bindings("single_select",
"drag_select",
"select_all",
"column_select",
"row_select",
"column_width_resize",
"double_click_column_resize",
"arrowkeys",
"row_height_resize",
"double_click_row_resize",
"right_click_popup_menu",
"rc_select")
self.sheet.popup_menu_add_command("Say Hello", self.new_right_click_button)
self.sheet.popup_menu_add_command("Edit Cell", self.edit_cell, index_menu = False, header_menu = False)
self.frame.grid(row = 0, column = 0, sticky = "nswe")
self.sheet.grid(row = 0, column = 0, sticky = "nswe")
def new_right_click_button(self, event = None):
print ("Hello World!")
def edit_cell(self, event = None):
r, c = self.sheet.get_currently_selected()
self.sheet.row_height(row = r, height = "text", only_set_if_too_small = True, redraw = False)
self.sheet.column_width(column = c, width = "text", only_set_if_too_small = True, redraw = True)
self.sheet.create_text_editor(row = r,
column = c,
text = self.sheet.get_cell_data(r, c),
set_data_ref_on_destroy = False,
binding = self.end_edit_cell)
def end_edit_cell(self, event = None):
newtext = self.sheet.get_text_editor_value(event,
r = event[0],
c = event[1],
set_data_ref_on_destroy = True,
move_down = True,
redraw = True,
recreate = True)
print (newtext)
app = demo()
app.mainloop()
- If you want to evaluate the value from the text editor you can set
set_data_ref_on_destroy
toFalse
and do the evaluation to decide whether or not to useset_cell_data()
. - If you want a totally new right click menu you can use
self.sheet.bind("<3>", <function>)
with atk.Menu
of your own design (right click is<2>
on MacOS) and don't use"right_click_popup_menu"
withenable_bindings()
.
This is to demonstrate displaying what the user has selected in the sheet.
from tksheet import Sheet
import tkinter as tk
class demo(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.grid_columnconfigure(0, weight = 1)
self.grid_rowconfigure(0, weight = 1)
self.frame = tk.Frame(self)
self.frame.grid_columnconfigure(0, weight = 1)
self.frame.grid_rowconfigure(0, weight = 1)
self.sheet = Sheet(self.frame,
data = [[f"Row {r}, Column {c}\nnewline1\nnewline2" for c in range(50)] for r in range(500)])
self.sheet.enable_bindings()
self.sheet.extra_bindings([("all_select_events", self.sheet_select_event)])
self.show_selections = tk.Label(self)
self.frame.grid(row = 0, column = 0, sticky = "nswe")
self.sheet.grid(row = 0, column = 0, sticky = "nswe")
self.show_selections.grid(row = 1, column = 0, sticky = "nswe")
def sheet_select_event(self, event = None):
try:
len(event)
except:
return
try:
if event[0] == "select_cell":
self.show_selections.config(text = f"Cells: ({event[1] + 1},{event[2] + 1}) : ({event[1] + 1},{event[2] + 1})")
elif "cells" in event[0]:
self.show_selections.config(text = f"Cells: ({event[1] + 1},{event[2] + 1}) : ({event[3] + 1},{event[4]})")
elif event[0] == "select_column":
self.show_selections.config(text = f"Columns: {event[1] + 1} : {event[1] + 1}")
elif "columns" in event[0]:
self.show_selections.config(text = f"Columns: {event[1][0] + 1} : {event[1][-1] + 1}")
elif event[0] == "select_row":
self.show_selections.config(text = f"Rows: {event[1] + 1} : {event[1] + 1}")
elif "rows" in event[0]:
self.show_selections.config(text = f"Rows: {event[1][0] + 1} : {event[1][-1] + 1}")
else:
self.show_selections.config(text = "")
except:
self.show_selections.config(text = "")
app = demo()
app.mainloop()
This is to demonstrate some simple customization to make a different sort of widget (a list box).
from tksheet import Sheet
import tkinter as tk
class Sheet_Listbox(Sheet):
def __init__(self,
parent,
values = []):
Sheet.__init__(self,
parent = parent,
show_horizontal_grid = False,
show_vertical_grid = False,
show_header = False,
show_row_index = False,
show_top_left = False,
empty_horizontal = 0,
empty_vertical = 0)
if values:
self.values(values)
def values(self, values = []):
self.set_sheet_data([[v] for v in values],
reset_col_positions = False,
reset_row_positions = False,
redraw = False,
verify = False)
self.set_all_cell_sizes_to_text()
class demo(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.grid_columnconfigure(0,
weight = 1)
self.grid_rowconfigure(0,
weight = 1)
self.listbox = Sheet_Listbox(self,
values = [f"_________ Item {i} _________" for i in range(2000)])
self.listbox.grid(row = 0,
column = 0,
sticky = "nswe")
#self.listbox.values([f"new values {i}" for i in range(50)]) set values
app = demo()
app.mainloop()
A very simple demonstration of row filtering using header dropdown boxes.
from tksheet import Sheet
import tkinter as tk
class demo(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.grid_columnconfigure(0, weight = 1)
self.grid_rowconfigure(0, weight = 1)
self.frame = tk.Frame(self)
self.frame.grid_columnconfigure(0, weight = 1)
self.frame.grid_rowconfigure(0, weight = 1)
self.data = ([["3", "c", "z"],
["1", "a", "x"],
["1", "b", "y"],
["2", "b", "y"],
["2", "c", "z"]])
self.sheet = Sheet(self.frame,
data = self.data,
theme = "dark",
height = 700,
width = 1100)
self.sheet.enable_bindings("copy",
"rc_select",
"arrowkeys",
"double_click_column_resize",
"column_width_resize",
"column_select",
"row_select",
"drag_select",
"single_select",
"select_all")
self.frame.grid(row = 0, column = 0, sticky = "nswe")
self.sheet.grid(row = 0, column = 0, sticky = "nswe")
self.sheet.create_header_dropdown(c = 0,
values = ["all", "1", "2", "3"],
set_value = "all",
selection_function = self.header_dropdown_selected)
self.sheet.create_header_dropdown(c = 1,
values = ["all", "a", "b", "c"],
set_value = "all",
selection_function = self.header_dropdown_selected)
self.sheet.create_header_dropdown(c = 2,
values = ["all", "x", "y", "z"],
set_value = "all",
selection_function = self.header_dropdown_selected)
def header_dropdown_selected(self, event = None):
hdrs = self.sheet.headers()
# this function is run before header cell data is set by dropdown selection
# so we have to get the new value from the event
hdrs[event.column] = event.text
if all(dd == "all" for dd in hdrs):
self.sheet.set_sheet_data(self.data,
reset_col_positions = False,
reset_row_positions = False)
else:
self.sheet.set_sheet_data([row for row in self.data if all(row[c] == e or e == "all" for c, e in enumerate(hdrs))],
reset_col_positions = False,
reset_row_positions = False)
app = demo()
app.mainloop()
The code used to make a screenshot for the readme file.
from tksheet import Sheet
import tkinter as tk
class demo(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.grid_columnconfigure(0, weight = 1)
self.grid_rowconfigure(0, weight = 1)
self.frame = tk.Frame(self)
self.frame.grid_columnconfigure(0, weight = 1)
self.frame.grid_rowconfigure(0, weight = 1)
self.sheet = Sheet(self.frame,
expand_sheet_if_paste_too_big = True,
empty_horizontal = 0,
empty_vertical = 0,
align = "w",
header_align = "c",
data = [[f"Row {r}, Column {c}\nnewline 1\nnewline 2" for c in range(6)] for r in range(21)],
headers = ["Dropdown Column", "Checkbox Column", "Center Aligned Column", "East Aligned Column", "", ""],
theme = "dark",
height = 520,
width = 930)
self.sheet.enable_bindings()
self.sheet.enable_bindings("edit_header")
self.frame.grid(row = 0, column = 0, sticky = "nswe")
self.sheet.grid(row = 0, column = 0, sticky = "nswe")
colors = ("#509f56",
"#64a85b",
"#78b160",
"#8cba66",
"#a0c36c",
"#b4cc71",
"#c8d576",
"#dcde7c",
"#f0e782",
"#ffec87",
"#ffe182",
"#ffdc7d",
"#ffd77b",
"#ffc873",
"#ffb469",
"#fea05f",
"#fc8c55",
"#fb784b",
"#fa6441",
"#f85037")
self.sheet.align_columns(columns = 2, align = "c")
self.sheet.align_columns(columns = 3, align = "e")
self.sheet.create_dropdown(r = "all",
c = 0,
values = ["Dropdown"] + [f"{i}" for i in range(15)])
self.sheet.create_checkbox(r = "all", c = 1, checked = True, text = "Checkbox")
self.sheet.create_header_dropdown(c = 0, values = ["Header Dropdown"] + [f"{i}" for i in range(15)])
self.sheet.create_header_checkbox(c = 1, checked = True, text = "Header Checkbox")
self.sheet.align_cells(5, 0, align = "c")
self.sheet.highlight_cells(5, 0, bg = "gray50", fg = "blue")
self.sheet.highlight_cells(17, canvas = "index", bg = "yellow", fg = "black")
self.sheet.highlight_cells(12, 1, bg = "gray90", fg = "purple")
for r in range(len(colors)):
self.sheet.highlight_cells(row = r,
column = 3,
fg = colors[r])
self.sheet.highlight_cells(row = r,
column = 4,
bg = colors[r],
fg = "black")
self.sheet.highlight_cells(row = r,
column = 5,
bg = colors[r],
fg = "purple")
self.sheet.highlight_cells(column = 5,
canvas = "header",
bg = "white",
fg = "purple")
#self.sheet.display_columns(indexes = [0, 1, 2], enable = True)
self.sheet.set_all_column_widths()
self.sheet.extra_bindings("all", self.all_extra_bindings)
def all_extra_bindings(self, event = None):
#print (event)
pass
app = demo()
app.mainloop()