初始化

This commit is contained in:
wangdan 2021-11-29 18:19:58 +08:00
parent 2395a69fcf
commit 01909ed49f
3 changed files with 639 additions and 0 deletions

136
compare.py Normal file
View File

@ -0,0 +1,136 @@
# -*- coding:utf-8 -*-
################################
# excel 表格对比
#
################################
import os
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog, dialog
class CompareData:
pass
class CompareFormat:
pass
class MainView:
def __init__(self, root: tk.Frame):
self.__root: tk.Frame = root
self.__select_template_file_mess: tk.StringVar = tk.StringVar()
self.__select_template_file_mess.set('请选择模版文件')
self.__template_file_name: tk.StringVar = tk.StringVar()
self.__template_file_name.set('')
self.__select_compare_file_mess: tk.StringVar = tk.StringVar()
self.__select_compare_file_mess.set('请选择对比文件')
self.__compare_file_name: tk.StringVar = tk.StringVar()
self.__compare_file_name.set('')
self.__conf_type: tk.IntVar = tk.IntVar() # 配置方式
self.__progress: tk.IntVar = tk.IntVar()
self.__progress.set(20)
def create_windows(self):
template_f = tk.Frame(self.__root, bg='gainsboro')
template_f.rowconfigure(0, weight=1)
template_f.columnconfigure(0, weight=1)
template_f.grid(row=0, column=0, padx=5, pady=5, sticky=tk.NW)
compare_f = tk.Frame(self.__root, bg='gainsboro')
compare_f.rowconfigure(0, weight=1)
compare_f.columnconfigure(0, weight=1)
compare_f.grid(row=1, column=0, padx=5, pady=5, sticky=tk.NW)
compare_type_f = tk.Frame(self.__root, bd=1, height=50)
compare_type_f.grid(row=2, column=0, padx=5, pady=5, sticky=tk.NW)
start_f = tk.Frame(self.__root, bd=1, height=50)
start_f.grid(row=3, column=0, padx=5, pady=5, sticky=tk.NW)
scala_f = tk.Frame(self.__root, bd=1, height=50)
scala_f.grid(row=4, column=0, padx=5, pady=5, sticky=tk.NW)
info_f = tk.Label(self.__root, bg='silver', text='自动判断列名并合并相同列数据')
info_f.grid(row=5, column=0, sticky=tk.NSEW)
template_f_select = ttk.Button(template_f, state=tk.NORMAL, text="选择模版文件", command=self.__select_template_file)
template_f_select.grid(row=0, column=0)
template_f_text = ttk.Label(template_f, textvariable=self.__select_template_file_mess)
template_f_text.grid(row=0, column=1)
compare_f_select = ttk.Button(compare_f, text="选择对比文件", command=self.__select_compare_file)
compare_f_select.grid(row=0, column=0)
compare_f_text = ttk.Label(compare_f, textvariable=self.__select_compare_file_mess)
compare_f_text.grid(row=0, column=1)
data_only_rb = ttk.Radiobutton(compare_type_f, variable=self.__conf_type, text='仅对比数据', value=0,
command=self.__conf_type_selection)
data_only_rb.grid(row=0, column=0, padx=5, sticky=tk.W)
format_only_rb = ttk.Radiobutton(compare_type_f, variable=self.__conf_type, text='仅对比格式', value=1,
command=self.__conf_type_selection)
format_only_rb.grid(row=0, column=1, padx=5, sticky=tk.W)
data_format_rb = ttk.Radiobutton(compare_type_f, variable=self.__conf_type, text='对比数据和格式', value=2,
command=self.__conf_type_selection)
data_format_rb.grid(row=0, column=2, padx=5, sticky=tk.W)
start_b = ttk.Button(start_f, state=tk.NORMAL, text="开始", command=self.__start_compare)
start_b.grid(row=0, column=0)
progressbar = ttk.Progressbar(scala_f, length=200, mode="determinate", orient=tk.HORIZONTAL,
variable=self.__progress)
progressbar.grid(row=0, column=0, padx=5, sticky=tk.NSEW)
def __select_template_file(self):
file = filedialog.askopenfilename(title=u'选择文件', initialdir=(os.path.expanduser('~/')),
filetypes=[('Excel xls', '*.xls')])
if len(file) > 0:
self.__select_template_file_mess.set('模版文件:' + file)
else:
self.__select_template_file_mess.set('请选择模版文件')
self.__template_file_name.set(file)
def __select_compare_file(self):
file = filedialog.askopenfilename(title=u'选择文件', initialdir=(os.path.expanduser('~/')),
filetypes=[('Excel xls', '*.xls')])
if len(file) > 0:
self.__select_compare_file_mess.set('对比文件:' + file)
else:
self.__select_compare_file_mess.set('请选择对比文件')
self.__compare_file_name.set(file)
def __conf_type_selection(self):
conf_type = self.__conf_type.get()
if conf_type == 0:
pass
elif conf_type == 1:
pass
elif conf_type == 2:
pass
def __start_compare(self):
pass
def main():
root = tk.Tk()
root.title('Excel 文件对比工具')
root.geometry('720x640')
root.minsize(720, 640)
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
master_frame = tk.Frame(root)
master_frame.grid(row=0, column=0, padx=5, pady=5, sticky=tk.NSEW)
w = MainView(master_frame)
w.create_windows()
root.mainloop()
if __name__ == '__main__':
main()

279
rowspan_alignment.py Normal file
View File

@ -0,0 +1,279 @@
# -*- coding:utf-8 -*-
################################
# excel 表格分级下沉填充
# 任意一个 1 级列的值发生变化,则 2级列停止下沉
# 同理 任意一个 2级列的值发生了变化时 3级列停止下沉以此类推
#
#
#
################################
import os
import sys
import xlrd
import xlwt
from xlutils.copy import copy
import tkinter as tk
from tkinter import filedialog, dialog
import tkinter.messagebox
from tkinter import ttk
file_path = ''
output_file_path = ''
config_str = ''
window = tk.Tk()
root = tk.Frame(window)
root.pack()
progress_scale = tk.Scale()
message_label = tk.Label()
file_path_tk_var = tk.StringVar()
file_path_tk_var.set('点击上面按钮选择文件')
out_file_path_tk_var = tk.StringVar()
out_file_path_tk_var.set('点击上面按钮设置保存位置')
message_tk_var = tk.StringVar()
message_tk_var.set("请选择文件并填写处理规则")
progress = tk.IntVar()
progress.set(0)
def create_file(file_name):
workbook = xlwt.Workbook() # 新建一个工作簿
sheet = workbook.add_sheet('Sheet1')
sheet.write(0, 0, None)
workbook.save(file_name)
def append_write(rows, file_name):
global message_label
message_tk_var.set("正在保存,请稍后...")
message_label.update()
index = len(rows)
workbook = xlrd.open_workbook(file_name)
sheets = workbook.sheet_names()
worksheet = workbook.sheet_by_name(sheets[0])
rows_old = worksheet.nrows
new_workbook = copy(workbook)
new_worksheet = new_workbook.get_sheet(0)
for i in range(0, index):
for j in range(0, len(rows[i])):
new_worksheet.write(i + rows_old, j, rows[i][j])
new_workbook.save(file_name) # 保存工作簿
print("xls格式表格【追加】写入数据成功")
def main():
global output_file_path
global file_path
global config_str
global progress
global message_label
create_file(output_file_path)
wb = xlrd.open_workbook(file_path)
st = wb.sheet_by_index(0)
title = st.row_values(0)
append_write([title], output_file_path)
message_tk_var.set("正在处理数据,请稍后...")
message_label.update()
batch_row = []
tmp_row = [None for _ in range(len(title))]
num_config = config_format()
tmp_array = [None for _ in range(len(num_config))] # [ {A = 1,B = 2},{I = 78},{K = 'ldk'} ]
for i in range(1, st.nrows):
row_v = st.row_values(i)
for step in range(0, len(num_config)): # 先检查缓存是否需要改变
cell = row_v[num_config[step][0]]
if (not (cell is None)) & (len(str(cell)) > 0):
for del_i in range(step, len(num_config)):
tmp_array[del_i] = None
new_dic = {}
for column_num in num_config[step]:
new_dic[column_num] = row_v[column_num]
tmp_array[step] = new_dic
tmp_row = [None for _ in range(len(title))]
for ci in range(0, len(row_v)):
tmp_row[ci] = row_v[ci]
for step in tmp_array:
if step is None:
continue
for k in step.keys():
tmp_row[k] = step[k]
batch_row.append(tmp_row)
if (len(batch_row) >= 100000) | (i == st.nrows - 1):
append_write(batch_row, output_file_path)
batch_row = []
message_tk_var.set("正在处理数据,请稍后...")
message_label.update()
if i % 100 == 0:
progress.set(i / st.nrows * 100)
global progress_scale
progress_scale.update()
tk.messagebox.showinfo(title='处理完成', message='文件保存至\n' + output_file_path)
progress.set(0)
message_tk_var.set("处理完成")
message_label.update()
def config_format():
global config_str
config_array = []
for line in config_str.split('\n'):
if len(line.replace(' ', '')) == 0:
continue
step_array = []
for column_str in line.split(','):
column_str = column_str.replace(' ', '')
if len(column_str) == 0:
continue
step_array.append(column_str)
if len(step_array) > 0:
config_array.append(step_array)
num_config = []
for step in config_array:
num_step = []
for column_name in step:
if len(column_name) == 1:
col = ord(column_name.upper()) - ord('A') + 1
num_step.append(col - 1)
# 输入为AA2类型
elif len(column_name) == 2:
col_1 = ord(column_name[0].upper()) - ord('A') + 1
col_2 = ord(column_name[1].upper()) - ord('A') + 1
col = col_1 * 26 + col_2
num_step.append(col - 1)
num_config.append(num_step)
return num_config
def open_file():
global file_path
file_path = filedialog.askopenfilename(title=u'选择文件', initialdir=(os.path.expanduser('~/')),
filetypes=[('Excel xls', '*.xls')])
if len(file_path) > 0:
file_path_tk_var.set(file_path)
def save_file():
global output_file_path
output_file_path = filedialog.asksaveasfilename(title=u'保存文件')
if len(output_file_path) > 0:
if not str(output_file_path).endswith('.xls'):
output_file_path = output_file_path + '.xls'
out_file_path_tk_var.set(output_file_path)
if __name__ == '__main__':
window.title('Excel 指定列下沉填充')
window.geometry('800x600')
window.minsize(500, 300)
def info():
info = """
excel 表格分级下沉填充
任意一个 1 级列的值发生变化 2级列停止下沉
同理 任意一个 2级列的值发生了变化时 3级列停止下沉以此类推
规则填写方法
在文本框中每一行代表一个等级:如第一行代表等级1第二行代表等级2以此类推
每一行中填写需要下沉填充的列号用逗号隔开 A,B,C,F,AE,AF
原表格结构:
--------------------------------------
A B C D E
1 100
2 45 89
3 iy qq
4 ip ui
--------------------------------------
使用规则
-----------------------
A
B,C
-----------------------
填充后的结果是
--------------------------------------
A B C D E
1 100
2 100 45 89
3 100 45 89 iy qq
4 100 45 89 ip ui
--------------------------------------
"""
tk.messagebox.showinfo(title='使用说明', message=info)
bt0 = ttk.Button(root, text='使用说明', command=info)
bt0.pack()
bt1 = ttk.Button(root, text='打开文件', width=15, command=open_file)
bt1.pack()
file_path_label = tk.Label(root, text='', textvariable=file_path_tk_var, bg='grey', font=('Arial', 12))
file_path_label.pack()
f1 = ttk.Frame(root)
s1 = ttk.Scrollbar(f1, orient=tk.VERTICAL)
s2 = ttk.Scrollbar(f1, orient=tk.HORIZONTAL)
config_label = ttk.Label(f1, text='请输入需要下沉填充的列:列名用逗号隔开,一行表示一个等级')
config_label.pack()
config_text = tk.Text(f1, width=60, highlightthickness=5, highlightbackground='grey', undo=True,
yscrollcommand=s1.set,
xscrollcommand=s2.set,
wrap=tk.NONE)
s1.pack(side=tk.RIGHT, fill=tk.Y)
s1.config(command=config_text.yview)
s2.pack(side=tk.BOTTOM, fill=tk.X)
s2.config(command=config_text.xview)
config_text.pack()
f1.pack()
bt2 = ttk.Button(root, text='保存文件', width=15, command=save_file)
bt2.pack()
out_file_path_label = tk.Label(root, text='', textvariable=out_file_path_tk_var, bg='grey', font=('Arial', 12), )
out_file_path_label.pack()
def start():
global config_str
if len(str(file_path)) < 1:
tk.messagebox.showwarning(title='未选择文件', message='请点击 "打开文件" 按钮选择需要处理的文件')
return
if len(str(output_file_path)) < 1:
tk.messagebox.showwarning(title='未选择输出文件', message='请点击 "保存文件" 按钮选择输出文件')
return
bt3['state'] = tk.DISABLED
try:
config_str = config_text.get("0.0", "end")
try:
main()
except Exception as e:
message_tk_var.set("执行过程出现错误,请重试")
message_label.update()
print(e)
except Exception as e:
message_tk_var.set("列配置填写错误,请检查")
message_label.update()
print(e)
bt3['state'] = tk.NORMAL
bt3 = ttk.Button(root, text='开始处理', command=start)
bt3.pack()
progress_scale = tk.Scale(root, label='进度', from_=0, to=100, orient=tk.HORIZONTAL, length=200, showvalue=0,
tickinterval=20,
variable=progress)
message_label = tk.Label(window, text='', textvariable=message_tk_var, bg='yellow', font=('Arial', 12))
message_label.pack()
progress_scale.pack()
window.mainloop()

224
workbooks_merge.py Normal file
View File

@ -0,0 +1,224 @@
# -*- coding:utf-8 -*-
################################
# excel 表格分级下沉填充
# 任意一个 1 级列的值发生变化,则 2级列停止下沉
# 同理 任意一个 2级列的值发生了变化时 3级列停止下沉以此类推
#
#
#
################################
import os
import sys
import xlrd
import xlwt
from xlutils.copy import copy
import tkinter as tk
from tkinter import filedialog, dialog
import tkinter.messagebox
from tkinter import ttk
class MergeWindows(object):
""" 配置项 key """
INCLUDE_ROW_HEAD = 'include_row_head'
INCLUDE_ROW_TAIL = 'include_row_tail'
INCLUDE_ROW_NAME = 'include_row_name'
INCLUDE_COL_HEAD = 'include_col_head'
INCLUDE_COL_TAIL = 'include_col_tail'
INCLUDE_COL_NAME = 'include_col_name'
EXCLUDE_ROW_HEAD = 'exclude_row_head'
EXCLUDE_ROW_TAIL = 'exclude_row_tail'
EXCLUDE_ROW_NAME = 'exclude_row_name'
EXCLUDE_COL_HEAD = 'exclude_col_head'
EXCLUDE_COL_TAIL = 'exclude_col_tail'
EXCLUDE_COL_NAME = 'exclude_col_name'
def __init__(self, master: tk.Frame = None):
super().__init__()
self.__master: tk.Frame = master
self.__conf_type: tk.IntVar = tk.IntVar() # 配置方式
self.__conf_type.set(0)
self.__f_auto_conf: tk.Frame = tk.Frame()
self.__f_handle_conf: tk.Frame = tk.Frame()
self.__conf_text_widgets: dict[str, tk.Text] = {}
self.__input_files_list: list[str] = []
self.__output_file: str = None
# 显示变量
self.__select_files_mess: tk.StringVar = tk.StringVar()
self.__select_files_mess.set('请选择要合并的文件')
self.__output_file_mess: tk.StringVar = tk.StringVar()
self.__output_file_mess.set('选择输出文件')
def __conf_type_selection(self):
conf_type = self.__conf_type.get()
if conf_type == 0:
self.__f_handle_conf.grid_remove()
self.__f_auto_conf.grid()
elif conf_type == 1:
self.__f_auto_conf.grid_remove()
self.__f_handle_conf.grid()
def __select_files(self):
file_list = filedialog.askopenfilenames(title=u'选择文件', initialdir=(os.path.expanduser('~/')),
filetypes=[('Excel xls', '*.xls')])
if len(file_list) != 0:
self.__select_files_mess.set('选中' + str(len(file_list)) + '个文件')
else:
self.__select_files_mess.set('请选择要合并的文件')
self.__input_files_list = file_list
def __save_file_path(self):
output_file_path = filedialog.asksaveasfilename(title=u'保存文件')
if len(output_file_path) > 0:
if (not str(output_file_path).endswith('.xls')) & (not str(output_file_path).endswith('.xlsx')):
output_file_path = output_file_path + '.xls'
self.__output_file = output_file_path
self.__output_file_mess.set(os.path.split(output_file_path)[1])
def __clear_conf(self):
for w_key in self.__conf_text_widgets.keys():
self.__conf_text_widgets.get(w_key).delete("0.0", "end")
self.__input_files_list = []
self.__output_file = None
self.__select_files_mess.set('请选择要合并的文件')
self.__output_file_mess.set('选择输出文件')
self.__conf_type.set(0)
def __start(self):
if self.__conf_type == 0:
pass
elif self.__conf_type == 1:
pass
def create_windows(self):
self.__widget_row_col_configure(self.__master, {2: 1}, {0: 1})
""" 顶端功能按钮 """
f_info = tk.Frame(self.__master, height=50, bd=1, bg='gainsboro')
f_info.grid(row=0, column=0, padx=5, pady=5, ipadx=2, ipady=2, sticky=tk.NSEW)
""" 文件选择栏 """
f_files = tk.Frame(self.__master, height=100, bd=1, bg='gainsboro')
f_files.grid(row=1, column=0, padx=5, pady=5, sticky=tk.EW)
""" 配置栏 """
f_config = tk.Frame(self.__master, bd=1, bg='gainsboro')
f_config.grid(row=2, column=0, padx=5, pady=5, sticky=tk.NSEW)
f_config.rowconfigure(1, weight=1)
f_config.columnconfigure(0, weight=1)
""" 顶端功能按钮控件布局 """
f_info.columnconfigure(0, weight=1)
l_massage = ttk.Label(f_info, text='请选择文件')
l_massage.grid(row=0, column=0, sticky=tk.EW)
b_start = ttk.Button(f_info, text="开始")
b_start.grid(row=0, column=1, padx=5, sticky=tk.E)
b_cancel = ttk.Button(f_info, text="取消")
b_cancel.grid(row=0, column=2, padx=5, sticky=tk.E)
b_reset = ttk.Button(f_info, text="重置", command=self.__clear_conf)
b_reset.grid(row=0, column=3, padx=5, sticky=tk.E)
b_help = ttk.Button(f_info, text="帮助")
b_help.grid(row=0, column=4, padx=5, sticky=tk.E)
""" 文件选择栏控件布局 """
self.__widget_row_col_configure(f_files, {}, {0: 1, 1: 1})
f_input = tk.Frame(f_files, bg='gainsboro')
f_input.grid(row=0, column=0, sticky=tk.NSEW)
f_output = tk.Frame(f_files, bg='gainsboro')
f_output.grid(row=0, column=1, sticky=tk.NSEW)
b_in_select = ttk.Button(f_input, text="选择要合并的文件", command=self.__select_files)
b_in_select.grid(row=0, column=0)
l_in_select = ttk.Label(f_input, textvariable=self.__select_files_mess)
l_in_select.grid(row=1, column=0)
b_out_select = ttk.Button(f_output, text="选择输出文件", command=self.__save_file_path)
b_out_select.grid(row=0, column=0)
l_out_select = ttk.Label(f_output, textvariable=self.__output_file_mess)
l_out_select.grid(row=1, column=0)
""" 配置规则控件布局 """
self.__f_auto_conf = tk.Frame(f_config, bd=1, bg='silver')
self.__f_auto_conf.grid(row=1, column=0, sticky=tk.NSEW)
self.__f_handle_conf = tk.Frame(f_config, bd=1, bg='silver')
self.__f_handle_conf.grid(row=1, column=0, padx=5, pady=5, sticky=tk.NSEW)
self.__widget_row_col_configure(self.__f_handle_conf, {0: 1}, {0: 1, 1: 1})
self.__f_handle_conf.grid_remove()
f_config_radio = tk.Frame(f_config, bd=1, height=50, bg='silver')
f_config_radio.grid(row=0, column=0, padx=5, pady=5, sticky=tk.NW)
r_auto = ttk.Radiobutton(f_config_radio, variable=self.__conf_type, text='自动合并', value=0,
command=self.__conf_type_selection)
r_auto.grid(row=0, column=0, sticky=tk.W)
r_handle = ttk.Radiobutton(f_config_radio, variable=self.__conf_type, text='手动配置', value=1,
command=self.__conf_type_selection)
r_handle.grid(row=0, column=1, sticky=tk.W)
t_auto_info = tk.Label(self.__f_auto_conf, bg='silver', text='自动判断列名并合并相同列数据')
t_auto_info.grid(row=0, column=0, sticky=tk.NSEW)
# 手动配置框
f_include_conf = tk.LabelFrame(self.__f_handle_conf, text='包含', padx=5, pady=5, bg='silver')
f_include_conf.grid(row=0, column=0, padx=3, pady=3, sticky=tk.NSEW)
self.__widget_row_col_configure(f_include_conf, {2: 1, 4: 1, 6: 1, 10: 1, 12: 1, 14: 1}, {0: 1})
l_include_0 = tk.Label(f_include_conf, text='行设置:(不填写代表包含全部行)', bg='silver')
l_include_0.grid(row=0, column=0, columnspan=2, )
self.__create_text(f_include_conf, self.INCLUDE_ROW_HEAD, '正数第N行', 1, 0)
self.__create_text(f_include_conf, self.INCLUDE_ROW_TAIL, '倒数第N行', 3, 0)
self.__create_text(f_include_conf, self.INCLUDE_ROW_NAME, '行名(取第一列数据作为行名)', 5, 0)
sep_0 = ttk.Separator(f_include_conf, orient='horizontal')
sep_0.grid(row=7, column=0, columnspan=2, padx=5, pady=5, sticky=tk.EW)
l_include_3 = tk.Label(f_include_conf, text='列设置:(不填写代表包含全部列)', bg='silver')
l_include_3.grid(row=8, column=0, columnspan=2)
self.__create_text(f_include_conf, self.INCLUDE_COL_HEAD, '正数第N列', 9, 0)
self.__create_text(f_include_conf, self.INCLUDE_COL_TAIL, '倒数第N列', 11, 0)
self.__create_text(f_include_conf, self.INCLUDE_COL_NAME, '列名(取第一行数据作为列名)', 13, 0)
f_exclude_conf = tk.LabelFrame(self.__f_handle_conf, text='不包含', padx=5, pady=5, bg='silver')
f_exclude_conf.grid(row=0, column=1, padx=3, pady=3, sticky=tk.NSEW)
self.__widget_row_col_configure(f_exclude_conf, {2: 1, 4: 1, 6: 1, 10: 1, 12: 1, 14: 1}, {0: 1})
l_exclude_0 = tk.Label(f_exclude_conf, text='行设置:(不填写代表没有需要排除的行)', bg='silver')
l_exclude_0.grid(row=0, column=0, columnspan=2)
self.__create_text(f_exclude_conf, self.EXCLUDE_ROW_HEAD, '正数第N行', 1, 0)
self.__create_text(f_exclude_conf, self.EXCLUDE_ROW_TAIL, '倒数第N行', 3, 0)
self.__create_text(f_exclude_conf, self.EXCLUDE_ROW_NAME, '行名(取第一列数据作为行名)', 5, 0)
sep_1 = ttk.Separator(f_exclude_conf, orient='horizontal')
sep_1.grid(row=7, column=0, columnspan=2, padx=5, pady=5, sticky=tk.EW)
l_exclude_3 = tk.Label(f_exclude_conf, text='列设置:(不填写代表没有需要排除的列)', bg='silver')
l_exclude_3.grid(row=8, column=0, columnspan=2)
self.__create_text(f_exclude_conf, self.EXCLUDE_COL_HEAD, '正数第N列', 9, 0)
self.__create_text(f_exclude_conf, self.EXCLUDE_COL_TAIL, '倒数第N列', 11, 0)
self.__create_text(f_exclude_conf, self.EXCLUDE_COL_NAME, '列名(取第一行数据作为列名)', 13, 0)
def __widget_row_col_configure(self, root: tk.Widget, rows: dict[int, int], columns: dict[int, int]):
for row in rows.keys():
root.rowconfigure(row, weight=rows[row])
for col in columns.keys():
root.columnconfigure(col, weight=columns[col])
def __create_text(self, root: tk.Widget, name: str, label_text: str, r: int, c: int):
label = tk.Label(root, text=label_text, bg='silver')
label.grid(row=r, column=c, columnspan=2, sticky=tk.W)
scroll_y = ttk.Scrollbar(root, orient=tk.VERTICAL)
text = tk.Text(root, yscrollcommand=scroll_y.set, undo=True, wrap=tk.NONE)
text.grid(row=r + 1, column=c, sticky=tk.NSEW)
scroll_y.grid(row=r + 1, column=c + 1, )
scroll_y.config(command=text.yview)
self.__conf_text_widgets[name] = text
def main():
root = tk.Tk()
root.title('Excel 文件合并工具')
root.geometry('720x640')
root.minsize(720, 640)
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
master_frame = tk.Frame(root)
master_frame.grid(row=0, column=0, padx=5, pady=5, sticky=tk.NSEW)
w = MergeWindows(master_frame)
w.create_windows()
root.mainloop()
if __name__ == '__main__':
main()