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 a list of all equipment. The list is maintained outside of the project management software. Production version needs to be cleaned. The sample version contains clean data.

resource_type resource_class resource_category date_in date_out owner
350D Excavator Equipment 45292 MB
350D Excavator Equipment 45292 MB
200D Excavator Equipment 45292 MB

Timesheet Data

Daily time sheets that are submitted by PM, PC and or Site Supervisor into project tracking software.

The 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 MB
P3183 Rem MB MB
P3202 Rem MB MB
P4975 Overhead MB MB

Business Dimension

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

business_dimension
MB
BC

Target

The target table is a manual table. In here we use a general hours per week target for all equipment.

Value
30

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_list, 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", "resource_type", "resource_class", "resource_category", "owner"}, {"asset_tag", "resource_type", "resource_class", "resource_category", "owner"}),
    #"Left Join Timesheet" = Table.NestedJoin(
        #"Expand Available Equipment", 
        {"asset_tag", "work_date"}, 
        timesheet_data, 
        {"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"}})
in
    #"Renamed Columns"

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}}
    ),
    #"Add Target Column" = Table.AddColumn(Source, "Target", each TargetTable / 7, Decimal.Type),
    #"Add Week Column" = Table.AddColumn(
        #"Add Target Column", 
        "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