我做生产排期那段时间,被 Excel 日期函数折腾过好几回。当时手里一张订单表,原材料到库日期、工序工时、检验周期都排好了,就差一列“承诺交期”。我心想日期推算还不简单,直接 =A2+14 往下拉,结果到了评审会上,计划员当场反问:中间夹着周末,你让客户在休息日签收吗?赶紧换成常规的 WORKDAY,又发现我们车间周六要上班,系统却默认周六周日都休,日期又往前提了一天。
后来我把 WORKDAY.INTL 从头到尾试了一遍,才真正理解这类需求的本质:不是“日期加天数”,而是在日历上做跳跃式前进,跳过哪些天,完全由你说了算。这就是“自定义工作日”的用法,也是今天想展开讲透的主题。这篇文章适合做生产计划、项目排期、采购交期、人事考勤、财务结算这类天天跟工作日打交道的人,尤其是那些周末不是标准双休、有厂休日、有节假日清单的公司,WORKDAY.INTL 基本上绕不开。
1. 从排期翻车说起:为什么要自定义工作日
1.1 直接用日期加天数,错在哪里
先看一个很常见的场景。你的开工日期是 2025年5月6日(周二),计划工期 10 个自然日,简单相加就是 5 月 16 日。但这个结果不会告诉你:5月10日、11日是周末,很多工厂停产,客户也未必收货;如果你把交货日期定在5月17日(周六),仓库没人做入库,整个计划在验收节点就会断掉。
所以只要涉及生产、项目、物流,就不能只按自然日推,必须换成“工作日”的概念。这里的工作日,指的是真正安排生产、办公、收货的那些天。普通 WORKDAY 函数已经能做到“从起始日开始往后数N个工作日”,但它有个硬限制:周末只能固定为星期六和星期日。一旦你的排班不是这个节奏,比如只休周日、只休周四、甚至休周一周二,WORKDAY 就无能为力了。
1.2 WORKDAY 和 WORKDAY.INTL 的分工差异
Excel 里这组日期函数的定位其实非常清晰:
WORKDAY(开始日期, 天数, [节假日]):按默认双休推算工作日,适用于大多数办公室场景。WORKDAY.INTL(开始日期, 天数, [周末规则], [节假日]):多了一个“周末规则”参数,可以自定义哪几天休息。NETWORKDAYS(开始日期, 结束日期, [节假日]):计算两个日期之间有多少个工作日,默认双休。NETWORKDAYS.INTL(开始日期, 结束日期, [周末规则], [节假日]):计算自定义工作日模式下的工作日天数,和WORKDAY.INTL正好配对使用。
人话理解就是:如果只关心“两个日期之间员工上了几天班”,用 NETWORKDAYS 一族;如果关心“从今天往后数第N个工作日是哪一天”,用 WORKDAY 一族。而带着 INTL 后缀的两个函数,就是把“周末是哪几天”这件最难标准化的事情开放给你配置。
1.3 什么情况下你会真正需要它
我自己总结的场景有这么几类:
- 制造业倒排交期:车间周六要上班,只有周日休息。
- 排班制单位:医院、客服、门店,休息日按周几固定但不一定是周六日。
- 跨节假日项目:计划里明确要排除法定节假日,而且放假调休规则经常变。
- 倒排开工时间:已经定了交付日,需要往前推N个工作日算出最晚开工日。
- 工时统计和考勤:统计两个日期之间实际出勤天数,同时排除公司规定的统一休息日。
在这些场景里,WORKDAY.INTL 的威力才能发挥出来。如果还是只会 =开始日期+天数,遇到跨周末已经容易出错,遇到跨节假日更是一团乱麻。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 函数参数拆解:把 weekend 和 holidays 吃透
2.1 核心参数逐个看
WORKDAY.INTL 的完整结构是这样:
excel复制=WORKDAY.INTL(start_date, days, [weekend], [holidays])
start_date:开始日期,必须是一个真正的 Excel 日期值。days:要向前或向后推算的工作日数量,正数代表往未来推,负数代表往过去推。weekend:可选参数,用来指定哪些天是周末,也就是休息日。holidays:可选参数,必须是一个日期列表,用于排除额外休息日。
省略 weekend 参数时,函数等价于 WORKDAY,休息日默认是周六、周日。省略 holidays 时,只按每周固定节奏推,不排除节假日。
这里有一个容易误会的点:days 到底算不算开始日期当天?Excel 的处理逻辑是——开始日期只是锚点,不算做第一天,从下一个工作日开始数。如果你的需求是“开工当天就算第1个工作日”,那就得把天数减 1,这块到后面高级实战部分我会专门讲。
2.2 weekend 的数字编码:看懂默认双休
weekend 参数有两种写法,一种是数字编码,一种是 7 位字符串,后面这种才是真正“自定义”的精髓。
先看数字编码,它解决的是“不同地区双休日不一样”的情况,能把连续两个休息日或单个休息日都预设好:
| weekend 数字 | 休息日 |
|---|---|
| 1(默认) | 周六、周日 |
| 2 | 周日、周一 |
| 3 | 周一、周二 |
| 4 | 周二、周三 |
| 5 | 周三、周四 |
| 6 | 周四、周五 |
| 7 | 周五、周六 |
| 8 | 仅周日 |
| 9 | 仅周一 |
| 10 | 仅周二 |
| 11 | 仅周三 |
| 12 | 仅周四 |
| 13 | 仅周五 |
| 14 | 仅周六 |
常见的标准双休选择数字 1,如果公司是“周日、周一休息”,就选 2。不过数字只能表达固定的连续休息模式,要表达“周一和周六休息”“周三周五休息”这种不规则安排,就要用到 7 位字符串。
2.3 更稳的 7 位模式:周一到周日的开关
7 位字符串的规则是这样的:一共 7 个字符,从左到右分别代表周一、周二、周三、周四、周五、周六、周日;字符只能是 0 或 1,0 表示上班,1 表示休息。
举几个直接能用的例子:
| 业务场景 | 7 位字符串 | 含义 |
|---|---|---|
| 标准双休 | "0000011" | 周六、周日休息 |
| 单休周日 | "0000001" | 仅周日休息 |
| 单休周六 | "0000010" | 仅周六休息 |
| 周一厂休 | "1000000" | 仅周一休息 |
| 周三、周四休息 | "0011000" | 周三、周四休息 |
| 周一、周六休息 | "1000010" | 周一、周六休息 |
这个写法的好处是直观,一眼就能看出来哪几天休息。但它有个特别容易踩的坑:第一位对应的是周一,不是周日。很多习惯从周日开始排星期的人,容易把字符串整体写反,结果休息日完全错位。第一次用的时候,最好先拿一小段日期验证一下。
2.4 提前把 holidays 设计成一张表
holidays 参数很多人只是随手选中一个日期区域,但实际项目中它会成为整个公式最关键的“基础设施”。
我推荐的做法是:单独建一张工作表,A 列专门放所有需要排除的日期,比如法定节假日、公司统一调休放假日期,每行一个真正的日期值。不要合并单元格,不要出现“国庆放假备注”这类文本,如果非要写说明,放到 B 列单独维护。然后选中这列日期,在“公式”选项卡里用名称管理器定义一个名称,例如 HolidayList。
这样做的好处很明显。第一,公式从 =WORKDAY.INTL(A2,10,"0000011",Sheet1!$F$2:$F$30) 变成 =WORKDAY.INTL(A2,10,"0000011",HolidayList),可读性翻倍。第二,每次维护假期表只需要往固定列里增删日期,所有引用这个名称的公式自动更新。第三,用表格对象(快捷键 Ctrl+T)定义动态区域后,也可以直接写 表名[日期],区域范围会自动扩展。
3. 实战案例:自定义休息日怎么推日期
3.1 场景一:单休车间推10个工作日
先看最典型的单休场景。车间生产节奏是周日休息,其余六天都上班。假设开工日期 A2 是 2025年5月6日(周二),要往后推 10 个工作日,需要完成的动作是:周二到周六上班、周日跳过、下周一继续数。公式这样写:
excel复制=WORKDAY.INTL(A2, 10, "0000001", HolidayList)
推出来结果会在 5 月中旬以后。如果我们把它换成默认双休的 WORKDAY(A2, 10, HolidayList),结果会明显往后偏,因为系统把本来要上班的星期六也当成了休息日,多跳了两三天。这个差异在单休车间特别致命,晚一天承诺,客户可能就转向其他供应商了。
所以公式里到底用数字 1 还是 7 位字符串,取决于休息日是否标准。车间只休周日、周六照常上班的情况,用 "0000001" 最清楚。
3.2 场景二:法定假期加调休日怎么处理
很多公司会用“调休”把周末变成工作日,这让频率变低但规则变乱。最稳妥的思路,不是试图在 weekend 字符串里把所有变化写出来,而是用“休息日清单”来驱动。
具体来说,把 weekend 参数设成 "0000000",也就是所有日期默认都算上班日,再把这一年所有真正的休息日全部放进 holidays 清单里。遇到调休上班的周六,那天不进清单,系统自动把它当工作日;遇到因调休而放假的周日,把它写进清单,系统就会跳过它。
这个方案的底层逻辑是:既然每周规则已经乱到没法用固定字符串表达,那就别让公式去猜,干脆把所有“非工作日”显式列出来。一年通常不会超过一百一十天休息日,维护成本完全可控,但出错率会大幅下降。很多做交付计划的大项目,最终都采用这种“白名单休息日”的方式,而不是每周末去改公式参数。
3.3 场景三:班次不走自然周怎么办
如果员工的班次是“上四休二”或“上二休一”,休息日跟星期几没有固定对应关系,这时候再用 WORKDAY.INTL 死磕就不合适了。因为它的周末规则是按自然周循环的,无法表达“干四天休息两天”这种动态循环。
处理办法很简单:先根据排班表生成员工的休息日期清单,再把这份清单当作 holidays 参数喂给公式。逻辑
