Home » Fill Down using dynamic arrays.

Fill Down using dynamic arrays.

Add the opening stock to each recorded stock during the day Note that this is not a running total but a stock adjustment For example, the last recording on the 10th is 201, i.e 200(open)+1(last record) Dynamic array function allowed, but Extra marks for Legacy solutions  or PowerQuery Solution

📌 Challenge Details and Links
Challenge Number: 47
Challenge Difficulty: ⭐
📥Link to the solutions on LinkedIn

Solving the challenge of Fill Down using dynamic arrays. with Power Query

Power Query solution 1 for Fill Down using dynamic arrays., proposed by Zoran Milokanović:
let
  Source = Excel.CurrentWorkbook(){[Name = "tblStock"]}[Content], 
  S = Table.FromRows(
    List.TransformMany(
      List.RemoveNulls(Source[Date]), 
      each 
        let
          t = Table.Skip(Source, (r) => r[Date] <> _), 
          f = t[Units]{0}
        in
          {f}
            & Table.FirstN(
              Table.Skip(Table.TransformColumns(t, {"Units", each _ + f})), 
              (r) => r[Date] = null
            )[Units], 
      (i, _) => {i, _}
    ), 
    {"Date", "Units"}
  )
in
  S
Power Query solution 2 for Fill Down using dynamic arrays., proposed by Kris Jaganah:
let
  A = Excel.CurrentWorkbook(){[Name = "tblStock"]}[Content], 
  B = Table.FillDown(A, {"Date"}), 
  C = Table.AddColumn(
    B, 
    "An", 
    each 
      let
        a = if [Instance] = null then null else [Units]
      in
        a
  ), 
  D = Table.FillDown(C, {"An"}), 
  E = Table.AddColumn(D, "Unit", each if [Instance] <> null then [An] else [Units] + [An])[
    [Date], 
    [Unit]
  ], 
  F = Table.RenameColumns(E, {{"Unit", "Units"}})
in
  F
Power Query solution 3 for Fill Down using dynamic arrays., proposed by Alejandro Simón 🇵🇦 🇪🇸:
let
  Source = Excel.CurrentWorkbook(){[Name = "tblStock"]}[Content], 
  Group = Table.Group(
    Source, 
    "Date", 
    {
      {
        "Units", 
        each {[Units]{0}} & List.Transform(List.RemoveFirstN([Units]), (x) => [Units]{0} + x)
      }
    }, 
    0, 
    (a, b) => Number.From(b <> null)
  ), 
  Sol = Table.ExpandListColumn(Group, "Units")
in
  Sol
Power Query solution 4 for Fill Down using dynamic arrays., proposed by Luan Rodrigues:
let
  Fonte = tblStock, 
  grp = Table.Group(
    Fonte, 
    "Date", 
    {
      {
        "tab", 
        each 
          let
            a = _[Units], 
            b = {a{0}} & List.Transform(List.Skip(a), (x) => a{0} + x)
          in
            b
      }
    }, 
    0, 
    (x, y) => Number.From(y <> null)
  ), 
  exp = Table.ExpandListColumn(grp, "tab")
in
  exp
Power Query solution 5 for Fill Down using dynamic arrays., proposed by Brian Julius:
let
  Source = Table.FillDown(
    Table.RemoveColumns(
      Table.TransformColumnTypes(
        Excel.CurrentWorkbook(){[Name = "tblStock"]}[Content], 
        {"Date", Date.Type}
      ), 
      "Instance"
    ), 
    {"Date"}
  ), 
  Group = Table.Group(Source, {"Date"}, {{"All", each _}}), 
  TransUnits = Table.AddColumn(
    Group, 
    "Ans", 
    each [
      a = [All][Units], 
      b = List.First(a), 
      c = List.Transform(List.Skip(a, 1), each b + _), 
      d = {b} & {c}{0}
    ][d]
  ), 
  Ans = Table.RenameColumns(
    Table.RemoveColumns(Table.ExpandListColumn(TransUnits, "Ans"), "All"), 
    {"Ans", "Units"}
  )
in
  Ans
Power Query solution 6 for Fill Down using dynamic arrays., proposed by Abdallah Ally:
let
  Source = Excel.CurrentWorkbook(){[Name = "tblStock2"]}[Content], 
  FillDown = Table.FillDown(Source, {"Date"}), 
  Transform = List.Transform(
    List.Distinct(FillDown[Date]), 
    each [
      a = Table.SelectRows(FillDown, (x) => x[Date] = _), 
      b = Table.TransformRows(
        a, 
        each [[Date]] & [Units = [Units] + Byte.From([Instance] = null) * a[Units]{0}]
      )
    ][b]
  ), 
  FromRecords = Table.FromRecords(List.Combine(Transform)), 
  Result = Table.TransformColumnTypes(FromRecords, {"Date", type date})
in
  Result
Power Query solution 7 for Fill Down using dynamic arrays., proposed by Ramiro Ayala Chávez:
let
  S = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  a = Table.TransformColumnTypes(Table.RemoveColumns(S, "Instance"), {"Units", type text}), 
  b = Table.AddColumn(a, "A", each if [Date] <> null then [Units] else null), 
  c = Table.AddColumn(
    Table.FillDown(b, {"A"}), 
    "B", 
    each 
      if [Date] <> null then
        [Units]
      else if Text.Length([Units]) = 2 then
        Text.RemoveRange([A], 1, 2) & [Units]
      else
        Text.RemoveRange([A], 2) & [Units]
  ), 
  Sol = Table.RenameColumns(Table.FillDown(c, {"Date"})[[Date], [B]], {"B", "Units"})
in
  Sol
Power Query solution 8 for Fill Down using dynamic arrays., proposed by 🇮🇷 Navid Esmaeilzadeh اسماعیل زاده:
let
  S = Excel.CurrentWorkbook(){[Name = "tblStock"]}[Content], 
  A = Table.FillDown(S, {"Date"}), 
  B = Table.TransformColumnTypes(A, {{"Date", type date}}), 
  C = Table.Group(B, {"Date"}, {{"T", each _}}), 
  D = Table.AddColumn(
    C, 
    "Units", 
    each 
      let
        A = [T][Units]{0}, 
        B = {A} & List.Transform(List.Skip([T][Units], 1), each _ + A)
      in
        B
  ), 
  E = Table.SelectColumns(D, {"Date", "Units"}), 
  F = Table.ExpandListColumn(E, "Units")
in
  F
Power Query solution 9 for Fill Down using dynamic arrays., proposed by Ahmed Ariem:
let
  f = (w) =>
    Table.Combine(
      Table.Group(
        w, 
        "Date", 
        {
          "tmp", 
          (x) =>
            [
              a = Table.AddColumn(
                x, 
                "Unit", 
                each if [Date] <> null then 0 + [Units] else [Units] + x[Units]{0}
              ), 
              b = Table.FillDown(a, {"Date"})
            ][b][[Date], [Unit]]
        }, 
        0, 
        (a, b) => Number.From(b <> null)
      )[tmp]
    ), 
  Source = f(Excel.CurrentWorkbook(){[Name = "tblStock"]}[Content])
in
  Source

Solving the challenge of Fill Down using dynamic arrays. with Excel

Excel solution 1 for Fill Down using dynamic arrays., proposed by Bo Rydobon 🇹🇭:
=LET(x,
   B3:B16,
   v,
   D3:D16,
   d,
   SCAN(
       ,
       x,
       MAX),
   HSTACK(d,
   LOOKUP(
       d,
       x,
       v)*(x=0)+v))
Excel solution 2 for Fill Down using dynamic arrays., proposed by Rick Rothstein:
=IF(
   B3="",
   MAX(
       B$2:B2),
   B3)

Put this formula in cell G2 and copy down...
=IF(
   B3="",
   LOOKUP(
       9^9,
       B$3:B3,
       D$3:D3)+D3,
   D3)
Excel solution 3 for Fill Down using dynamic arrays., proposed by Rick Rothstein:
=HSTACK(
   SCAN(
       ,
       B3:B16,
       MAX),
   MAP(
       B3:B16,
       D3:D16,
       LAMBDA(
           b,
           d,
           IF(
               b="",
               LOOKUP(
                   9^9,
                   B3:b,
                   D3:d)+d,
               d))))
Excel solution 4 for Fill Down using dynamic arrays., proposed by 🇰🇷 Taeyong Shin:
=LET(
   u,
   D3:D16,
   d,
   B3:B16,
   s,
   SCAN(
       ,
       d,
       MAX),
   HSTACK(
       s,
       NOT(
           d)*u+XLOOKUP(
           s,
           s,
           u)))
Excel solution 5 for Fill Down using dynamic arrays., proposed by Kris Jaganah:
=LET(
   a,
   tblStock[Date],
   b,
   tblStock[Units],
   c,
   SCAN(
       ,
       a,
       LAMBDA(
           x,
           y,
           IF(
               y,
               y,
               x))),
   d,
   SCAN(
       0,
       a,
       LAMBDA(
           x,
           y,
           IF(
               y,
               OFFSET(
                   y,
                   ,
                   2),
               x))),
   VSTACK(
       {"Date",
       "Units"},
       HSTACK(
           c,
           IF(
               a,
               b,
               d+b))))
Excel solution 6 for Fill Down using dynamic arrays., proposed by Julian Poeltl:
=LET(
   I,
   tblStock[Date],
   U,
   tblStock[Units],
   D,
   HSTACK(
       SCAN(
           "",
           I,
           LAMBDA(
               A,
               B,
               IF(
                   B="",
                   A,
                   B)))),
   HSTACK(
       D,
       XLOOKUP(
           D,
           I,
           U)+IF(
           I="",
           U,
           0)))
Excel solution 7 for Fill Down using dynamic arrays., proposed by Hussein SATOUR:
=LET(
   d,
   B3:B16,
   u,
   D3:D16,
   a,
   SCAN(
       ,
       d,
       LAMBDA(
           x,
           y,
           IF(
               y="",
               x,
               y))),
   HSTACK(
       a,
       XLOOKUP(
           a,
           d,
           u)+IF(
           C3:C16="Opening",
           0,
           u)))
Excel solution 8 for Fill Down using dynamic arrays., proposed by Oscar Mendez Roca Farell:
=LOOKUP(2,
   1/(B$3:B3>0),
   B$3:B3)
For Units: =LOOKUP(2,
   1/(B$3:B3>0),
   D$3:D3)+D3*(B3=0)

Dynamic Array:
=LET(d,
    B3:B16,
    u,
    D3:D16,
    m,
    SCAN(
        ,
         d,
         MAX),
    HSTACK(m,
    (d=0)*u+INDEX(
        u,
         XMATCH(
             m,
              d))))
Excel solution 9 for Fill Down using dynamic arrays., proposed by Sunny Baggu:
=HSTACK(
SCAN(
    "",
     tblStock[Date],
     LAMBDA(
         x,
          y,
          IF(
              y = "",
               x,
               y))),
   
SCAN(
    
     0,
    
     IF(
         
          tblStock[Instance] = tblStock[@Instance],
         
          tblStock[Units],
         
          0
          ),
    
     LAMBDA(
         a,
          v,
          IF(
              v = 0,
               a,
               v))
     ) + tblStock[Units] * (tblStock[Instance] <> tblStock[@Instance]))
Excel solution 10 for Fill Down using dynamic arrays., proposed by Md. Zohurul Islam:
=LET(
   
    A,
    tblStock221[Date],
   
    B,
    tblStock221[Instance],
   
    C,
    tblStock221[Units],
   
    dates,
    SCAN(
        0,
         A,
         LAMBDA(
             x,
              y,
              MAX(
                  x,
                   y))),
   
    E,
    XLOOKUP(
        dates,
         dates,
         C),
   
    F,
    ROW(
        C),
   
    G,
    B = 0,
   
    H,
    F / G,
   
    J,
    XLOOKUP(
        F,
         H,
         C,
         0),
   
    units,
    E + J,
   
    result,
    HSTACK(
        dates,
         units),
   
    header,
    {"Date",
    "Units"},
   
    Report,
    VSTACK(
        header,
         result),
   
    Report
   )
Excel solution 11 for Fill Down using dynamic arrays., proposed by Hamidi Hamid:
=LET(
   x,
   IF(
       C3:C16<>"",
       D3:D16,
       ""),
   y,
   IF(
       C3:C16<>"",
       0,
       D3:D16),
   z,
   SCAN(
       ,
       x,
       LAMBDA(
           a,
           b,
           IF(
               b<>"",
               b,
               a))),
   HSTACK(
       SCAN(
           ,
           B3:B16,
           LAMBDA(
               a,
               b,
               IF(
                   b<>"",
                   b,
                   a))),
       y+z))
Excel solution 12 for Fill Down using dynamic arrays., proposed by Asheesh Pahwa:
=LET(
   d,
   B3:B16,
   un,
   D3:D16,
   sc,
   SCAN(
       ,
       d,
       LAMBDA(
           x,
           y,
           IF(
               y,
               y,
               x))),
   u,
   UNIQUE(
       sc),
   DROP(
       REDUCE(
           "",
           u,
           LAMBDA(
               x,
               y,
               VSTACK(
                   x,
                   LET(
                       f,
                       FILTER(
                           un,
                           sc=y),
                       t,
                       TAKE(
                           f,
                           1),
                       s,
                       t+DROP(
                           f,
                           1),
                       IFNA(
                           HSTACK(
                               y,
                               VSTACK(
                                   t,
                                   s)),
                           y))))),
       1))
Excel solution 13 for Fill Down using dynamic arrays., proposed by Ankur Sharma:
=HSTACK(
   MAP(
       tblStock[Date],
        LAMBDA(
            z,
             TEXT(
                 IF(
                     z <> "",
                      z,
                      MAX(
                          B3:z)),
                  "dd-mmm-yyyy"))),
    MAP(
        tblStock[Date],
         tblStock[Units],
         LAMBDA(
             y,
             z,
              IF(
                  y <> "",
                   z,
                   FILTER(
                       tblStock[Units],
                        tblStock[Date] = MAX(
                            B3:y)) + z))))
Excel solution 14 for Fill Down using dynamic arrays., proposed by Milan Shrimali:
=let(
   a,
   filter(
       B3:D16,
       C3:C16<>""),
   tbl1,
   hstack(
       byrow(
           choosecols(
               a,
               3),
           lambda(
               x,
               arrayformula(
                   match(
                       x,
                       D3:D16,
                       0)+1))),
       a),
   fnl,
   hstack(
       byrow(
           D3:D16,
           lambda(
               x,
               xlookup(
                   row(
                       x),
                   choosecols(
                       tbl1,
                       1),
                   choosecols(
                       tbl1,
                       2,
                       3,
                       4),
                   "",
                   -1))),
       D3:D16),
   hstack(
       choosecols(
           fnl,
           1),
       byrow(
           fnl,
           lambda(
               x,
               if(
                   choosecols(
                       x,
                       3)=CHOOSECOLS(
                       x,
                       4),
                   choosecols(
                       x,
                       3),
                   choosecols(
                       x,
                       3)+CHOOSECOLS(
                       x,
                       4))))))
Excel solution 15 for Fill Down using dynamic arrays., proposed by Tomasz Jakóbczyk:
=SCAN(
   tblStock[@Date],
   tblStock[Date],
   LAMBDA(
       t,
       v,
       IF(
           ISBLANK(
               v),
           t,
           v)))
G3:=IF(
   F2<>F3,
   tblStock[@Units],
   SUM(
       XLOOKUP(
           F3,
           $F$3:F3,
           $D$3:D3,
           ,
           0,
           1),
       XLOOKUP(
           F3,
           $F$3:F3,
           $D$3:D3,
           ,
           0,
           -1)))
Excel solution 16 for Fill Down using dynamic arrays., proposed by Md. Shah Alam, Microsoft Certified Trainer:
=DROP(
   --TEXTSPLIT(
       CONCAT(
           " "&TOCOL(
               TOCOL(
                   tblStock2[Date],
                   3)&"/"&LET(
                   x,
                   WRAPROWS(
                       tblStock2[Units],
                       7),
                   HSTACK(
                       TAKE(
                           x,
                           ,
                           1),
                       DROP(
                           x,
                           ,
                           1)+TAKE(
                           x,
                           ,
                           1))))),
       "/",
       " "),
   1)
Excel solution 17 for Fill Down using dynamic arrays., proposed by Petya Koleva:
=HSTACK(IF(
   C3="Opening",
   B3,
   XLOOKUP(
       "Opening",
       $C$2:C2,
       $B$2:B2,
       ,
       ,
       -1)),
   IF(C3="Opening",
   D3,
   XLOOKUP(1,
   ($B$3:$B$16=IF(
       C3="Opening",
       B3,
       XLOOKUP(
           "Opening",
           $C$2:C2,
           $B$2:B2,
           ,
           ,
           -1)))*($C$3:$C$16="Opening"),
   $D$3:$D$16)+D3))

Solving the challenge of Fill Down using dynamic arrays. with Python

Python solution 1 for Fill Down using dynamic arrays., proposed by Konrad Gryczan, PhD:
import pandas as pd
path = "files/Excel Challenge October 13th.xlsx"
input = pd.read_excel(path, usecols="B:D", skiprows=1, nrows=15)
test = pd.read_excel(path, usecols="F:G", skiprows=1, nrows=15).rename(columns=lambda x: x.replace('.1', ''))
input['Date'] = input['Date'].ffill()
input['open'] = input.groupby('Date')['Units'].transform('first')
input['Units'] = input.apply(lambda row: row['open'] + row['Units'] if pd.isna(row['Instance']) else row['Units'], axis=1)
result = input[['Date', 'Units']]
print(result.equals(test))  # True
Python solution 2 for Fill Down using dynamic arrays., proposed by Luan Rodrigues:
Py Soluiton!
import pandas as pd
file = 'Excel Challenge October 13th.xlsx'
df = pd.read_excel(file,usecols="B:D",skiprows=1)
df['Date'] = df['Date'].ffill()
def grp(x):
 a = x['Units'].values
 b = [y + a[:1] for y in a[1:]]
 c = [a[:1]] + b
 rst = pd.DataFrame(c,columns=['Units']).reset_index(drop=True)
 rst['Date'] = x['Date'].values
 return rst
df_grp = df.groupby('Date', group_keys=False).apply(grp)
df_fim = df_grp[['Date','Units']]
print(df_fim)

Solving the challenge of Fill Down using dynamic arrays. with Python in Excel

Python in Excel solution 1 for Fill Down using dynamic arrays., proposed by Abdallah Ally:
df = xl("tblStock[
#All]", headers=True)
# Perform data manipulation
df['Date'] = df['Date'].ffill()
dfs = []
for date in df['Date'].unique():
 dfd = df[df['Date'] == date].reset_index(drop=True)
 dfd['Units'] = dfd.apply(
 lambda x: x[2] + int(pd.isna(x[1])) * first, axis=1
 )
 dfs.append(dfd)
 
df = pd.concat(dfs, ignore_index=True)[['Date', 'Units']]
df
Python in Excel solution 2 for Fill Down using dynamic arrays., proposed by Ümit Barış Köse, MSc:
I optimized my previous solution
df = xl("tblStock[
#All]", headers=True)
df['Date'] = df['Date'].ffill()
df['Base_Units'] = df['Units'].where(df['Instance'] == 'Opening').ffill()
df_result = df.assign(Units=df['Base_Units'] + df['Units'].where(df['Instance'] != 'Opening', 0))[['Date', 'Units']]
Python in Excel solution 3 for Fill Down using dynamic arrays., proposed by Ümit Barış Köse, MSc:
df=xl("tblStock[
#All]", headers=True)
df['Date'] = df['Date'].ffill()
opening_mask = df['Instance'] == 'Opening'
df['Base_Units'] = df['Units'].where(opening_mask)
df['Base_Units'] = df['Base_Units'].ffill()
df['Result_Units'] = df['Base_Units'] + df['Units'].where(~opening_mask, 0)
df_result = df[['Date', 'Result_Units']].rename(columns={'Result_Units': 'Units'})

Solving the challenge of Fill Down using dynamic arrays. with R

R solution 1 for Fill Down using dynamic arrays., proposed by Konrad Gryczan, PhD:
library(tidyverse)
library(readxl)
path = "files/Excel Challenge October 13th.xlsx"
input = read_excel(path, range = "B2:D16")
test = read_excel(path, range = "F2:G16")
result = input %>%
 fill(Date, .direction = "down") %>%
 group_by(Date) %>%
 mutate(open = first(Units)) %>%
 mutate(Units = ifelse(is.na(Instance) , open + Units, Units)) %>%
 select(Date, Units)
all.equal(result, test, check.attributes = FALSE)
# [1] TRUE

Leave a Reply