本文目录导读:

我来帮你创建一个自动生成排班表的Python脚本,以下是一个功能完善的示例:
基础排班表生成器
import pandas as pd
import random
from datetime import datetime, timedelta
from typing import List, Dict
class ShiftScheduler:
def __init__(self, employees: List[str], shifts: Dict[str, int]):
"""
初始化排班器
:param employees: 员工名单
:param shifts: 班次配置,如 {"早班": 2, "中班": 2, "晚班": 1}
"""
self.employees = employees
self.shifts = shifts
self.schedule = {}
def generate_monthly_schedule(self, year: int, month: int) -> pd.DataFrame:
"""生成月度排班表"""
# 获取月份的天数
start_date = datetime(year, month, 1)
if month == 12:
end_date = datetime(year + 1, 1, 1)
else:
end_date = datetime(year, month + 1, 1)
days_in_month = (end_date - start_date).days
schedule_data = []
# 为每一天分配班次
for day in range(1, days_in_month + 1):
date = datetime(year, month, day)
daily_schedule = self._generate_daily_schedule(date)
schedule_data.append(daily_schedule)
# 创建DataFrame
df = pd.DataFrame(schedule_data)
df['日期'] = [f"{month}/{day}" for day in range(1, days_in_month + 1)]
df['星期'] = [self._get_weekday(datetime(year, month, day)) for day in range(1, days_in_month + 1)]
return df
def _generate_daily_schedule(self, date: datetime) -> Dict:
"""生成单日排班"""
daily = {}
# 检查是否为周末
is_weekend = date.weekday() >= 5
for shift_name, count in self.shifts.items():
available_employees = self._get_available_employees(date, shift_name)
if len(available_employees) >= count:
# 随机选择需要的员工数
selected = random.sample(available_employees, count)
daily[shift_name] = ', '.join(selected)
else:
# 如果可用员工不足,使用所有可用员工
daily[shift_name] = ', '.join(available_employees)
return daily
def _get_available_employees(self, date: datetime, shift_name: str) -> List[str]:
"""获取可用员工列表"""
available = []
for emp in self.employees:
# 这里可以添加更多约束条件
# 连续工作不超过X天,同一天不能同时安排多个班次等
if not self._is_already_scheduled(date, emp, shift_name):
available.append(emp)
return available
def _is_already_scheduled(self, date: datetime, employee: str, shift_name: str) -> bool:
"""检查员工是否已经被安排"""
# 简化的检查逻辑,实际应用需要更复杂的检查
try:
current_date_str = f"{date.month}/{date.day}"
if current_date_str in self.schedule:
daily = self.schedule[current_date_str]
for shift, workers in daily.items():
if shift != shift_name and employee in workers:
return True
except:
pass
return False
def _get_weekday(self, date: datetime) -> str:
"""获取星期几的中文名称"""
weekdays = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日']
return weekdays[date.weekday()]
def save_to_excel(self, df: pd.DataFrame, filename: str):
"""保存为Excel文件"""
with pd.ExcelWriter(filename, engine='openpyxl') as writer:
df.to_excel(writer, sheet_name='排班表', index=False)
# 调整格式
worksheet = writer.sheets['排班表']
# 设置列宽
for column in df.columns:
column_width = max(len(str(column)) * 2, 15)
col_idx = df.columns.get_loc(column) + 1
worksheet.column_dimensions[chr(64 + col_idx)].width = column_width
# 设置标题行样式
for cell in worksheet[1]:
cell.font = pd.io.formats.excel.ExcelFormatter.bold()
cell.alignment = pd.io.formats.excel.ExcelFormatter.center()
class AdvancedScheduler(ShiftScheduler):
"""高级排班器,包含更多约束条件"""
def __init__(self, employees, shifts, constraints=None):
super().__init__(employees, shifts)
self.constraints = constraints or {}
self.work_history = {emp: [] for emp in employees}
def generate_balanced_schedule(self, year: int, month: int) -> pd.DataFrame:
"""生成平衡的排班表,确保工作量公平"""
# 获取月份的天数
start_date = datetime(year, month, 1)
if month == 12:
end_date = datetime(year + 1, 1, 1)
else:
end_date = datetime(year, month + 1, 1)
days_in_month = (end_date - start_date).days
schedule_data = []
# 初始化员工工作量统计
workload = {emp: 0 for emp in self.employees}
for day in range(1, days_in_month + 1):
date = datetime(year, month, day)
daily_schedule = self._generate_balanced_daily_schedule(date, workload)
schedule_data.append(daily_schedule)
df = pd.DataFrame(schedule_data)
df['日期'] = [f"{month}/{day}" for day in range(1, days_in_month + 1)]
df['星期'] = [self._get_weekday(datetime(year, month, day)) for day in range(1, days_in_month + 1)]
return df
def _generate_balanced_daily_schedule(self, date, workload):
"""生成平衡的单日排班"""
daily = {}
is_weekend = date.weekday() >= 5
# 按工作量排序,工作量少的优先选择
sorted_employees = sorted(self.employees, key=lambda x: workload[x])
for shift_name, count in self.shifts.items():
selected = []
for emp in sorted_employees:
if len(selected) >= count:
break
if self._can_work(emp, date, shift_name):
selected.append(emp)
workload[emp] += 1
daily[shift_name] = ', '.join(selected) if selected else '无人'
return daily
def _can_work(self, employee, date, shift_name):
"""检查员工是否可以工作"""
# 检查连班限制
if self.constraints.get('max_consecutive_days'):
recent_work = self.work_history[employee][-self.constraints['max_consecutive_days']:]
if len(recent_work) >= self.constraints['max_consecutive_days']:
if all(day == date - timedelta(days=i) for i, day in enumerate(recent_work)):
return False
# 检查总工作量限制
if self.constraints.get('max_work_days_per_month'):
pass # 将在主方法中处理
# 更新工作历史
self.work_history[employee].append(date)
return True
# 使用示例
def main():
# 配置参数
employees = ['张三', '李四', '王五', '赵六', '钱七', '孙八']
shifts = {
'早班 (08:00-16:00)': 2,
'中班 (14:00-22:00)': 2,
'晚班 (22:00-08:00)': 1
}
# 创建排班器
scheduler = AdvancedScheduler(
employees,
shifts,
constraints={
'max_consecutive_days': 3, # 最多连续工作3天
'max_work_days_per_month': 22 # 每月最多工作22天
}
)
# 生成2024年1月的排班表
schedule_df = scheduler.generate_balanced_schedule(2024, 1)
# 显示排班表
print("排班表预览:")
print(schedule_df.head(10))
# 保存到Excel
scheduler.save_to_excel(schedule_df, '排班表_2024年1月.xlsx')
print("排班表已保存到 '排班表_2024年1月.xlsx'")
if __name__ == "__main__":
# 安装依赖
# pip install pandas openpyxl
# 如果需要生成随机种子来复现结果
random.seed(42) # 设置随机种子,确保每次运行结果一致
main()
简易版本(适合快速使用)
import random
from datetime import datetime, timedelta
def simple_schedule():
# 基本配置
employees = ['张三', '李四', '王五', '赵六']
shifts = ['早班', '中班', '晚班']
# 获取当前月份的天数
now = datetime.now()
days_in_month = 30 # 简化为30天
# 生成排班表
schedule = {}
for day in range(1, days_in_month + 1):
# 随机分配班次
random.shuffle(employees) # 打乱员工顺序
daily = {
'早班': employees[0],
'中班': employees[1],
'晚班': employees[2] if len(employees) > 2 else employees[0]
}
schedule[day] = daily
# 输出排班表
print("简易排班表")
print("=" * 50)
for day, shifts in schedule.items():
print(f"第{day:2d}天 | 早班: {shifts['早班']} | 中班: {shifts['中班']} | 晚班: {shifts['晚班']}")
if __name__ == "__main__":
simple_schedule()
使用说明
-
安装依赖:
pip install pandas openpyxl
-
自定义配置:
- 修改
employees数组为你的员工名单 - 调整
shifts字典配置班次和每班所需人数 - 可选的约束条件如最大连续工作天数
- 修改
-
运行脚本:
python shift_scheduler.py
扩展建议
你可以根据实际需求添加更多功能:
- 员工偏好设置(如某些员工不能上夜班)
- 法定节假日特殊安排
- 输出HTML格式的排班表
- 自动发送邮件通知
- 支持Web界面操作
这个脚本可以作为基础模板,根据实际情况进行修改和扩展。