Excel Lesson 48 – HR Dashboard | Dataplexa
Lesson 48 · Final Projects Project

HR Dashboard Project

HR teams live in spreadsheets. Headcount reports, turnover analysis, hire trend charts, department breakdowns — all of it lands in Excel because that is where HR professionals work. This project builds a complete HR Performance Dashboard from scratch: a multi-table data model in Power Pivot, DAX measures for turnover rate and average tenure, PivotTables feeding a clean dashboard sheet, and slicers for department and year filtering. By the end you have a dashboard that answers the four questions every HR leader asks every month — how many people do we have, who left, when did we hire them, and where do we stand by department.

Dashboard Blueprint

HR Dashboard — Layout Preview
199
Total Headcount
23
New Hires (YTD)
12.4%
Turnover Rate
4.2 yrs
Avg Tenure
Headcount by Department
Sales
54
IT
43
Finance
32
Marketing
27
HR
21
Ops
22
Hire Trend — New Hires per Month
Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec
Turnover Rate by Department
DeptLeaversRate
Sales916.7%
Marketing414.8%
IT49.3%
Finance26.3%
HR29.5%
Tenure Distribution
0-1 yrs
18%
1-3 yrs
26%
3-5 yrs
22%
5-10 yrs
19%
10+ yrs
15%
Department Slicer:
All Sales IT Finance Marketing HR
KPI cards · bar chart · column chart · turnover table · tenure chart · department slicer — all connected via Report Connections

The Data Model — Three Tables

Table 1: Employees (fact-style — one row per employee, current and former)
  Columns: EmpID, First Name, Last Name, Department, Start Date, Leave Date,
           Salary, Status (Active / Leaver), Start Year, Tenure Years,
           Tenure Band, Salary Band

Table 2: DimDate (Date dimension — one row per calendar day)
  Columns: Date, Year, Month, MonthNum, Quarter, MonthYear
  Create this in Power Query using M:
  let
    StartDate = #date(2015, 1, 1),
    EndDate   = #date(2026, 12, 31),
    Days      = Duration.Days(EndDate - StartDate) + 1,
    DateList  = List.Dates(StartDate, Days, #duration(1,0,0,0)),
    AsTable   = Table.FromList(DateList, Splitter.SplitByNothing()),
    Typed     = Table.TransformColumnTypes(AsTable, {{"Column1", type date}}),
    Renamed   = Table.RenameColumns(Typed, {{"Column1", "Date"}}),
    AddYear   = Table.AddColumn(Renamed, "Year",     each Date.Year([Date]),   Int64.Type),
    AddMonth  = Table.AddColumn(AddYear, "Month",    each Date.ToText([Date], "MMM"), type text),
    AddMonthN = Table.AddColumn(AddMonth,"MonthNum", each Date.Month([Date]),  Int64.Type),
    AddQtr    = Table.AddColumn(AddMonthN,"Quarter", each "Q" & Text.From(Date.QuarterOfYear([Date])), type text),
    AddMY     = Table.AddColumn(AddQtr,  "MonthYear",each Date.ToText([Date], "MMM yyyy"), type text)
  in AddMY

Table 3: DimDept (Department lookup)
  Columns: Department, DeptCode, DeptHead, CostCentre
  Small manual table — 6 rows (one per department)

Relationships in Power Pivot:
  Employees[Start Date]   → DimDate[Date]   (many-to-one)
  Employees[Leave Date]   → DimDate[Date]   (many-to-one — second relationship)
  Employees[Department]   → DimDept[Department] (many-to-one)
Data Model Diagram
DimDate
Date 🔑
Year
Month
MonthNum
Quarter
MonthYear
Start Date
Leave Date
Employees ⭐ Fact
EmpID 🔑
First Name / Last Name
Department
Start Date
Leave Date
Salary
Status
Tenure Years
Tenure Band
DimDept
Department 🔑
DeptCode
DeptHead
CostCentre

DAX Measures — HR Metric Library

Create a dedicated measures table called "HR Metrics":
  Power Pivot → Home → Add Table to Model → create a blank 1-row helper table
  Right-click the table in the diagram → rename "HR Metrics"
  All measures below go into this table

-- Core headcount measures --

Total Headcount =
  COUNTROWS(Employees)

Active Headcount =
  CALCULATE(COUNTROWS(Employees), Employees[Status] = "Active")

Total Leavers =
  CALCULATE(COUNTROWS(Employees), Employees[Status] = "Leaver")

New Hires This Year =
  CALCULATE(
    COUNTROWS(Employees),
    YEAR(Employees[Start Date]) = YEAR(TODAY())
  )

-- Turnover rate --
-- Industry standard: Leavers / Average Headcount during period --

Avg Headcount =
  DIVIDE(
    [Active Headcount] + [Total Headcount],
    2
  )

Turnover Rate =
  DIVIDE([Total Leavers], [Avg Headcount], 0)

-- Tenure --

Avg Tenure Years =
  AVERAGEX(
    FILTER(Employees, Employees[Status] = "Active"),
    Employees[Tenure Years]
  )

-- Salary --

Avg Salary Active =
  CALCULATE(AVERAGE(Employees[Salary]), Employees[Status] = "Active")

Total Payroll =
  CALCULATE(SUM(Employees[Salary]), Employees[Status] = "Active")

-- Dept-level metrics (used in PivotTable rows) --

Leavers This Year =
  CALCULATE(
    COUNTROWS(Employees),
    Employees[Status] = "Leaver",
    YEAR(Employees[Leave Date]) = YEAR(TODAY())
  )

Dept Turnover Rate =
  DIVIDE([Leavers This Year], [Active Headcount], 0)
Total Headcount: 199 · Active: 178 · Leavers: 21 · New Hires YTD: 23 · Turnover Rate: 12.4% · Avg Tenure: 4.2 yrs · Avg Salary: £46,200 · Total Payroll: £8,223,600

PivotTables — Five Tables on a Hidden Helper Sheet

Create a sheet named "PT_Helper" — all five PivotTables live here.
Right-click the sheet tab → Hide when dashboard is complete.

PivotTable 1: KPI Cards source
  Rows:    (none)
  Values:  Active Headcount, New Hires This Year, Turnover Rate, Avg Tenure Years
  Purpose: Single-row output feeding GETPIVOTDATA formulas in KPI cards

PivotTable 2: Headcount by Department
  Rows:    Department (from DimDept)
  Values:  Active Headcount
  Sort:    Values descending
  Purpose: Horizontal bar chart showing department size

PivotTable 3: Hire Trend by Month
  Rows:    MonthNum (from DimDate, sorted ascending), Month
  Filters: Year (from DimDate)
  Values:  New Hires This Year → actually use COUNTROWS filtered to [Start Date] year
           Replace with: Hires by Start Month =
             CALCULATE(COUNTROWS(Employees), YEAR(Employees[Start Date]) = SELECTEDVALUE(DimDate[Year]))
  Purpose: Column chart — hire volumes per calendar month

PivotTable 4: Turnover by Department
  Rows:    Department
  Values:  Total Leavers, Active Headcount, Dept Turnover Rate
  Purpose: Department turnover rate table (not a chart)

PivotTable 5: Tenure Distribution
  Rows:    Tenure Band (from Employees)
  Values:  Active Headcount
  Purpose: Horizontal bar chart showing tenure spread

Building the Dashboard Sheet

Sheet setup:
  New sheet named "Dashboard"
  View → uncheck Gridlines, Formula Bar, Headings
  Zoom: 90%
  Background: fill A1:Z100 with #f1f5f9 (light slate)

KPI Card construction (one example — replicate for all four):
  Select B2:D5 → Merge cells
  Fill: #0f172a (dark navy)
  Formula bar (in merged cell):
    =GETPIVOTDATA("Active Headcount", PT_Helper!$A$1)
  Font: 32px, white, bold
  Below the number cell (B6:D7, merged):
    Type: "Total Headcount"
    Font: 10px, #94a3b8 (muted), uppercase

  Repeat for New Hires (green #15803d),
  Turnover Rate (red #dc2626, format as %),
  Avg Tenure (blue #1d4ed8, & " yrs" concatenated)

Charts — paste as linked pictures from PT_Helper:
  In PT_Helper: create chart from PivotTable 2 (Headcount by Dept)
  Format: horizontal bar, remove gridlines, remove legend
  Copy chart → Dashboard sheet → Paste Special → Linked Picture
  Linked pictures update automatically when PivotTable refreshes
  Repeat for hire trend chart (column) and tenure chart (bar)

Turnover table — use GETPIVOTDATA in a styled table:
  Build a manual HTML-style table using cell borders and fills
  Pull values from PivotTable 4 using GETPIVOTDATA per department
  Apply conditional formatting: red >15%, amber 10-15%, green <10%

Slicer setup:
  Click any PivotTable → Insert → Slicer → Department
  PivotTable Analyse → Report Connections → tick ALL five PivotTables
  Format slicer: remove header, 6 columns, custom style matching dashboard colours
  Position below KPI row, spanning full dashboard width

The Turnover Rate Formula — Getting It Right

Turnover rate is one of those metrics that looks simple but hides a subtle calculation problem. Most people calculate it as leavers divided by current headcount. That gives a slightly wrong answer because it uses the end-of-period headcount, not the average across the period. The correct HR industry formula uses average headcount: leavers divided by the average of opening and closing headcount. Here is what the difference looks like in practice.

Turnover Rate — Two Methods Compared
Simplified Industry Standard ✓
Formula Leavers ÷ Headcount Leavers ÷ Avg(Opening + Closing)
Opening headcount Not used 200
Closing headcount 178 178
Leavers 21 21
Result 11.8% (understated) 12.4% ✓
The difference matters when benchmarking against published industry averages — those use the standard method

QA Checklist

Before sharing the dashboard, verify each of the following:

Data model:
  ✓ All three tables loaded into Power Pivot (Data Model)
  ✓ Both date relationships active (Start Date AND Leave Date to DimDate)
  ✓ No circular relationships or ambiguity warnings in Diagram View

Measures:
  ✓ Total Headcount = Active Headcount + Total Leavers (verify manually)
  ✓ Turnover Rate uses average headcount, not closing headcount
  ✓ Avg Tenure filtered to Active employees only (not Leavers)

PivotTables:
  ✓ All five PivotTables pulling from the Data Model (not worksheet ranges)
  ✓ Hire trend months sorted Jan-Dec, not alphabetically
  ✓ Turnover table shows correct Dept Turnover Rate per row

Dashboard:
  ✓ All four KPI card values match PivotTable 1 directly
  ✓ Slicer Report Connections tick all five PivotTables
  ✓ Selecting "Sales" slicer updates all charts and the turnover table
  ✓ Conditional formatting on turnover table updates when slicer applied
  ✓ PT_Helper sheet hidden before sharing
  ✓ File saved as .xlsx (not .xlsm — no macros in this project)
💡 Teacher's Note
Two things separate a professional HR dashboard from an amateur one. First, the turnover rate formula — always use average headcount, not closing headcount; anyone who knows HR benchmarks will spot the wrong version immediately. Second, the Avg Tenure measure — filter it to Active employees only. Including leavers in the average tenure calculation understates it significantly because leavers by definition have shorter tenures. These two details are the kind of thing that builds credibility with an HR director in the first thirty seconds of a presentation.

🠐 Practice

Q1. The Avg Tenure Years DAX measure uses AVERAGEX with a FILTER to Active employees. Why not simply use AVERAGE(Employees[Tenure Years]) without a filter?




Q2. You have two relationships from the Employees table to DimDate — one on Start Date and one on Leave Date. When you use a DimDate[Year] filter in a PivotTable, how does Power Pivot know which relationship to use?




Q3. Why are charts pasted onto the Dashboard sheet as Linked Pictures rather than copied directly as chart objects?



🟣 Quiz

Q1. The Employees table has two date columns: Start Date and Leave Date. Both relate to DimDate. What does Power Pivot require when you have two relationships between the same pair of tables?







Q2. A hiring manager filters the dashboard to show the IT department only. The Turnover Rate KPI card shows 9.3%. What must be true about the DAX measure for this to work correctly?







Q3. Your dashboard shows a Hire Trend chart by month. January appears last because months are sorted alphabetically (Apr, Aug, Dec…). What is the correct fix in Power Pivot?






Next up — Finance Dashboard Project, where we build a P&L summary view, a budget vs actuals variance analysis, and an expense breakdown chart from a multi-year finance dataset.