Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

排班引擎 V7.2

Google Apps Script 自動排班系統,適用於公司同仁班表管理。

功能特色

  • 自動產生月班表(N×M 搜索架構 + ILS 迭代優化)
  • 動態評分機制:自動適應不同月份結構(如 2 月年假密集期)
  • 智慧優化:Gap-Fixing Swap(空班填補交換)+ Hour-Balancing Swap(工時平衡交換)
  • 人力吃緊日識別與保護機制(Look-ahead 預判)
  • 跨月約束檢查:參考上月最後 5 天班表,確保月初排班符合所有法規約束
  • 支援排休意願、指定班表、公假
  • 差勤匯出 (CSV)
  • 行事曆匯出 (ICS)

專案結構

本專案由三個 JavaScript 檔案組成,需全部貼入 Google Apps Script:

檔案 說明 主要功能
scheduling.js 排班主程式 選單建立、排班流程控制、核心排班迴圈、輸出寫入
helper.js 輔助函式庫 候選人篩選/評分、連續天數檢查、智慧優化 (Swap)、ILS 演算法
load.js 資料讀取模組 讀取工作表並解析為結構化資料(含上月班表)

使用教學

方法 A:快速開始(建議)

直接建立範本副本即可開始使用。範本內已包含所有必要的工作表格式以及 Apps Script 程式碼。

  1. 取得範本點此開啟「排班系統」範本

  2. 建立副本:點擊選單 「檔案」「建立副本」

    建立副本

  3. 完成:您現在擁有一個已經設定好的試算表了!請直接跳至 步驟 5:授權與執行 進行授權。


方法 B:手動建立教學

如果您希望從頭開始建立試算表,請依照以下步驟操作:

步驟 1:建立 Google 試算表

  1. 前往 Google Sheets
  2. 點擊 「空白」 建立新試算表
  3. 將試算表命名為 排班系統 (或任意名稱)

新建試算表


步驟 2:建立工作表

在試算表底部,點擊 「+」 新增工作表,並依照以下 名稱完全一致 建立:

# 工作表名稱 用途 必要
1 人員名單 (Staff) 員工基本資料 必要
2 班別資料庫 (Shift_DB) 班別定義 必要
3 系統參數 (System_Params) 假日設定、預設規則 必要
4 每日需求 (Daily_Needs) 特定日期人力需求 必要
5 指定班表 (Fixed_Shifts) 強制指定班別 必要
6 排休意願 (Leave_Requests) 員工請假/畫休/公假 必要
7 上月班表 (Prev_Month) 上月最後 5 天班表(跨月約束) 選填
8 排班主表 (Scheduler) 【輸出】產生的班表 必要
9 統計報告 (Summary) 【輸出】工時統計 必要
10 差勤匯出 (CSV_Export) 【輸出】差勤格式 必要

重要:名稱必須 完全一致(含空格、括號),否則程式會報錯! 提示:第 7 項「上月班表」為選填,不建立也不影響排班功能。

工作表分頁


步驟 3:設定工作表欄位

1. 人員名單 (Staff)

A 欄 B 欄 C 欄 D 欄 E 欄
員工代號 姓名 工號 啟用 (顏色標記)

範例資料:

員工代號  姓名      工號      啟用    (E欄可留空)
A         王小明    EMP001    TRUE
B         李小華    EMP002    TRUE
C         張大文    EMP003    FALSE   ← 不參與排班

提示:E 欄可設定背景顏色,該顏色會顯示在班表上

人員名單


2. 班別資料庫 (Shift_DB)

A 欄 B 欄 C 欄 D 欄 E 欄 F 欄 G 欄
班別代號 班別名稱 開始時間 結束時間 工時 差勤代碼 11小時限制

必要班別(系統需要這三個):

班別代號  班別名稱  開始時間  結束時間  工時  差勤代碼  11小時限制
S1        正規班    08:00     17:00     8     125-2     FALSE
CA        公假      08:00     17:00     8     CA        FALSE
OFF       休息      -         -         0     0         FALSE

可選班別(夜班範例):

S2        夜班CF    14:00     01:00     11    CF        TRUE
S3        夜班CL    15:00     02:00     11    CL        TRUE

關鍵代碼說明

  • 125-2:預設工作班(必須有)
  • CA:請假班(必須有)
  • 0:休息班(必須有)
  • 11小時限制 = TRUE:該班下班後,隔天不能排早班

班別資料庫


3. 排休意願 (Leave_Requests)

A 欄 B 欄 C 欄 D 欄 E 欄 ...
日期 星期 (姓名1) (姓名2) (姓名3) ...

範例資料:

(A1 留空)  (B1 留空)   ← 第 1 行:空白或標題
(A2 留空)  (B2 留空)   ← 第 2 行:空白或標題
1          三          王小明    李小華*
2          四          張大文
3          五

重要:前兩行為 header,系統會跳過,請從第 3 行開始填寫資料

命名規則

  • 王小明:畫休(輪休,無工時)
  • 王小明*王小明(公假):請假(CA,計算工時)
  • 王小明(公)王小明(公):公假(OL,計算連續上班天數,8 小時工時)

排休意願


4. 每日需求 (Daily_Needs)

A 欄 B 欄 C 欄
日期 班別代號 需求人數

範例資料:

日期        班別代號  需求人數
2025/1/15   S1        8        ← 1/15 需要 8 人上正規班
2025/1/15   S2        0        ← 1/15 不需要夜班
2025/1/20   S1        10       ← 1/20 全員動員

重要:若某日有特殊需求,必須所有工作班別都指定人數才會正常運作。例如 1/15 要調整 S1 人數,則 S2、S3 也必須一併指定,否則未指定的班別會使用預設規則。

每日需求


5. 系統參數 (System_Params)

A 欄 B 欄 C 欄 D 欄 E 欄
假日日期 (備註) 規則類型 班別代號 需求人數

範例資料:

假日日期     備註      規則類型   班別代號  需求人數
2025/1/1     元旦      weekday    S1        6
2025/1/29    除夕      weekday    S2        2
                       holiday    S1        3
                       holiday    S2        1

規則類型

  • weekday:平日預設需求
  • holiday:假日預設需求

重要:非六日的國定假日(如元旦、春節、端午等)必須在 A 欄手動輸入日期,否則系統會將該日視為平日排班。

系統參數


6. 指定班表 (Fixed_Shifts)

A 欄 B 欄 C 欄 D 欄 ...
日期 班別代號 姓名1 姓名2 ...

範例資料:

日期        班別代號  (指定人員)
2025/1/10   S2        王小明    李小華
2025/1/11   S3        張大文

說明:指定班表優先權最高,會覆蓋排休意願

指定班表


7. 上月班表 (Prev_Month)(選填)

格式與「排班主表 (Scheduler)」的輸出格式相同。用於跨月約束檢查,只需填入上月最後 5 天的班表資料。

第一行為 header,格式範例:

排休      125-2(6)  CF(2)   CL(1)
  • 排休:該欄列出當天排休的員工姓名(格式:姓名(公), 姓名(假), 姓名(休),逗號分隔)
  • 125-2(6):班別名稱 + 括號內數字(數字可為任意值,系統只看班別名稱)
  • 各班別欄位中填入該班的員工姓名,一行一天

資料列範例(假設上月為 1 月,填最後 5 天):

排休                          125-2(6)          CF(2)       CL(1)
王小明(休), 李小華(假)         張大文, 陳小芳     趙六        錢七
...

提示

  • 最簡單的做法:直接從上月「排班主表」整份複製(含 header)貼上即可,系統會自動只取最後 5 天的資料
  • 若不建立此工作表,系統行為與以前完全一致(月初不做跨月約束檢查)

上月班表


8-10. 輸出工作表

以下三個工作表 不需要手動填寫,系統會自動產生:

  • 排班主表 (Scheduler) - 產生的班表
  • 統計報告 (Summary) - 工時統計
  • 差勤匯出 (CSV_Export) - 差勤系統格式

步驟 4:貼上程式碼

  1. 在試算表中,點擊選單 「擴充功能」「Apps Script」

  2. 刪除編輯器中預設的程式碼:

    function myFunction() {
    
    }
  3. 建立 三個 檔案,並分別貼上對應的程式碼:

    Apps Script 檔案名稱 來源檔案 說明
    scheduling.gs scheduling.js 主程式(含 onOpen 選單)
    helper.gs helper.js 輔助函式與優化演算法
    load.gs load.js 資料讀取模組

    在 Apps Script 編輯器中,點擊左側檔案列表旁的 「+」「指令碼」 來新增檔案。 提示:新增檔案時只需輸入檔名前綴(如 scheduling),Apps Script 會自動加上 .gs 副檔名。

    Apps Script 編輯器

  4. 點擊 「儲存」 圖示 (或按 Ctrl+S)

  5. 將專案命名為 排班引擎


步驟 5:授權與執行

  1. 首次執行需要授權

    • 點擊 「執行」 按鈕(或從試算表選單執行)
    • 出現「需要授權」對話框,點擊 「查看權限」
    • 選擇你的 Google 帳號
    • 點擊 「進階」「前往 排班引擎 (不安全)」
    • 點擊 「允許」

    查看權限

    允許授權

  2. 重新整理試算表(按 F5 或重新開啟)

  3. 試算表選單會出現 「排班引擎 V7.2」

自訂選單


使用方式

產生班表

  1. 點擊選單 「排班引擎 V7.2」「1. 產生本月班表」
  2. 輸入 年份 (例如: 2025)
  3. 輸入 月份 (例如: 1)
  4. 確認執行
  5. 系統執行運算,視人數多寡約需 2-5 分鐘

輸入年份

輸入月份

確認執行

執行中進度

提示:執行中的進度訊息會顯示在試算表右下角,顯示目前處理到第幾個初始解及 ILS 迭代進度。

運算完成

產生統計報告

  1. 先產生班表(或手動修改過班表後想重新計算統計)
  2. 點擊 「2. 產生統計報告 (Summary)」
  3. 輸入年份確認
  4. 結果會寫入 統計報告 (Summary) 工作表

提示:產生班表時會自動產生統計報告。此功能適用於手動調整班表後,需要重新計算統計數據的情境。

匯出差勤 CSV

  1. 先產生班表
  2. 點擊 「3. 產生差勤匯出 (CSV)」
  3. 輸入年份確認
  4. 結果會寫入 差勤匯出 (CSV_Export) 工作表

匯出行事曆 ICS

  1. 先產生班表
  2. 點擊 「4. 產生行事曆 (ICS)」
  3. 輸入年份確認
  4. ICS 檔案會存到 Google Drive 資料夾

輸出結果範例

排班主表

統計報告


排班演算法架構

N×M 搜索流程

每個初始解都獨立做 ILS 優化,最後取全域最佳,搜索廣度遠優於「先選最佳再優化」。

Phase 0: 載入上月班表 (若有)
  └─ Warm-up:回放上月最後 5 天,初始化連續天數/lastShift 等狀態

Phase 1+2: N×M 搜索 (50 個初始解 × 20 次 ILS = 1,000 次運算)
  For each 初始解:
  ├─ 核心排班 (coreScheduler)
  │   ├─ P0 吃緊日預排
  │   ├─ P1 每日需求分配
  │   ├─ P2 請假處理
  │   ├─ P3 畫休處理
  │   └─ P4B 剩餘人員填補 (燃盡圖邏輯)
  ├─ 空班補救 (fillUnfilledSlots)
  ├─ 智慧優化 (Gap-Fixing Swap + Hour-Balancing Swap)
  ├─ 工時消減 (reduceOverworkedStaff)
  ├─ ILS 迭代優化 (最多 20 次)
  │   ├─ 擾動 (Perturbation)
  │   │   ├─ 策略 A: 同日交換兩人班別
  │   │   ├─ 策略 B: 隨機切換上班/休息
  │   │   └─ 策略 C: 跨日交換 (同一人不同天)
  │   └─ 局部搜索 + 接受/拒絕判定
  └─ 與全域最佳比較,保留更優解

Phase 3: 最終驗收
  ├─ 計算空班數
  ├─ 計算工時全距
  └─ 輸出結果報告

優先順序

指定班表 > 公假 > 每日需求 > 排休意願 > 畫休意願 > 自動填補

約束條件

規則 說明
全域連續上限 最多連續上班 5 天
含夜班連續上限 含夜班時最多連續 3 天
純夜班連續上限 純夜班最多連續 3 天
11 小時規則 夜班 (S2/S3) 後隔天不能接早班(雙向檢查)
吃緊日保護 人力吃緊日預排結果受保護,不被後續覆蓋
Look-ahead 預判 排班時預判是否會與未來吃緊日衝突
跨月約束 月初排班參考上月最後 5 天,所有約束跨月生效

工時計算

  • 目標工時 = 當月工作日數 × 8 小時
  • 系統透過 ILS 優化,盡量讓全員工時全距 ≤ 4 小時
  • 完美達成條件:零空班 + 工時全距 ≤ 4 小時

動態評分機制

系統會根據當月結構自動調整評分權重,解決 2 月等假日密集月份的超時問題:

優先順序:工時全距 >> 超工時 >= 空班

指標 權重 說明
工時全距 56,000 / 小時 最高優先,確保全員工時均衡
超工時 5,000 × sqrt 遞減效應,避免糾結不可避免的超時
空班數 3,000 / 空班 填班重要但不強制

動態超時門檻:系統自動計算當月「結構性超時」(總需求 > 總容量時不可避免的超時),門檻會自動上移,讓演算法專注於可改善的項目。

例:2 月目標工時 120h,但需求換算人均 140h → 門檻自動提升至 144h,低於門檻不扣分


智慧優化機制

Gap-Fixing Swap(空班填補交換)

當某個班別出現空缺時,尋找可行的三方交換:

  1. 找到空班 T(Target Shift)
  2. 找到員工 A:目前上 S 班,但可以上 T 班
  3. 找到員工 B:目前休息,但可以上 S 班
  4. 交換:A 補 T,B 接手 S

Hour-Balancing Swap(工時平衡交換)

計算全員平均工時,讓工時高於平均的人將班次轉給工時低於平均的人,縮小整體工時差距。

ILS 迭代優化

每個初始解各自進行「擾動 + 局部搜索」循環,透過隨機擾動跳脫局部最佳解,並設有:

  • 連續無改善上限(8 次)自動停止
  • 時間上限(5 分鐘)保護
  • 機率性接受較差解(10%)避免陷入局部最優

常見問題

Q: 出現「找不到工作表」錯誤

A: 請確認工作表名稱完全一致,包含空格和括號。

Q: 某人一直沒被排到班

A: 檢查「人員名單」的 D 欄(啟用)是否為 TRUE

Q: 排班結果不符合預期

A:

  1. 檢查「系統參數」的 weekday/holiday 規則
  2. 檢查「每日需求」是否有特殊設定
  3. 檢查「指定班表」是否有強制指派

Q: 夜班後隔天還是被排早班

A: 確認「班別資料庫」的 G 欄(11小時限制)設為 TRUE

Q: 執行時間很長

A: V7.2 採用 N×M 搜索架構(50 個初始解 × 20 次 ILS = 1,000 次運算),通常需要 2-5 分鐘。每個初始解都有機會被優化到各自的局部最優,最後取全域最佳,品質比舊架構更好。

Q: 公假怎麼設定

A: 在「排休意願」工作表中,姓名後加上 (公)(公),例如 王小明(公)。公假會計算 8 小時工時並計入連續上班天數。

Q: 上月班表怎麼設定?不設定會影響排班嗎?

A: 「上月班表 (Prev_Month)」工作表為選填。不建立此工作表,系統行為與以前完全一致。 若要啟用跨月約束檢查,最簡單的做法是:從上月排好的「排班主表」複製最後 5 行(含第一行 header)貼到「上月班表」即可。系統會自動參考這些資料,確保月初不會出現上月夜班隔天接早班、連續上班超過上限等違規情況。

Q: 上月班表只填 3 天可以嗎?

A: 可以。系統只取最後 5 天資料,若不足 5 天則以實際天數為準。填越多天數,跨月約束檢查越完整。


版本紀錄

  • V7.2 - N×M 搜索架構(50×20)+ 動態評分機制(自動適應 2 月等特殊月份)
  • V7.1 - 跨月約束檢查:讀取上月最後 5 天班表,月初排班所有約束跨月生效
  • V7.0 - ILS 迭代優化架構 + 預先初始化 finalSchedule
  • V6.9.25 - 智慧優化演算法:Gap-Fixing Swap 空班填補交換
  • V6.9.24 - 空班補救支援 S2/S3 + 11hr 雙向檢查
  • V6.9.23 - 吃緊日保護機制 + Look-ahead 預判,減少空班
  • V6.9.22 - 空班補救機制(只補空班,不強制工時達標)
  • V6.9.20 - 修正含夜班連續天數限制 hasNightInStreak
  • V6.9.19 - 公假明天不排夜班的往前看規則
  • V6.9.18 - 公假獨立結構 (OL)
  • V6.9.17 - 新增公假虛擬班別
  • V6.9.15 - 動態班別排序(候選人少的優先)
  • V6.9.12 - 人力吃緊日識別機制
  • V6.9.11 - 班別分配順序:S2 → S3 → S1
  • V6.9.10 - 修正姓名匹配邏輯
  • V6.9.9 - 新增班別計數統計
  • V6.9.8 - 修正 11 小時規則
  • V6.8 - 新增工時平衡重跑機制

授權條款

本專案採用 MIT License 授權。

About

For the fair scheduling with realted Taiwan banned rules

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages