
生产排程的难点不在于把订单按日期排成一列,而在于同时遵守物料齐套、可用产线、日产能、交期和急单优先等约束。本案例用 Excel VBA 构建一个可操作的排产窗体:读取 18 条生产订单,在 5 个工作日内按确定性规则分配产线,并把预览、确认写回和关闭重开串成完整流程。
最终固定回归结果为 16 条排入、2 条待料、0 条因产能不足而未排入。急单 SO-URG-01 被安排到 2026-09-15 的 A 线;SO-011 和 SO-016 因物料未齐套保持待料。本文重点解释数据模型、排序与选位规则、事务式写回、窗体状态管理和验收方法。
为什么有限产能排产比普通排序复杂
普通排序只决定先后顺序,有限产能排产还要回答三个问题:订单能否进入排程、应该落在哪一天、同一天应该选择哪条产线。本案例还增加了急单插入和结果持久化,因此必须把业务规则写成可重复验证的步骤。
- 订单编号必须唯一,数量和单件工时必须大于 0。
- 物料未齐套的订单不占用产能,结果状态写为待料。
- 急单只使用虚拟优先级 999 参与本次计算,不修改源表优先级。
- 单个订单不拆分,日累计工时不能超过对应产线容量。
- 同一参数连续运行三次,排序和排程结果必须一致。
- 预览只显示在窗体中,用户确认后才重建结果表数据区。

生产订单源表
图 1 生产订单表提供订单编号 产品系列 数量 工时 交期 优先级 可用产线和物料齐套状态
数据模型和工作表职责
| 工作表 | 主要内容 | 在流程中的职责 |
|---|---|---|
| 生产订单 | 18 条订单及工时 交期 优先级 可用产线 齐套状态 | 只读业务输入和验收基准 |
| 排产参数 | 默认日期 工作日数 产线容量 窗体控件与规则 | 驱动窗体默认值和算法约束 |
| 排产结果 | 状态区和 10 列结果数据 | 用户确认后一次性写回并供重开回读 |
代码把界面层、业务层、数据层和自检层分开。窗体事件负责读取输入、触发预览和二次确认;Module1 负责读表、校验、生成工作日、排产计算和写回;自检回归 则使用固定答案逐行比对订单编号、计划日期、产线、状态和原因。
语音或自然语言描述可以自动生成窗体;生成后的窗体可在 VBA 中手动编辑和微调。本案例采用钢蓝办公主题,保留 5 个输入项、4 个按钮和 1 个结果区域,业务逻辑仍由独立模块承担。
确定性排序让结果可以复现
急单优先不应直接覆盖源数据。本案例先在内存中建立排序块:急单获得虚拟优先级 999,其他订单沿用源优先级;随后按优先级降序、交期升序、总工时降序、订单编号升序排序。
If 编号 = Trim(急单编号) Then 优先级 = 急单虚拟优先级
排序块(i, 1) = 优先级
排序块(i, 2) = 交期
排序块(i, 3) = 总工时
排序块(i, 4) = 编号
排序后 = SortByCols(排序块, "f1-,f2+,f3-,f4+", 0)
最后使用订单编号作为稳定的第四排序键,可以消除同优先级、同交期和同工时时的随机性。固定输入因此会得到固定输出,便于定位修改是否破坏业务规则。
选位规则同时约束日期 产线和容量
排程循环按工作日从早到晚寻找空位。对同一天的候选产线,代码先排除不在订单可用产线列表中的产线,再检查“已用工时加本单工时”是否超过日产能。多个候选都可行时,选择已用工时最少的产线;负荷相同再按产线字母排序。
If 已用值 + 总工时 <= 容量(线名) + 容差 Then
If 最小已用 < 0 Or 已用值 < 最小已用 - 容差 Then
最小已用 = 已用值
选中线 = 线名
ElseIf Abs(已用值 - 最小已用) <= 容差 Then
If 线名 < 选中线 Then 选中线 = 线名
End If
End If
物料未齐套会在选位前被拦截,因此不会消耗任何产线容量。周期内找不到可行时段时,订单必须进入结果表并标记未排入,原因写为产能不足,避免出现静默丢单。
预览和写回之间设置确认边界
预览阶段只在窗体的结果列表中生成 18 行计划,不修改工作表。点击确认写回后,代码先清空结果表的数据区,再一次性写入当前批次。这个做法属于工作表级的事务式写回,不等同于数据库事务,但能避免重复运行时不断追加相同批次。
ws.Range(ws.Cells(首行, 1), ws.Cells(末行, 结果列数)).Clear
n = UBound(结果, 1)
ws.Range(ws.Cells(首行, 1), _
ws.Cells(首行 + n - 1, 结果列数)).Value = 结果
批次号由开始日、工作日数和急单编号组成。本次批次为 B20260915_5_SO-URG-01。保存工作簿后,窗体从结果表回读同一批次,因此关闭再打开不会重新随机排程。

有限产能排产窗体
图 2 窗体预览显示参数和排产结果 确认写回前工作表数据区保持不变
日期读取错误如何被固定回归发现
初次回归时,日期值经过 Val() 后只保留了年份,计划日期因此出现偏差。修正后,日期字段按表格日期序列读取,并在输出时统一格式化为 yyyy-mm-dd。这类错误很难靠浏览代码发现,却会立刻被逐行固定答案比对捕获。

VBA 代码和回归日志
图 3 VBE 中显示最终业务模块 边界测试通过并记录三次一致写回
验收矩阵覆盖正常路径和边界条件
| 验收项 | 固定输入或动作 | 实际结果 |
|---|---|---|
| 急单优先 | SO-URG-01 开始日 2026-09-15 | 最早排入 2026-09-15 A 线 |
| 物料门禁 | SO-011 和 SO-016 未齐套 | 2 条待料且不占产能 |
| 完整处理 | 生产订单 18 条 | 结果 18 行 其中 16 排入 2 待料 |
| 容量约束 | A B C 三条产线日产能 | 每条产线每日容量差均不小于 0 |
| 重复运行 | 同一参数连续运行 3 次 | 结果一致且不追加重复批次 |
| 取消确认 | 预览后取消写回 | 排产结果表保持不变 |
| 保存重开 | 写回 保存 关闭并重新打开窗体 | 同一批次和结果可回读 |
| 边界输入 | 急单不存在 空产线 超大工时 非法日期 | 阻止预览或明确写入未排原因 |

排产结果工作表
图 4 排产结果表写入批次 B20260915_5_SO-URG-01 并保留 18 行可核验结果
WorkBuddy 提示词如何约束生成过程
本案例的第一条实际提示为:
读取 VBA 技能、VBA 窗体技能、当前工作簿及“排产参数”表规则。先为“生产订单有限产能排产与插单调整窗体”建立窗体 YAML、完成校验并打开真实设计预览,暂不写业务逻辑;预览后等我确认生成。使用“钢蓝办公”(office-steel)主题和明亮浅色外观,严格保证对齐、等宽、间距、完整显示,并控制为5个输入、4个按钮和1个状态/结果区域。

WorkBuddy 首轮提示
图 5 首轮提示先限定案例目标 技能 工作簿规则和窗体预览阶段
这条提示保持简短,但包含五个必要部分:案例目标明确要做有限产能排产窗体;指定读取 VBA 与窗体技能;要求读取当前工作簿和排产参数;先完成设计预览,不提前混入业务逻辑;最后给出控件数量和视觉验收条件。如果缺少阶段边界,界面和业务代码容易同时生成,发现布局问题时修改成本更高。
确认窗体后,第二条实际提示要求复用参数表规则和现有服务,补齐读取、校验、预览、二次确认、事务式写回、幂等运行、保存重开和固定答案回归。回归暴露日期偏差后,只描述可见错误、正确目标和验收结果,让 AI 定点修正数值读取,而不是重新生成整个项目。

WorkBuddy 修正和回归过程
图 6 WorkBuddy 定位日期读取偏差 修正后固定答案回归达到 18 比 18
可复用的需求提示模板如下:
读取当前 VBA 技能和窗体技能,并读取当前工作簿中的业务数据、参数表和规则。先建立符合指定主题的窗体,完成真实设计预览,检查文字、控件、对齐和裁切,等待确认后再生成。随后补齐读取、校验、预览、二次确认、事务式写回、重复运行不堆叠、保存重开回读和边界测试。使用一组固定输入给出逐行期望结果,发现偏差后继续修正,直到固定答案全部通过。
AI 加速的是学习闭环而不是业务判断
AI 能缩短需求澄清、代码骨架、运行、验证和修改之间的往返时间。本案例中,它帮助完成窗体结构、模块拆分、代码同步和日期错误修正。业务人员仍需决定急单优先是否合理、产线容量是否可信、哪些订单允许拆分,以及结果能否进入真实生产流程。
在生产环境复用这套方法前,还应加入权限、历史批次备份、并发修改检测和更完整的异常日志。本次演示证明的是固定数据与既定规则下的可复现实现,不代表代码已经覆盖所有制造场景。
案例数据摘要
- 案例编号:VBA-0092
- 源订单:18 条
- 排程周期:从 2026-09-15 开始的 5 个工作日
- 急单:SO-URG-01
- 结果:16 条排入 2 条待料 0 条产能不足未排入
- 固定答案:18 项逐行结果全部通过
- 重复性:同一参数连续运行 3 次结果一致
- 成片质检:基础文件检查和推广画面检查均通过

