Work out the Start and End Stock for all line items. For first occurrence of Item & Store combination Start Stock = Stock IN End Stock = Start Stock – Stock OUT For succeeding occurrences of Item & Store combination Start Stock = End Stock in previous occurrence End Stock = Start Stock + Stock IN – Stock OUT
📌 Challenge Details and Links
ExcelBI Power Query Challenge Number: 197
Challenge Difficulty: ⭐️⭐️⭐️⭐️⭐️
📥Download Sample File
📥Link to the solutions on LinkedIn
Solving the challenge of Calculate Stock Start End with Power Query
Power Query solution 1 for Calculate Stock Start End, proposed by Zoran Milokanović:
let
Source = Excel.CurrentWorkbook(){[Name = "Input"]}[Content],
S = Table.ExpandRecordColumn(
Table.AddColumn(
Source,
"E",
each
let
t = Table.SelectRows(
Table.FirstN(Source, (r) => r <> _),
(r) => r[Item] = [Item] and r[Store] = [Store]
),
b = (List.Sum(t[Stock IN]) - List.Sum(t[Stock OUT]) ?? 0)
in
[S = Byte.From(Table.RowCount(t) = 0) * [Stock IN] + b, E = [Stock IN] - [Stock OUT] + b]
),
"E",
{"S", "E"},
{"Start Stock", "End Stock"}
)
in
S
Power Query solution 2 for Calculate Stock Start End, proposed by Zoran Milokanović:
let
Source = Excel.CurrentWorkbook(){[Name = "Input"]}[Content],
S = Table.FromRows(
List.Accumulate(
Table.ToRows(Source),
{},
(b, n) =>
let
s = List.Sum(
List.Transform(List.Select(b, each {n{1}, n{2}} = {_{1}, _{2}}), each _{3} - _{4})
)
in
b & {n & {s ?? n{3}, n{3} - n{4} + (s ?? 0)}}
),
Table.ColumnNames(Source) & {"Start Stock", "End Stock"}
)
in
S
Power Query solution 3 for Calculate Stock Start End, proposed by Aditya Kumar Darak 🇮🇳:
let
Source = Excel.CurrentWorkbook(){[Name = "data"]}[Content],
Index = Table.AddIndexColumn(Source, "Index"),
Group = Table.Group(
Index,
{"Item", "Store"},
{
"R",
each List.Generate(
() => [a = 0, b = _{a}, c = b[Stock IN], d = c - b[Stock OUT]],
(f) => f[a] < Table.RowCount(_),
(f) => [a = f[a] + 1, b = _{a}, c = f[d], d = c + b[Stock IN] - b[Stock OUT]],
(f) => f[b] & [Opening = f[c], Closing = f[d]]
)
}
),
Table = Table.FromRecords(List.Combine(Group[R])),
Sort = Table.Sort(Table, {"Index"}),
Return = Table.RemoveColumns(Sort, {"Index"})
in
Return
Power Query solution 4 for Calculate Stock Start End, proposed by Aditya Kumar Darak 🇮🇳:
Power Query solution 5 for Calculate Stock Start End, proposed by Alejandro Simón 🇵🇦 🇪🇸:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
Idx = Table.AddIndexColumn(Source, "Idx", 1, 1),
Group = Table.Combine(
Table.Group(
Idx,
{"Item", "Store"},
{
{
"A",
each
let
a = _,
b = List.Skip(
List.Generate(
() => [x = 0, y = a[Stock IN]{0}],
each [x] <= Table.RowCount(a),
each [
x = [x] + 1,
y =
if [x] = 0 then
[y] - a[Stock OUT]{[x]}
else
[y] + a[Stock IN]{[x]} - a[Stock OUT]{[x]},
z = {[y], y}
],
each [z]?
)
),
c = List.Transform({0 .. Table.RowCount(a) - 1}, each Table.ToRows(a){_} & b{_}),
d = Table.FromRows(c, Table.ColumnNames(a) & {"Start Stock", "End Stock"})
in
d
}
}
)[A]
),
Sol = Table.RemoveColumns(Table.Sort(Group, {{"Idx", Order.Ascending}}), {"Idx"})
in
Sol
Power Query solution 6 for Calculate Stock Start End, proposed by Hussein SATOUR:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
Group = Table.Group(
Source,
{"Item", "Store"},
{
{
"All",
each _,
type table [Month = text, Item = text, Store = text, Stock IN = number, Stock OUT = number]
}
}
),
AddCust = Table.AddColumn(
Group,
"Custom",
each [
a = Table.AddIndexColumn([All], "Ind", 1),
b = Table.AddColumn(
a,
"End",
each List.Sum(List.FirstN(a[Stock IN], [Ind])) - List.Sum(List.FirstN(a[Stock OUT], [Ind]))
),
c = Table.AddColumn(b, "Start", each [End] + [Stock OUT] - [Stock IN])
][c]
),
Expand = Table.ExpandTableColumn(
AddCust,
"Custom",
{"End", "Month", "Start", "Stock IN", "Stock OUT"},
{"End", "Month", "Start", "Stock IN", "Stock OUT"}
),
Removs = Table.RemoveColumns(Expand, {"All"})
in
Removs
Power Query solution 7 for Calculate Stock Start End, proposed by Eric Laforce:
let
Source = Excel.CurrentWorkbook(){[Name = "tData197"]}[Content],
Add_Index = Table.AddIndexColumn(Source, "Index", 0, 1, Int64.Type),
Group = Table.Group(
Add_Index,
{"Item", "Store"},
{
"G",
each List.Generate(
() => [i = 0, r = _{i}, ss = r[Stock IN], es = ss - r[Stock OUT]],
(x) => x[i] < Table.RowCount(_),
(x) => [i = x[i] + 1, r = _{i}, ss = x[es], es = ss + r[Stock IN] + r[Stock OUT]],
each [r] & [#"Start Stock" = [ss], #"End Stock" = [es]]
)
}
),
Combine = Table.FromRecords(List.Combine(Group[G])),
SortBack = Table.RemoveColumns(Table.Sort(Combine, "Index"), "Index")
in
SortBack
Power Query solution 8 for Calculate Stock Start End, proposed by 🇮🇷 Navid Esmaeilzadeh اسماعیل زاده:
let
S = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
A = Table.Group(
S,
{"Item", "Store"},
{
{
"Tbl",
each _,
type table [Month = text, Item = text, Store = text, Stock IN = number, Stock OUT = number]
}
}
),
MF = (T) =>
let
B = Table.AddIndexColumn(T, "I", 0, 1, Int64.Type),
C = Table.AddColumn(B, "S", each [Stock IN] - [Stock OUT], type number),
D = Table.AddColumn(
C,
"End Stock",
each if [I] = 0 then [S] else List.Sum(List.FirstN(C[S], [I] + 1))
),
E = Table.AddColumn(
D,
"Start Stock",
each if [I] = 0 then [Stock IN] else D[End Stock]{[I] - 1}
),
F = Table.SelectColumns(
E,
{"Month", "Item", "Store", "Stock IN", "Stock OUT", "Start Stock", "End Stock"}
)
in
F,
B = Table.AddColumn(A, "MF", each MF([Tbl])),
C = Table.SelectColumns(B, {"MF"}),
D = Table.ExpandTableColumn(
C,
"MF",
{"Month", "Item", "Store", "Stock IN", "Stock OUT", "Start Stock", "End Stock"},
{"Month", "Item", "Store", "Stock IN", "Stock OUT", "Start Stock", "End Stock"}
),
E = Table.AddColumn(D, "IM", each List.PositionOf(List.Distinct(S[Month]), [Month])),
F = Table.Sort(
E,
{{"IM", Order.Ascending}, {"Item", Order.Ascending}, {"Store", Order.Ascending}}
),
G = Table.RemoveColumns(F, {"IM"})
in
G
Solving the challenge of Calculate Stock Start End with Excel
Excel solution 1 for Calculate Stock Start End, proposed by Bo Rydobon 🇹🇭:
=LET(l,
LAMBDA(y,
MAP(E2:E21,
LAMBDA(v,
LET(a,
B2:v,
r,
ROWS(
a
),
b,
BYROW(
TAKE(
a,
,
2
),
CONCAT
),
x,
TAKE(
b,
-1
),
IF(IF(
y,
XMATCH(
x,
b
)=r,
0
),
INDEX(
a,
r,
3
),
SUM(DROP(DROP(
a,
,
2
)*{1,
-1}*(b=x),
-y))))))),
HSTACK(
A2:E21,
l(
1
),
l(
0
)
))
Excel solution 2 for Calculate Stock Start End, proposed by محمد حلمي:
=XLOOKUP(
B2&C2,
$B$1:B1&$C$1:C1,
$Q$1:Q1,
D2,
,
-1
)
Q2:
=IF(
P2<>D2,
P2-E2+D2,
D2-E2
)
Excel solution 3 for Calculate Stock Start End, proposed by محمد حلمي:
=REDUCE(M1:N1,
D2:D21,
LAMBDA(a,
v,
LET(
s,
XLOOKUP(
CONCAT(
TAKE(
B2:v,
-1,
2
)
),
B1:OFFSET(
v,
-1,
-2
)&C1:OFFSET(
v,
-1,
-1
),
TAKE(
a,
,
-1
),
v,
,
-1
),
VSTACK(a,
HSTACK(s,
(s<>v)*s+v-OFFSET(
v,
,
1
))))))
Excel solution 4 for Calculate Stock Start End, proposed by Julian Poeltl:
=LET(T,
A1:E21,
TT,
DROP(
T,
1
),
In,
CHOOSECOLS(
TT,
4
),
D,
In-TAKE(
TT,
,
-1
),
M,
MONTH(
1&TAKE(
TT,
,
1
)
),
I,
CHOOSECOLS(
TT,
2
),
S,
CHOOSECOLS(
TT,
3
),
ES,
MAP(M,
I&S,
LAMBDA(A,
B,
SUM(FILTER(D,
(M<=A)*(I&S=B))))),
SS,
MAP(M,
I&S,
LAMBDA(A,
B,
IFERROR(SUM(FILTER(D,
(M
Solving the challenge of Calculate Stock Start End with Python
Python solution 1 for Calculate Stock Start End, proposed by Konrad Gryczan, PhD:
import pandas as pd
path = "PQ_Challenge_197.xlsx"
input = pd.read_excel(path, usecols="A:E")
test = pd.read_excel(path, usecols="H:N")
test.columns = test.columns.str.replace(".1", "")
input["Month"] = pd.to_datetime(input["Month"], format="%b").dt.month
input = input.sort_values(["Store", "Item", "Month"]).reset_index(drop=True)
input["Row"] = input.groupby(["Store", "Item"]).cumcount()+1
for i in range(len(input)):
if input.loc[i, "Row"] == 1:
input.loc[i, "Start Stock"] = input.loc[i, "Stock IN"]
input.loc[i, "End Stock"] = input.loc[i, "Stock IN"] - input.loc[i, "Stock OUT"]
else:
input.loc[i, "Start Stock"] = input.loc[i-1, "End Stock"]
input.loc[i, "End Stock"] = input.loc[i, "Start Stock"] - input.loc[i, "Stock OUT"] + input.loc[i, "Stock IN"]
input["Month"] = pd.to_datetime(input["Month"], format="%m").dt.strftime("%b")
input["Start Stock"] = input["Start Stock"].astype("int64")
input["End Stock"] = input["End Stock"].astype("int64")
result = test.merge(input, on=["Store", "Item", "Month", "Stock IN"], how="left", suffixes=("_test", ""))
result = result[["Month","Item","Store", "Stock IN", "Stock OUT", "Start Stock", "End Stock"]]
print(result.equals(test))
Solving the challenge of Calculate Stock Start End with R
R solution 1 for Calculate Stock Start End, proposed by Konrad Gryczan, PhD:
library(tidyverse)
library(readxl)
path = "Power Query/PQ_Challenge_197.xlsx"
input = read_xlsx(path, range = "A1:E21")
test = read_xlsx(path, range = "H1:N21")
result <- input %>%
group_by(Item, Store) %>%
mutate(data = accumulate(`Stock IN` - `Stock OUT`, `+`, .init = 0)[-1],
`Start Stock` = lag(data, default = first(`Stock IN`)),
`End Stock` = data) %>%
ungroup() %>%
select(-data)
identical(result, test)
#> [1] TRUE
R solution 2 for Calculate Stock Start End, proposed by Anil Kumar Goyal:
df <- read_excel("PQ/PQ_Challenge_197.xlsx", range = cell_cols(LETTERS[1:5])) %>%
janitor::clean_names()
df %>%
mutate(data = 0,
data = lag(data, default = first(stock_in)),
data = accumulate2(stock_in - stock_out, data,
.f = ~list(start = ..1[["end"]] + ..3,
end = ..1[["end"]] + ..2),
.init = list(start = NA, end = 0))[-1],
.by = c(item, store)) %>%
unnest_wider(data)
Solving the challenge of Calculate Stock Start End with DAX
DAX solution 1 for Calculate Stock Start End, proposed by Zoran Milokanović:
EVALUATE
ADDCOLUMNS(Input,
"Start Stock",
COALESCE(CALCULATE(SUMX(Input, Input[Stock IN] - Input[Stock OUT]), ALLEXCEPT(Input, Input[Item], Input[Store]),
FIND(Input[Month], "JanFebMarAprMayJunJulAugSepOctNovDec") < FIND(EARLIER(Input[Month]), "JanFebMarAprMayJunJulAugSepOctNovDec")), Input[Stock IN]),
"End Stock",
CALCULATE(SUMX(Input, Input[Stock IN] - Input[Stock OUT]), ALLEXCEPT(Input, Input[Item], Input[Store]),
FIND(Input[Month], "JanFebMarAprMayJunJulAugSepOctNovDec") <= FIND(EARLIER(Input[Month]), "JanFebMarAprMayJunJulAugSepOctNovDec"))
)
&&&
