Equipment Utilization

Sep 17, 2024

About

The workbook that I am about to go through is a simplified recreation of the equipment portion of one of the weekly reports that were run and distributed at one of employments. The production verion queries directly to a SQL server using select statements. From there I futher refine the data in power query and create custom measures in power query.

The goal of this project is to report the reported equiment utilization from the field on given projects and compare that to a given target utilization for a given period of time. The report takes into account ownership of equipment and tracks equipment hours against all projects the pieces are used on. This ensures that any borrowed equipment is being reported and recognized as utilized.

Link to the file used for this demo Equipment Utilization

The Tables

Below I will briefly outline and expain the tables in the workbook coresponding data

Equipment List

Is an extraction from the equipoment list that is maintained outside of the project management software.

asset_tag resource_type resource_class resource_category
EX509 350D Excavator Equipment
EX510 350D Excavator Equipment
EX137 200D Excavator Equipment

Equipment History List

Is a table that I maintain to track the equipment and its owners. The table is designed and maintianed by myself and the quipment manager. It is built with the intent that if equipent equiment changes ownershtip it will acuratly reflect the changes in reporting. The target field reprisents the target hours per machine. That way we can fine tune the hours as needed. Example the target hours for a packer or boring machine vs an excavator may vary drastically as a packer only sees limited use.

asset_tag date_in date_out owner target
EX509 1/1/2024 MB 30
EX510 1/1/2024 MB 30
EX137 1/1/2024 MB 30
PT527 1/5/2024 MB 30
PT208 11/1/2023 9/6/2024 MB 30

Timesheet Data

Daily time sheets that are submitted by PM, PC and or Site Supervisor into project tracking software. In production the data is queiried directly from the database.

The demo table Structure is as follows

workdate project_code resource_name resource_class resource_category asset_tag quantity
2024-09-02 P3202 Excavator equipment EX509 5
2024-09-03 P3202 Excavator equipment EX509 5
2024-09-04 P3202 Excavator equipment EX509 5

Project Data

Information on the project including which business dimension is the owner.

project_code project_type business_dimension
P3183 Rem MB
P3202 Rem MB
P4975 Overhead MB

Business Dimension

The list of Business Dimensions which equates to sections of the country.

business_dimension
MB
BC

Parameters

The parameters tab is where I store most if not all parameters to perform queries. In this example I use dates to store the parameters. I also use this page to store slicers and other items to filter the reports.

Power Query - Putting It All Together

Date Managagment

In power query I select the date parameters DateFrom and DateTo which are named ranges on the parameters tab.

DateFrom

= DateTime.Date(Excel.CurrentWorkbook(){[Name="DateFrom"]}[Content][Column1]{0})

DateTo

= DateTime.Date(Excel.CurrentWorkbook(){[Name="DateTo"]}[Content][Column1]{0})

Getting the dates in the period

let
    countDays = Duration.Days(date_to - date_from) +1,

    Source = Table.FromList(
        List.Dates(date_from, countDays, #duration(1,0,0,0)), 
        Splitter.SplitByNothing(), 
        {"work_date"}
    ),

    #"Transform to Date" = Table.TransformColumnTypes(Source, {"work_date", type date})
in
    #"Transform to Date"

Querying the data

Equipment Utilization Base

This report will serve as a base for the later summary report. This report catpures the fine grained detail of what pieces of equipment are being used where. We start by performing a conditional cross join with our equipment list to the list of dates taking into account the equipments in and out dates.

The ross join is achieved by utilizing the function ‘selectEquipmentByDate’ that is define at the start of my query. Then calling Table.AddColumn function. As the AddColumn iterates through the work dates the ‘selectEquipmentByDate’ function is called and the current work date is passed through. We then left join our timesheet onto the query we just performed.

let
    selectEquipmentByDate = (dateToCompare as date) => 
        Table.SelectRows(equipment_owner_history, each [date_in] <= dateToCompare and ([date_out] > dateToCompare or [date_out] = null)
    ),

    Source = Table.AddColumn(work_dates, "available equipment", each selectEquipmentByDate([work_date])),
    #"Expand Available Equipment" = Table.ExpandTableColumn(
        Source,
        "available equipment", 
        {
            "asset_tag", 
            "owner",
            "target"
        }, 
        {
            "asset_tag", 
            "owner",
            "target"
        }
    ),
    
    #"Left Join EquipmentList" = Table.NestedJoin(
        #"Expand Available Equipment", 
        {"asset_tag"}, 
        equipment_list, 
        {"asset_tag"}, 
        "equipment_list"
    ),

    #"Expand Equipment List" = Table.ExpandTableColumn(#"Left Join EquipmentList", "equipment_list", {"resource_type", "resource_class"}, {"resource_type", "resource_class"}),

    //Group timesheet to avoid any issues alter when joining due to multiple entreis for unit against a day
    #"Group Timesheet" = Table.Group (
        timesheet_data,
        {"workdate", "asset_tag", "project_code"},
        {"quantity", each List.Sum([quantity])}
    ),

    #"Left Join Timesheet" = Table.NestedJoin(
        #"Expand Equipment List" , 
        {"asset_tag", "work_date"}, 
        #"Group Timesheet", 
        {"asset_tag", "workdate"}, 
        "timesheet"
    ),
                            
    #"Expand Timesheet" = Table.ExpandTableColumn(#"Left Join Timesheet", "timesheet", {"project_code", "quantity"}, {"project_code", "quantity"}),
    
    #"Renamed Columns" = Table.RenameColumns(#"Expand Timesheet",{{"work_date", "Work Date"}, {"asset_tag", "Asset Tag"}, {"resource_type", "Resource Type"}, {"resource_class", "Resource Class"}, {"owner", "Owner"}, {"quantity", "Hours"}}),
    
    #"Table Buffer" = Table.Buffer(#"Renamed Columns" )
in
     #"Table Buffer"

The query ends with some clean up to rename the columns to be more readable to the end user. The Utilization Base is then added to the data model. I will linking it later so that we can make use of some global slicers that I have added to the workbook.

Equipment Utilization Report

The equipment Utilization report is a summary of the base, we remove all project related data and focus on raw hours entered. This is done by grouping the data by date, resource class,asset tag, owner, and suming the hours.

From there I add a column to get the target daily hours by dividing our weekly by 7. I also add a column for the start of the week, this column is based on a monday and used for our weekly views and reports.

let
    Source = Table.Group(
        equipment_report_base,
        {"Work Date", "Asset Tag", "Resource Class", "Owner"},
        {
            {"Hours", each List.Sum([Hours]), type nullable number},
            {"Target", each List.Sum([target]) /7, type nullable number}
        }
    ),
    #"Add Week Column" = Table.AddColumn(
        Source, 
        "Week", 
        each Date.StartOfWeek(
            [Work Date],
            1
        ),
        Date.Type
    ),
    #"Replace Null Hours" = Table.ReplaceValue(#"Add Week Column",null,0,Replacer.ReplaceValue,{"Hours"})
in
    #"Replace Null Hours"

I then add the table to the data model and later create some measures to calculate percentage based on target hours.

Power Pivot - Linking the Tables

Attached is the schema which we will use. For my weekly report we are mainly concerned with our region and will filter by our Business Dimension.

Power Pivot Schema

Adding the Percentage Measure

Percentage:=SUMX(FILTER(equipment_report_summary, equipment_report_summary[Asset Tag] = [Asset Tag]),[Hours]) / SUMX(FILTER(equipment_report_summary, equipment_report_summary[Asset Tag] = [Asset Tag]),[Target])

Finalaizing The Report

Last steps are to create the pivot tables and link the slicers. For this will omit the instructions on table and slicer creation.

Link to the file used for this demo Equipment Utilization