gpt-4o继续迭代考场安排程序 一键生成考场清单

        接上两篇gpt-4o考场安排-CSDN博客,考场分层次安排,最终exe版-CSDN博客

当然你也可以只看这一篇。

今天又添加了以下功能,程序见后。

1、自动分页,每个考场打印一页

2、添加了打印试场单页眉

3、添加了页脚 第X页,其X页, 打印时间

表结构

程序运行界面

测试分配考场环境,共15个班分为两个层次由字段“层次”指定a, b。a层次9个考场,b层次15个,从b层开始编号,a层次考场号从16开编。

预览结果b层次

层次a预览结果

完整程序


import sysimport pandas as pdimport randomimport openpyxlfrom openpyxl.worksheet.pagebreak import Breakfrom openpyxl.styles import Font, Alignment, PatternFill, Border, Sidefrom openpyxl.worksheet.page import PageMarginsfrom datetime import datetimefrom PyQt5.QtWidgets import (QApplication, QLabel, QLineEdit, QPushButton, QFileDialog,QVBoxLayout, QWidget, QMessageBox)from PyQt5.QtGui import QFont as QPyQtFontdef load_data(filename):return pd.read_excel(filename)def save_data(df, filename, exam_name):df.to_excel(filename, index=False)format_excel(filename, df, exam_name)def assign_seats(df, total_halls, start_hall=1):grouped = df.groupby('班级')groups = [group.sample(frac=1).reset_index(drop=True) for _, group in grouped]groups.sort(key=lambda x: len(x), reverse=True)iterators = [iter(group.iterrows()) for group in groups]arranged_data = []hall_number = start_hallseat_number = 1total_students = len(df)students_per_hall = total_students // total_hallsextra_students = total_students % total_hallswhile iterators:random.shuffle(iterators)for it in iterators[:]:try:_, student = next(it)student_data = student.to_dict()student_data["考场"] = hall_numberstudent_data["考号"] = f"{seat_number:02d}"arranged_data.append(student_data)seat_number += 1if seat_number > students_per_hall + (1 if hall_number - start_hall + 1 <= extra_students else 0):hall_number += 1seat_number = 1if hall_number >= start_hall + total_halls:hall_number = start_hallexcept StopIteration:iterators.remove(it)return arranged_datadef check_and_adjust_seating(arranged_data):def has_adjacent_same_class(data):for i in range(len(data) - 1):if data[i]['班级'] == data[i + 1]['班级']:return ireturn -1def find_valid_swap(index, data):current_class = data[index]['班级']for j in range(len(data)):if j != index and data[j]['班级'] != current_class:if (j == 0 or data[j - 1]['班级'] != current_class) and (j == len(data) - 1 or data[j + 1]['班级'] != current_class):return jreturn -1swap_operations = []while True:index = has_adjacent_same_class(arranged_data)if index == -1:breakswap_index = find_valid_swap(index + 1, arranged_data)if swap_index == -1:raise ValueError("Cannot find a valid swap to adjust the seating arrangement.")swap_operations.append((index + 1, swap_index))arranged_data[index + 1], arranged_data[swap_index] = arranged_data[swap_index], arranged_data[index + 1]return arranged_data, swap_operationsdef reassign_seats(arranged_data, total_halls, start_hall=1):hall_number = start_hallseat_number = 1total_students = len(arranged_data)students_per_hall = total_students // total_hallsextra_students = total_students % total_hallsfor i, student in enumerate(arranged_data):student['考场'] = hall_numberstudent['考号'] = f"{seat_number:02d}"seat_number += 1if seat_number > students_per_hall + (1 if hall_number - start_hall + 1 <= extra_students else 0):hall_number += 1seat_number = 1if hall_number >= start_hall + total_halls:hall_number = start_hallreturn arranged_datadef format_excel(filename, df, exam_name):if '层次' in df.columns:df = df.drop(columns=['层次'])wb = openpyxl.Workbook()ws = wb.activews.title = "考场安排结果"# 将标题从第一行开始写入for col_num, column_title in enumerate(df.columns, 1):cell = ws.cell(row=1, column=col_num, value=column_title)cell.font = Font(bold=True, color="FFFFFF", size=16)cell.fill = PatternFill(start_color="4F81BD", end_color="4F81BD", fill_type="solid")cell.alignment = Alignment(horizontal="center", vertical="center")for row_num, row_data in enumerate(df.itertuples(index=False, name=None), 2):for col_num, cell_value in enumerate(row_data, 1):ws.cell(row=row_num, column=col_num, value=cell_value)for col in ws.columns:max_length = 0column = col[0].column_letter# Check if the column header is "考号"if ws.cell(row=1, column=col[0].col_idx).value == "考号":adjusted_width = 20  # 设置考号列的宽度为20else:for cell in col:if cell.value is not None:max_length = max(max_length, len(str(cell.value)))adjusted_width = max_length + 10ws.column_dimensions[column].width = adjusted_width# 调整页面边距ws.page_margins = PageMargins(left=1.5, right=0.75, top=1.2, bottom=0.5)ws.print_title_rows = '1:1'  # 标题行在第一行开始ws.page_setup.orientation = 'portrait'ws.page_setup.paperSize = ws.PAPERSIZE_A4ws.page_setup.fitToPage = Truews.page_setup.fitToWidth = 1ws.page_setup.fitToHeight = Falsews.page_setup.horizontalCentered = Truews.page_setup.verticalCentered = Truepage_height_in_inches = 11.69 - ws.page_margins.top - ws.page_margins.bottompage_height_in_points = page_height_in_inches * 72header_height_in_points = 50available_row_height_in_points = page_height_in_points - header_height_in_pointshall_groups = df.groupby('考场')previous_max_row = 1  # 前一个最大行号调整为1以考虑空行thin_border = Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'), bottom=Side(style='thin'))for hall_number, (hall_id, hall_df) in enumerate(hall_groups):row_count = len(hall_df) + 1max_row = hall_df.index[-1] + 2  # 从第二行开始每个考场的数据row_height = available_row_height_in_points / row_countrow_height = max(row_height, 15)for row in range(previous_max_row, max_row + 1):ws.row_dimensions[row].height = row_heightfor cell in ws[row]:cell.border = thin_bordercell.font = Font(size=15)cell.alignment = Alignment(horizontal="center", vertical="center")if max_row < ws.max_row:ws.row_breaks.append(Break(max_row))previous_max_row = max_row + 1# 添加页眉和页脚,并使用制表符来向左移动页眉ws.oddHeader.center.text = f"&\"微软雅黑,Bold\"&20\t{exam_name}"  # 添加制表符以向左移动ws.oddFooter.center.text = "第 &P 页,共 &N 页"ws.oddFooter.right.text = f"&D &T"wb.save(filename)def dataframe_to_rows(df, index=True, header=True):if header:rows = [list(df.columns)]else:rows = [[]]for row in df.itertuples(index=index, name=None):rows.append(list(row)[1:])return rowsdef run_allocation(input_filename, a_total_halls, b_total_halls, start_level, exam_name):df = load_data(input_filename)if start_level == 'b':other_level = 'a'first_total_halls = b_total_hallssecond_total_halls = a_total_hallselse:other_level = 'b'first_total_halls = a_total_hallssecond_total_halls = b_total_hallsfirst_level_students = df[df['层次'] == start_level]arranged_first_students = assign_seats(first_level_students, first_total_halls, start_hall=1)adjusted_first_students, _ = check_and_adjust_seating(arranged_first_students)final_first_students = reassign_seats(adjusted_first_students, first_total_halls, start_hall=1)second_level_students = df[df['层次'] == other_level]arranged_second_students = assign_seats(second_level_students, second_total_halls, start_hall=first_total_halls + 1)adjusted_second_students, _ = check_and_adjust_seating(arranged_second_students)final_second_students = reassign_seats(adjusted_second_students, second_total_halls,start_hall=first_total_halls + 1)combined_students = final_first_students + final_second_studentsarranged_df = pd.DataFrame(combined_students)current_time = datetime.now().strftime("%Y%m%d_%H%M%S")output_filename = f"考场安排结果_{current_time}.xlsx"save_data(arranged_df, output_filename, exam_name)return output_filenameclass ExamArrangementApp(QWidget):def __init__(self):super().__init__()self.initUI()def initUI(self):layout = QVBoxLayout()font = QPyQtFont("Arial", 14)self.file_label = QLabel('选择文件:')self.file_label.setFont(font)layout.addWidget(self.file_label)self.file_btn = QPushButton('选择文件')self.file_btn.setFont(font)self.file_btn.clicked.connect(self.select_file)layout.addWidget(self.file_btn)self.exam_name_label = QLabel('考试名称:')self.exam_name_label.setFont(font)layout.addWidget(self.exam_name_label)self.exam_name_input = QLineEdit()self.exam_name_input.setFont(font)layout.addWidget(self.exam_name_input)self.a_halls_label = QLabel('A层次考场数:')self.a_halls_label.setFont(font)layout.addWidget(self.a_halls_label)self.a_halls_input = QLineEdit()self.a_halls_input.setFont(font)layout.addWidget(self.a_halls_input)self.b_halls_label = QLabel('B层次考场数:')self.b_halls_label.setFont(font)layout.addWidget(self.b_halls_label)self.b_halls_input = QLineEdit()self.b_halls_input.setFont(font)layout.addWidget(self.b_halls_input)self.start_level_label = QLabel('首先开始编号的层次 (a/b):')self.start_level_label.setFont(font)layout.addWidget(self.start_level_label)self.start_level_input = QLineEdit()self.start_level_input.setFont(font)layout.addWidget(self.start_level_input)self.run_btn = QPushButton('运行')self.run_btn.setFont(font)self.run_btn.clicked.connect(self.run)layout.addWidget(self.run_btn)self.setLayout(layout)self.setWindowTitle('考场安排工具,By Bobo googaobo@gmail.com')self.resize(900, 630)self.center()def select_file(self):options = QFileDialog.Options()options |= QFileDialog.DontUseNativeDialogfile_name, _ = QFileDialog.getOpenFileName(self, "选择Excel文件", "", "Excel Files (*.xlsx);;All Files (*)",options=options)if file_name:self.file_label.setText(f'文件: {file_name}')self.input_filename = file_namedef run(self):try:a_total_halls = int(self.a_halls_input.text())b_total_halls = int(self.b_halls_input.text())start_level = self.start_level_input.text()exam_name = self.exam_name_input.text()output_filename = run_allocation(self.input_filename, a_total_halls, b_total_halls, start_level, exam_name)QMessageBox.information(self, "成功", f"已成功生成文件:{output_filename}", QMessageBox.Ok)except Exception as e:QMessageBox.critical(self, "错误", str(e), QMessageBox.Ok)def center(self):qr = self.frameGeometry()cp = self.screen().availableGeometry().center()qr.moveCenter(cp)self.move(qr.topLeft())if __name__ == '__main__':app = QApplication(sys.argv)ex = ExamArrangementApp()ex.show()sys.exit(app.exec_())

程序已打包exe,点赞留言QQ,发送程序。程序运行中有问题请评论区留言交流!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/330715.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于 Java 的浏览器——JxBrowser使用分享

软件介绍 JxBrowser 是一个基于 Java 的浏览器&#xff0c;它使用 Chromium 引擎来提供高性能的网页渲染和丰富的功能。它支持多种 GUI 框架&#xff0c;如 Swing、JavaFX 和 SWT&#xff0c;使得在 Java 应用程序中嵌入浏览器组件变得简单。 JxBrowser 是一个适用于多种用途…

一维前缀和[模版]

题目链接 题目: 分析: 因为要求数组中连续区间的和, 可以使用前缀和算法注意:下标是从1开始算起的, 真正下标0的位置是0第一步: 预处理出来一个前缀和数组dp dp[i] 表示: 表示[1,i] 区间所有元素的和dp[i] dp[i-1] arr[i]例如示例一中: dp数组为{1,3,7}第二步: 使用前缀数…

CSS基础(第二天)

Emmet语法 快速生成HTML结构语法 1. 生成标签 直接输入标签名 按tab键即可 比如 div 然后tab 键&#xff0c; 就可以生成 <div></div> 2. 如果想要生成多个相同标签 加上 * 就可以了 比如 div*3 就可以快速生成3个div 3. 如果有父子级关系的标签&#xff0c;可以…

Spark介绍

Spark简介 Spark,是一种通用的大数据计算框架,正如传统大数据技术Hadoop的MapReduce、Hive引擎,以及Storm流式实时计算引擎等. Spark是加州大学伯克利分校AMP实验室(Algorithms Machines and People Lab)开发的通用内存并行计算框架,用于构建大型的、低延迟的数据分析应用程序…

网站流量统计分析

网站流量统计分析&#xff1a;洞悉用户行为的关键 在当今数字化时代&#xff0c;网站流量统计分析已经成为了企业成功的关键因素之一。通过深入了解用户的行为和偏好&#xff0c;企业可以更好地调整其营销策略、优化用户体验以及提高转化率。本文将探讨网站流量统计分析的重要性…

13.js对象

定义 一种复杂数据类型&#xff0c;是无序的&#xff08;不保留键的插入顺序&#xff09;&#xff0c;以键值对&#xff08;{key:value})形式存放的数据集合 对象的创建 &#xff08;1&#xff09;字面量创建 var 对象名{ } &#xff08;2&#xff09;内部构造函数创建 v…

模板编译之入口分析

Vue 是一个渐进式 JavaScript 框架&#xff0c;提供了简单易用的模板语法&#xff0c;帮助开发者以声明式的方式构建用户界面。Vue 的模板编译原理是其核心之一&#xff0c;它将模板字符串编译成渲染函数&#xff0c;并在运行时高效地更新 DOM。本文将深入探讨 Vue 模板编译的原…

Logstash笔记

目录​​​​​​​ 一、简介 二、单个输入和输出插件 三、多个输入和输出插件 四、pipeline结构 五、队列和数据弹性 六、内存队列 七、持久化队列 八、死信队列 (DLQ) 九、输入插件 1)、beats 2)、dead_letter_queue 3)、elasticsearch 4)、file 5)、redis 十、…

【研发日记】嵌入式处理器技能解锁(一)——多任务异步执行调度的三种方法

文章目录 前言 Timer中断调度 Event中断调度 StateFlow调度 分析和应用 总结 参考资料 前言 近期在一些嵌入式系统开发项目中&#xff0c;在使用嵌入式处理器时&#xff0c;遇到了挺多费时费力的事情。所以利用晚上和周末时间&#xff0c;在这些方面深入研究了一下&…

2024年学浪视频怎么下载到手机相册

随着2024年的到来&#xff0c;学浪平台继续为广大学习者提供优质的在线教育资源。然而&#xff0c;如何将这些宝贵的视频内容下载到手机相册&#xff0c;方便随时离线观看呢&#xff1f;无论您是想在旅途中学习&#xff0c;还是希望在没有网络的情况下复习课程&#xff0c;本文…

selenium安装出错

selenium安装步骤&#xff08;法1&#xff09;&#xff1a; 安装失败法1 第一次实验&#xff0c;失败 又试了一次&#xff0c;失败 安装法2-失败&#xff1a; ERROR: Could not install packages due to an EnvironmentError: [WinError 5] 拒绝访问。: c:\\programdata\\a…

YoloV9实战与改进——专栏目录

摘要 &#x1f525;&#x1f680;本专栏教你如何嗨翻Yolov9&#xff01;&#x1f680;&#x1f525; &#x1f680;炸裂升级&#xff1a;嗨&#xff0c;小伙伴们&#xff01;这里有一波Yolov9的升级大招&#xff0c;带你领略最新论文的精华&#xff01;&#x1f4a5; 什么注意…

【EXCEL_VBA_基础知识】08 在VBA中使用公式 ※

课程来源&#xff1a;王佩丰老师的《王佩丰学VBA视频教程》&#xff0c;如有侵权&#xff0c;请联系删除&#xff01; 目录 1. 函数在哪找&#xff1f; 1.1 工作表函数&#xff08;Application.WorksheetFunction.func&#xff09; 1.2 VBA函数 2. 常用VBA变量 3. 函数应用…

乡村振兴与乡村文化传承创新:保护和传承乡村文化,推动乡村文化创新发展,打造具有文化魅力的美丽乡村

一、引言 在当代中国&#xff0c;乡村振兴已成为国家发展的重要战略之一。乡村不仅是自然资源的富集地&#xff0c;更是中华优秀传统文化的发源地。保护和传承乡村文化&#xff0c;推动乡村文化创新发展&#xff0c;对于打造具有文化魅力的美丽乡村&#xff0c;实现乡村全面振…

从需求角度介绍PasteSpider(K8S平替部署工具适合于任何开发语言)

你是否被K8S的强大而吸引&#xff0c;我相信一部分人是被那复杂的配置和各种专业知识而劝退&#xff0c;应该还有一部分人是因为K8S太吃资源而放手&#xff01; 这里介绍一款平替工具PasteSpider&#xff0c;PasteSpider是一款使用c#编写的linux容器部署工具(使用PasteSpider和…

基于Docker部署GitLab环境搭建

文件在D:\E\学习文档子目录压缩\专项进阶&#xff0c;如ngnix,webservice,linux,redis等\docker 建议虚拟机内存2G以上 1.下载镜像文件 docker pull beginor/gitlab-ce:11.0.1-ce.0 注意&#xff1a;一定要配置阿里云的加速镜像 创建GitLab 的配置 (etc) 、 日志 (log) 、数…

Eclipse下载安装教程(包含JDK安装)【保姆级教学】【2024.4已更新】

目录 文章最后附下载链接 第一步&#xff1a;下载Eclipse&#xff0c;并安装 第二步&#xff1a;下载JDK&#xff0c;并安装 第三步&#xff1a;Java运行环境配置 安装Eclipse必须同时安装JDK &#xff01;&#xff01;&#xff01; 文章最后附下载链接 第一步&#xf…

上位机图像处理和嵌入式模块部署(mcu常见三种烧录方法)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 和单纯的windows上位机开发、嵌入式linux开发不一样&#xff0c;mcu的开发&#xff0c;是需要通过烧录器把编译好的镜像烧入到开发板里面的。这是很…

Unreal Engine5 Landscape地形材质无法显示加载

UE5系列文章目录 文章目录 UE5系列文章目录前言一、解决办法 前言 在使用ue5做地形编辑的时候&#xff0c;明明刚才就保存的Landscape地形完全消失不见&#xff0c;或者是地形的材质不见了。重新打开UE5发现有时候能解决&#xff0c;但大多数时候还是没有解决&#xff0c;我下…

QT5.15.2及以上版本安装

更新时间&#xff1a;2024-05-20 安装qt5.15以上版本 系统&#xff1a;ubuntu20.04.06 本文安装&#xff1a;linux-5.15.2 下载安装 # 安装编译套件g sudo apt-get install build-essential #安装OpenGL sudo apt-get install libgl1-mesa-dev# 下载qt安装器 https://downl…