ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Excel WEEKNUM周数计算:年度与月度周数及跨年边界

Excel WEEKNUM周数计算:年度与月度周数及跨年边界

1. 先把“周数”这件事的边界划清楚

做数据整理的人大多有过这种经历:一份日报汇总表,按天记录得好好的,领导一句“按周看趋势”,整张表就得重做;换成“按月度周数对齐一次促销节奏”,公式立刻开始飘。我第一次碰这块,是在一份跨部门共用的排期表里,当时我想当然地觉得WEEKNUM就是“输入日期、返回第几周”,两分钟搞定,结果第二天早上被打回来——1月初的两行数据被算成了第53周,跨年度的透视表直接把两个年份的数据混成了一坨。后面我花了整整半天,才把WEEKNUM的return_type参数、两种“第一周”判定系统、以及“月度周数”和“年度周数”根本不是一回事这三层逻辑捋顺。

这篇整理就是那次返工之后沉淀下来的东西。核心围绕WEEKNUM这一个函数展开,但真正要讲清楚的是三件事:年度周数怎么算才不出边界事故、月度周数怎么用纯公式推出来、以及周数结果怎么接进真实报表而不被坑。适合已经会用SUMIF、VLOOKUP,但一碰到日期就靠猜的人;也适合被“这个月第几周”“这周属于哪个月”反复折磨、想一次性把逻辑钉死的人。我会把参数表、推导过程、验证数据和踩过的坑都摊开写,你可以直接抄公式,但更建议先看懂每一步为什么这么写。

需要提前说一个前提:周数这个东西没有唯一正确答案,只有“约定”。一周从周几开始、跨年的那一周算谁的,这两件事一旦约定不同,同一个日期的周数就会差 1 甚至差 52。所以所有周数公式的第一件事不是写代码,而是先跟使用这张表的人把约定对齐。这一点想明白了,后面所有的公式错误都会变得很好定位。

2. WEEKNUM 的语法与 return_type 全景对照

2.1 语法结构与两个参数到底在控制什么

WEEKNUM的完整写法是WEEKNUM(serial_number, [return_type]),两个参数,简单到容易让人掉以轻心。第一个参数serial_number要的是一个日期序列值,注意是“序列值”,不是“看起来像日期的文本”。这是新手第一道坎:单元格里显示2024/3/1不代表它是日期,可能是文本,WEEKNUM直接抛#VALUE!。判断方法很土但很好用——选中单元格看编辑栏,如果日期前面带单引号,或者格式是“文本”,那就是假的。真日期做一次A2+1会变成第二天,假日期会报错或者原样拼接。

第二个参数return_type才是这个函数的灵魂,也是几乎所有周数事故的源头。它同时控制两件事:一周从星期几开始,以及“一年的第一周”怎么判定。很多人只知道前半句,不知道后半句,于是写出了“看起来对、跨年就错”的公式。我见过最典型的写法就是=WEEKNUM(A2),什么都不填,默认按周日起始、按“包含 1 月 1 日的那一周为第 1 周”来算。在纯周日起始习惯的团队里没问题,但只要对方是按周一对齐排产的,整张表就会系统性偏移一天到六天。

还有一个细节值得单独点出来:return_type省略和显式写1是等价的,但在团队协作的表里我强烈建议显式写。原因不在技术,在可维护性——半年后接手的人看到WEEKNUM(A2, 2)会立刻明白这是周一起始,看到WEEKNUM(A2)就得回去翻文档猜。省两个字符换来的理解成本,完全不划算。

2.2 return_type 取值对照表与选型建议

把取值摊成表来看,逻辑会清楚很多。下面这张表是我自己贴在笔记里的版本,比官方文档多了一列“什么时候用它”:

return_type一周起始日第一周判定系统典型使用场景
1 或省略周日系统 1沿用周日起始习惯的旧表、少量个人统计
2周一系统 1绝大多数国内排产、考勤、周报场景
11周一系统 1与 2 结果基本一致,建议不要混用
12周二系统 1特殊行业排期,极少见
13周三系统 1同上
14周四系统 1同上
15周五系统 1同上
16周六系统 1同上
17周日系统 1等价于 1,一般不用
21周一系统 2(ISO 8601)需要与国际通用周号对齐、跨系统交换数据

选型其实只有三条建议,很干脆。第一,只要没有特殊要求,统一用2,周一起始符合大部分国内业务的直觉,月初月末对账也顺。第二,如果数据要和外部系统交换、或者对方明确说“用 ISO 周号”,直接上21或者干脆换成ISOWEEKNUM,不要试图用2去凑。第三,11到17这一组我基本不用,因为它们和2在常规场景下结果一样,混在表里只会制造“为什么这两个单元格公式不一样”的疑问,属于给自己找麻烦。

这里补一句关于11的说明:网上有些资料会强调11和2存在细微差别,实践中在主流版本里两者结果是一致的,但既然存在争议,最稳的做法就是全表统一用一个值,别一半用2一半用11。统一约定比追求“哪个更正确”重要得多。

2.3 系统 1 与系统 2:两种“第一周”的判定逻辑

这是整篇文章最需要掰开讲的一块。系统 1 的规则是:包含 1 月 1 日的那一周,就是这一年的第 1 周。系统 2(ISO 8601)的规则是:包含 1 月 4 日的那一周,才是这一年的第 1 周。

为什么差这几天?因为系统 1 优先保证“1 月 1 日必须有归属”,不管这一周有几天落在新年里;系统 2 优先保证“每一周都是完整的七天”,并且要求一年的第一周至少有四天落在本年内。这两种诉求本身没有对错,但结果会在跨年附近打架。

拿一个真实感很强的例子:2024 年 1 月 1 日是周一,2024 年是闰年共 366 天,正好 53 个完整周。用=WEEKNUM("2024-12-31", 2)算出来是 53,因为 2024 年 1 月 1 日那一周就是第 1 周,往后数到 12 月 30 日开始的这一周,正好第 53 周。但用=ISOWEEKNUM("2024-12-31")算出来是1,因为 2025 年 1 月 4 日落在 12 月 30 日开始的这一周里,按 ISO 规则这已经是 2025 年的第 1 周了。

同一个日期,一个说 53,一个说 1。如果一张表里混用了这两种算法,做年度汇总时就会出现“2024 年第 1 周”和“2025 年第 1 周”同时存在两行,数据被打散。我遇到的那次返工就是这个问题:日报表用默认的WEEKNUM,月度分析表用了ISOWEEKNUM,两份数据一碰,1 月初和 12 月末各有一段对不上。

注意:不要试图用“加一天”“减一天”这种补丁式写法去弥合系统 1 和系统 2 的差异。年份不同、闰年与否不同,偏移量会变,补丁一定会失效。要么全用系统 1,要么全用系统 2,约定一次,写进字段说明里。

3. 年度周数的精准计算与跨年边界处理

3.1 最省事的写法,以及它的隐患在哪里

单看某一天是当年第几周,=WEEKNUM(A2, 2)就够了,不需要任何花活。这个公式的可靠性其实很高,问题从来不在函数本身,而在使用者对结果的解读。隐患集中在三个位置:跨年的 12 月末、跨年的 1 月初、以及用周数去做排序和分组的时候。

12 月末的隐患是“第 53 周”这个存在感很低的值。很多人默认一年 52 周,公式里写了MOD(周数, 52)之类的处理,结果 53 被映射成 1,和真正的第 1 周撞车。1 月初的隐患正好相反:有些日期会被算成上一年的第 52 或 53 周,如果你的汇总表是按年份字段筛选的,这部分数据会被悄悄漏掉——筛选 2024 年,拿不到 2024 年 1 月 1 日的数据,因为它被标成了 2023 年第 53 周。这种漏数据最要命,因为它不报错。

还有一个容易被忽略的点:周数单独拿出来是没有唯一性的。第 5 周这个值,在 2023 年、2024 年、2025 年都会出现,它必须和年份绑定才有意义。所以任何用于分组、去重、匹配的场景,都不应该只用WEEKNUM的结果当键,必须构造成“年 + 周”的复合键。这是我在一次去重失败之后刻进肌肉记忆的规则。

3.2 跨年边界的三种处理套路

跨年怎么算,取决于你要回答的问题是什么。我总结了三种常见诉求,各自的写法不一样。

第一种,按自然年归属。就是无论这一周跨不跨年,1 月 1 日之后的日子一律算新年。这正是系统 1 的行为,直接=WEEKNUM(A2, 2)配合=YEAR(A2)就行,最省事,也是大多数国内周报的默认逻辑。

第二种,按 ISO 周归属。用=ISOWEEKNUM(A2),年份不能直接用YEAR(A2),得单独算 ISO 年份。这里的技巧是“周四归属法”:一周里周四落在哪一年,这一周就属于哪一年。公式写法:

=YEAR(A2 - WEEKDAY(A2, 2) + 3)

逻辑很直白:WEEKDAY(A2,2)得到今天是本周第几天(周一为 1),减掉它再加 1 就是本周周一,再加 3 就是本周周四。周四在哪年,这周就归哪年。配合ISOWEEKNUM用,跨年时不会出现“年份和 ISO 周号互相矛盾”的情况。

第三种,按业务周期归属。比如排产表以“每周一为界”,跨年的那一周整周算新年第一周,即使它有几天在去年。这种就是自定义规则了,没法靠内置参数解决,只能自己构造。常用写法是先算出本周周一,再看周一落在哪一年:

=YEAR(A2 - WEEKDAY(A2, 2) + 1) & "-W" & TEXT(WEEKNUM(A2 - WEEKDAY(A2, 2) + 1, 2), "00")

先把日期归一到所在周的周一,再用周一的年度周数当身份,这样整周只有一个标识,不会出现同一周里两天算出不同结果的情况。这个思路在按周汇总时非常关键,下面还会反复用到。

3.3 构造“年-周”唯一键的几种写法对比

只要涉及分组汇总,“年-周”复合键就绕不开。我试过几种写法,各有适用面,列出来供你按场景挑。

写法公式示例优点缺点
简单拼接=YEAR(A2)&"-"&WEEKNUM(A2,2)好懂、好维护跨年周会被拆成两个键
周四归属法=YEAR(A2-WEEKDAY(A2,2)+3)&"-"&WEEKNUM(A2,2)跨年周归并正确与 ISO 周号仍需对齐验证
周一归属法=TEXT(A2-WEEKDAY(A2,2)+1,"yyyy-mm-dd")唯一性最强、可直接排序可读性差,不像“第几周”
直接存周一日期=A2-WEEKDAY(A2,2)+1可排序、可做日期区间计算需要额外格式化展示

我现在的做法是:分组键用“周一日期”,展示列用“第几周”。因为周一的日期天然唯一、天然可排序、天然能算区间,而“第几周”只作为人看的标签。这样既避免了字符串拼接带来的排序混乱(2024-1和2024-10按文本排序会跑到2024-2前面),也避免了跨年归属的争议。如果你只想记一条,就记这条:能用日期当键,就不要用拼出来的字符串当键。

4. 月度周数的公式推导与落地

4.1 需求澄清:三种“月度周数”根本不是一回事

标题里的“月度周数”是个含糊说法,实操中至少对应三种完全不同的需求,先分清楚再写公式,否则一定白干。

第一种,这个日期在当月是第几周。比如 3 月 15 日,问它是 3 月的第几周。这是最常见的需求,用于月度内的节奏分析、促销分期。

第二种,这个月一共有几周。比如 3 月是 5 周还是 6 周,用于生成周维度的空行模板、算月度周均值。

第三种,这一周属于哪个月。这是反向问题,用于把按周汇总的数据归到月份。麻烦在于跨月周必然有争议:一周里 3 天在 2 月、4 天在 3 月,算哪个月?通常按“多数天数归属”或者“周四归属”来定。

这三种需求里,第一种和第二种可以用同一套逻辑推出来,第三种是它的镜像。下面重点推第一种,因为它最容易出错,也最能体现公式的设计思路。

4.2 公式推导:从“当月 1 日所在周”倒推

需求定义先钉死:把包含当月 1 日的那一周定义为当月第 1 周,之后每过一个周一,周数加 1。这个定义符合直觉,也和年度周数的系统 1 逻辑保持一致。

推导分三步,我用手算的方式写一遍,看懂了就不用背公式。

第一步,找到当月 1 日。设目标日期在 A2,当月 1 日就是A2 - DAY(A2) + 1,因为DAY(A2)是当月的第几天,减掉再补 1 就回到了 1 号。

第二步,找到当月 1 日所在那一周的周一。设 1 日是星期 W(周一为 1,周日为 7),那本周的周一就是1日 - (W - 1)。用WEEKDAY(当月1日, 2)就能拿到 W。

第三步,算目标日期距离这个周一有多少天,除以 7 取整再加 1。距离 =(DAY(A2) - 1) + (W - 1),化简就是DAY(A2) + W - 2。

合并成一条公式:

=INT((DAY(A2) + WEEKDAY(A2 - DAY(A2) + 1, 2) - 2) / 7) + 1

手动验证一遍,选 2024 年 3 月。3 月 1 日是周五,WEEKDAY返回 5。代入 3 月 1 日:(1 + 5 - 2) / 7 = 0.57,取整 0,加 1 得1,正确,因为 3 月 1 日所在周就是 3 月第 1 周。再代入 3 月 3 日周日:(3 + 5 - 2) / 7 = 0.857,取整 0,还是第 1 周,正确。代入 3 月 4 日周一:(4 + 5 - 2) / 7 = 1,取整 1,加 1 得2,正确,跨过周一了。代入 3 月 31 日周日:(31 + 5 - 2) / 7 = 4.857,取整 4,加 1 得5,说明 2024 年 3 月有 5 个周。核对一下:2 月 26 日至 3 月 3 日、3 月 4 日至 10 日、11 日至 17 日、18 日至 24 日、25 日至 31 日,正好 5 段,公式站得住。

再换一个容易翻车的月份:2023 年 1 月。1 月 1 日是周日,WEEKDAY返回 7。代入 1 月 1 日:(1 + 7 - 2) / 7 = 0.857,取整 0,得第 1 周。代入 1 月 2 日周一:(2 + 7 - 2) / 7 = 1,取整 1,得第 2 周。代入 1 月 31 日周二:(31 + 7 - 2) / 7 = 5.14,取整 5,加 1 得6。也就是说 2023 年 1 月有 6 个“月度周”。这不是公式错了,是真实情况——1 月 1 日孤零零占了第 1 周,后面 30 天正好排满 4 周多 2 天,凑出第 6 周。这个结果第一次看到会以为出错,实际是对的。

由此可以总结出一条规律,非常实用:当月的第 1 周包含几天,取决于 1 日是周几。1 日是周一,第 1 周满 7 天;1 日是周二,第 1 周 6 天;依次递减,1 日是周日,第 1 周只有 1 天。31 天的月份,如果第 1 周只有 1 到 2 天,剩下来的 29 到 30 天就会撑出第 6 周。所以“1 日落在周六或周日,且当月 31 天”这个组合,必然出现 6 个周。反过来,30 天的月份最多 5 周,2 月最多 5 周。这个判断在做月度报表模板时很有用,能提前知道要不要预留第 6 行,不至于做好的模板月底突然溢出。

4.3 换周起始日、换月份边界时的公式变体

上面那条公式默认周一为一周起始。如果团队习惯周日起始,只改一个地方——把WEEKDAY的第二参数从2换成1,其余不动:

=INT((DAY(A2) + WEEKDAY(A2 - DAY(A2) + 1, 1) - 1) / 7) + 1

注意这里减数从 2 变成了 1,因为周日的序号是 1,公式里的常数要跟着变。这种“改参数顺带改常数”的地方最容易漏,我一开始就漏过,结果整月数据差一天,排查了半小时。稳妥做法是别手改,直接把起始日做成一个参数单元格,公式里引用它:

=INT((DAY(A2) + WEEKDAY(A2 - DAY(A2) + 1, $F$1) - IF($F$1 = 1, 1, 2)) / 7) + 1

F1 里填 1 或 2,整表跟着变。这种参数化的写法在共用模板里特别值钱,省掉了“给不同部门各维护一份”的麻烦。

第二个变体是“月度周数”的第二种需求——算这个月总共几周。用同一条公式套在月末日期上即可:

=INT((DAY(EOMONTH(A2, 0)) + WEEKDAY(EOMONTH(A2, 0) - DAY(EOMONTH(A2, 0)) + 1, 2) - 2) / 7) + 1

EOMONTH(A2, 0)返回当月最后一天,把它当成目标日期代进去,得到的就是当月总周数。这条公式可以直接填进模板的第一行,用来生成周次下拉列表。

第三个变体是反向归属——某一天所在的周属于哪个月。这里必须先明确规则,我一般用“周四归属法”,和 ISO 的思路一致:一周里周四落在哪个月,这周就归哪个月。公式:

=TEXT(A2 - WEEKDAY(A2, 2) + 3, "yyyy-mm")

减WEEKDAY加 1 得周一,再 +3 得周四,取月份。这样跨月周不会出现“同一周的数据被拆到两个月”的情况。如果业务上更接受“多数天数归属”,那就在周一到周日之间找中间那天,效果类似,关键是全表统一。

4.4 实操记录:一份月度排期表的完整验证

光看公式容易飘,拿一张具体的表验证一遍才踏实。我搭了一个小样表,A 列放 2024 年 3 月的全部 31 天,B 列是年度周数,C 列是月度周数,D 列是“本周周一”,E 列是月度周数对应的周区间标签。

日期年度周数月度周数本周周一区间标签
2024/3/1912024/2/262/26-3/3
2024/3/3912024/2/262/26-3/3
2024/3/41022024/3/43/4-3/10
2024/3/171132024/3/113/11-3/17
2024/3/241242024/3/183/18-3/24
2024/3/311352024/3/253/25-3/31

验证过程中有几个发现值得记下来。第一,年度周数和月度周数在月初是不同步的,3 月 1 日的年度周数是 9,月度周数是 1,这两个数字没有任何换算关系,不能互相推。这一点看起来是废话,但我见过有人写“月度周数 = 年度周数 - 上个月最后一周的年度周数”这种公式,一旦跨年立刻崩。第二,同一周内的所有日期,月度周数必须相同,这是公式正确性的自检标准——如果一周里出现两个不同的月度周数值,公式一定有问题。第三,第 1 周往往不完整,2 月 26 日到 29 日这四天也属于 3 月的第 1 周,做月度统计时要决定这四天的数据算不算进 3 月,这是业务问题不是公式问题,得提前跟使用方确认。

区间标签那一列是我额外加的,写法很简单:

=TEXT(A2-WEEKDAY(A2,2)+1,"m/d") & "-" & TEXT(A2-WEEKDAY(A2,2)+7,"m/d")

有了它,透视表的行标签就不再是干巴巴的“第 3 周”,而是“3/11-3/17”,业务方一眼能对上实际日期。这个小改动看起来无关紧要,实际上省掉了大量“第 3 周到底是哪几天”的来回问询,我个人认为性价比极高。

5. 常见问题与排查速查表

5.1 六类高频异常:现象、成因与处理

用WEEKNUM出问题,八成逃不出下面六种,我把它们按“现象”组织,方便对着报错反查。

第一类,#VALUE!报错。九成是参数是文本型日期。判断方法前面说过,看编辑栏有没有隐藏的单引号。处理方式是=WEEKNUM(DATEVALUE(A2), 2)或者直接分列转日期。还有一种少见情况:日期是从别的系统导出的,带不可见字符,DATEVALUE也救不了,得先CLEAN再处理。

第二类,#NUM!报错。return_type填了非法值,比如 3、4、5 或者 20。合法值只有 1、2、11 到 17、21。这个错误比较好排查,因为报错是显性的。

第三类,结果比预期大 1 或小 1。这是最常见的“不报错但错”的类型,原因几乎都是系统 1 和系统 2 混用,或者周起始日没对齐。排查方法是拿一个已知的跨年日期做基准测试,比如 2024 年 12 月 31 日,2应该给 53,21应该给 1,对不上就是参数写错了。

第四类,明明是同一天,两个单元格算出不同的周数。检查两个单元格的公式是不是一个用了WEEKNUM、一个用了ISOWEEKNUM,或者一个省略了return_type、一个写了2。这种不一致在复制粘贴时特别容易发生。

第五类,筛选某一年时数据少了。这是 1 月初和 12 月末的数据被算到相邻年份了。处理办法是别用YEAR(A2)配WEEKNUM,改成第 3 章讲的周四归属法构造年份。

第六类,月度周数算出 6,被当成错误改了。前面验证过,1 日落在周六或周日的 31 天月份真的会有 6 个周。这不是 bug,是定义决定的。要做的是在模板里预留 6 行,而不是去改公式。

5.2 排查速查表

下面这张表我直接印在了自己的备忘卡上,遇到问题从上往下扫一遍,基本能定位:

现象最可能原因一步验证处理方式
#VALUE!参数为文本日期=ISNUMBER(A2)是否 FALSEDATEVALUE转换或分列
#NUM!return_type非法看第二参数值改成 1、2、21 之一
跨年差 1系统 1 与系统 2 混用用 12/31 做基准测试全表统一为2或21
周起始日错位省略了第二参数检查公式有无, 2显式写明起始日
年度筛选漏数据1 月初被判给上一年找 1 月 1 日那一行改用周四归属法算年份
月度周数出现 61 日为周六/周日且 31 天手算第 1 周天数模板预留第 6 行
同一周算出两个周数公式不一致对比两个单元格公式统一模板、锁定引用
排序后周次乱序用了文本拼接键看键是不是文本格式改用周一日期当键

5.3 几个我实际踩过的坑

第一个坑是“把周数当成了可以跨年连续的序号”。我曾经做过一张连续 52 周的看板,图省事直接用了周数当横轴,结果第 52 周之后接第 1 周,折线图直接来了个断崖式下降,看起来像是业务崩了。后来改成“年-周”标签,横轴才正常。教训是:周数是一个循环值,不是递增序号,任何需要连续性、需要排序的地方,都得补上年份或者直接用日期。

第二个坑是“用TEXT(A2,"ww")代替WEEKNUM”。这两者在多数环境下结果一致,但TEXT的行为会受系统区域设置影响,换一台机器打开可能就变了。而且TEXT返回的是文本,参与计算还要再转一次。需要周数就用WEEKNUM,需要格式化就套TEXT在外面,别指望一个函数干两件事。

第三个坑是“在公式里写死年份”。见过不少模板写成=WEEKNUM(DATE(2024, A2, B2), 2),年份硬编码在公式里,第二年复制一份改年份,改漏一个就全错。正确的做法是年份放在一个参数单元格里,公式全部引用它,跨年只需要改一个格子。

第四个坑相对隐蔽:跨月周的数据在月度汇总里被重复计入。比如 2 月 26 日到 29 日属于 3 月的第 1 周,如果同时按 2 月和 3 月做汇总,这四天可能被算两次。解决方式是先确定归属规则(按周四、按多数天数、还是按自然日),然后在汇总前先把归属列算好,汇总时只按归属列分组,不要同时用两个时间维度。

提示:任何涉及周数的表,交付前一定要做一次“边界测试”。挑四个日期——当年 1 月 1 日、当年 12 月 31 日、某个 31 天月份的 1 日、某个闰年 2 月 29 日——单独验证一遍结果,能挡掉八九成的隐患。这个习惯花不了五分钟,但省下的返工时间非常可观。

6. 进阶用法:把周数接进真实报表

6.1 周数与日期区间的双向映射

周数真正发挥价值的地方,是它能把“按天”的数据压缩成“按周”,或者反过来把“第 N 周”还原成具体日期。两个方向都需要一组固定公式。

从日期求区间,前面已经写过:周一 =A2 - WEEKDAY(A2,2) + 1,周日 =A2 - WEEKDAY(A2,2) + 7。这两条是所有周维度计算的基石,记住它们比记住WEEKNUM更有用。

从“某年第 N 周”反求周一,要分系统 1 和系统 2 两种写法。系统 1、周一起始:

=DATE(2024,1,1) - WEEKDAY(DATE(2024,1,1),2) + 1 + 7*(N-1)

系统 2(ISO):

=DATE(2024,1,4) - WEEKDAY(DATE(2024,1,4),2) + 1 + 7*(N-1)

区别就在基准日从 1 月 1 日换成了 1 月 4 日,正好对应两种“第一周”的判定规则。这两条公式我用过很多次,用于生成周报表的空行模板——先铺 1 到 53 周,再用公式算出每行的周一和周日,一张全年的周维度模板两分钟就能搭好,比手工敲日期快得多,也不会错。

反向映射还有一个实用场景:把周序号转换成“第几周(起止日期)”这种人类可读的标签。用TEXT拼接即可,格式用m/d而不是yyyy/m/d,标签会短很多,放进透视表行标签里刚好不挤。

6.2 与透视表、条件格式的配合

周数算出来只是中间产物,真正交付的一般是透视表。这里有两个细节值得说。

一是透视表的行标签排序。如果把“第 9 周”“第 10 周”这种文本直接放进去,排序会变成 10、11、9 这种字典序,非常难看。解决办法是加一个辅助列存纯数字周数,透视表里用数字排序,展示用文本标签,两者配合。或者更彻底,直接用周一日期做行标签,透视表自带日期分组,排序天然正确。

二是隔周交替的视觉分组。周维度的表看久了容易串行,用条件格式做个隔周底色会舒服很多。公式很简单:

=MOD(WEEKNUM($A2, 2), 2) = 0

应用到一个区域,双周变色。这样看一眼就知道哪几行属于同一周,尤其适合一周多行的明细表。这个技巧不解决任何计算问题,但能显著降低阅读成本,我在所有周维度的交付表里都会加。

6.3 封装成一个可复用的自定义函数

如果月度周数的公式要在几十个文件里重复用,可以考虑用LAMBDA封装一次,之后调用就只剩一个名字。写法是把前面推导的公式套进LAMBDA,参数留日期和起始日两个:

= LAMBDA(d, start, INT((DAY(d) + WEEKDAY(d - DAY(d) + 1, start) - IF(start = 1, 1, 2)) / 7) + 1)

在名称管理器里定义成MONTHWEEK,之后任何单元格写=MONTHWEEK(A2, 2)就能出结果。好处是公式只维护一份,改规则只改名称管理器里的定义,全表跟着变。坏处也明显:别人打开你的文件,看不到公式内部逻辑,排查问题会变难;而且低版本 Excel 不支持LAMBDA,跨版本协作时容易出问题。

我的取舍是:自己长期用的模板封装,交付给别人的表不封装。交付表里保留完整公式,旁边加一行注释说明“月度周数 = 含 1 日那周为第 1 周”,让对方能看懂、能改。这个习惯听起来保守,但确实减少了很多“表是你做的,为什么这里算出来是 6”的沟通成本。

我在实际使用中的体会是,WEEKNUM这类日期函数真正的难点从来不在函数本身,而在“约定”二字。一周从哪天开始、跨年那周算谁的、跨月那周归哪个月,这三件事只要在使用者之间达成一致并写进字段说明,剩下的公式都是十分钟能搞定的事;反过来,如果不先对齐约定就直接写公式,写得再漂亮也会被推翻重来。所以我现在做任何周维度的表,第一步永远是拉一个空白页,把这三条约定写成三行字发出去确认,确认完了再动手。这个动作看着慢,实际是最快的一条路。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进