根据给定的日期计算期间

Calculate period based on the dates given

我在 O 列中有从 O5 到 O1200 的某些日期。我需要确定这个日期属于哪个时期,然后 return AO 列中从 AO5 到 AO1200 的时期。下图给出了不同时期的数据范围。

Data range for different periods

我最初使用公式来计算它,但我想使该过程自动化。代码如下:

=IF(ISBLANK(B5)=TRUE,"",IF(ISBLANK(O5)=TRUE,"Missing PSD",@IFERROR(IFS(
AND(O5>=Calendar!$B,O5<=Calendar!$C),"P01",
AND(O5>=Calendar!$B,O5<=Calendar!$C),"P02",
AND(O5>=Calendar!$B,O5<=Calendar!$C),"P03",
AND(O5>=Calendar!$B,O5<=Calendar!$C),"P04",
AND(O5>=Calendar!$B,O5<=Calendar!$C),"P05",
AND(O5>=Calendar!$B,O5<=Calendar!$C),"P06",
AND(O5>=Calendar!$B,O5<=Calendar!$C),"P07",
AND(O5>=Calendar!$B,O5<=Calendar!$C),"P08",
AND(O5>=Calendar!$B,O5<=Calendar!$C),"P09",
AND(O5>=Calendar!$B,O5<=Calendar!$C),"P10",
AND(O5>=Calendar!$B,O5<=Calendar!$C),"P11",
AND(O5>=Calendar!$B,O5<=Calendar!$C),"P12"
),IF((DATE(2019,10,1)-O5)>0,"FY20 or before",IF((DATE(2019,10,1)-O5)<0,"FY22+","")))))

如前所述,我想自动执行此过程并在 VBA 上进行计算,而不是在 excel 列中插入公式。

非常感谢任何帮助。

试试这个。我想我是对的。 请注意更改日期和输出所在 sheet 的 sheet 名称,因为您没有在问题中提及它。

另请注意:i2 = 3 到 14 是您的日历列表范围。根据需要更改我只是基于您的公式。以及日历中的“A”列 sheet 具有此代码用于获取值的“PO”值。

Dim i1 As Long, i2 As Long, Cal As Worksheet, Data As Worksheet, OldDate As Date

Set Cal = Sheets("Calendar")
Set Data = Sheets("Sheet1") 'Need to change this to the sheet with the dates/output
OldDate = DateValue("1 Oct, 2019")

For i1 = 5 To 1200 'Your range of dates
    If Data.Range("B" & i1) <> "" Then
        If Data.Range("O" & i1) = "" Then
            Data.Range("AO" & i1) = "Missing PSD"
        Else
            For i2 = 3 To 14 'Your range within the Calendar sheet your are checking against
                If Data.Range("O" & i1) >= Cal.Range("B" & i2) And Data.Range("O" & i1) <= Cal.Range("C" & i2) Then
                    Data.Range("AO" & i1) = Cal.Range("A" & i2)
                    GoTo Nexti1
                End If
            Next i2
            If OldDate - Data.Range("O" & i1) > 0 Then
                Data.Range("AO" & i1) = "FY20 or before"
            ElseIf OldDate - Data.Range("O" & i1) < 0 Then
                Data.Range("AO" & i1) = "FY22+"
            End If
        End If
    End If
Nexti1:
Next i1

通过使用通用函数(如下),您甚至不需要日期范围 table,因为可以直接从任何日期计算时间段。那么你的公式就变成了:

=FinancialPeriod(CellReferenceWithDate)
Option Explicit

    Public Const MaxWeekdayCountInMonth As Integer = 5
    Public Const DaysPerWeek            As Long = 7

' Returns the financial period of a calendar date.
'
' 2020-09-20. Gustav Brock, Cactus Data ApS, CPH.
'
Public Function FinancialPeriod(ByVal Date1 As Date) As String

    Const FirstPeriod   As Integer = 1
    Const LastPeriod    As Integer = 12
    Const FirstMonth    As Integer = 10
    Const FirstDay      As Integer = 1
    Const MaximumDay    As Integer = 25
    Const Occurrence    As Integer = 4
    Const PeriodFormat  As String = "\P00"
    
    Dim YearStart       As Date
    Dim PeriodEnd       As Date
    Dim Period          As Integer
    
    YearStart = DateSerial(Year(Date1) - Abs(Month(Date1) < FirstMonth), FirstMonth, FirstDay)
    For Period = FirstPeriod To LastPeriod - 1
        PeriodEnd = DateWeekdayInMonth(DateAdd("m", Period - 1, YearStart), Occurrence, vbFriday)
        If Day(PeriodEnd) > MaximumDay Then
            PeriodEnd = DateAdd("ww", -1, PeriodEnd)
        End If
        If Date1 <= PeriodEnd Then
            Exit For
        End If
    Next
    
    FinancialPeriod = Format(Period, PeriodFormat)
    
End Function

' Calculates the date of the occurrence of Weekday in the month of DateInMonth.
'
' If Occurrence is 0 or negative, the first occurrence of Weekday in the month is assumed.
' If Occurrence is 5 or larger, the last occurrence of Weekday in the month is assumed.
'
' If Weekday is invalid or not specified, the weekday of DateInMonth is used.
'
' 2019-12-08. Gustav Brock, Cactus Data ApS, CPH.
'
Public Function DateWeekdayInMonth( _
    ByVal DateInMonth As Date, _
    Optional ByVal Occurrence As Integer, _
    Optional ByVal Weekday As VbDayOfWeek = vbUseSystemDayOfWeek) _
    As Date
    
    Dim Offset          As Integer
    Dim Month           As Integer
    Dim Year            As Integer
    Dim ResultDate      As Date
    
    ' Validate Weekday.
    Select Case Weekday
        Case _
            vbMonday, _
            vbTuesday, _
            vbWednesday, _
            vbThursday, _
            vbFriday, _
            vbSaturday, _
            vbSunday
        Case Else
            ' vbUseSystemDayOfWeek, zero, none or invalid value for VbDayOfWeek.
            Weekday = VBA.Weekday(DateInMonth)
    End Select
    
    ' Validate Occurence.
    If Occurrence < 1 Then
        ' Find first occurrence.
        Occurrence = 1
    ElseIf Occurrence > MaxWeekdayCountInMonth Then
        ' Find last occurrence.
        Occurrence = MaxWeekdayCountInMonth
    End If
    
    ' Start date.
    Month = VBA.Month(DateInMonth)
    Year = VBA.Year(DateInMonth)
    ResultDate = DateSerial(Year, Month, 1)
    
    ' Find offset of Weekday from first day of month.
    Offset = DaysPerWeek * (Occurrence - 1) + (Weekday - VBA.Weekday(ResultDate) + DaysPerWeek) Mod DaysPerWeek
    ' Calculate result date.
    ResultDate = DateAdd("d", Offset, ResultDate)
    
    If Occurrence = MaxWeekdayCountInMonth Then
        ' The latest occurrency of Weekday is requested.
        ' Check if there really is a fifth occurrence of Weekday in this month.
        If VBA.Month(ResultDate) <> Month Then
            ' There are only four occurrencies of Weekday in this month.
            ' Return the fourth as the latest.
            ResultDate = DateAdd("d", -DaysPerWeek, ResultDate)
        End If
    End If
    
    DateWeekdayInMonth = ResultDate
  
End Function

我已经上传了一个带有一年日期的演示供下载 here