在Google Sheets中基于允许的工作日、重复次数和时段生成日期范围
带工作日约束的医疗任务日程自动生成方案(Google Sheets)
核心思路
- 先修正起始日期:自动定位起始日及之后第一个符合允许工作日的日期
- 基于有效起始日,生成符合工作日规则的日期序列,满足重复次数/天数要求
- 关联时段标记,展开为每条任务对应的「日期+名称+时段」条目
分步公式实现
1. 定义允许的工作日数组
假设允许的工作日在B2:H2(周一到周日,1=允许),先提取有效工作日的数字(周一=1,周日=7):
=FILTER(SEQUENCE(7), B2:H2=1)
示例返回{1,3,5},代表仅周一、周三、周五可执行任务。
2. 批量修正起始日期(自动适配工作日)
用以下公式生成每个任务的首个有效起始日,支持自动数组填充,无需手动下拉:
=ARRAYFORMULA(IF(A2:A="",, LET( start_dates, A2:A, allowed_days, FILTER(SEQUENCE(7), B2:H2=1), MAP(start_dates, LAMBDA(sd, IF(sd="",, LET( current_weekday, WEEKDAY(sd, 2), // 找当前起始日之后的第一个有效工作日 next_valid, FILTER(allowed_days, allowed_days >= current_weekday), IF(COUNTA(next_valid) > 0, sd + MIN(next_valid - current_weekday), // 若本周剩余无有效日,取下周第一个有效日 sd + MIN(allowed_days + 7 - current_weekday) ) ) ) )) ) ))
注:A2:A为任务起始日期列,需替换为你的实际列引用。
3. 生成符合重复规则的日期序列
假设:
I2:I为重复次数(与重复天数互斥)J2:J为重复天数K2:P2为时段标记(1=有效时段,按每日时段数计算总任务量)
用以下公式生成满足要求的有效日期数组:
=ARRAYFORMULA(IF(A2:A="",, LET( base_dates, 【步骤2的结果列】, allowed_days, FILTER(SEQUENCE(7), B2:H2=1), repeat_counts, I2:I, repeat_days, J2:J, // 计算总任务次数:重复次数优先,否则用重复天数×每日时段数 total_tasks, IF(repeat_counts<>"", repeat_counts, repeat_days*COUNTA(FILTER(K2:P2, K2:P2=1))), MAP(base_dates, total_tasks, LAMBDA(bd, tt, IF(bd=""||tt="",, LET( // 循环遍历允许的工作日,生成日期序列 cycle_idx, MOD(SEQUENCE(tt)-1, COUNTA(allowed_days)), cycle_weekdays, INDEX(allowed_days, cycle_idx+1), base_weekday, WEEKDAY(bd, 2), days_offset, cycle_weekdays - base_weekday + 7*QUOTIENT(SEQUENCE(tt)-1, COUNTA(allowed_days)), bd + days_offset ) ) )) ) ))
4. 展开时段并生成最终任务列表
把日期序列和有效时段合并为每条任务条目,再用FLATTEN展开:
=ARRAYFORMULA(FLATTEN( LET( task_names, A2:A, date_lists, 【步骤3的结果列】, // 提取有效时段的编号(比如1=上午,2=下午) valid_slots, FILTER(SEQUENCE(COLUMNS(K2:P2)), K2:P2=1), MAP(task_names, date_lists, LAMBDA(tn, dl, IF(tn=""||dl="",, BYROW(valid_slots, LAMBDA(slot, TEXT(INDEX(dl, slot), "DD.MM.YY") & " | " & tn & " | 时段" & slot )) ) )) ) ))
若需拆分到单独列,可在结果后用|分隔,再用SPLIT函数拆分。
有效日期范围生成
要生成如15.12.24-22.12.24的日期范围,提取序列的首尾日期拼接即可:
=ARRAYFORMULA(IF(A2:A="",, LET( date_seq, 【步骤3的结果列】, first_date, TEXT(INDEX(date_seq, 1), "DD.MM.YY"), last_date, TEXT(INDEX(date_seq, COUNTA(date_seq)), "DD.MM.YY"), first_date & "-" & last_date ) ))
内容的提问来源于stack exchange,提问作者Toshchak Pёs
相关产品推荐
相关产品推荐

