我有一个包含ID的数据表,其中包含与两者相关的开始日期和结束日期。
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
我需要扩展(即,取消忽略)此表,以便为每个AcNo的开始和结束日期(包括)之间的每个eomonth允许一行。行号不重要。
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
我可以用一对像这样的公式来做每行
'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
但是我有数千行AcNos,这对于单个行执行起来很笨重。
我还使用VBA的DateDiff为各行形成一个循环。
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
同样,这一次只会扩展一行。
如何将每个系列堆叠成一列的行循环?我们欢迎任何有关调整公式或代码的建议。
答案 0 :(得分:3)
尝试使用DateDiff作为嵌套For ... Next循环来确定月数。在将数据转储回工作表之前,收集数组中的渐进值将加快执行速度。
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的DateSerial用作EOMONTH生成器。
请注意,在下图中,生成的月份是系列中每个月的EOMONTH,其中mmm yy单元格编号格式化。
答案 1 :(得分:3)
只是因为您似乎在寻求多个选项,这里没有VBA:
=IF(EOMONTH(Table1[@[StartDate]:[StartDate]],COLUMNS($A:A))<Table1[@[EndDate]:[EndDate]],EOMONTH(Table1[@[StartDate]:[StartDate]],COLUMNS($A:A)),"")
Power Query
或Data Get & Transform
取消透视除前两列之外的所有内容:(在GUI中轻松完成,但我会粘贴以下代码以获取兴趣) let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"RowNo", Int64.Type}, {"AcNo", type text}, {"StartDate", type datetime}, {"EndDate", type datetime}, {"Column1", type datetime}, {"Column2", type datetime}, {"Column3", type datetime}, {"Column4", type datetime}, {"Column5", type datetime}, {"Column6", type datetime}, {"Column7", type datetime}, {"Column8", type datetime}, {"Column9", type datetime}, {"Column10", type datetime}, {"Column11", type datetime}, {"Column12", type datetime}, {"Column13", type datetime}, {"Column14", type datetime}, {"Column15", type datetime}, {"Column16", type datetime}, {"Column17", type datetime}, {"Column18", type datetime}, {"Column19", type datetime}, {"Column20", type datetime}, {"Column21", type datetime}, {"Column22", type datetime}, {"Column23", type datetime}, {"Column24", type datetime}, {"Column25", type datetime}, {"Column26", type datetime}, {"Column27", type datetime}, {"Column28", type datetime}, {"Column29", type datetime}, {"Column30", type datetime}, {"Column31", type datetime}, {"Column32", type datetime}, {"Column33", type datetime}, {"Column34", type datetime}}),
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Changed Type", {"RowNo", "AcNo"}, "Attribute", "Value"),
#"Removed Columns" = Table.RemoveColumns(#"Unpivoted Other Columns",{"Attribute"}),
#"Renamed Columns" = Table.RenameColumns(#"Removed Columns",{{"Value", "EOM Date"}}),
#"Changed Type1" = Table.TransformColumnTypes(#"Renamed Columns",{{"EOM Date", type date}})
in
#"Changed Type1"
请注意,当这样做时,第一个日期实际上是一个BOM日期,但是如果你在结果中格式化它们,mmm yy,它看起来是一样的。如果这是一个问题,事情很容易改变。
如果不希望第一个月作为BOM日期:
=IF(EOMONTH(Table1[@[StartDate]:[StartDate]],COLUMNS($A:A)-1)<=Table1[@[EndDate]:[EndDate]],EOMONTH(Table1[@[StartDate]:[StartDate]],COLUMNS($A:A)-1),"")
Data Get & Transform
时,请删除查询GUI编辑器中的StartDate
列,因为这不会影响当时的其他列。