Calculate the number of complete Months per Year per Project For example, Proj A starts in 2022 (for 10 months), 2023(12 months), Ends 2024(6 months) Dynamic array function allowed, but Extra marks for Legacy solutions or PowerQuery Solution
📌 Challenge Details and Links
Challenge Number: 32
Challenge Difficulty: ⭐
📥Link to the solutions on LinkedIn
Solving the challenge of Extract Complete Months with Power Query
Power Query solution 1 for Extract Complete Months, proposed by Kris Jaganah:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
Years = Table.ExpandListColumn(
Table.AddColumn(
Source,
"Years",
each {Date.Year(List.Min(Source[#"Start Date "])) .. Date.Year(List.Max(Source[End Date]))}
),
"Years"
),
Mths = Table.AddColumn(
Years,
"Months",
each
let
a = [End Date],
b = [#"Start Date "],
c = Date.Year(a),
d = Date.Year(b),
e = Date.Month(a),
f = Date.Month(b),
g = [Years],
h = if g = d then 13 - f else if g > d and g < c then 12 else if g = c then e else null
in
h
),
Type = Table.TransformColumnTypes(Mths, {{"Years", type text}}),
Pivot = Table.Pivot(Type, List.Distinct(Type[Years]), "Years", "Months", List.Sum)
in
Pivot
Power Query solution 2 for Extract Complete Months, proposed by Alejandro Simón 🇵🇦 🇪🇸:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
Pros = Table.AddColumn(
Source,
"A",
each
let
a = {Number.From([#"Start Date "]) .. Number.From([End Date])},
b = List.Distinct(
List.Transform(a, each {Date.Year(Date.From(_)), Date.Month(Date.From(_))})
),
c = Table.FromRows(b)
in
c
)[[Project], [A]],
Expand = Table.ExpandTableColumn(Pros, "A", {"Column1", "Column2"}),
Sol = Table.Pivot(
Table.TransformColumnTypes(Expand, {{"Column1", type text}}),
List.Distinct(Table.TransformColumnTypes(Expand, {{"Column1", type text}})[Column1]),
"Column1",
"Column2",
List.Count
)
in
Sol
Power Query solution 3 for Extract Complete Months, proposed by Brian Julius:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
DateList = Table.ExpandListColumn(
Table.AddColumn(
Source,
"Date",
each List.Transform(
{Number.From([#"Start Date "]) .. Number.From([End Date])},
each Date.From(_)
)
),
"Date"
),
Day = Table.AddColumn(DateList, "Day", each Date.Day([Date]), Int64.Type),
Month = Table.AddColumn(Day, "Month", each Date.Month([Date]), Int64.Type),
Year = Table.AddColumn(Month, "Year", each Date.Year([Date]), Int64.Type),
Group = Table.RemoveColumns(
Table.Group(
Year,
{"Project", "Start Date ", "End Date", "Month", "Year"},
{"Complete", each if Table.RowCount(_) = List.Max([Day]) then 1 else 0}
),
"Month"
),
Pivot = Table.Pivot(
Table.TransformColumnTypes(Group, {{"Year", type text}}, "en-US"),
List.Distinct(Table.TransformColumnTypes(Group, {{"Year", type text}}, "en-US")[Year]),
"Year",
"Complete",
List.Sum
),
Retype = Table.TransformColumnTypes(Pivot, {{"Start Date ", type date}, {"End Date", type date}})
in
Retype
Power Query solution 4 for Extract Complete Months, proposed by 🇮🇷 Navid Esmaeilzadeh اسماعیل زاده:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
#"Added Custom" = Table.AddColumn(
Source,
"L",
each List.Transform(
{Number.From([#"Start Date "]) .. Number.From([End Date])},
each Date.From(_)
)
),
#"Expanded L" = Table.ExpandListColumn(#"Added Custom", "L"),
#"Inserted Year" = Table.AddColumn(#"Expanded L", "Year", each Date.Year([L]), Int64.Type),
#"Inserted Month Name" = Table.AddColumn(
#"Inserted Year",
"Month Name",
each Date.MonthName([L]),
type text
),
#"Grouped Rows" = Table.Group(
#"Inserted Month Name",
{"Project", "Year", "Month Name"},
{{"Count", each Table.RowCount(_), Int64.Type}}
),
#"Grouped Rows1" = Table.Group(
#"Grouped Rows",
{"Project", "Year"},
{{"Count", each Table.RowCount(_), Int64.Type}}
),
#"Pivoted Column" = Table.Pivot(
Table.TransformColumnTypes(#"Grouped Rows1", {{"Year", type text}}, "en-US"),
List.Distinct(
Table.TransformColumnTypes(#"Grouped Rows1", {{"Year", type text}}, "en-US")[Year]
),
"Year",
"Count",
List.Sum
)
in
#"Pivoted Column"
Power Query solution 5 for Extract Complete Months, proposed by Yaroslav Drohomyretskyi:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
Dates = Table.ExpandListColumn(Table.AddColumn(Table.TransformColumnTypes(Source,{{"Start Date ", type date}, {"End Date", type date}}), "Dates", each List.Dates([#"Start Date "], Duration.Days([End Date] -[#"Start Date "]) +1 ,
hashtag
#duration(1,0,0,0) )), "Dates"),
YearMonth = Table.AddColumn( Table.AddColumn(Dates, "Year", each Date.Year([Dates]), Int64.Type), "Month", each Date.Month([Dates]), Int64.Type),
Group = Table.Group(YearMonth, {"Project", "Start Date ", "End Date", "Year", "Month"}, {{"Count", each Table.RowCount(_), Int64.Type}}),
Pivot = Table.Pivot(Table.TransformColumnTypes(Table.Group(Table.SelectRows(Table.AddColumn(Group, "Custom", each if Date.DaysInMonth(
hashtag
#date([Year],[Month],1))=[Count] then 1 else null), each [Custom] <> null and [Custom] <> ""), {"Project", "Start Date ", "End Date", "Year"}, {{"Count", each Table.RowCount(_), Int64.Type}}), {{"Year", type text}}, "en-US"), List.Distinct(Table.TransformColumnTypes(Group, {{"Year", type text}}, "en-US")[Year]), "Year", "Count", List.Sum)
in
Pivot
Power Query solution 6 for Extract Complete Months, proposed by Mahmoud Bani Asadi:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
ChType = Table.TransformColumnTypes(Source, {{"Start Date", type date}, {"End Date", type date}}),
Custom = Table.AddColumn(
ChType,
"Custom",
each [
a = {Number.From([Start Date]) .. Number.From([End Date])},
b = List.Transform(a, each Date.ToText(Date.From(_), "yyy/MM")),
c = List.Transform(List.Distinct(b), each Text.Start(_, 4)),
d = Table.AddColumn(Table.FromList(c), "i", each 1),
e = Table.Pivot(d, List.Distinct(d[Column1]), "Column1", "i", List.Sum)
][e]
),
Custom1 = Table.ExpandTableColumn(
Custom,
"Custom",
Table.ColumnNames(Table.Combine(Custom[Custom]))
)
in
Custom1
Power Query solution 7 for Extract Complete Months, proposed by Mahmoud Bani Asadi:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
ChType = Table.TransformColumnTypes(Source, {{"Start Date", type date}, {"End Date", type date}}),
Custom = Table.AddColumn(
ChType,
"Custom",
each Table.PromoteHeaders(
Table.Transpose(
Table.Group(
Table.FromList(
List.Transform(
List.Distinct(
List.Transform(
{Number.From([Start Date]) .. Number.From([End Date])},
each Date.ToText(Date.From(_), "yyy/MM")
)
),
each Text.Start(_, 4)
)
),
"Column1",
{"x", Table.RowCount}
)
)
)
),
Expand = Table.ExpandTableColumn(
Custom,
"Custom",
List.Transform(
{Date.Year(List.Min(Custom[Start Date])) .. Date.Year(List.Max(Custom[End Date]))},
Text.From
)
)
in
Expand
Power Query solution 8 for Extract Complete Months, proposed by Nelson Mwangi:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
DateList = Table.AddColumn(Source, "Custom", each [
Start =Date.From([#"Start Date "]),
End =Date.From( [End Date]),
Dates = List.Dates(Start, Duration.Days(End - Start) + 1,
hashtag
#duration(1, 0, 0, 0))
][Dates]),
Expand = Table.ExpandListColumn(DateList, "Custom"),
MonthYear = Table.AddColumn(Expand, "Period", each [Year = Date.Year([Custom]), Month = Date.Month([Custom])]),
Xpand = Table.ExpandRecordColumn(MonthYear, "Period", {"Year", "Month"}),
RemoveCols = Table.SelectColumns(Xpand, {"Project", "Year", "Month"}),
TypeText = Table.TransformColumnTypes(RemoveCols, {{"Year", type text}}),
Group = Table.Group(TypeText, {"Project", "Year"}, {{"Count", each Table.RowCount(Table.Distinct(_)), Int64.Type}}),
Pivot = Table.Pivot(Group, List.Distinct(TypeText[Year]), "Year", "Count", List.Sum)
in
Pivot
Solving the challenge of Extract Complete Months with Excel
Excel solution 1 for Extract Complete Months, proposed by Bo Rydobon 🇹🇭:
=LET(
s,
+C4:C7,
n,
YEARFRAC(
s,
D4:D7+1)*12,
m,
SEQUENCE(
,
MAX(
n),
0),
y,
IFS(
m
Excel solution 2 for Extract Complete Months, proposed by Rick Rothstein:
=LET(r,
C4:D7,
m,
MIN(
YEAR(
r)),
y,
SEQUENCE(
,
MAX(
YEAR(
r))-m+1,
m),
s,
0+TEXTSPLIT(TEXTJOIN("|",
,
MAP(C4:C7,
D4:D7,
LAMBDA(c,
d,
LET(u,
0+LEFT(
UNIQUE(
TEXT(
SEQUENCE(
,
d-c+1,
c),
"em"),
1),
4),
MID(REDUCE("",
y,
LAMBDA(a,
x,
a&"-"&SUM(0+(u=x)))),
2,
99))))),
"-",
"|"),
VSTACK(
y,
IF(
s,
s,
"")))
Excel solution 3 for Extract Complete Months, proposed by محمد حلمي:
=REDUCE(SORT(
UNIQUE(
TOROW(
YEAR(
C4:D7)),
1),
,
,
1),
D4:D7,
LAMBDA(a,
v,
VSTACK(a,
LET(k,
TAKE(
a,
1),
j,
TAKE(
v:C7,
1),
y,
YEAR(
j),
e,
XLOOKUP(
k,
y,
{13,
0}-MONTH(
j),
0),
IFS(e,
ABS(
e),
(k<@+y)+(k>MAX(
y)),
"",
1,
12)))))
////
TAKE(
a,
1) = SORT(
UNIQUE(
TOROW(
YEAR(
C4:D7)),
1),
,
,
1)
TAKE(
v:C7,
1)
Excel solution 4 for Extract Complete Months, proposed by Julian Poeltl:
=LET(
T,
C4:D7,
UY,
UNIQUE(
SORT(
YEAR(
TOCOL(
T)))),
SP,
--TEXTSPLIT(
TEXTJOIN(
"|",
,
BYROW(
T,
LAMBDA(
A,
LET(
S,
SEQUENCE(
INDEX(
A,
,
2)-INDEX(
A,
,
1)+1,
,
INDEX(
A,
,
1)),
M,
RIGHT(
UNIQUE(
MONTH(
S)&YEAR(
S)),
4),
TEXTJOIN(
",",
,
MAP(
UY,
LAMBDA(
B,
COUNT(
--IFERROR(
FILTER(
M,
--M=B),
""))))))))),
",",
"|"),
VSTACK(
TRANSPOSE(
UY),
IF(
SP>0,
SP,
"")))
Excel solution 5 for Extract Complete Months, proposed by Aditya Kumar Darak 🇮🇳:
=IFERROR(
DATEDIF(
MAX(
$C4,
DATE(
E$3,
1,
1)),
MIN(
$D4,
DATE(
E$3,
12,
31)),
"M") + 1,
"")
Excel solution 6 for Extract Complete Months, proposed by Oscar Mendez Roca Farell:
=LET(c,
E3:I3,
m,
--("1/1/"&c),
d,
D4:D7,
e,
EDATE(
m,
12),
IF((YEAR(
C4:C7)<=c)*(YEAR(
d)>=c),
DATEDIF(
MAP(
C4:C7&"|"&e&"|"&m,
LAMBDA(
a,
MEDIAN(
--TEXTSPLIT(
a,
"|")))),
IF(
d<=e,
EDATE(
+d,
1),
e),
"m"),
""))
Excel solution 7 for Extract Complete Months, proposed by Sunny Baggu:
=LET(
_y,
E3:I3,
REDUCE(
_y,
SEQUENCE(
ROWS(
C4:C7)),
LAMBDA(
x,
y,
VSTACK(
x,
LET(
_c1,
INDEX(
C4:C7,
y,
1),
_c2,
INDEX(
D4:D7,
y,
1),
LET(
_a,
EOMONTH(
_c1,
SEQUENCE(
1 + DATEDIF(
_c1,
_c2,
"M"),
,
-1)) + 1,
_b,
BYCOL(
N(
YEAR(
_a) = _y),
LAMBDA(
A,
SUM(
A))),
IF(
_b,
_b,
"")
)
)
)
)
)
)
Excel solution 8 for Extract Complete Months, proposed by Hamidi Hamid:
=INT(SUM(LET(x,
SEQUENCE(
366,
,
DATE(
E$3,
1,
1),
1),
(x>=$C4)*(x<=$D4)))/30)
Excel solution 9 for Extract Complete Months, proposed by Ankur Sharma:
=LET(a,
C4:C7,
b,
D4:D7,
c,
YEAR(
MIN(
a)),
d,
SEQUENCE(
,
YEAR(
MAX(
b)) - c + 1,
c),
VSTACK(d,
IFERROR(TEXTSPLIT(TEXTJOIN("$",
,
MAP(a,
b,
LAMBDA(y,
z,
TEXTJOIN("@",
,
IFERROR(EXPAND(" ",
,
-(c - YEAR(
y)),
" "),
""),
12 - MONTH(
y) + 1,
SEQUENCE(
,
YEAR(
z) - YEAR(
y) - 1,
12,
0),
MONTH(
z))))),
"@",
"$"),
"")))
Excel solution 10 for Extract Complete Months, proposed by Meganathan Elumalai:
=SUM(1*(TEXT(
EOMONTH(
$C4,
ROW(
INDIRECT(
"1:"&DATEDIF(
$C4,
$D4,
"m")+1))-1),
"yyyy")=(K$3&"")))
Excel solution 11 for Extract Complete Months, proposed by JvdV -:
=IFERROR(--TEXT(DATEDIF($C4,
MIN($D4+1,
("12/31/"&E$3)+1),
"m")-SUM(
$D4:D4)+$D4,
"[>0]"),
"")
Excel solution 12 for Extract Complete Months, proposed by Gerson Pineda:
=DROP(REDUCE(1,
E3:I3,
LAMBDA(i,
x,
HSTACK(i,
MAP(C4:C7,
D4:D7,
LAMBDA(s,
e,
SUM(--(YEAR(
EOMONTH(
s-1,
SEQUENCE(
DATEDIF(
s-1,
e,
"m"))))=x))))))),
,
1)
Excel solution 13 for Extract Complete Months, proposed by Mey Tithveasna:
=MAX(0,
INT((MIN($D4,
--("31/12/"&E$3))-MAX($C4,
--("1/1/"&E$3)))/30))
Excel solution 14 for Extract Complete Months, proposed by Mey Tithveasna:
=IFERROR(DATEDIF(MAX($C4,
--("1/1/"&E$3)),
MIN($D4,
--("31/12/"&E$3)),
"m")+1,
"")
Excel solution 15 for Extract Complete Months, proposed by Milan Shrimali:
=let(
yr,
torow(
sort(
unique(
arrayformula(
year(
tocol(
C4:D7)))),
1,
1)),
vstack(yr,
map(C4:C7,
D4:D7,
lambda(x,
y,
let(a,
x,
b,
y,
c,
map(
a,
b,
lambda(
x,
y,
let(
a,
SEQUENCE(
DATEDIF(
x,
y,
"d"),
1,
x,
1),
arrayformula(
hstack(
a,
month(
a),
year(
a)))))),
d,
bycol(yr,
lambda(x,
count(unique(filter(CHOOSECOLS(
c,
2),
(choosecols(
c,
3)=x)))))),
bycol(
d,
lambda(
x,
if(
x>0,
x,
""))))))))
Excel solution 16 for Extract Complete Months, proposed by Peter Bartholomew:
= Breakdownλ(yearStart,
5,
@startDate,
@endDate)
=LET(
yearstart,
DATE(
SEQUENCE(
1,
n,
2022),
1,
1),
lower,
SORT(
HSTACK(
yearstart,
startDate),
,
,
TRUE),
upper,
1 + SORT(
HSTACK(
yearstart,
endDate),
,
,
TRUE),
months,
DATEDIF(
lower,
upper,
"M"),
months
)
Excel solution 17 for Extract Complete Months, proposed by Tomasz Jakóbczyk:
=IFS(
YEAR(
$D4)E$3,
0,
AND(
YEAR(
$C4)=YEAR(
$D4),
YEAR(
$C4)=E$3,
YEAR(
$D4)=E$3),
DATEDIF(
$C4-1,
$D4+1,
"m"),
AND(
YEAR(
$C4)$C4),
12
)
Excel solution 18 for Extract Complete Months, proposed by William Kiarie:
=IF(
OR(
DATE(
E$3,
12,
31)<$C4,
DATE(
E$3,
12,
31)>$D4),
"",
IF(
AND(
$C4=DATE(
E$3,
12,
31)),
12,
DATEDIF(
$C4,
DATE(
E$3,
12,
31),
"m")))
Solving the challenge of Extract Complete Months with Python
Python solution 1 for Extract Complete Months, proposed by Konrad Gryczan, PhD:
import pandas as pd
path = "files/Excel Challenge 30th June.xlsx"
input = pd.read_excel(path, usecols="B:D", skiprows=2, nrows=4)
test = pd.read_excel(path, usecols="E:I", skiprows=2, nrows=4).fillna(0).astype(int)
result = input.copy()
result['seq'] = result.apply(lambda x: pd.date_range(start=x["Start Date "], end=x["End Date"], freq='M'), axis=1)
result = result.explode('seq')
result['year'] = result['seq'].dt.year
result['val'] = 1
result = result[['Project', 'year', 'val']].
pivot_table(index='Project', columns='year', values='val', aggfunc='sum').
fillna(0).astype(int)
result = result.reset_index().drop(columns='Project')
print(result.equals(test))
Solving the challenge of Extract Complete Months with R
R solution 1 for Extract Complete Months, proposed by Konrad Gryczan, PhD:
library(tidyverse)
library(readxl)
path = "files/Excel Challenge 30th June.xlsx"
input = read_xlsx(path, range = "B3:D7")
test = read_xlsx(path, range = "E3:I7")
result = input %>%
mutate(seq = map2(`Start Date`, `End Date`, seq, by = "month")) %>%
unnest_longer(seq) %>%
mutate(year = year(seq),
val = 1) %>%
select(Project, year, val) %>%
pivot_wider(names_from = year, values_from = val, values_fn = sum) %>%
select(-Project)
identical(result, test)
# [1] TRUE
