python实现,excel随机抽取特定行到新表中(附上源码和桌面软件)

引言

最近,经常抽查excel表中的一些行,到一个新表中;于是想着写一个程序,自动完成。

功能

基础功能

  • 从原表中随机抽取n行,到一个新表中(可用于老师抽查学生作业,领导抽查核酸(坏笑.jpg))
  • 抽取某行后,将原表中该行背景填充为黄色。每次抽查时,首先判断当前行是否为黄色,若不是,则抽查;若是,则换成下一行;保证了多次抽查,没有重复名单。

基础功能简单,适用于普通用户或者急于使用的用户。只需要原表的路径(注意:是绝对路径,如C:\Users\admin\Desktop\2.xlsx),和要抽取的行数即可,抽取后生成的新表,将会保存在和软件统一目录下。

软件界面如下
python实现,excel随机抽取特定行到新表中(附上源码和桌面软件)_第1张图片
点击确定后,显示导出成功。
python实现,excel随机抽取特定行到新表中(附上源码和桌面软件)_第2张图片
然后,在和软件相同的目录下,找抽查.xlsx,打开即可。

软件下载地址

链接:https://pan.baidu.com/s/1TCePlzptsMwqrCKFT7CVGA 
提取码:zjoy 

拓展功能

代码基本框架已经给出,懂代码的朋友,根据需求酌情修改即可。
如可以实现,多个工作簿的读取,给行填充不同的颜色,随机抽查的算法根据使用场景酌情改进等等。
代码写的有些仓促,有不足或者可以改进的地方,欢迎各位同仁讨论交流。
源码已经给出。

源码

from openpyxl import load_workbook, Workbook
from openpyxl.styles import PatternFill
import random
import sys
import os
import tkinter as tk
import tkinter.messagebox


# 黄色 FFFFFF00
# 粉色 ffc7ce

# 生成随机数,并排序
def gen_random(l, r, cnt):
    a = []
    a = random.sample(range(l, r + 1), cnt)
    a.sort()
    return a


# 随机选取学生的函数, 可以在进一部优化
def gen_random_students(l, r, cnt):
    print(cnt)
    a = random.sample(range(l, (int)(r / 2)), (int)(cnt / 2))
    b = random.sample(range((int)(r / 2), r), cnt - (int)(cnt / 2))
    c = a + b
    c.sort()
    print("生成的随机数:")
    print(c)
    return c


def new_excel(filename, first_row):
    a = Workbook()
    # 获取当前活跃的工作薄
    ws = a.active
    ws.title = "Sheet1"
    # 插入第一行标题
    ws.append(first_row)
    a.save(filename=filename)
    return a

def deal(excel_path, sheet_name, cnt, col_l, col_r, wb2):
    """
    :param excel_path: excel的绝对路径
    :param sheet_name: 工作表名称
    :param cnt: 抽查人数
    :param col_l: 从第几列开始取
    :param col_r: 到第几列结束
    :param wb2: 要保存的新表
    :return:
    """

    # 保存路径
    new_excel_path = os.path.dirname(os.path.realpath(sys.argv[0]))

    # 默认可读写,若有需要可以指定write_only和read_only为True
    wb = load_workbook(excel_path)
    # 根据sheet名字获得sheet
    sheet1 = wb[sheet_name]

    # 获得最大列和最大行
    max_row = sheet1.max_row
    max_col = sheet1.max_column
    print("行数max_row: " + str(max_row))

    if col_r == -1:
        col_r = max_col

    if wb2 == None:
        wb2 = Workbook()
        ws = wb2.active
        ws.title = "Sheet1"
        wb2.save(new_excel_path + "\\" + "抽查.xlsx")

    # 生成随机数,并排序
    res = gen_random_students(2, max_row, cnt)
    # 设置颜色填充,FFFFFF00为填充黄色标准色:00000000
    yellow_fill = PatternFill(fill_type="solid", fgColor="FFFFFF00")

    # 因为按行,所以返回A1, B1, C1这样的顺序
    k = 0
    for i, row in zip(range(1, max_row + 1), sheet1.rows):
        if i == res[k]:
            # 本行不合法,换下一行抽
            if str(row[0].value) == "None" or str(sheet1.cell(row=i, column=1).fill.fgColor.rgb) == "FFFFFF00":
                print(str(i) + "行不合法 " + str(str(row[0].value)) + "  --->换下一行处理")
                res[k] += 1
                continue

            print("i: " + str(i), end="  ")
            print("抽查序号 : " + str(k + 1))
            k += 1

            # 本行不为空,且未被抽过
            list1 = []
            print(str(i), end=" ")
            for j, cell in zip(range(col_l, col_r + 1), row):
                # 当前单元格填充为黄色
                sheet1.cell(row=i, column=j).fill = yellow_fill
                list1.append(str(cell.value))
                print(str(cell.value), end=" ")
            print("")

            # 添加抽到的行,到新表中
            wb2['Sheet1'].append(list1)

            if k == cnt:
                break
            # 保证当遇到抽取的两个数非常近,且之前都被选中的情况
            res[k] = i + 1 if res[k] <= i else res[k]

    # 此处待优化解决
    if k < cnt:
        print("!!!!未抽查够人数")

    # 保存修改
    wb.save(excel_path)
    wb2.save(new_excel_path + "\\" + "抽查.xlsx")
    tk.messagebox.showinfo('提示', '导出完成!')
    pass


def start1(excel_path, check_cnt):
    print(excel_path)
    print(check_cnt)
    deal(excel_path, "Sheet1", int(check_cnt), 1, -1, None)


# 启动程序
def set_up():
    window = tk.Tk()
    window.geometry('500x540+1000+500')
    window.title('excel 随机抽查行')

    # 软件介绍
    label_txt = "本软件旨在随机从excel表中随机抽取部分行到\n新表中,并将已抽取的行填空为黄色,下次不再抽取,\n保证抽出的行是不重复的,直至全部抽查完。\n 结果保存该软件所在位置,名为“抽查.xlsx”"
    label0 = tk.Label(window, text=label_txt, bg='yellow', font=('KaiTi', 15), justify="left")

    # 原表路径和输入文本框
    label1 = tkinter.Label(window, text="原表路径", bg="LightSkyBlue", font=('KaiTi', 20))
    txt1 = tk.StringVar()
    t1 = tk.Entry(window, font=20, textvariable=txt1, width=30, state='normal', selectforeground="red")

    # # 选取表中的,工作薄sheet名称
    # label2 = tkinter.Label(window, text="sheet名称", bg="pink", font=('KaiTi', 20))
    # txt2 = tk.StringVar()
    # t2 = tk.Entry(window, font=20, textvariable=txt2, width=30, state='normal', selectforeground="red")

    # 要抽查的人数
    label3 = tkinter.Label(window, text="抽查人数", bg="LightSkyBlue", font=('KaiTi', 20))
    txt3 = tk.StringVar()
    t3 = tk.Entry(window, font=20, textvariable=txt3, width=30, state='normal', selectforeground="red")

    # # 抽查导入新表的名称;若为空时,在当前路径下,新建一个表
    # label4 = tkinter.Label(window, text="新表路径", bg="pink", font=('KaiTi', 20))
    # txt4 = tk.StringVar()
    # t4 = tk.Entry(window, font=20, textvariable=txt4, width=30, state='normal', selectforeground="red")

    ok = tk.Button(window, text='确定', width=30, bg="violet", command=lambda: start1(txt1.get(), txt3.get()))

    # 声明
    label5 = tkinter.Label(window, text="声明:该软件仅供学习使用,\n不得用于任何商业用途", bg="red", font=('KaiTi', 15))

    # ps:
    label5 = tkinter.Label(window, text="为了方便大部分用户使用,该软件仅封装了一个简单\n的抽取功能;其实许多复杂地抽取,均可\n以该软件为基础改进,实现定制化抽取。\n代码已开源,欢迎交流。",
                           bg="pink", font=('KaiTi', 12))

    # 以下内容为各个组件的排版
    label0.grid(ipadx=10, ipady=10, row=0, columnspan=2)

    label1.grid(ipadx=10, padx=10, pady=10, row=1, column=0)
    t1.grid(ipadx=10, ipady=10, pady=10, row=1, column=1)

    # label2.grid(ipadx=10, padx=10, pady=10, row=2, column=0)
    # t2.grid(ipadx=10, ipady=10, pady=10, row=2, column=1)

    label3.grid(ipadx=10, padx=10, pady=10, row=3, column=0)
    t3.grid(ipadx=10, ipady=10, pady=10, row=3, column=1)

    # label4.grid(ipadx=10, padx=10, pady=10, row=4, column=0)
    # t4.grid(ipadx=10, ipady=10, pady=10, row=4, column=1)

    ok.grid(ipadx=10, ipady=5, pady=10, row=5, columnspan=2)

    label5.grid(ipadx=10, padx=10, pady=30, row=6, columnspan=2)

    window.mainloop()
    pass

# 启动程序
set_up()

你可能感兴趣的:(小demo,python,excel,开发语言,经验分享)