Yesterday’s challenge was a tough one. Here, is an easier one though not straightforward in Power Query. Find the closing stock every day for table T1. The open stock on 1-Nov-23 has been given in table T2. Closing stock on 1-Nov-23 = Open Stock from Table T2 + IN-OUT Closing stock on succeeding days = Previous day’s closing stock + IN – OUT
📌 Challenge Details and Links
ExcelBI Power Query Challenge Number: 134
Challenge Difficulty: ⭐️⭐️⭐️
📥Download Sample File
📥Link to the solutions on LinkedIn
Solving the challenge of Daily Stock Closing Value with Power Query
Power Query solution 1 for Daily Stock Closing Value, proposed by Zoran Milokanović:
let
Source = each Excel.CurrentWorkbook(){[Name = _]}[Content],
T1 = Source("Table1"),
S = Table.AddColumn(
T1,
"Closing Stock",
(r) =>
let
l = List.Sum,
t = Table.SelectRows(T1, each [Store] = r[Store] and [Date] <= r[Date])
in
Source("Table2"){[Store = r[Store]]}[Open Stock] + l(t[IN]) - l(t[OUT])
)
in
S
Power Query solution 2 for Daily Stock Closing Value, proposed by Zoran Milokanović:
let
Source = each Excel.CurrentWorkbook(){[Name = _]}[Content],
T1 = Source("Table1"),
S = Table.FromRows(
List.Accumulate(
Table.ToRows(T1),
{},
(s, c) =>
s
& {
c
& {
let
l = List.Last(s, {""})
in
c{2}
- c{3}
+ (if l{0} = c{0} then l{4} else Source("Table2"){[Store = c{0}]}[Open Stock])
}
}
),
Table.ColumnNames(T1) & {"Closing Stock"}
)
in
S
Power Query solution 3 for Daily Stock Closing Value, proposed by Alejandro Simón 🇵🇦 🇪🇸:
let
Source = T1,
Sol = Table.Combine(
Table.Group(
Source,
{"Store"},
{
{
"All",
(x) =>
let
a = T2[Open Stock]{List.PositionOf(T2[Store], x[Store]{0})},
b = Table.AddColumn(x, "A", each [IN] - [OUT]),
c = List.Skip(List.Accumulate(b[A], {a}, (s, c) => s & {List.Last(s) + c})),
d = Table.FromColumns(
Table.ToColumns(x) & {c},
Table.ColumnNames(x) & {"Closing Stock"}
)
in
d
}
}
)[All]
)
in
Sol
Power Query solution 4 for Daily Stock Closing Value, proposed by Luan Rodrigues:
let
Fonte = Tabela1,
add = Table.AddColumn(
Fonte,
"Acc",
each [
a = Table.SelectRows(Tabela2, (x) => [Store] = x[Store] and Date.Day(Date.From([Date])) = 1)[
Open Stock
]{0}?
?? [IN]
- [OUT],
b = if Date.Day(Date.From([Date])) = 1 then [IN] - [OUT] + a else [IN] - [OUT]
][b]
),
gp = Table.Group(
add,
{"Store"},
{
{
"Contagem",
each [
a = Table.AddIndexColumn(_, "Ind", 1, 1),
b = Table.AddColumn(a, "Valor", each List.Sum(List.FirstN(a[Acc], [Ind])))
][b]
}
}
),
res = Table.ExpandTableColumn(gp, "Contagem", {"Date", "IN", "OUT", "Valor"})
in
res
Power Query solution 5 for Daily Stock Closing Value, proposed by Alexis Olson:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(
Source,
{{"Store", type text}, {"Date", type date}, {"IN", Int64.Type}, {"OUT", Int64.Type}}
),
#"Added Custom" = Table.AddColumn(#"Changed Type", "NET", each [IN] - [OUT], Int64.Type),
#"Merged Queries" = Table.NestedJoin(
#"Added Custom",
{"Store"},
T2,
{"Store"},
"T2",
JoinKind.LeftOuter
),
#"Expanded T2" = Table.ExpandTableColumn(#"Merged Queries", "T2", {"Open Stock"}, {"Open Stock"}),
#"Grouped Rows" = Table.Group(
#"Expanded T2",
{"Store"},
{
{
"Subtable",
each
let
OpenStock = List.Max([Open Stock]),
NetInOut = List.Buffer([NET]),
RunningTotal = List.Generate(
() => [RT = NetInOut{0} + OpenStock, i = 0],
each [i] < List.Count(NetInOut),
each [i = [i] + 1, RT = [RT] + NetInOut{i}],
each [RT]
)
in
Table.FromColumns(
Table.ToColumns(_) & {RunningTotal},
Table.ColumnNames(_) & {"Closing Stock"}
)
}
}
),
#"Expanded Subtable" = Table.ExpandTableColumn(
#"Grouped Rows",
"Subtable",
{"Date", "IN", "OUT", "Closing Stock"}
)
in
#"Expanded Subtable"
Power Query solution 6 for Daily Stock Closing Value, proposed by Ramiro Ayala Chávez:
let
Origen = Excel.CurrentWorkbook(){[Name = "Tabla2"]}[Content],
a = Excel.CurrentWorkbook(){[Name = "Tabla1"]}[Content],
d = Table.AddColumn(
a,
"O",
each
let
b = Origen[Open Stock],
c = List.PositionOf(Origen[Store], [Store])
in
b{c}
),
e = Table.Group(d, {"Store"}, {{"B", each _}})[[B]],
f = Table.TransformColumns(
e,
{
"B",
each
let
g = Table.AddColumn(_, "C", each [IN] - [OUT]),
h = Table.InsertRows(
g,
0,
{[Store = null, Date = null, IN = null, OUT = null, O = null, C = [O]{0}]}
),
i = Table.AddIndexColumn(h, "I", 1),
j = Table.Skip(
Table.AddColumn(i, "Closing Stock", each List.Sum(List.Range(i[C], 0, [I])))
)
in
j
}
),
Sol = Table.Combine(f[B])[[Store], [Date], [IN], [OUT], [Closing Stock]]
in
Sol
Power Query solution 7 for Daily Stock Closing Value, proposed by Eric Laforce:
let
t1 = Excel.CurrentWorkbook(){[Name = "tData134"]}[Content],
t2 = Table.Buffer(Excel.CurrentWorkbook(){[Name = "tData134_2"]}[Content]),
Group = Table.Group(
t1,
{"Store"},
{
"All",
(t) =>
let
_OpenStk = t2[Open Stock]{List.PositionOf(t2[Store], t[Store]{0})},
_Transform = List.Accumulate(
Table.ToRecords(t),
[Stk = _OpenStk, r = {}],
(s, c) =>
let
_NewStk = s[Stk] + c[IN] - c[OUT]
in
[Stk = _NewStk, r = s[r] & {Record.AddField(c, "Closing Stock", _NewStk)}]
)
in
Table.FromRecords(_Transform[r])
}
),
Combine = Table.Combine(Group[All])
in
Combine
Power Query solution 8 for Daily Stock Closing Value, proposed by 🇮🇷 Navid Esmaeilzadeh اسماعیل زاده:
let
S1 = Excel.CurrentWorkbook(){[Name = "T_1"]}[Content],
S2 = Excel.CurrentWorkbook(){[Name = "T_2"]}[Content],
G = Table.Group(
S1,
{"Store"},
{
{
"Tbl",
each _,
type table [
Store = nullable text,
Date = nullable datetime,
IN = nullable number,
OUT = nullable number
]
}
}
),
A = Table.AddColumn(G, "Tbl2", each Table.AddIndexColumn([Tbl], "I", 1, 1)),
R = Table.SelectColumns(A, {"Tbl2"}),
Tbls = (Tbl) =>
let
In = Table.AddColumn(Tbl, "S", each [IN] - [OUT], Int64.Type),
A2 = Table.AddColumn(In, "C", each List.Sum(List.FirstN(In[S], [I])))
in
A2,
IN2 = Table.AddColumn(R, "Tbls", each Tbls([Tbl2])),
R2 = Table.SelectColumns(IN2, {"Tbls"}),
Ex = Table.ExpandTableColumn(
R2,
"Tbls",
{"Store", "Date", "IN", "OUT", "I", "S", "C"},
{"Store", "Date", "IN", "OUT", "I", "S", "C"}
),
C2 = Table.NestedJoin(Ex, {"Store"}, S2, {"Store"}, "New", JoinKind.LeftOuter),
E = Table.ExpandTableColumn(C2, "New", {"Open Stock"}, {"Open Stock"}),
In3 = Table.AddColumn(E, "S1", each [Open Stock] + [C], type number),
R3 = Table.RenameColumns(In3, {{"S1", "Closing Stock"}}),
Rem = Table.SelectColumns(R3, {"Store", "Date", "IN", "OUT", "Closing Stock"})
in
Rem
Power Query solution 9 for Daily Stock Closing Value, proposed by Dominic Walsh:
let
T1 = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
T2 = Excel.CurrentWorkbook(){[Name = "Table2"]}[Content],
Join = Table.Join(T1, "Store", T2, "Store"),
Sort = Table.Sort(Join, {{"Store", Order.Ascending}, {"Date", Order.Ascending}}),
Shift = Table.FromColumns(
Table.ToColumns(Sort) & {{null} & List.RemoveLastN(Sort[Store], 1)},
Table.ColumnNames(Sort) & {"Shifted"}
),
End = Table.AddIndexColumn(Shift, "End", 0, 1, Int64.Type),
Start = Table.AddColumn(End, "Start", each if [Store] <> [Shifted] then [End] else null),
Fill = Table.FillDown(Start, {"Start"}),
Sum = Table.AddColumn(
Fill,
"Closing Stock",
each List.Sum(List.Range(Start[IN], [Start], [End] - [Start] + 1))
- List.Sum(List.Range(Start[OUT], [Start], [End] - [Start] + 1))
+ [Open Stock]
),
Final = Table.RemoveColumns(Sum, {"End", "Open Stock", "Shifted", "Start"})
in
Final
Solving the challenge of Daily Stock Closing Value with Excel
Excel solution 1 for Daily Stock Closing Value, proposed by Bo Rydobon 🇹🇭:
=HSTACK(A2:D12,MAP(A2:A12,C2:C12,D2:D12,LAMBDA(a,c,d,VLOOKUP(a,F2:G4,2,)+SUMIFS(C2:c,A2:a,a)-SUMIFS(D2:d,A2:a,a))))
Excel solution 2 for Daily Stock Closing Value, proposed by Rick Rothstein:
=IF(A2<>A1,LOOKUP(A2,G$2:G$4,H$2:H$4),E1)
Excel solution 3 for Daily Stock Closing Value, proposed by محمد حلمي:
=SCAN(0,A2:A12,LAMBDA(a,c,IF(c=OFFSET(c,-1,),a,
VLOOKUP(c,F2:G4,2,))+SUM(OFFSET(c,,2,,2)*{1,-1})))
Excel solution 4 for Daily Stock Closing Value, proposed by محمد حلمي:
=MAP(A2:A12,LAMBDA(d,INDEX(SCAN(VLOOKUP(d,F2:G4,2,),FILTER(C2:C12-D2:D12,A2:A12=d),LAMBDA(c,v,c+v)),
COUNTIF(A2:d,d))))
Excel solution 5 for Daily Stock Closing Value, proposed by محمد حلمي:
=REDUCE("Closing Stock",F2:F4,LAMBDA(A,d,
VSTACK(A,SCAN(VLOOKUP(d,F2:G4,2,),FILTER(
C2:C12-D2:D12,A2:A12=d),LAMBDA(c,v,c+v)))))
=REDUCE("Closing Stock",
UNIQUE(A2:A12),LAMBDA(A,d,LET(
i,FILTER(C2:D12,A2:A12=d),VSTACK(A,SCAN(VLOOKUP(
d,F2:G4,2,),TAKE(i,,1)-DROP(i,,1),LAMBDA(c,v,c+v))))))
Excel solution 6 for Daily Stock Closing Value, proposed by Kris Jaganah:
=LET(a,A1:A12,b,B1:B12,c,C1:C12,d,D1:D12,e,F2:F4,f,G2:G4,g,IF(b=MIN(b),XLOOKUP(a,e,f),0),h,TOCOL(HSTACK(IF(g>0,a,1/0),c-d+g),3),i,SCAN(0,h,LAMBDA(x,y,IF(ISTEXT(y),0,x+y))),HSTACK(a,b,c,d,VSTACK("Closing Stock",FILTER(i,i<>0)))
Excel solution 7 for Daily Stock Closing Value, proposed by Duy Tùng:
=LET(a,A2:A12,b,ROW(a),HSTACK(A1:D12,VSTACK("Closing Stock",LOOKUP(a,F2:G4)-MMULT((a=TOROW(a))*(b>=TOROW(b)),D2:D12-C2:C12))))
Excel solution 8 for Daily Stock Closing Value, proposed by Sunny Baggu:
=HSTACK(
A2:D12,
DROP(
REDUCE(
"",
F2:F4,
LAMBDA(a, v,
VSTACK(
a,
SCAN(
XLOOKUP(v, F2:F4, G2:G4),
FILTER(C2:C12 - D2:D12, A2:A12 = v),
LAMBDA(x, y, x + y)
)
)
)
),
1
)
)
Excel solution 9 for Daily Stock Closing Value, proposed by Mey Tithveasna:
=VSTACK (A1:E1,HSTACK(A2:D12,MAP(A2:A12,C2:C12,D2:D12, LAMBDA(a,c,d,
LOOKUP(a,F2:G4)+SUMIF(A2:a,a,C2:c)-SUMIF(A2:a,a,D2:d)))))
Excel solution 10 for Daily Stock Closing Value, proposed by Ziad A.:
={A2:D12,SCAN(,A2:A12,LAMBDA(a,c,IF(c=OFFSET(c,-1,),a,VLOOKUP(c,F2:G4,2,))+OFFSET(c,,2)-OFFSET(c,,3)))
Excel solution 11 for Daily Stock Closing Value, proposed by Edwin Tisnado:
=LET(a,A2:D12,b,F2:G4,v,HSTACK(A1:D1,"Closing Stock"),i,TAKE(a,,-2),j,TAKE(i,,1)-TAKE(i,,-1),c,TAKE(a,,1),s,c=OFFSET(c,-1,),t,VLOOKUP(c,b,2),f,SCAN(0,SEQUENCE(ROWS(a)),LAMBDA(x,y,LET(u,INDEX(j,y),IF(INDEX(s,y),x+u,u)))),VSTACK(v,HSTACK(a,f+t)))
Excel solution 12 for Daily Stock Closing Value, proposed by Hazem Hassan:
=IF(A2=A1,I1+C2-D2,VLOOKUP(A2,$F$2:$G$4,2,)+C2-D2)
Solving the challenge of Daily Stock Closing Value with Python in Excel
Python in Excel solution 1 for Daily Stock Closing Value, proposed by Alejandro Campos:
df = pd.merge(
xl("A1:D12", headers=True).sort_values(by=['Store', 'Date']).assign(
Date=lambda x: pd.to_datetime(x['Date'], format='%d/%m/%Y')),
xl("F1:G4", headers=True),
on='Store')
df['Closing Stock'] = df.groupby('Store').apply(
lambda g: g.assign(Closing_Stock=g['Open Stock'].cumsum() + g['IN'].cumsum() - g['OUT'].cumsum()))
.reset_index(drop=True)['Closing_Stock']
result_df = df[['Store', 'Date', 'IN', 'OUT', 'Closing Stock']].to_numpy().tolist()
result_df
Solving the challenge of Daily Stock Closing Value with R
R solution 1 for Daily Stock Closing Value, proposed by Konrad Gryczan, PhD:
I yesterday was at 10/10, today we have like strong 8/10.
library(tidyverse)
library(readxl)
input1 = read_excel("PQ_Challenge_134.xlsx", range = "A1:D12")
input2 = read_excel("PQ_Challenge_134.xlsx", range = "F1:G4")
test = read_excel("PQ_Challenge_134.xlsx", range = "J1:N12")
opening = input2 %>%
mutate(Date = min(input1$Date)) %>%
rename(open = `Open Stock`)
result <- opening %>%
rename(IN = open, OUT = integer(length(open))) %>%
bind_rows(input1) %>%
group_by(Store) %>%
arrange(Store, Date) %>%
mutate(OUT = ifelse(is.na(OUT), 0, OUT),
closing_stock = cumsum(IN) - cumsum(OUT)) %>%
ungroup() %>%
filter(OUT != 0) %>%
select(Store, Date, IN, OUT, `Closing Stock` = closing_stock)
&&
