用python重写了座位表生成器
如图,用python重写了座位表生成器,在会议排座时方便使用,手残党可以直接下载
from tkinter import Tk, Button, Frame, Label, Entry, Checkbutton, StringVar, BooleanVar, messagebox, filedialog
import pandas as pd
import numpy as np
import os
import sys
from pandas import ExcelWriter
def resource_path(relative_path):
""" 获取资源绝对路径 """
try:
# PyInstaller创建临时文件夹,将路径存储于_MEIPASS
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
class SeatingChart:
def __init__(self):
self.window = Tk()
self.window.title("座位表生成器")
# 设置窗口图标(如果有的话)
try:
self.window.iconbitmap(resource_path("icon.ico"))
except:
pass
# 设置窗口大小和位置
window_width = 400
window_height = 300
screen_width = self.window.winfo_screenwidth()
screen_height = self.window.winfo_screenheight()
x = (screen_width - window_width) // 2
y = (screen_height - window_height) // 2
self.window.geometry(f"{window_width}x{window_height}+{x}+{y}")
self.names = []
# 添加说明文字
note_label = Label(self.window, text="注意:EXCEL文件必须包含姓名和备注列", fg="red")
note_label.pack(pady=10)
# 创建打开文件按钮
self.open_btn = Button(self.window, text="打开姓名列表", command=self.open_file)
self.open_btn.pack(pady=10)
# 创建输入框框架
input_frame = Frame(self.window)
input_frame.pack(pady=10)
# 左侧列数输入
Label(input_frame, text="左:").grid(row=0, column=0)
self.left_var = StringVar(value="8")
self.left_entry = Entry(input_frame, textvariable=self.left_var, width=10)
self.left_entry.grid(row=0, column=1, padx=5)
# 中间列数输入
Label(input_frame, text="中:").grid(row=0, column=2)
self.middle_var = StringVar(value="10")
self.middle_entry = Entry(input_frame, textvariable=self.middle_var, width=10)
self.middle_entry.grid(row=0, column=3, padx=5)
# 右侧列数输入
Label(input_frame, text="右:").grid(row=0, column=4)
self.right_var = StringVar(value="8")
self.right_entry = Entry(input_frame, textvariable=self.right_var, width=10)
self.right_entry.grid(row=0, column=5, padx=5)
# 添加交替排列复选框
self.alternate_var = BooleanVar(value=True)
self.alternate_check = Checkbutton(self.window, text="左右两侧交替排列",
variable=self.alternate_var)
self.alternate_check.pack(pady=5)
# 创建生成按钮
self.generate_btn = Button(self.window, text="生成座位表", command=self.generate_seating)
self.generate_btn.pack(pady=10)
def open_file(self):
file_path = filedialog.askopenfilename(filetypes=[("Excel files", "*.xlsx")])
if file_path:
try:
df = pd.read_excel(file_path)
# 检查文件格式
if not {'姓名', '备注'}.issubset(df.columns):
messagebox.showerror("错误", "文件格式错误,需要工作表中包含姓名和备注列")
return
self.names = df[df['备注'].isna()]['姓名'].tolist()
except Exception as e:
messagebox.showerror("错误", f"读取文件时出错:{str(e)}")
def generate_seating(self):
try:
# 检查是否已导入数据
if not self.names:
messagebox.showerror("错误", "请先选择姓名列表文件")
return
left_cols = int(self.left_var.get())
middle_cols = int(self.middle_var.get())
right_cols = int(self.right_var.get())
# 创建空的座位表
total_rows = (len(self.names) + middle_cols + left_cols + right_cols - 1) // (middle_cols + left_cols + right_cols)
seating = np.full((total_rows, left_cols + middle_cols + right_cols), "", dtype=object)
# 用于记录每个学生的座位位置
seat_index = []
# 填充座位
name_index = 0
for row in range(total_rows):
if name_index >= len(self.names):
break
# 先填充中间部分
middle_start = left_cols
middle_end = left_cols + middle_cols
middle_center = middle_start + middle_cols // 2
# 从中间向两边填充
positions = []
# 先添加中心位置
if middle_cols % 2 == 0:
positions.append(middle_center)
positions.append(middle_center - 1)
# 然后向两边扩展
for i in range(1, middle_cols // 2):
if middle_center + i < middle_end:
positions.append(middle_center + i)
if middle_center - i - 1 >= middle_start:
positions.append(middle_center - i - 1)
else:
positions.append(middle_center)
# 先添加左边的位置,再添加右边的位置
for i in range(1, middle_cols // 2 + 1):
if middle_center - i >= middle_start:
positions.append(middle_center - i)
if middle_center + i < middle_end:
positions.append(middle_center + i)
# 填充中间位置
for pos in positions:
if name_index < len(self.names):
seating[row][pos] = self.names[name_index]
seat_index.append((self.names[name_index], f"第{row+1}排中{pos-left_cols+1}"))
name_index += 1
# 填充左右两侧
if self.alternate_var.get():
# 交替排列模式
left_idx = left_cols - 1
right_idx = left_cols + middle_cols
while (left_idx >= 0 or right_idx < left_cols + middle_cols + right_cols) and name_index < len(self.names):
if left_idx >= 0:
seating[row][left_idx] = self.names[name_index]
seat_index.append((self.names[name_index], f"第{row+1}排左{left_idx+1}"))
name_index += 1
left_idx -= 1
if right_idx < left_cols + middle_cols + right_cols and name_index < len(self.names):
seating[row][right_idx] = self.names[name_index]
seat_index.append((self.names[name_index], f"第{row+1}排右{right_idx-left_cols-middle_cols+1}"))
name_index += 1
right_idx += 1
else:
# 先左后右模式
# 填充左侧
left_idx = left_cols - 1
while left_idx >= 0 and name_index < len(self.names):
seating[row][left_idx] = self.names[name_index]
seat_index.append((self.names[name_index], f"第{row+1}排左{left_idx+1}"))
name_index += 1
left_idx -= 1
# 填充右侧
right_idx = left_cols + middle_cols
while right_idx < left_cols + middle_cols + right_cols and name_index < len(self.names):
seating[row][right_idx] = self.names[name_index]
seat_index.append((self.names[name_index], f"第{row+1}排右{right_idx-left_cols-middle_cols+1}"))
name_index += 1
right_idx += 1
# 创建输出DataFrame
header = ['行号', '过道']
header.extend([f'左{i+1}' for i in range(left_cols)])
header.append('过道')
header.extend([f'中{i+1}' for i in range(middle_cols)])
header.append('过道')
header.extend([f'右{i+1}' for i in range(right_cols)])
output_data = []
for row in range(total_rows):
row_data = [f'第{row+1}排', '']
row_data.extend(seating[row, :left_cols])
row_data.append('')
row_data.extend(seating[row, left_cols:left_cols+middle_cols])
row_data.append('')
row_data.extend(seating[row, left_cols+middle_cols:])
output_data.append(row_data)
# 创建两个DataFrame
df_seating = pd.DataFrame(output_data, columns=header)
df_index = pd.DataFrame(seat_index, columns=['姓名', '座位'])
# 使用ExcelWriter保存到不同的工作表
with pd.ExcelWriter('座位表.xlsx') as writer:
df_seating.to_excel(writer, sheet_name='座位表', index=False)
df_index.to_excel(writer, sheet_name='座位索引', index=False)
messagebox.showinfo("成功", "座位表已生成!")
except ValueError:
messagebox.showerror("错误", "请输入有效的数字!")
except Exception as e:
messagebox.showerror("错误", f"生成座位表时出错:{str(e)}")
def run(self):
self.window.mainloop()
if __name__ == "__main__":
app = SeatingChart()
app.run()