一、文件拆分
1.1 需求逻辑
选择需要拆分的excel文件(.xls格式),按照以下规则生成子Excel
- 第一个sheet复制到每一个子Excel的第一个sheet
- 第二个sheet将按照输入的拆分行数:num,将该sheet中的所有数据分批写入到子sheet,每个子sheet有num行数据(第一行为表头,复制到每个子Excel)
- 例:若该sheet有11行数据,拆分行数为 num = 3,那么子Excel将会生成 10/3=4 个(向上取整),第一个子Excel的数据是原表的第1行到第3行。第二个子Excel的数据是原表的第4行到第6行。第三个子Excel的数据是原表的第7行到第9行。第四个子Excel的数据是原表的第10行到第11行
1.2 编写代码
1.2.1 安装依赖
pip install tkinter -i https://mirrors.aliyun.com/pypi/simple/
pip install xlrd -i https://mirrors.aliyun.com/pypi/simple/
pip install xlwt -i https://mirrors.aliyun.com/pypi/simple/
1.2.2 源代码
window.py
from tkinter import Button
from tkinter.filedialog import askopenfilename, askdirectory
import tkinter as tk
import xlrd
import xlwt
import math
import os
# 注册窗口
win = tk.Tk()
win.title('拆分Excel')
win.geometry('580x220')
win.resizable(0, 0)
# 打开文件函数
def openFile():
filepath = askopenfilename() # 选择打开什么文件,返回文件名
if filepath.strip() != '':
filename.set(filepath) # 设置变量filename的值
else:
print("do not choose file")
# 打开文件夹函数
def openDir():
fileDir = askdirectory() # 选择目录,返回目录名
if fileDir.strip() != '':
dirpath.set(fileDir) # 设置变量outputpath的值
else:
print("do not choose Dir")
# 拆分主逻辑
def split_main(source_path, target_path, split_num):
try:
# 读取表
try:
wb = xlrd.open_workbook(source_path)
except(FileNotFoundError,):
return False, "文件不存在"
if not os.path.exists(target_path):
return False, "目标路径不存在"
# 获取表名
excel_name = os.path.basename(source_path).split(".")[0]
print(f"当前表的名称为:{excel_name}")
# 获取所有的sheet名
sheet_names = wb.sheet_names()
# 定义拆分结果
flag = False
msg = "文件拆分成功"
# 计算需要生成的excel数量
nrows = wb.sheets()[1].nrows
try:
if int(split_num) < 0:
raise ValueError
excel_num = math.ceil(nrows / int(split_num))
except(TypeError, ValueError):
flag = False
msg = "请输入正确的拆分行数"
return flag, msg
print(f"当前需要生成的excel的数量为{excel_num}")
for i in range(excel_num):
# 生成excel
new_wb = xlwt.Workbook()
# 一、处理第一个sheet:不拆分
old_sheet0 = wb.sheets()[0]
new_sheet0 = new_wb.add_sheet(sheet_names[0])
# 开始复制
for j in range(old_sheet0.nrows):
# 单行所有数据
row_list = old_sheet0.row_values(j)
# 按列循环
for k in range(old_sheet0.ncols):
# 写入数据:write(行数,列数,数据)
new_sheet0.write(j, k, row_list[k])
# 二、处理第二个sheet
old_sheet1 = wb.sheets()[1]
new_sheet1 = new_wb.add_sheet(sheet_names[1])
# 表头不动
head_list = old_sheet1.row_values(0)
for j in range(old_sheet1.ncols):
new_sheet1.write(0, j, head_list[j])
# 开始处理表体
for j in range(i * int(split_num) + 1, (i + 1) * int(split_num) + 1):
# 如果实际的行数小于当前处理的行,结束循环
if nrows == j:
break
# 单行所有数据
row_list = old_sheet1.row_values(j)
# 按列循环
for k in range(old_sheet1.ncols):
# 写入数据:write(行数,列数,数据)
if j % int(split_num) == 0:
r = int(split_num)
else:
r = j % int(split_num)
new_sheet1.write(r, k, row_list[k])
# 生成excel
sub_file = f"{target_path}\{excel_name}{i}.xls"
print(f"生成Excel路径:{sub_file}")
new_wb.save(sub_file)
return True, msg
except(Exception,):
return False, Exception
# 源文件
filename = tk.StringVar()
tk.Label(win, text='选择文件:').grid(row=1, column=0, padx=5, pady=5)
tk.Entry(win, textvariable=filename, width=60).grid(row=1, column=1, padx=5, pady=5)
tk.Button(win, text='打开文件', command=openFile).grid(row=1, column=2, padx=5, pady=5)
# 拆分行数
num = tk.StringVar()
tk.Label(text='拆分行数:').grid(row=2, column=0, padx=5, pady=5)
tk.Entry(win, textvariable=num, width=60).grid(row=2, column=1, padx=5, pady=5)
# 目标路径
dirpath = tk.StringVar()
tk.Label(text='输出路径:').grid(row=3, column=0, padx=5, pady=5)
tk.Entry(win, textvariable=dirpath, width=60).grid(row=3, column=1, padx=5, pady=5) # 创建Entry,显示选择的目录
tk.Button(win, text='打开目录', command=openDir).grid(row=3, column=2, padx=5, pady=5) # 创建一个Button,点击弹出打开目录窗口
# 结果反馈窗口:
def prompt(flag, msg):
popup = tk.Toplevel(win)
popup.geometry('300x200+840+300')
if flag:
popup.title("拆分成功!")
# 在子窗口中添加文字
label = tk.Label(popup, text="拆分成功!")
label.pack(pady=10)
else:
popup.title("拆分失败!")
label = tk.Label(popup, text=msg)
label.pack(pady=10)
# 在子窗口中添加按钮
tk.Button(popup, text="关闭", command=popup.destroy).place(x=125, y=135, width=50, height=30)
# 拆分按钮
def split():
source_path = None
target_path = None
split_num = None
# 拆分结果信息
flag = False
msg = ""
if filename.get() != None and filename.get() != "":
source_path = filename.get()
else:
flag = False
msg = "源文件路径为空"
if num.get() != None and num.get() != "":
split_num = num.get()
else:
flag = False
msg += "\n拆分行数为空"
if dirpath.get() != None and dirpath.get() != "":
target_path = dirpath.get()
else:
flag = False
msg += "\n目录路径为空"
if filename.get() != None and filename.get() != "" and num.get() != None and num.get() != "" and dirpath.get() != None and dirpath.get() != "":
print(f"源文件路径:{source_path},目录路径:{target_path},拆分行数:{split_num}")
flag, msg = split_main(source_path, target_path, split_num)
prompt(flag, msg)
Button(text='开始拆分', command=split).place(x=250, y=180, width=100, height=30)
win.mainloop()
1.3 打包EXE程序
注意:当前打包方法仅限于打一个.py文件,有依赖关系的其他.py文件无法打包进来
pip install Pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple
移动到需要打包成exe的.py路径下
执行打包命令
Pyinstaller -F -w 文件名.py
等待打包成功
打包完成的文件路径在.py同路径的dist下