The accounting month of this company finishes on last Friday of the month. Hence, next accounting month starts on Saturday following this last Friday of the month. For example – For Feb-23, last Friday is 24-Feb-23 and last Friday of Jan-23 is 27-Jan-23. Hence, for accounting month Feb, date range would be 28-Jan-23 to 24-Feb-23. There is an exception of the above rule. Jan will always start on 1-Jan and Dec will always finish on 31-Dec. Find the total sales for all months.
📌 Challenge Details and Links
ExcelBI Power Query Challenge Number: 92
Challenge Difficulty: ⭐️⭐️⭐️⭐️
📥Download Sample File
📥Link to the solutions on LinkedIn
Solving the challenge of Sales Based on Custom Month Range with Power Query
Power Query solution 1 for Sales Based on Custom Month Range, proposed by Omid Motamedisedeh:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
Custom1 = Table.Group(Table.TransformColumns(Source, {"Date", each [ a=Date.EndOfMonth(_),b=Date.DayOfWeek(Date.EndOfMonth(_),Day.Friday),c=Date.StartOfMonth(_),d=6-Date.DayOfWeek(Date.StartOfMonth(_),Day.Friday),e=if _hashtag#date(2023,12,10)) then _ else if _>Date.AddDays(c,-d) then _ else Date.AddDays(_,-10) else Date.AddDays(_,10), f=Date.MonthName(e) ][f]}),"Date",{"x",each List.Sum([Sales])})
in
Custom1
Power Query solution 2 for Sales Based on Custom Month Range, proposed by Bo Rydobon 🇹🇭:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
Last = List.Transform({2..13}, each let d = hashtag#date(2023,_,1) in try d-Duration.From(Number.Mod(Date.DayOfWeek(d,5)+6,7)+1) otherwise hashtag#date(2023,12,31) ),
Ans = Table.Group(Table.AddColumn(Source,"Month",each Date.ToText(List.First(List.Select(Last,(l)=> l>= Date.From([Date]))),"MMM")), "Month",{"Total Sale" ,each List.Sum([Sales])})
in
Ans
Power Query solution 3 for Sales Based on Custom Month Range, proposed by Zoran Milokanović:
let
Source = Excel.CurrentWorkbook(){[Name = "Input"]}[Content],
MonthShort = Table.AddColumn(
Source,
"Month",
each
let
d = Date.From([Date]),
lf = Date.AddDays(Date.EndOfMonth(d), - Date.DayOfWeek(Date.EndOfMonth(d), Day.Friday))
in
Text.Start(
Date.MonthName(if d <= lf or Date.Month(d) = 12 then d else Date.AddDays(d, 7)),
3
)
),
S = Table.Group(MonthShort, {"Month"}, {{"Total Sales", each List.Sum([Sales])}})
in
S
Power Query solution 4 for Sales Based on Custom Month Range, proposed by Alejandro Simón 🇵🇦 🇪🇸:
let
Source = List.Transform({Number.From(hashtag#date(2023,01,01))..Number.From(hashtag#date(2023,12,31))}, Date.From),
Tabla = Table.FromColumns({Source, List.Transform(Source, each Text.Start(Date.MonthName(_), 3)), List.Transform(Source, Date.DayOfWeekName)}, {"Date", "Mes", "Days"}),
Ajuste = Table.FillDown(Table.FillUp(Table.AddColumn(Tabla, "Month", each if [Days] = "Friday" then [Mes] else null), {"Month"}), {"Month"})[[Date], [Month]],
Sol = Table.Group(Table.AddColumn(Ajuste, "Total Sales", each try Table1{[Date = DateTime.From([Date])]}[Sales] otherwise null), {"Month"}, {{"Total Sales", each List.Sum([Total Sales])}})
in
Sol
Power Query solution 5 for Sales Based on Custom Month Range, proposed by Luan Rodrigues:
let
Fonte = Tabela1,
p = let
a = Table.FromList(List.Transform({Number.From(hashtag#date(2023,01,01))..Number.From(hashtag#date(2023,12,31))}, Date.From),Splitter.SplitByNothing(), null, null),
b = Table.AddColumn(a, "Personalizar", each
if Date.DayOfWeekName([Column1]) = "Friday" then Date.DayOfWeekName([Column1])& Date.ToText([Column1],"MMM") else null )
in
Table.FillDown(Table.FillUp(b,{"Personalizar"}),{"Personalizar"}),
tipo = Table.TransformColumnTypes(Fonte,{{"Date", type date,"en-us"}}),
mesc = Table.NestedJoin(p, {"Column1"}, tipo, {"Date"}, "Fonte", JoinKind.LeftOuter),
ex = Table.ExpandTableColumn(mesc, "Fonte", {"Sales"}, {"Sales"}),
add = Table.AddColumn(ex, "Month", each Text.End([Personalizar],3) ),
res = Table.Group(add, {"Month"}, {{"Total Sales", each List.Sum([Sales]), type nullable number}})
in
res
Power Query solution 6 for Sales Based on Custom Month Range, proposed by Eric Laforce:
let
Source = Excel.CurrentWorkbook(){[Name="tData92"]}[Content],
ChangeType = Table.TransformColumnTypes(Source,{{"Date", type date}}),
Add_Month = Table.AddColumn(ChangeType, "Month", each let
_EOM = Date.EndOfMonth([Date]),
_LastFriday = Date.AddDays(_EOM, -Date.DayOfWeek(_EOM,Day.Friday)*Number.From(Date.Month(_EOM)<>12)),
_Month = hashtag#date(1900,Date.Month([Date]) + Number.From([Date]>_LastFriday),1)
in Text.Start(Date.MonthName(_Month,"en-US"),3) ),
Group = Table.Group(Add_Month, "Month", {"Total Sales", each List.Sum([Sales])})
in
Group
Power Query solution 7 for Sales Based on Custom Month Range, proposed by Venkata Rajesh:
let
Source = Data,
Month = Table.AddColumn(
Source,
"Month",
each [
a = Date.StartOfWeek(Date.EndOfMonth([Date]), Day.Friday),
b = Date.StartOfWeek(Date.EndOfMonth(Date.AddMonths([Date], 1)), Day.Friday),
c = if Date.Month([Date]) = 12 then Date.EndOfMonth([Date]) else if [Date] <= a then a else b,
d = Text.Start(Date.MonthName(c), 3)
][d]
),
Output = Table.Group(Month, {"Month"}, {{"Sales", each List.Sum([Sales]), type nullable number}})
in
Output
Solving the challenge of Sales Based on Custom Month Range with Excel
Excel solution 1 for Sales Based on Custom Month Range, proposed by Bo Rydobon 🇹🇭:
=LET(d,A2:A114,m,SEQUENCE(12),y,2023,e,(m+1)&"/"&y,t,IFERROR(e-WEEKDAY(e,16),DATE(y,13,)),
HSTACK(TEXT(t-1,"mmm"),SUMIFS(B2:B114,d,">="&VSTACK("1/"&y,DROP(t,-1)+1),d,"<="&t)))
Excel solution 2 for Sales Based on Custom Month Range, proposed by محمد حلمي:
=LET(a,A2:A114,e,UNIQUE(WORKDAY.INTL(EOMONTH(+a,0)+1,-1,"1111011")),r,IF(MONTH(e)=12,EOMONTH(e,0),e),
HSTACK(TEXT(r,"mmm"),SUMIFS(B2:B114,a,">"&VSTACK(0,DROP(r,-1)),a,"<="&r)))
Excel solution 3 for Sales Based on Custom Month Range, proposed by محمد حلمي:
=LET(a,A2:A114,e,UNIQUE(WORKDAY.INTL(EOMONTH(+a,0)+1,-1,"1111011")),r,IF(MONTH(e)=12,EOMONTH(e,0),e),HSTACK(TEXT(r,"mmm"),MAP(r,VSTACK(0,DROP(r,-1)),LAMBDA(v,d,SUM(IF((a>d)*(a<=v),B2:B114))))))
Excel solution 4 for Sales Based on Custom Month Range, proposed by Kris Jaganah:
=LET(a,A2:A114,b,B2:B114,c,YEAR(TAKE(a,1)),d,DATE(c,12,31),e,EOMONTH(d,-12),f,DATE(c,1,SEQUENCE((d-e))),h,MAP(SEQUENCE(12),LAMBDA(x,MAX(FILTER(f,(MONTH(f)=x)*(WEEKDAY(f,2)=5))))),i,IF(MONTH(h)=12,MAX(f),h),j,VSTACK(e,DROP(i,-1))+1,VSTACK({"Month","Total Sales"},HSTACK(TEXT(h,"Mmm"),MAP(j,i,LAMBDA(v,w,SUM(((a)>=v)*((a)<=w)*b))))))
Excel solution 5 for Sales Based on Custom Month Range, proposed by Sunny Baggu:
=LET(
_seq, DATE(2023, SEQUENCE(12), 1),
_end, VSTACK(
DROP(MAP(_seq, LAMBDA(a, EOMONTH(a, 0) + 1 - WEEKDAY(EOMONTH(a, 0) + 1 - 6))), -1),
DATE(2023, 12, 31)
),
_start, VSTACK(DATE(2023, 1, 1), DROP(_end + 1, -1)),
_sales, DROP(
REDUCE(
"",
SEQUENCE(12),
LAMBDA(a, v,
VSTACK(
a,
SUM(FILTER(B2:B114, (A2:A114 >= INDEX(_start, v, 1)) * (A2:A114 <= INDEX(_end, v, 1))))
)
)
),
1
),
HSTACK(TEXT(_seq, "mmm"), _sales)
)
Excel solution 6 for Sales Based on Custom Month Range, proposed by LEONARD OCHEA 🇷🇴:
=LET(t,A2:B114,d,TAKE(t,,1),s,TAKE(t,,-1),m,MAP(d,LAMBDA(a,LET(f,EOMONTH(a,0),IF(a<=f+1-WEEKDAY(f,15),MONTH(a),MONTH(a)+IF(MONTH(a)=12,0,1))))),u,UNIQUE(m),VSTACK(HSTACK("Month","Total Sales"),HSTACK(TEXT(u&"-23","mmm"),MMULT((TOROW(m)=u)*TOROW(s),m^0))))
Excel solution 7 for Sales Based on Custom Month Range, proposed by Asheesh Pahwa:
=LET(a,A3:B115,
b,TAKE(a,,1),
c,TAKE(a,,-1),
d,MAP(b,LAMBDA(z,EOMONTH(z,0)-CHOOSE(WEEKDAY(EOMONTH(z,0),2),3,4,5,6,0,1,2))),
e,MAP(b,d,LAMBDA(x,y,IF(x<=y,y,IF(INDIRECT(ADDRESS(ROW(x)+1,1))=0,x,
INDIRECT(ADDRESS(ROW(x)+1,1)))))),
f,TEXT(e,"mmm"),
g,UNIQUE(f),
_Val,MAP(g,LAMBDA(q,SUM((f=q)*(c)))),
HSTACK(g,_Val))
Solving the challenge of Sales Based on Custom Month Range with Python in Excel
Python in Excel solution 1 for Sales Based on Custom Month Range, proposed by Alejandro Campos:
from datetime import datetime, timedelta
df = xl("A1:B114", headers=True)
df['Date'] = pd.to_datetime(df['Date'], dayfirst=True)
def last_friday(year: int, month: int):
last_day = datetime(year, month + 1, 1) - timedelta(days=1)
offset = (last_day.weekday() - 4) % 7
return last_day - timedelta(days=offset)
def calculate_monthly_sales(df):
sales, date = {}, datetime(2023, 1, 1)
while date.year < 2024:
y, m = date.year, date.month
start = datetime(y, 1, 1) if m == 1 else last_friday(y, m - 1) + timedelta(1)
end = datetime(y, 12, 31) if m == 12 else last_friday(y, m)
sales[f'{y}-{m:02d}'] = df.loc[(df['Date'] >= start) & (df['Date'] <= end), 'Sales'].sum()
date = (date + timedelta(32)).replace(day=1)
return sales
monthly_sales_df = pd.DataFrame(calculate_monthly_sales(df).items(), columns=['Month', 'Total Sales'])
monthly_sales_df['Month'] = pd.to_datetime(monthly_sales_df['Month'], format='%Y-%m').dt.strftime('%b')
monthly_sales_df
&&&
