python应用

该文章提供了一个使用Python编程来拆分Excel文件的解决方案,主要涉及Tkinter库用于图形界面,xlrd和xlwt库用于读写Excel。程序允许用户指定拆分行数和输出目录,然后将Excel的第一个sheet保持不变,第二个sheet按行拆分。此外,还介绍了如何用PyInstaller将Python脚本打包成可执行的EXE程序。
摘要由CSDN通过智能技术生成

一、文件拆分

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HOJNFYgK-1687501920061)(7、python成果.assets/image-20230623142622960.png)]

移动到需要打包成exe的.py路径下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w92SNC24-1687501920062)(7、python成果.assets/image-20230623142714312.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-grrvhVyf-1687501920063)(7、python成果.assets/image-20230623142841823.png)]

执行打包命令

Pyinstaller -F -w 文件名.py

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RRDh5oq9-1687501920064)(7、python成果.assets/image-20230623142741294.png)]

等待打包成功

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jbq87SdG-1687501920064)(7、python成果.assets/image-20230623142938332.png)]

打包完成的文件路径在.py同路径的dist下

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值