根据给定的日期计算期间
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。
我在 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。