Excel-在给定特定年份和月份值的范围内查找月份的最后一天

时间:2019-11-07 13:01:53

标签: excel vba

enter image description here

我想知道我可以使用哪些Excel / VBA函数在具有特定年份和月份输入值的范围内查找月份的最后一天。 例如,对于'1995'和'3',它应返回'3/31/1995'。 对于'1995'和'4',它应该返回'4/28/1995'。

请注意,实际的最后一天'04 / 1995'是'4/30/1995'。我正在寻找范围'4/28/1995'的最后一天,所以不能盲目使用EOMONTH函数。

3 个答案:

答案 0 :(得分:0)

下面是一个VBA解决方案,它应该可以运行并且相对较快。

我将与年份和月份匹配的范围中的所有项目添加到ArrayList中。然后,我以升序对列表进行排序,并选择列表中的最后一个项目(该项目应具有集合中的最大值)。

此程序运行不到一秒钟,遍历了大约800个项目。

功能

Option Explicit

Public Function MaxDateInRange(SearchRange As Range, _
                               YearNumber As Long, _
                               MonthNumber As Long) As String
    Dim cell        As Range
    Dim ListIndex   As Long
    Dim List        As Object: Set List = CreateObject("System.Collections.ArrayList")

    'Go thorugh all cells, and all items that match the month and year to a list
    For Each cell In SearchRange
        If IsDate(cell) Then
            If Month(cell) = MonthNumber And Year(cell) = YearNumber Then List.Add (cell)
        End If
    Next

    'Sort the list ascending, then select the last item in that list
    List.Sort
    ListIndex = List.Count - 1

    'Bounds check, to see if anything was found, otherwise return ""
    If ListIndex >= 0 Then
        MaxDateInRange = List(ListIndex)
    Else
        MaxDateInRange = vbNullString
    End If

End Function

用法:

Public Sub Example()
    Dim rng As Range: Set rng = Sheets(2).Range("D1:D795")
    Dim t   As Double
    t = Timer

    Debug.Print MaxDateInRange(rng, 2019, 3)
    Debug.Print MaxDateInRange(rng, 2019, 4)

    Debug.Print "Process took " & Timer - t
End Sub

基于示例数据的调试输出:

2019-03-28
2019-04-25
Process took 0.04296875

答案 1 :(得分:0)

另一种方法可能是,我还没有完全测试过,但是可以让人深思。

Function get_latest_date(rngInput As Excel.Range, intMonth As Integer, lngYear As Long) As Date

get_latest_date = 0

On Error Resume Next

get_latest_date = Application.Evaluate( _
                "=MAX(IF((YEAR(" & _
                rngInput.Address & _
                ")=" & lngYear & _
                ")*(MONTH(" & _
                rngInput.Address & _
                ")=" & intMonth & ")," & rngInput.Address & "))")

End Function

这将使用根据传入的参数构建的数组公式求值。

从2015年到2030年,我有10,000个虚拟日期。我使用以下内容进行了快速测试

Function test_get_last_date()

Dim r As Excel.Range
Dim lYear As Long
Dim iMonth As Integer
Dim dTimer As Double

Set r = Range("a1:a10000")

dTimer = Timer

For lYear = 2015 To 2030

    For iMonth = 1 To 12

        Debug.Print get_latest_date(r, iMonth, lYear), "Took : "; Timer - dTimer
        dTimer = Timer

    Next iMonth

Next lYear


End Function

这给出了这些结果

31/05/2017    Took :  0.02734375 
30/06/2017    Took :  0.015625 
31/07/2017    Took :  0.015625 
31/08/2017    Took :  0.015625 
30/09/2017    Took :  0.01953125

答案 2 :(得分:0)

您有2个选择:

  1. 您的数据已排序,您可以将match与1或-1第三个选项一起使用。正如Darren Bartrup-Cook的评论所说

  2. 否则,您必须添加两列公式来对解决方案进行排序:

B列,公式then;合并您的条件

C列,来自单元格C2 =year(A:A)&MONTH(A:A)的公式;然后向下展开公式

B列中每个唯一月份的C列中的最后一个值将是您的答案。您可以使用单元格D2 =IFERROR(MAX((B$1:B1=B2)*(C$1:C1)),A2)中的公式提取D列中的结果;然后向下展开公式