Excel 从日期中减去 X 天,然后找到最后一个特定工作日的日期

Excel subtract X days from date and then find last specific workday date

这是我的问题:

我们有一个 Excel sheet 在工作,以管理所有在单独指定的时间表上设置的各种任务 - 我们每月谈论数百个任务,这些任务的日期目前都在维护中手动。

假设我们有任务 A,并且该任务有截止日期。该任务分为几个子任务,每个子任务都有各自的截止日期。日期 1 将始终是截止日期 - 10 天,日期 2 将是截止日期 - 20 天,日期 3 将是截止日期 - 17 天,依此类推。然后,这会创建一个清晰的时间表,说明何时需要完成所有事情。

这本身就足够简单了,问题是所有这些子任务也必须在特定的工作日完成。这意味着子任务 1 不仅必须在截止日期 - 10 天完成,而且还必须在星期一完成 - 如果由于某种原因截止日期 - 10 恰好落在星期三,则必须减去还有 2 天。然后真正的问题是日期 2 和 3 每个都必须在不同的工作日和任务 B 再次有一个完全不同的时间表。

现在,我想到的第一件事就是尝试嵌套几个 IF - 我什至设法为此想出了一个可行的公式。这里的问题是它太长了而且(感谢 Excel)完全不可读 - 如果出于某种原因其他人必须更改它的某些内容或从现在起 1-2 年对整个文件进行故障排除,他们可能不得不至少花一个小时来重建它到底是如何工作的。这听起来对我们没有特别的吸引力。

下面是有助于说明情况的屏幕截图: 这是当前公式的草案,尽管它在某种程度上起到了作用,但我真的不满意: =IF(AND(WEEKDAY(K2-VLOOKUP(B2,Table1,3,FALSE),11)>5,VLOOKUP(B2,Table1,5,FALSE)=0),(K2-VLOOKUP(B2,Table1,3,FALSE))-(WEEKDAY(K2-VLOOKUP(B2,Table1,3,FALSE),11)-5), IF(VLOOKUP(B2,Table1,5,FALSE)=0,K2-VLOOKUP(B2,Table1,3,FALSE), IF(WEEKDAY((K2-VLOOKUP(B2,Table1,3,FALSE)),11)=0,K2-VLOOKUP(B2,Table1,3,FALSE), (VLOOKUP(B2,Table1,5,FALSE)-WEEKDAY(K2-VLOOKUP(B2,Table1,3,FALSE),11))+K2-VLOOKUP(B2,Table1,3,FALSE))))

我现在的问题是:有没有人知道如何以不那么混乱和不清楚的方式解决这个问题?我试图使用 =CHOOSE() 来完成一些事情,但最终遇到了同样的问题,最终不得不求助于 7 个 IF 和数十个 LOOKUP,使得最终公式一样长。我不会拒绝某种帮手 table 将最后 7 天和他们的工作日分配给一年中的每一天......但我不认为将另外 20,000 个计算单元格扔到一个文件中已经有数以万计的其他计算单元确实是一个有用的替代方案……或者使情况变得不那么模糊。 那么,有人知道如何去做吗?还是真的没有比使用一堆 IF 更现实的选择?

编辑:忘记提及 1 个特例: 还有一种情况是日期不必落在特定的工作日 - 在这种情况下它只是截止日期 - X 天。这里的问题是,在这些情况下,日期可能是周末,因此公式也必须将这些日期移到上周五。

假设您有某个日期并且想要“备份”十天然后到前一个星期一,除非结果日期是星期一。一般公式类似于:

=A2-10+1-WEEKDAY(A2-10-DOW)

DOW 转化为

Sunday=0
Monday=1
Tuesday=2
...

您应该能够修改您的公式以将此算法用于星期几。

如果两个表分别命名为thisTablekeyTable,下面的365公式是一种实现方式:

如果你的表格如下,你可以在B2中输入公式,向下横填。参考文献应 self-adjust 和 return 正确的日期。

请注意,在 keyTable 中,我输入了上面定义的星期几 DOW,而不是文本日期。

=LET(dys,VLOOKUP(thisTable[@[Task]:[Task]],KeyTable,COLUMNS($A:A)*2,FALSE),
     dow,VLOOKUP(thisTable[@[Task]:{Task]],KeyTable,COLUMNS($A:A)*2+1,FALSE),
      due,thisTable[@[DueDate]:[DueDate]],
IF(dow="flexible",WORKDAY(due-dys+1,-1),due-dys+1-WEEKDAY(due-dys-dow)))

如果你想让结果是最近的工作日,而不是前一个工作日,那么你需要在 LET 函数中添加两个子句

  • 计算后续工作日日期
  • 然后用一个IF到return最接近原目标的

例如:

=LET(dys,VLOOKUP(thisTable[@[Task]:[Task]],KeyTable,COLUMNS($A:A)*2,FALSE),
     dow,VLOOKUP(thisTable[@[Task]:[Task]],KeyTable,COLUMNS($A:A)*2+1,FALSE),
     due,thisTable[@[DueDate]:[DueDate]],
     dayPrev,IF(dow="flexible",WORKDAY(due-dys+1,-1),due-dys+1-WEEKDAY(due-dys-dow)),
     daySubseq,IF(dow="flexible",WORKDAY(due-dys+1,-1),due-dys+7-WEEKDAY(due-dys-1-dow)),
  IF((daySubseq-due+dys)>3,dayPrev,daySubseq))