Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

excel - Expand Start Date to End Date with Series of EOMONTHs

I have a data table containing ids with a start date and end date associated with both.

RowNo   AcNo     StartDate     EndDate
  1     R125     01/10/2017    30/09/2020
  2     R126     01/10/2017    30/09/2018
  3     R127     01/10/2017    30/09/2019
  4     R128     01/10/2017    30/09/2020

I need to expand (i.e. unpivot) this table to allow one row for each eomonth between the start and end date (inclusive) for each AcNo. The row numbers are unimportant.

AcNo    EOMONTHs
R125    Oct 17
R125    Nov 17
R125    Dec 17
R125    Jan 18
R125    Feb 18
R125    Mar 18
    ...
R128    Apr 20
R128    May 20
R128    Jun 20
R128    Jul 20
R128    Aug 20
R128    Sep 20

I can do each row with a pair of formulas like this,

'in F2
=IF(ROW(1:1)-1<DATEDIF(C$2, D$2, "m"), B$2, TEXT(,))
'in G2
=IF(ROW(1:1)-1<DATEDIF(C$2, D$2, "m"), EOMONTH(C$2, ROW(1:1)-1), TEXT(,))
'F2:G2 filled down

However I have thousands of rows of AcNos and this is unwieldy to perform for individual rows.

I've also used VBA's DateDiff to form a loop for individual rows.

    Dim m As Long, ms As Long
    With Worksheets("Sheet2")
        .Range("F1:G1") = Array("AcNo", "EOMONTHs")
        ms = DateDiff("m", .Cells(2, "C").Value2, .Cells(2, "D").Value2)
        For m = 1 To ms + 1
            .Cells(m, "M") = .Cells(2, "B").Value2
            .Cells(m, "N").Formula = "=EOMONTH(C$2, " & m - 1 & ")"
        Next m
    End With

Again this only expands one row at a time.

How would I loop through the rows stacking each series into a single column? Any suggestions for adjustments to my formula or code would be welcome.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Try it as a nested For ... Next loop using DateDiff to determine the number of months. Collecting the progressive values in an array will speed up execution before dumping them back to the worksheet.

Option Explicit

Sub eoms()
    Dim a As Long, m As Long, ms As Long, vals As Variant
    With Worksheets("Sheet2")
        .Range("F1:G1") = Array("AcNo", "EOMONTHs")
        For a = 2 To .Cells(.Rows.Count, "B").End(xlUp).Row
            ms = DateDiff("m", .Cells(a, "C").Value2, .Cells(a, "D").Value2)
            ReDim vals(1 To ms + 1, 1 To 2)
            For m = 1 To ms + 1
                vals(m, 1) = .Cells(a, "B").Value2
                vals(m, 2) = DateSerial(Year(.Cells(a, "C").Value2), _
                                        Month(.Cells(a, "C").Value2) + m, _
                                        0)
            Next m
            .Cells(.Rows.Count, "F").End(xlUp).Offset(1, 0).Resize(UBound(vals, 1), UBound(vals, 2)) = vals
        Next a
        .Range(.Cells(2, "G"), .Cells(.Rows.Count, "G").End(xlUp)).NumberFormat = "mmm yy"
    End With
End Sub

VBA's DateSerial can be used as a EOMONTH generator by setting the day to zero of the following month.

Note in the following image that the generated months are the EOMONTH of each month in the series with mmm yy cell number formatting.

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...