本文目录导读:

我来帮你创建一个自动生成排班表的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界面操作
这个脚本可以作为基础模板,根据实际情况进行修改和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播