Forum Discussion

Anonymous's avatar
Anonymous
Not applicable
8 years ago
Solved

Power Query M code - find number of working days between 2 dates

Hello,   Please can you tell me how to find the number of working days between 2 dates using Power Query / M code (I have a table with all public holidays listed for my country). My current M code ...
  • MarcelBeug's avatar
    MarcelBeug
    8 years ago

    fhill Also a nice solution, but I think the List.Generate was a mistake?

     

    Additionally your solution will be much faster if the Holiday table is buffered.

     

    This is what I made of your solution:

     

    let
        BufferedHolidays = Table.Buffer(Holidays),
        Source = Data,
        #"Added Index" = Table.AddIndexColumn(Source, "Index", 1, 1),
        #"Added Custom" = Table.AddColumn(#"Added Index", "DatesBetween", each { Number.From([StartDate])..Number.From([EndDate]) }),
        #"Expanded DatesBetween" = Table.ExpandListColumn(#"Added Custom", "DatesBetween"),
        #"Changed Type" = Table.TransformColumnTypes(#"Expanded DatesBetween",{{"DatesBetween", type date}}),
        #"Added Custom1" = Table.AddColumn(#"Changed Type", "IsHoliday", 
            each if List.Contains ( Table.Column(BufferedHolidays, "Date") ,  [DatesBetween] ) 
            or Date.DayOfWeek ( [DatesBetween] ) = 0
            or Date.DayOfWeek ( [DatesBetween] ) = 6
            then 0 else 1),
        #"Grouped Rows" = Table.Group(#"Added Custom1", {"StartDate", "EndDate", "Index", "Excel networkdays"}, {{"Networkdays FHill", each List.Sum([IsHoliday]), type number}}),
        #"Removed Columns" = Table.RemoveColumns(#"Grouped Rows",{"Index"})
    in
        #"Removed Columns"

     

    An even faster solution is to translate the function logic from my previous post, into a query, so the merges will not be done with individual nested tables, but with the entire table at once.

    A drawback is that the query code becomes somewhat more complex.

     

    let
        Weekend = #table(type table[Weekday = Int64.Type],{{0},{6}}),
        Source = Data,
        #"Added Index" = Table.AddIndexColumn(Source, "Index", 0, 1),
        #"Added Custom" = Table.AddColumn(#"Added Index", "Dates", each Table.FromColumns({List.Dates([StartDate],1+Duration.Days([EndDate]-[StartDate]),#duration(1,0,0,0))}, type table[Dates = date])),
        #"Expanded Dates" = Table.ExpandTableColumn(#"Added Custom", "Dates", {"Dates"}),
        #"Inserted Day of Week" = Table.AddColumn(#"Expanded Dates", "Day of Week", each Date.DayOfWeek([Dates]), type number),
        #"Merged Queries" = Table.NestedJoin(#"Inserted Day of Week",{"Day of Week"},Weekend,{"Weekday"},"Inserted Day of Week",JoinKind.LeftAnti),
        #"Merged Queries1" = Table.NestedJoin(#"Merged Queries",{"Dates"},Holidays,{"Date"},"Holidays",JoinKind.LeftAnti),
        #"Grouped Rows" = Table.Group(#"Merged Queries1", {"Index"}, {{"PQ Networkdays", each Table.RowCount(_), type number}}),
        #"Merged Queries2" = Table.NestedJoin(#"Added Index",{"Index"},#"Grouped Rows",{"Index"},"Grouped Rows",JoinKind.LeftOuter),
        #"Expanded Grouped Rows" = Table.ExpandTableColumn(#"Merged Queries2", "Grouped Rows", {"PQ Networkdays"}, {"PQ Networkdays"}),
        #"Replaced Value" = Table.ReplaceValue(#"Expanded Grouped Rows",null,0,Replacer.ReplaceValue,{"PQ Networkdays"}),
        #"Sorted Rows" = Table.Sort(#"Replaced Value",{{"Index", Order.Ascending}}),
        #"Removed Columns" = Table.RemoveColumns(#"Sorted Rows",{"Index"})
    in
        #"Removed Columns"