You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于每月首个周一为工作日编号?附VBA首周一获取函数

实现跨月连续工作日编号(从每月首个周一至次月首个周一)

需求说明

从每月首个周一开始为工作日连续编号,编号持续至次月首个周一,周末不计入编号(例:周五编号为5时,下周一编号为6)。基于已有的FirstMonday函数完成编号功能。

基础函数:获取每月首个周一

你提供的FirstMonday函数可正确返回指定日期所在月份的首个周一,代码如下:

Public Function FirstMonday(myDate As Date) As Date
    Dim d As Date, w As Long
    d = DateSerial(Year(myDate), Month(myDate), 1)
    w = Weekday(d, vbMonday)
    FirstMonday = d + IIf(w <> 1, 8 - w, 0)
End Function

实现工作日编号函数

以下提供两种方案,对应不同的跨月编号逻辑:

方案1:当月周期内编号(次月首个周一重置为1)

每个月的编号从当月首个周一开始,从1递增,周末跳过;次月首个周一作为新月份的编号起点,重置为1。

Public Function GetWorkdayID_Reset(targetDate As Date) As Variant
    ' 周末不计入编号,返回空值
    Dim dayOfWeek As Long
    dayOfWeek = Weekday(targetDate, vbMonday) ' 1=周一,5=周五,6=周六,7=周日
    If dayOfWeek >= 6 Then
        GetWorkdayID_Reset = Empty
        Exit Function
    End If
    
    ' 获取当月首个周一作为周期起始
    Dim cycleStart As Date
    cycleStart = FirstMonday(targetDate)
    
    ' 日期早于当月首个周一,返回空值
    If targetDate < cycleStart Then
        GetWorkdayID_Reset = Empty
        Exit Function
    End If
    
    ' 优先用Excel内置函数计算工作日数量,提高效率
    On Error Resume Next
    GetWorkdayID_Reset = WorksheetFunction.NetworkDays(cycleStart, targetDate)
    On Error GoTo 0
    
    ' 兼容无NetworkDays函数的环境,手动计算
    If IsEmpty(GetWorkdayID_Reset) Then
        Dim count As Long, currentDate As Date
        count = 0
        currentDate = cycleStart
        Do While currentDate <= targetDate
            If Weekday(currentDate, vbMonday) <= 5 Then
                count = count + 1
            End If
            currentDate = currentDate + 1
        Loop
        GetWorkdayID_Reset = count
    End If
End Function

方案2:跨月连续编号(次月首个周一延续上月编号)

编号从当月首个周一开始连续递增,周末跳过,直至次月首个周一(该周一的编号延续上月);次月首个周一之后的工作日重置为1。

Public Function GetWorkdayID_Continue(targetDate As Date) As Variant
    ' 周末不计入编号,返回空值
    Dim dayOfWeek As Long
    dayOfWeek = Weekday(targetDate, vbMonday)
    If dayOfWeek >= 6 Then
        GetWorkdayID_Continue = Empty
        Exit Function
    End If
    
    Dim cycleStart As Date
    ' 判断目标日期是否为次月首个周一(前一天属于上月)
    If targetDate = FirstMonday(targetDate) And Month(targetDate - 1) <> Month(targetDate) Then
        ' 以上月首个周一作为周期起始
        cycleStart = FirstMonday(DateAdd("m", -1, targetDate))
    Else
        ' 以当月首个周一作为周期起始
        cycleStart = FirstMonday(targetDate)
    End If
    
    ' 计算工作日数量
    On Error Resume Next
    GetWorkdayID_Continue = WorksheetFunction.NetworkDays(cycleStart, targetDate)
    On Error GoTo 0
    
    ' 手动计算兼容
    If IsEmpty(GetWorkdayID_Continue) Then
        Dim count As Long, currentDate As Date
        count = 0
        currentDate = cycleStart
        Do While currentDate <= targetDate
            If Weekday(currentDate, vbMonday) <= 5 Then
                count = count + 1
            End If
            currentDate = currentDate + 1
        Loop
        GetWorkdayID_Continue = count
    End If
End Function

使用方法

在Excel单元格中直接调用函数即可:

  • 方案1调用:=GetWorkdayID_Reset(A1)(A1为存放日期的单元格)
  • 方案2调用:=GetWorkdayID_Continue(A1)

注意事项

  • 两个函数均会对周末日期返回空值,符合“周末不计入编号”的要求
  • NetworkDays函数依赖Excel对象库,若在非Excel环境使用,会自动切换为手动计算逻辑

内容的提问来源于stack exchange,提问作者Nata

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 05:25:56