思路想法:整理自己的需求>deepseek生成VBA代码>调试BUG>搞定!
一、 引言:排班难题,一键解决!
- 1.1 排班的烦恼还在为每月排班头疼?人员、时间、特殊要求… 🤯 每次排班都像一场“烧脑大战”!
- 1.2 DeepSeek来帮忙今天给大家介绍一个排班神器——DeepSeek助力EXCEL/WPS表格的VBA!它能帮你轻松搞定值班表,省时省力,告别烦恼!😊
二、 准备工作:明确需求,事半功倍!
- 2.1 打开DeepSeek首先,访问DeepSeek官网(https://chat.deepseek.com/),直接使用即可。用不了,请坛子里搜索下吧。或者换用其他AI!
- 2.2 梳理值班需求在开始排班前,我们需要清晰地了解值班需求,这包括:
- 值班周期: 例如,一周、一个月?
- 值班人员: 参与值班的所有人员名单。
- 班次类型: 例如,早班、晚班、夜班?
- 特殊日期: 例如,节假日、调休?
- 人员限制: 例如,某人不能上夜班,某两人不能同时值班?
我的实战案例:①值班表不区分工作日和休息日。②男的带班领导搭配女的值班人员,女的带班领导搭配男的值班人员。③每天要求1名带班领导和2名值班人员进行值班。
三、 步骤详解:手把手教你生成值班表! (实战)
-
- 3.1 输入指令:告诉DeepSeek你的需求登录DeepSeek后,找到对话框或类似输入指令的地方。当然了,为了一劳永逸,建议用excel,这样,以后每个月都非常简单啦。你可以这样告诉DeepSeek:
请帮我生成一个excel的VBA程序用来生成我的值班表。值班规则:
1.值班表不区分工作日和休息日。
2.男的带班领导搭配女的值班人员,女的带班领导搭配男的值班人员。
3.每天要求1名带班领导和2名值班人员进行值班。
4.为了保证公平,所有带班领导按照表格顺序轮流带班,所有值班人员按照表格顺序依次排班。
5.我会在表格内表明最后一次值班人员姓名,进而在生成下次值班表时,继续生成,而不是从表格第一行直接开始。
表格数据具体信息如下:
sheet1的A列为“值班日期”,B列为”带班领导”,C列为”值班人员1”,D列为”值班人员2”。
sheet2的A列为”带班领导名单”,B列为”带班领导性别”。C类为”值班人员名单”,D列为”值班人员性别”。
同时,因为要长久使用,需要考虑到每个月开始的人员并不一致的问题。
在sheet2继续添加数据内容。即E列为上月最后一天值班的带班领导姓名,F列为上月最后一天值班的男值班人员1姓名。G列为上月最后一天值班的男值班人员2姓名,H列为上月最后一天值班的女值班人员1姓名,I列为上月最后一天值班的女值班人员2姓名。
等了10分钟后,发现还没好,我查看了一下思考内容,我是男女值班人员混排的,这样VBA太过复杂了,deepseek思考了10分钟,还没想好。所以,优化了一下,重新让AI思考。主要是将值班人员的男女表格重新列明,减少VBA的工作难度。同时,先把数据给deepseek,再告诉他值班规则,能够有效减少他阅读值班规则时候的各种假设,做出来的值班表也更具针对性。
请帮我生成一个excel的VBA程序用来生成我的值班表。
表格数据具体信息如下:
sheet1的A列为“值班日期”,B列为”带班领导”,C列为”值班人员1”,D列为”值班人员2”。
sheet2的A列为”带班领导名单”,B列为”带班领导性别”。C类为”男性值班人员名单”,D列为”女性值班人员名单”。
同时,因为要长久使用,需要考虑到每个月开始的人员并不一致的问题。
在sheet2继续添加数据内容。即E列为上月最后一天值班的带班领导姓名,F列为上月最后一天值班的男值班人员1姓名。G列为上月最后一天值班的男值班人员2姓名,H列为上月最后一天值班的女值班人员1姓名,I列为上月最后一天值班的女值班人员2姓名。
值班规则:
1.值班表不区分工作日和休息日。
2.男的带班领导搭配女的值班人员,女的带班领导搭配男的值班人员。
3.每天要求1名带班领导和2名值班人员进行值班。
4.为了保证公平,所有带班领导按照表格顺序轮流带班,所有值班人员按照表格顺序依次排班。
5.我会在表格内表明最后一次值班人员姓名,进而在生成下次值班表时,继续生成,而不是从表格第一行直接开始。
3.2 调整参数:
精细化你的排班DeepSeek会根据你的指令生成初步的排班表。如果对结果不满意,你可以通过调整参数进行优化。例如:
调整班次时长: 更改早班、晚班的具体时间。
指定班次: 明确要求某人在某天值某个班次。
你可以继续在对话框中输入新的指令,DeepSeek会根据你的反馈进行调整。
3.3 生成与优化:多次尝试,直到满意不断尝试不同的指令和参数组合,直到DeepSeek生成你满意的排班表。DeepSeek的强大之处在于,它能理解你的各种要求,并智能地进行调整,避免冲突,确保排班的公平性和合理性。好了,等待了若干个10分钟后,现在献上最终的代码
Sub GenerateDutySchedule()
Dim ws1 As Worksheet, ws2 As Worksheet
Dim leaders As Variant, males As Variant, females As Variant
Dim leaderIndex As Long, maleIndex As Long, femaleIndex As Long
Dim lastLeader As String, lastMale1 As String, lastMale2 As String
Dim lastFemale1 As String, lastFemale2 As String
Dim targetRow As Long, i As Long
Set ws1 = ThisWorkbook.Sheets(“Sheet1”)
Set ws2 = ThisWorkbook.Sheets(“Sheet2”)
‘ 读取上次值班记录
With ws2
lastLeader = .Range(“E2”).Value
lastMale1 = .Range(“F2”).Value
lastMale2 = .Range(“G2”).Value
lastFemale1 = .Range(“H2”).Value
lastFemale2 = .Range(“I2”).Value
End With
‘ 获取人员名单
With ws2
leaders = .Range(“A2:B” & .Cells(.Rows.Count, “A”).End(xlUp).Row).Value
males = .Range(“C2:C” & .Cells(.Rows.Count, “C”).End(xlUp).Row).Value
females = .Range(“D2:D” & .Cells(.Rows.Count, “D”).End(xlUp).Row).Value
End With
‘ 确定起始索引
leaderIndex = GetStartIndex(leaders, lastLeader, 1)
maleIndex = GetDoubleStartIndex(males, lastMale1, lastMale2)
femaleIndex = GetDoubleStartIndex(females, lastFemale1, lastFemale2)
‘ 查找需要填充的起始行
targetRow = ws1.Cells(ws1.Rows.Count, “B”).End(xlUp).Row + 1
‘ 生成排班记录
Do While ws1.Cells(targetRow, “A”).Value <> “” And targetRow <= 365
Dim currentLeader As String, leaderGender As String
currentLeader = leaders((leaderIndex Mod UBound(leaders)) + 1, 1)
leaderGender = leaders((leaderIndex Mod UBound(leaders)) + 1, 2)
‘ 生成值班人员
Dim staff1 As String, staff2 As String
If leaderGender = “男” Then
staff1 = females((femaleIndex Mod UBound(females)) + 1, 1)
staff2 = females(((femaleIndex + 1) Mod UBound(females)) + 1, 1)
femaleIndex = femaleIndex + 2
Else
staff1 = males((maleIndex Mod UBound(males)) + 1, 1)
staff2 = males(((maleIndex + 1) Mod UBound(males)) + 1, 1)
maleIndex = maleIndex + 2
End If
‘ 写入数据
ws1.Cells(targetRow, “B”).Value = currentLeader
ws1.Cells(targetRow, “C”).Value = staff1
ws1.Cells(targetRow, “D”).Value = staff2
‘ 更新索引
leaderIndex = leaderIndex + 1
targetRow = targetRow + 1
Loop
MsgBox “已生成 ” & (targetRow – ws1.Cells(ws1.Rows.Count, “B”).End(xlUp).Row – 1) & ” 条新排班记录”
End Sub
Function GetStartIndex(arr As Variant, searchValue As String, offset As Long) As Long
Dim i As Long
For i = 1 To UBound(arr)
If arr(i, 1) = searchValue Then
GetStartIndex = (i + offset – 1) Mod UBound(arr)
Exit Function
End If
Next i
GetStartIndex = 0
End Function
Function GetDoubleStartIndex(arr As Variant, firstVal As String, secondVal As String) As Long
Dim i As Long
If firstVal = “” Or secondVal = “” Then Exit Function
For i = 1 To UBound(arr) – 1
If arr(i, 1) = firstVal And arr(i + 1, 1) = secondVal Then
GetDoubleStartIndex = (i + 1) Mod UBound(arr)
Exit Function
End If
Next i
‘ 处理循环匹配
If arr(UBound(arr), 1) = firstVal And arr(1, 1) = secondVal Then
GetDoubleStartIndex = 1
Else
GetDoubleStartIndex = 0
End If
End Function
使用方法
按Alt+F11打开VBA编辑器插入新模块并粘贴代码按需修改日期范围(当前设置为生成当月排班)按F5运行宏为了方便使用,我们可以在宏窗口插入一个按钮,点击直接运行宏,这样更加方便。比如:点击“开发者”选项卡。在“控件”组中,点击“插入”按钮。在下拉菜单中选择“表单控件”(如果是旧版Excel,直接选择“按钮”)。在工作表上拖动鼠标绘制一个按钮。如果在绘制按钮后没有出现“分配宏”对话框,我们插入按钮后,进入设计模式,点击按钮修改名称,然后点击查看代码。修改该按钮的代码如下,即可实现点击运行啦
Private Sub CommandButton1_Click()
Call GenerateDutySchedule
End Sub
2025年2月24日更新完善一下,重新调整了代码
‘ 获取用户输入的年份和月份
yearInput = InputBox(“请输入年份 (YYYY):”, “年份”)
monthInput = InputBox(“请输入月份 (MM):”, “月份”)
‘ 验证输入
If Not IsNumeric(yearInput) Or Not IsNumeric(monthInput) Then
MsgBox “输入的年份或月份无效!”, vbCritical
Exit Sub
End If
‘ 计算起始和结束日期
startDate = DateSerial(yearInput, monthInput, 1)
endDate = DateSerial(yearInput, monthInput + 1, 0)
‘ 清除旧数据(保留表头)
ws1.Range(“A2:D” & ws1.Cells(ws1.Rows.Count, “A”).End(xlUp).Row).ClearContents
增加了一些细节调整:
1.调整运行按钮至SHEET2页面,因为上次值班的人员还是手动输入,防止出现错误不懂的人不会改。此外,由于VBA的名称变了,且从sheet2要调用sheet1的VBA代码,这个按钮的代码也小改了一下。
[size=4]Private Sub CommandButton1_Click()
[color=rgb(152, 195, 121)]’ 确保指定工作表Sheet1,然后调用GenerateMonthlyDutySchedule过程
Sheet1.GenerateMonthlyDutySchedule
End Sub[/color][/size]
2.单列的表格不方便打印,新增sheet3,将值班表变为A4纸直接打印的多列横表。
设置好表格模版,然后,让sheet3自动填上月份,简单写一个小公式,直接获取sheet1值班的月份即可,比如在sheet3的A2处直接=TEXT(sheet1!A2,”m月”)
再通过一个简单公式,先把日期都显示出来,比如A3=TEXT(sheet1!A2,”d日”) ,是不是和月份显示有异曲同工之妙。哈哈
=TEXT(sheet1!A2,”d日”)
然后,按照顺序填充,到A11=TEXT(sheet1!A12,”d日”)。然后修改一下公式,E3=TEXT(sheet1!A13,”d日”),继续填充,以此类推,全部填充完成。
最后,让显示0日的这些不显示。这个操作比较复杂了,让我们问一问deepseek吧。简单的思考后,deepseek竟然给出了我两种方法。
于是,我们直接在I9,也就是这个月的29日这一表格输入公式=IF(sheet1!A30=””,””,TEXT(sheet1!A30,”d日”))然后依次填充至最下面一行。即I12=IF(sheet1!A33=””,””,TEXT(sheet1!A33,”d日”));I13=IF(sheet1!A34=””,””,TEXT(sheet1!A34,”d日”))
值班人员同理。以J9为例:=IF(sheet1!B30=””,””,sheet1!B30)。
最终实现的效果就是sheet2页输入值班人员信息和最后一次值班信息,然后就能在sheet3直接看到最终值班表了。
下载地址: