Home » Process Time Running Totals

Process Time Running Totals

1. Find the running total in hours in each process groups for duration of the steps i.e. Finish Time – Start Time of the steps and then working out Running Total. 2. Find the calendar hours duration for each process group which is max of Finish Time – min of Start Time for a process group.

📌 Challenge Details and Links
ExcelBI Power Query Challenge Number: 98
Challenge Difficulty: ⭐️⭐️⭐️⭐️⭐️
📥Download Sample File
📥Link to the solutions on LinkedIn

Solving the challenge of Process Time Running Totals with Power Query

Power Query solution 1 for Process Time Running Totals, proposed by Bo Rydobon 🇹🇭:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  Group = Table.Combine(
    Table.Group(
      Source, 
      "Process", 
      {
        "T", 
        each 
          let
            D = List.Accumulate(
              Table.AddColumn(
                _, 
                "Du", 
                each DateTime.From([Finish Time]) - DateTime.From([Start Time])
              )[Du], 
              {}, 
              (s, l) => s & {List.Last(s, 0) + Number.From(l) * 24}
            ), 
            E = Table.FromColumns(
              Table.ToColumns(_) & {D}, 
              Table.ColumnNames(_) & {"Running Total"}
            )
          in
            Table.AddColumn(
              E, 
              "Duration", 
              (t) =>
                Number.From(
                  DateTime.From(List.Last([Finish Time])) - DateTime.From([Start Time]{0})
                )
                  * 24
            )
      }
    )[T]
  )
in
  Group
Power Query solution 2 for Process Time Running Totals, proposed by Zoran Milokanović:
let
  Source = Table.TransformColumnTypes(
    Excel.CurrentWorkbook(){[Name = "Input"]}[Content], 
    {{"Start Time", type datetime}, {"Finish Time", type datetime}}
  ), 
  S = Table.ExpandTableColumn(
    Table.Group(
      Source, 
      {"Process"}, 
      {
        {
          "All", 
          each 
            let
              t = Table.AddColumn(_, "D", each Number.From([Finish Time] - [Start Time]) * 24)
            in
              Table.AddColumn(
                t, 
                "Running Total", 
                each List.Sum(List.FirstN(t[D], List.PositionOf(t[Steps], [Steps]) + 1))
              )
        }, 
        {"Duration", each Number.From(List.Max([Finish Time]) - List.Min([Start Time])) * 24}
      }
    ), 
    "All", 
    {"Steps", "Start Time", "Finish Time", "Running Total"}
  )
in
  S
Power Query solution 3 for Process Time Running Totals, proposed by Alejandro Simón 🇵🇦 🇪🇸:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  Group = Table.Group(
    Source, 
    {"Process"}, 
    {
      {
        "All", 
        each 
          let
            a = Table.AddIndexColumn(_, "Idx"), 
            b = Table.AddColumn(
              a, 
              "New", 
              each Number.Round(
                Number.From(
                  DateTime.From(a[Finish Time]{[Idx]}) - DateTime.From(a[Start Time]{[Idx]})
                )
                  * 24, 
                1
              )
            ), 
            c = Table.AddColumn(b, "Running Total", each List.Sum(List.FirstN(b[New], [Idx] + 1))), 
            d = Table.AddColumn(
              c, 
              "Duration", 
              each Number.Round(
                Number.From(
                  DateTime.From(a[Finish Time]{List.Last(a[Idx])}) - DateTime.From(a[Start Time]{0})
                )
                  * 24, 
                1
              )
            )
          in
            d
      }
    }
  )[[All]], 
  Sol = Table.ExpandTableColumn(
    Group, 
    "All", 
    Table.ColumnNames(Source) & {"Running Total", "Duration"}
  )
in
  Sol
Power Query solution 4 for Process Time Running Totals, proposed by Luan Rodrigues:
let
  Fonte = Query_Tabela1, 
  gp = Table.Group(
    Fonte, 
    {"Process"}, 
    {
      {
        "Contagem", 
        each [
          a = Table.AddColumn(
            _, 
            "Total", 
            each Number.Round(
              Number.From(DateTime.From([Finish Time]) - DateTime.From([Start Time])) * 24, 
              1
            )
          ), 
          b = Table.AddIndexColumn(a, "Ind", 1, 1), 
          c = Table.AddColumn(b, "Total Acc", each List.Sum(List.FirstN(b[Total], [Ind]))), 
          d = Table.AddColumn(
            c, 
            "Duration", 
            each Number.Round(
              Number.From(
                DateTime.From(List.Last(c[Finish Time])) - DateTime.From(List.First(c[Start Time]))
              )
                * 24, 
              1
            )
          )
        ][d]
      }
    }
  ), 
  res = Table.ExpandTableColumn(
    gp, 
    "Contagem", 
    List.RemoveFirstN(Table.ColumnNames(Fonte), 1)
      & List.LastN(Table.ColumnNames(gp[Contagem]{0}), 2)
  )
in
  res
Power Query solution 5 for Process Time Running Totals, proposed by Eric Laforce:
let
  fxDuration.ToHours = (d as duration) => Number.Round(Number.From(d) * 24, 1), 
  Source = Excel.CurrentWorkbook(){[Name = "tData98"]}[Content], 
  ChangeType = Table.TransformColumnTypes(
    Source, 
    {{"Start Time", type datetime}, {"Finish Time", type datetime}}
  ), 
  Group = Table.Group(
    ChangeType, 
    {"Process"}, 
    {
      "G", 
      (_T) =>
        let
          _GD = fxDuration.ToHours(List.Max(_T[Finish Time]) - List.Min(_T[Start Time])), 
          _TR = List.Accumulate(
            Table.ToRecords(_T), 
            [r = {}, rt = 0], 
            (s, c) =>
              let
                _SD        = fxDuration.ToHours(c[Finish Time] - c[Start Time]), 
                _RT        = s[rt] + _SD, 
                _NewRecord = Record.Combine({c, [#"Running Total" = _RT, Duration = _GD]})
              in
                [r = s[r] & {_NewRecord}, rt = _RT]
          )
        in
          _TR[r]
    }
  ), 
  ToTable = Table.FromRecords(List.Combine(Group[G]))
in
  ToTable
Power Query solution 6 for Process Time Running Totals, proposed by Matthias Friedmann:
let
 Source = Excel.CurrentWorkbook(){[Name="ProcessLength"]}[Content],
 GRT = Table.FromColumns(
 Table.ToColumns(Source) & {fxGRT( List.Buffer(Source[Start Time]) , List.Buffer(Source[Finish Time]) , List.Buffer(Source[Process]) )},
 Table.ColumnNames(Source) & {"Running Total"}
 ),
 Grouped = Table.Group(GRT, {"Process"}, {{"All", each _, type table [Process=text, Steps=text, Start Time=datetime, Finish Time=datetime, Running Total=number]},{"Duration", each 24*Number.From(List.Max([Finish Time])-List.Min([Start Time])), type number}}),
 Expanded = Table.ExpandTableColumn(Grouped, "All", {"Steps", "Start Time", "Finish Time", "Running Total"})
in
 Expanded
fxGRT with List.Generate:
(start as list, finish as list, grouping as list) as list =>
let
 GRTList = List.Generate( 
 ()=> [ GRT = 24*Number.From(finish{0}-start{0}), i = 0 ],
 each [i] < List.Count(start),
 each try 
 if grouping{[i]} = grouping{[i] + 1} 
 then [GRT = [GRT] + 24*Number.From(finish{[i] + 1}-start{[i] + 1}), i = [i] + 1]
 else [GRT = 24*Number.From(finish{[i] + 1}-start{[i] + 1}), i = [i] + 1]
 otherwise [i = [i] + 1] ,
 each [GRT]
 )
in
 GRTList
                    
                  
          
Power Query solution 7 for Process Time Running Totals, proposed by Sandeep Marwal:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  S1 = Table.Group(Source, {"Process"}, {{"Count", each _}}), 
  S2 = Table.TransformColumns(
    S1, 
    {
      "Count", 
      each [
        r5 = Table.AddColumn(_, "Subtraction", each [Finish Time] - [Start Time], type duration), 
        r6 = Table.AddColumn(
          r5, 
          "Total Hours", 
          each Duration.TotalHours([Subtraction]), 
          type number
        ), 
        #"Added Index" = Table.AddIndexColumn(r6, "Index", 1, 1, Int64.Type), 
        #"Added Custom" = Table.AddColumn(
          #"Added Index", 
          "Running Total", 
          each List.Sum(List.FirstN(#"Added Index"[Total Hours], [Index]))
        ), 
        r2 = Table.AddColumn(
          #"Added Custom", 
          "Duration", 
          each Duration.TotalHours(
            List.Max(#"Added Index"[Finish Time]) - List.Min(#"Added Index"[Start Time])
          )
        ), 
        r1 = Table.RemoveColumns(r2, {"Process", "Subtraction", "Total Hours", "Index"})
      ][r1]
    }
  ), 
  S3 = Table.ExpandTableColumn(
    S2, 
    "Count", 
    {"Steps", "Start Time", "Finish Time", "Running Total", "Duration"}
  ), 
  S4 = Table.TransformColumns(
    S3, 
    {{"Duration", each Number.Round(_, 1)}, {"Running Total", each Number.Round(_, 1)}}
  ), 
  S5 = Table.TransformColumnTypes(
    S4, 
    {{"Start Time", type datetime}, {"Finish Time", type datetime}}
  )
in
  S5

Solving the challenge of Process Time Running Totals with Excel

Excel solution 1 for Process Time Running Totals, proposed by Bo Rydobon 🇹🇭:
=LET(p,A2:A15,HSTACK(A2:D15,SCAN(0,p,LAMBDA(a,v,(OFFSET(v,-1,)=v)*a+OFFSET(v,,3)-OFFSET(v,,2)))*24,(XLOOKUP(p,p,D2:D15,,,-1)-XLOOKUP(p,p,C2:C15))*24))
Excel solution 2 for Process Time Running Totals, proposed by محمد حلمي:
=MAXIFS(D2:D15,A2:A15,A2:A15) 
Not give a result because the numbers are stored as text,

If sum 0 on D2:D15 to be

=MAXIFS(D2:D15+0,A2:A15,A2:A15)
Excel solution 3 for Process Time Running Totals, proposed by محمد حلمي:
=LET(i,A2:A15,HSTACK(SCAN(0,i,LAMBDA(a,d,LET(e,24*(OFFSET(d,,3)-OFFSET(d,,2)),IF(d=OFFSET(d,-1,),a+e,e)))),
MAP(i,LAMBDA(a,LET(e,FILTER(C2:D15,i=a)*24,MAX(e)-MIN(e))))))
Excel solution 4 for Process Time Running Totals, proposed by Sunny Baggu:
=HSTACK(
 A2:D15,
 LET(
 _p, A2:A15,
 HSTACK(
 DROP(
 REDUCE(
 "",
 UNIQUE(_p),
 LAMBDA(x, y, VSTACK(x, SCAN(0, FILTER((D2:D15 - C2:C15) * 24, _p = y), LAMBDA(a, v, a + v))))
 ),
 1
 ),
 SCAN(0, _p, LAMBDA(a, v, (TAKE(FILTER(D2:D15, _p = v), -1) - TAKE(FILTER(C2:C15, _p = v), 1)) * 24))
 )
 )
)
Excel solution 5 for Process Time Running Totals, proposed by LEONARD OCHEA 🇷🇴:
=LET(t,A1:D15,c,LAMBDA(x,DROP(INDEX(t,,x),1)),r,24*(c(4)-c(3)),f,REDUCE("Running Total",UNIQUE(c(1)),LAMBDA(a,b,VSTACK(a,SCAN(0,FILTER(r,c(1)=b),LAMBDA(c,d,c+d))))),g,REDUCE("Duration",c(1),LAMBDA(a,b,VSTACK(a,24*(MAX(--FILTER(c(4),c(1)=b))-MIN(--FILTER(c(3),c(1)=b)))))),HSTACK(t,f,g))

Solving the challenge of Process Time Running Totals with Python

Python solution 1 for Process Time Running Totals, proposed by Murat E.:
import pandas as pd
from datetime import datetime
def fxGRT(start, finish, grouping):
 GRTList = []
 i = 0
 while i < len(start):
 GRT = 24 * (finish[i] - start[i]).total_seconds() / 3600
 if i + 1 < len(start) and grouping[i] == grouping[i + 1]:
 GRT += 24 * (finish[i + 1] - start[i + 1]).total_seconds() / 3600
 i += 1
 GRTList.append(GRT)
 i += 1
 return GRTList
data = {
 'Process': ['Process1', 'Process1', 'Process2', 'Process2', 'Process2'],
 'Steps': ['Step1', 'Step2', 'Step1', 'Step2', 'Step3'],
 'Start Time': ['2023-07-20 08:00:00', '2023-07-20 10:30:00', '2023-07-21 12:00:00', '2023-07-21 14:30:00', '2023-07-21 16:00:00'],
 'Finish Time': ['2023-07-20 10:00:00', '2023-07-20 12:30:00', '2023-07-21 13:30:00', '2023-07-21 16:00:00', '2023-07-21 18:00:00']
}
df = pd.DataFrame(data)
df['Start Time'] = pd.to_datetime(df['Start Time'])
df['Finish Time'] = pd.to_datetime(df['Finish Time'])
def calculate_duration(row):
 return 24 * (row['Finish Time'] - row['Start Time']).total_seconds() / 3600
df['Running Total'] = df.apply(calculate_duration, axis=1)
df['Running Total'] = df.groupby('Process')['Running Total'].cumsum()
result = df[['Process', 'Steps', 'Start Time', 'Finish Time', 'Running Total']]
                    
                  

&&&

Leave a Reply