Board logo

標題: [發問] 自動分配交期 [打印本頁]

作者: adam2010    時間: 2022-10-1 12:13     標題: 自動分配交期

請教各位先進高手,小弟有一個訂單的樞紐分析
日期欄位從H欄開始,截止日期及欄位數量不一定,最後面會有一個加總,有訂單的才會出現日期,非故定間隔
[attach]35245[/attach]
[attach]35244[/attach]
因為希望能夠現性生產,想要將訂單往前平均攤平,往前平均不跨月 (如下~),請問各位是否有比較好的方法,謝謝!
[attach]35246[/attach]
[attach]35247[/attach]
[attach]35248[/attach]
[attach]35249[/attach]
[attach]35250[/attach]
作者: Andy2483    時間: 2022-10-3 15:50

回復 1# adam2010


    謝謝前輩發表此主題與範例
後學學習過程中練習過排程看板,前輩的需求跟排程看板類似!
當月提前分配,用什麼規則做分配?
1.與上班工時有關嗎?例如:24小時生產!全年無休?或0800~1200 & 1300~1700生產例假日休息?
2.每個成品生產週期有關嗎?例如:每個成品生產週期10分鐘?或生產過程有待料時間?
3.跟成品良率有關嗎?例如:統計數據10個成品約8個是良品?
作者: adam2010    時間: 2022-10-3 20:09

本帖最後由 adam2010 於 2022-10-3 20:12 編輯

回復 2# Andy2483
您好~
當月提前分配,用什麼規則做分配?
→ 後續會再針對各料號分佈的站點狀況分配交期,所以如果沒有先將交期作一個攤平動作,有可能出現多批次同日交期,難以區分優先順序,無法達成線性生產的目標,而訂單的放置各客戶有當月最終交貨日的問題,無法根據生管的需求攤平放置,所以才需要此後製
1.與上班工時有關嗎?例如:24小時生產!全年無休?或0800~1200 & 1300~1700生產例假日休息?
→目前公司除了歲修以外基本上是24H生產型態,故不需考慮延時加班的問題
2.每個成品生產週期有關嗎?例如:每個成品生產週期10分鐘?或生產過程有待料時間?
3.跟成品良率有關嗎?例如:統計數據10個成品約8個是良品?
→生產週期是後續排程要考量各料號途程與各站點標準工時、良率等問題分配給各生產批次;各站點生產順序基本上用類似CR值 (critical ratio,計算方法=交期減去目前日期之差額,再除以工期,數值越小表示緊急程度越高,排程優先級高 ) 的方式換算程順序讓產線知道要先產哪些批次
不知道有沒有回答到您的問題?
作者: Andy2483    時間: 2022-10-4 16:47

回復 3# adam2010


    謝謝前輩回覆
請前輩先試看看
1.轉置方式是否適合
2.攤平方式是否適用

今天習得 資料轉置,攤平天數
練習陣列
  1. Option Explicit
  2. Sub 資料轉置()
  3. Dim Brr, Crr, c&, i&, j&, x&, xR, R, T, v, Y, Z, xA, Sc&, Sr&
  4. Dim B#, K%, P$, Q, Ra, Rs, Rn, n&, Avgd&, Avgv
  5. Set xA = ActiveSheet.Cells
  6. Set Y = CreateObject("Scripting.Dictionary")
  7. For Each Ra In xA.SpecialCells(2)
  8.    R = Ra.Address
  9.    Rn = IIf(Ra = "總計" And Rn = "" And Rs <> "", Ra.Address, Rn)
  10.    Rs = IIf(Ra = "總計" And Rs = "", Ra.Address, Rs)
  11. Next
  12. Brr = xA.Range(Rs, Rn)
  13. Rs = Brr(1, 8)
  14. Rn = Brr(1, UBound(Brr, 2) - 1)
  15. Sc = Rn - Rs + 1 '天數
  16. Sr = UBound(Brr) - 2 '品號數
  17. ReDim Crr(1 To Sc * Sr, 1 To 13)
  18. For j = 2 To Sr + 1
  19.    For i = 1 To Sc
  20.       n = n + 1
  21.       Crr((j - 2) * Sc + i, 1) = n
  22.       Crr((j - 2) * Sc + i, 2) = Rs + (i - 1)
  23.       Crr((j - 2) * Sc + i, 13) = Brr(j, UBound(Brr, 2))
  24.       For x = 1 To 7
  25.          Crr(n, x + 2) = Brr(j, x)
  26.       Next
  27.       
  28.       For x = 8 To UBound(Brr, 2) - 1
  29.          If Brr(1, x) = Rs + (i - 1) Then
  30.             Crr((j - 2) * Sc + i, 12) = Brr(j, x)
  31.          End If
  32.       Next
  33.    Next
  34. Next
  35. For j = n To 1 Step -1
  36.    If Crr(j, 12) > 0 Then
  37.       For i = j - 1 To 1 Step -1
  38.          If Crr(i, 12) > 0 Or Crr(i, 3) <> Crr(j, 3) Or i = 1 Then
  39.             Avgd = j - i
  40.             If Avgd > 0 Then
  41.                Avgv = Crr(j, 12) / Avgd
  42.             End If
  43.             If Crr(1, 12) = "" And i = 1 Then
  44.                Avgd = j - i + 1
  45.                If Avgd > 0 Then
  46.                   Avgv = Crr(j, 12) / Avgd
  47.                End If
  48.             End If
  49.             Exit For
  50.          End If
  51.       Next
  52.    End If
  53.    Crr(j, 10) = Avgd
  54.    Crr(j, 11) = Avgv
  55.    If j > 1 Then
  56.       Avgd = IIf(Crr(j, 3) = Crr(j - 1, 3), Avgd, 0)
  57.       Avgv = IIf(Crr(j, 3) = Crr(j - 1, 3), Avgv, 0)
  58.    End If
  59. Next
  60. If Crr(1, 12) <> "" Then
  61.    Crr(1, 10) = 1
  62.    Crr(1, 11) = Crr(1, 12)
  63. End If
  64. Workbooks.Add
  65. [A1].Resize(1, 13) = Split("NO/日期/料號/吋/摻/可用庫存/1300/" _
  66. & "在制量/Var/攤平天數/攤平數量/訂單數量/總計", "/")
  67. [A2].Resize(UBound(Crr), UBound(Crr, 2)) = Crr
  68. Cells.Columns.AutoFit
  69. Cells.Rows.AutoFit
  70. Cells.Columns.AutoFit
  71. [2:2].Select
  72. ActiveWindow.FreezePanes = True
  73. [1:1].AutoFilter
  74. [A1].Select
  75. Cells.Borders.LineStyle = xlContinuous
  76. End Sub
複製代碼

作者: adam2010    時間: 2022-10-4 20:57

本帖最後由 adam2010 於 2022-10-4 21:00 編輯

回復 4# Andy2483
感謝Andy2483大大鼎力相助,已經有攤平的效果,不過因為後續接續公司排程系統,上傳需要原來的樞紐格式
Sorry~之前沒有說清楚,不過還是很感謝您的協助~
原始資料~
[attach]35264[/attach]
執行後~
1.A~G欄不變
2.將起訖日期中間的日期填滿(黃底部分)
2.將訂單平均往前攤平(四捨五入取整數)但不可跨月
如下~
[attach]35266[/attach]
作者: hcm19522    時間: 2022-10-5 11:30

https://blog.xuite.net/hcm19522/twblog/590570424
作者: Andy2483    時間: 2022-10-7 13:43

回復 5# adam2010


    謝謝前輩回覆
請前輩試看看
今天習得亂數帶入輔助檢測
練習陣列與字典
[attach]35272[/attach]

攤平前:
[attach]35273[/attach]

顯示攤平總後誤差量:
[attach]35274[/attach]

往前攤平結果:
[attach]35275[/attach]
作者: Andy2483    時間: 2022-10-7 13:49

回復 5# adam2010


    輔助檢測正確性說明如下:
另設一按鈕,輔助檢測程式碼執行結果的正確性:
[attach]35276[/attach]

亂數帶入表格,檢測100次的結果:
[attach]35277[/attach]

呈現最後一筆亂數帶入表格,檢測的結果
[attach]35278[/attach]
作者: adam2010    時間: 2022-10-8 22:56

回復 6# hcm19522


    感謝hcm19522大提供的公式,前幾天進不了站線在才看到,謝謝~
作者: adam2010    時間: 2022-10-8 23:03

回復 7# Andy2483

感謝Andy2483大提供的巨集,前幾天進不來現在才看到,實在太感謝您了
其實因為後續生產出來的數量會因為良率預估與實際良率的落差而會跟訂單量有些許落差,
所以四捨五入的少許誤差是可以忽略的,看各產業的OTD計算方式,有的一定要交足有的容許一定的誤差量就算達成
自製銷售與代工也會有所不同
作者: Andy2483    時間: 2022-10-11 12:34

回復 10# adam2010
    謝謝前輩測試回覆
做了心得註解更發現自己許多沒必要的可簡化的程式碼!
檢視出了很多邏輯上的缺點!
拋磚引玉!請前輩們指導如何簡化!或其他方法! 謝謝!
以下心得供前輩參考
Option Explicit
Public PP&, Ch0, Ch1
Sub 橫向往前攤平()
Application.ScreenUpdating = False
Dim Brr, Crr, i&, j&, x&, Tj&, Ti&, y, xA, Sc&, Sr&, R$
Dim Ra, Rs, Rn, Avgd&, Avgv, M0&, M1&, Sv, Cc, Bc, K, H
'↑宣告變數
Ch0 = 0: Ch1 = 0
'↑令Ch0是0,令Ch1是0
Set xA = Sheets("PP").Cells
'↑令xA是 "PP" 工作表的所有儲存格
Set y = CreateObject("Scripting.Dictionary")
'↑令y是字典
For Each Ra In xA.SpecialCells(2)
'↑設定迴圈去找xA非空格裡右上角跟左下角是 "總計" 的儲存格位址
   Rn = IIf(Ra = "總計" And Rn = "" And Rs <> "", Ra.Address, Rn)
   '↑令Rn是左下角的 "總計" 儲存格位址
   '把這行擺在前面的用意是:
   '右上角的 "總計" 儲存格位址如果還沒找到! And Rs <> ""這條件就不成立
   'And Rn = ""是只認定第二個 "總計" 儲存格位址

   Rs = IIf(Ra = "總計" And Rs = "", Ra.Address, Rs)
   '↑令Rn是右上角的 "總計" 儲存格位址
Next
Brr = xA.Range(Rs, Rn)
'↑令Brr是兩個總計儲存格範圍的值陣列
Bc = UBound(Brr, 2)
'↑令Bc是Brr橫方向的欄數
Rs = Brr(1, 8)
'↑令Rs是第一列第八欄這值(有訂單的開始日期)
Rn = Brr(1, Bc - 1)
'↑令Rn是第一列倒數第二個值(有訂單的最後日期)
Sc = Rn - Rs + 1
'↑令Sc是頭尾區間的天數!一定要加1才能包含最後一天
Sr = UBound(Brr) - 2
'↑令Sr是Brr的列數減掉2列
Ch0 = Brr(UBound(Brr, 1), UBound(Brr, 2))
'↑令Ch0是最右下角的值(總合計)
ReDim Crr(1 To Sr + 2, 1 To Sc + 1)
'↑宣告Crr這空陣列的範圍:縱方向Sr + 2 列
'橫方向Sc + 1 欄

Cc = UBound(Crr, 2)
'↑令Cc是Crr的橫方向欄數
For i = 1 To Sc
'↑設迴圈把全部日期放到Crr陣列的第一列
'↑y字典也用這些序號當key,item設為0初始值,
'讓後面累加為當天攤平總和

   Crr(1, i) = Rs + (i - 1)
   y(i) = 0
Next
For i = 1 To UBound(Brr)
'↑設迴圈把原始右側的小計放入Crr的最後一欄
   Crr(i, Cc) = Brr(i, Bc)
Next
For j = 2 To Sr + 1
'↑設迴圈把原始定單放入Crr的當日訂單位置
   For i = 1 To Sc
      For x = 8 To Bc - 1
         If Brr(1, x) = Rs + (i - 1) Then
            Crr(j, i) = Brr(j, x)
         End If
      Next
   Next
Next
For x = 1 To Sr
'↑以下設三層迴圈把訂單往前攤平!且不必跨月攤平!
'↑先設正外迴圈

   Avgd = 0: Avgv = 0: M0 = 0: M1 = 0
   '↑Avgd:攤平天數,Avgv:攤平量,
   'M0:前一個月的月數,M1:當格的月數
   '做歸零

     For j = Sc To 1 Step -1
     '↑設中層倒迴圈!讓符合條件就填入攤平值
     '不能攤平就填入原訂單值
     '沒有訂單就空格

      If j = 1 Then
         y(j) = y(j) + Crr(x + 1, j)
         Exit For
         '↑如果倒迴圈能跑到j = 1,就讓合計加上原訂單量
         ',就跳出中層這迴圈

      End If
      M1 = Format(Crr(1, j), "mm")
      '↑令M1是當格的訂單月份數
      Tj = Crr(x + 1, j)
      '↑令Tj是要判定須不須!能不能攤平的當格值
      If Tj <> 0 And j = Sc Then
      '↑如果當格值不是0 而且是最後一個日期訂單
         Avgd = 1
         '↑令可攤平天數=1
         For i = j - 1 To 1 Step -1
            '↑設內層倒迴圈!從j當格前一格開始到最前面那天
            M0 = Format(Crr(1, i), "mm")
            '↑令M0是i當格的月分數
            Ti = Crr(x + 1, i)
            '↑令Ti是要判定能不能吃下攤平值的當格
            If Ti <> 0 And Avgd = 1 Then
            '↑如果前方格的值不是0,且可攤平天數是1
               If i = Sc - 1 Then
               '↑如果i是倒數第二天
                  Avgd = 0
                  '↑條件成立!就可攤平天數=0
                  '因為沒得攤平

                  Else
                     Avgd = Avgd + 1
                     Avgv = Tj
                     '↑否則可攤平天數+1
                     '↑可被攤平的數量就是j的當格值

               End If
               y(j) = y(j) + Tj
               '↑當天全部攤平總和要累加
               GoTo 111
               '↑跳到 111的位置繼續執行
            End If
            If (Ti <> 0 And Avgd > 1) Or M0 <> M1 Then
            '↑(如果前方格不是0且可攤平天數大於1)或月數已經不一樣了
               GoTo 111
               '↑跳到 111的位置繼續執行
            End If
            If Ti = 0 Then
            '↑如果前方格是0
               Avgd = Avgd + 1
               '↑可攤平天數+1
               Avgv = Round(Tj / Avgd, PP)
               '↑攤平值=須攤平值除以可攤平天數之後四捨五入取整數
            End If
         Next i
      End If
      If Tj <> 0 And j <> Sc Then
      '↑如果當格值不是0 而且不是最後一個日期訂單
         Avgd = 1
         '↑令可攤平天數=1
         For i = j - 1 To 1 Step -1
         '↑設內層倒迴圈!從j當格前一格開始到最前面那天
            M0 = Format(Crr(1, i), "mm")
            '↑令M0是i當格的月分數
            Ti = Crr(x + 1, i)
            '↑令Ti是要判定能不能吃下攤平值的當格
            If Ti <> 0 And Avgd = 1 Then
            '↑如果前方格的值不是0,且可攤平天數是1
               Avgv = Tj
               '↑可被攤平的數量就是j的當格值
               GoTo 111
               '↑跳到 111的位置繼續執行
            End If
            If Ti = 0 And M0 <> M1 And Avgd = 1 Then
            '↑如果前方格是0且可攤平天數等於1且月數已經不一樣了
               Avgv = Tj
               '↑可被攤平的數量就是j的當格值
            End If
            If (Ti <> 0 And Avgd > 1) Or M0 <> M1 Then
            '↑(如果前方格不是0且可攤平天數大於1)或月數已經不一樣了
               GoTo 111
               '↑跳到 111的位置繼續執行
            End If
            If Ti = 0 Then
            '↑如果前方格是0
               Avgd = Avgd + 1
               '↑可攤平天數+1
               Avgv = Round(Tj / Avgd, PP)
               '↑攤平值=須攤平值除以可攤平天數之後四捨五入取整數
            End If
         Next i
      End If
111
      If Avgd > 1 And Avgv <> 0 Then
      '↑如果可攤平天數大於1 且 攤平值不等於 0
         Crr(x + 1, j) = Avgv
         '↑就把攤平值倒入相對位置
         Avgd = Avgd - 1
         '↑可攤平天數就減1
         '可攤平天數因為後面GoTo 111 就必須減到條件不成立

         y(j) = y(j) + Avgv
         '↑當天全部攤平總和要累加
         j = j - 1
         '↑j當格的前一天被用掉了!j就要前進一格
         GoTo 111
         '↑跳到 111位置執行
         ElseIf Avgd = 1 And Avgv <> 0 Then
         '↑否則如果可攤平天數等於1 且 攤平值不等於 0
            Crr(x + 1, j) = Avgv
            '↑就把攤平值倒入相對位置
            Avgd = Avgd - 1
            '↑可攤平天數就減1
            y(j) = y(j) + Avgv
            '↑當天全部攤平總和要累加
            Avgv = 0
            '↑攤平值歸零
      End If
   Next j
Next x
For j = 1 To Sc
'↑設正迴圈讓當日合計放入Crr陣列最後一列
   Crr(UBound(Crr), j) = y(j)
Next
For i = 2 To UBound(Crr) - 1
'↑設正迴圈把所有攤平與不能攤平的訂單值加起來
   For x = 1 To UBound(Crr, 2) - 1
      Ch1 = Ch1 + Crr(i, x)
      '↑Ch1加到最後就是攤平後的總合計
   Next
Next
With Sheets("PP-平均")
'↑下面是有關工作表的程序
   .UsedRange.Offset(1, 0).EntireRow.Delete
   '↑把工作表有使用的列往下偏移一列的範圍刪除
   
   .[2:2].Font.Size = 10
   '↑令第二列字體大小是10
   
   .Range(.Cells(2, 8), .Cells(2, 8 + Cc)).NumberFormatLocal = "m/d;@"
   '↑令即將要放入日期的那幾格的格式是 月/日
   
   .[A2].Resize(UBound(Brr), Bc) = Brr
   '↑先將Brr陣列從A2開始倒入
   .[H2].Resize(UBound(Crr), Cc) = Crr
   '↑再將Crr陣列從H2開始倒入
   .UsedRange.Offset(1, 0).EntireRow.Borders.LineStyle = xlContinuous
   '↑讓儲存格顯示格線
   .[A1] = xA(1, 1)
   '↑把 "PP"工作表的[A1]值帶到此表[A1]
End With
Sheets("PP-平均").Activate
'↑畫面跳到 "PP-平均" 工作表
ActiveWindow.FreezePanes = False
'↑把凍結窗格取消
[H3].Activate: ActiveWindow.FreezePanes = True: [A1].Activate
'↑將H3為界線!讓左側欄位凍結!讓上方列位凍結
Set Brr = Nothing
Set Crr = Nothing
Set y = Nothing
End Sub
Sub 正式執行_檢查()
PP = 0
Call 橫向往前攤平
MsgBox "**誤差量: " & Ch0 - Ch1 & "  **"
End Sub
作者: adam2010    時間: 2022-10-12 21:40

回復 11# Andy2483


    感謝Andy2483大不但協助回復還詳細說明,真是太有心了




歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)