|
楼主 |
发表于 2024-11-18 14:51
|
显示全部楼层
哎,我只能做到这里了,但还是没有办法把设备的最大化利用起来
Sub ScheduleProductionWithPriorityAndSequence() '2024-11-8-2
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("排产清单") ' 使用"排产清单"工作表
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row ' 获取最后一行的行号
Dim data As Variant
Dim i As Long, j As Long
Dim temp As Variant '声明临时变量
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary") ' 使用字典来存储设备占用情况
Call 排序
' 将数据存储到数组中
ReDim data(1 To lastRow - 1, 1 To 14) ' 假设有14列数据
For i = 2 To lastRow
For j = 1 To 14
data(i - 1, j) = ws.Cells(i, j).Value
Next j
Next i
' 计算开始日期和结束日期
Dim startDate As Date '声明开始日期变量
Dim endDate As Date '声明结束日期变量
Dim duration As Long '声明工期变量
Dim equipment As String '声明设备变量
Dim previousOrderNum As String '声明上一个订单号
Dim nextAvailableDate As Date '声明下一个可用日期
startDate = Date ' 设置开始日期为当前日期
previousOrderNum = "" ' 初始化上一个订单号为空
For i = 1 To UBound(data, 1)
If data(i, 1) <> previousOrderNum Then '用于识别和处理新订单号的开始。确保每个订单号内的操作只针对该订单号内的工序执行,而不会影响到其他订单号的工序。
startDate = Date ' 如果是新订单,则开始日期为当前日期
previousOrderNum = data(i, 1) '更新变量 previousOrderNum 的值为当前处理的工序的订单号。订单号存储在第一列
End If
equipment = data(i, 9) '对设备变量赋值
duration = data(i, 11) '对工期变量赋值
If dict.Exists(equipment) Then ' 如果设备已经在字典中,获取设备的下一个可用时间
' 检查设备的空档期
If dict(equipment) >= startDate Then '检查设备的下一个可用时间是否不早于计划的开始日期。
startDate = Max(dict(equipment) + 1, startDate)
'比较 dict(equipment) + 1(设备下一个可用日期的下一天)和 startDate(工序计划的开始日期)。比较这两个日期值,并返回两者中较晚的一个日期
End If
End If
' 检查是否有等待中的工序可以提前安排
If startDate + duration <= data(i, 10) And data(i, 13) > 3 Then
'工序计划的开始日期+工序的工期(持续时间)<=设备下一次被占用的日期
'这个条件检查工序的结束日期(startDate + duration)是否早于或等于设备下一次被占用的日期。如果为真,这意味着在当前工序完成后,设备在下一次被占用之前还有空闲时间。
'data(i, 13):这是工序的优先级
'3:这是一个阈值,用于确定工序的优先级。
'这个条件检查工序的优先级是否大于3。如果为真,这意味着工序的优先级不是最高的(因为优先级数字越小,优先级越高)。
startDate = data(i, 10) '用于设置工序的开始日期。这行代码直接将工序的开始日期设置为数组 data 中第 i 行第 10 列的值。
End If
endDate = startDate + duration - 1 '结束日期=开始日期+工期-1天
ws.Cells(i + 1, 10).Value = startDate ' 开始日期
ws.Cells(i + 1, 11).Value = duration ' 工期/天
ws.Cells(i + 1, 12).Value = endDate ' 结束日期
dict(equipment) = endDate ' 更新设备占用
startDate = endDate + 1 ' 下一个工序的开始日期
Next i
End Sub
'进行日期排产
Function Max(ByVal val1 As Date, ByVal val2 As Date) As Date
'函数 Max(ByVal val1 As Date, ByVal val2 As Date) As Date 是一个自定义的 VBA 函数,它用来比较两个日期值 val1 和 val2,并返回这两个日期中较晚的一个。
'ByVal val1 As Date 和 ByVal val2 As Date:这是函数的参数。ByVal 表示按值传递,即直接传递参数的值给函数。val1 和 val2 是参数的名称,As Date 指定了参数的数据类型为 Date,即日期类型。
'As Date:指定函数返回值的数据类型为 Date。
If val1 > val2 Then
Max = val1
Else
Max = val2
End If
End Function
Sub 排序()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("排产清单") ' 请根据实际情况修改工作表名称
Dim lastRow As Long '声明最后一行
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
' 先按优先级排序
ws.Range("A2:N" & lastRow).Sort key1:=ws.Range("M2:M" & lastRow), order1:=xlAscending
' 对每个订单号内的工序按工序号排序,但不排序订单号
Dim i As Long
Dim currentOrder As String '声明当前订单号
Dim startRow As Long '声明开始行
Dim endRow As Long '声明结束行
For i = 2 To lastRow
currentOrder = ws.Cells(i, "A").Value
startRow = i
Do While i <= lastRow And ws.Cells(i, "A").Value = currentOrder
i = i + 1
Loop
endRow = i - 1
ws.Range("A" & startRow & ":N" & endRow).Sort key1:=ws.Range("F" & startRow & ":F" & endRow), order1:=xlAscending
Next i
End Sub
请老师继续给完善一下吧 |
|