Skip to main content

Manufacturing Analytics in Power BI: OEE, Quality, and Throughput

Build a Power BI manufacturing dashboard covering OEE calculation, quality metrics, production throughput, downtime analysis, and SPC charts — with complete DAX formulas.

E
ECOSIRE Research and Development Team
|March 19, 202612 min read2.3k Words|

World-class manufacturing facilities run at 85%+ OEE. The average manufacturer runs at 60%. That 25-percentage-point gap translates directly to capacity — a facility that improves from 60% to 85% OEE adds 41% more output without a single new machine or hire.

Part of our Manufacturing in the AI Era series

Read the complete guide

World-class manufacturing facilities run at 85%+ OEE. The average manufacturer runs at 60%. That 25-percentage-point gap translates directly to capacity — a facility that improves from 60% to 85% OEE adds 41% more output without a single new machine or hire. The difference between world-class and average is almost always not equipment — it is the visibility to see waste and the data to eliminate it.

Power BI, connected to MES (Manufacturing Execution System) and ERP data, provides that visibility. This guide builds a complete manufacturing analytics platform covering OEE calculation, quality SPC charts, downtime root cause analysis, and throughput management — with the precise DAX formulas manufacturing engineers need.

Key Takeaways

  • OEE = Availability × Performance × Quality (world class = 85%+)
  • Each OEE component requires separate data streams: downtime logs, production counts, scrap records
  • SPC (Statistical Process Control) charts in Power BI use custom visuals or calculated control limits
  • Downtime Pareto analysis (top 20% of reasons cause 80% of downtime) drives prioritized improvement
  • First Pass Yield (FPY) and Defects per Million Opportunities (DPMO) are the key quality KPIs
  • Throughput analysis compares actual vs theoretical capacity using bottleneck theory
  • Power BI streaming datasets enable near-real-time OEE dashboards updating every minute
  • ERP integration (Odoo Manufacturing, SAP PP, Dynamics 365 SCM) provides work order context

Data Model for Manufacturing Analytics

Core Manufacturing Tables

Production_Runs (one row per production run / work order):

ColumnDescription
RunIDWork order or production run ID
MachineIDFK to Machine dimension
ProductIDFK to Product
ShiftIDFK to Shift
StartTimeRun start datetime
EndTimeRun end datetime
PlannedStartTimeScheduled start
PlannedEndTimeScheduled end
PlannedQuantityTarget output quantity
ActualQuantityActual units produced
GoodQuantityUnits passing quality check
ScrapQuantityDefective units
ReworkQuantityUnits requiring rework
IdealCycleTimeSeconds per unit at design speed

Downtime_Events (one row per stoppage):

ColumnDescription
DowntimeIDUnique ID
MachineIDFK to Machine
RunIDFK to Production Run (if applicable)
StartTimeDowntime start
EndTimeDowntime end
DurationMinutesTotal downtime duration
DowntimeCategoryPlanned (PM, changeover) / Unplanned
DowntimeReasonCodeSpecific reason code
DowntimeReasonDescDescription
IsScheduledMaintenancePlanned maintenance flag
ResponseTimeMinutesTime until technician responded
RepairTimeMinutesActive repair time

Quality_Events (one row per defect/inspection):

ColumnDescription
InspectionIDUnique ID
RunIDFK to Production Run
MachineIDFK to Machine
InspectionDateDate/time of inspection
DefectCodeFK to Defect Type
DefectCountNumber of defects found
SampleSizeUnits inspected
MeasuredValueVariable measurement (for SPC)
IsInSpecBoolean — within tolerance

Dim_Machine:

  • MachineID, MachineName, Line, Cell, Department, MachineType, IdealRunRate, PlannedCapacity

Dim_Shift:

  • ShiftID, ShiftName, StartTime, EndTime, PlannedMinutes, PlannedBreakMinutes

OEE Calculation in Power BI

OEE = Availability × Performance × Quality

Availability

Availability = Actual Run Time / Planned Production Time

// Planned Production Time (from shift schedule minus planned downtime)
Planned Production Time =
SUMX(
    Production_Runs,
    DATEDIFF(Production_Runs[PlannedStartTime],
              Production_Runs[PlannedEndTime], MINUTE)
)

// Unplanned Downtime (excludes scheduled maintenance, changeovers)
Unplanned Downtime =
CALCULATE(
    SUM(Downtime_Events[DurationMinutes]),
    Downtime_Events[DowntimeCategory] = "Unplanned"
)

// Changeover Time (planned but reduces availability)
Changeover Time =
CALCULATE(
    SUM(Downtime_Events[DurationMinutes]),
    Downtime_Events[DowntimeReasonCode] = "CHANGEOVER"
)

// Actual Run Time
Actual Run Time = [Planned Production Time] - [Unplanned Downtime] - [Changeover Time]

// OEE Availability
Availability =
DIVIDE([Actual Run Time], [Planned Production Time], 0)

Performance

Performance = (Ideal Cycle Time × Total Count) / Actual Run Time Or equivalently: Actual Output / Theoretical Maximum Output

// Theoretical Maximum Output at ideal run rate
Theoretical Max Output =
SUMX(
    Production_Runs,
    [Actual Run Time Per Run] / Production_Runs[IdealCycleTime]
)

// Actual total output (good + scrap + rework)
Total Output =
SUM(Production_Runs[ActualQuantity])

// OEE Performance
Performance =
DIVIDE([Total Output], [Theoretical Max Output], 0)

// Performance per machine (for benchmarking)
Machine Performance =
DIVIDE(
    SUMX(Production_Runs, Production_Runs[ActualQuantity]),
    SUMX(Production_Runs,
        DATEDIFF(Production_Runs[StartTime], Production_Runs[EndTime], MINUTE) /
        RELATED(Dim_Machine[IdealCycleTime]) * 60
    ),
    0
)

Quality

Quality = Good Output / Total Output (excludes all defects)

// Good Quantity (first pass, no rework)
Good Quantity = SUM(Production_Runs[GoodQuantity])

// Total Quantity Produced (good + scrap + rework)
Total Quantity = SUM(Production_Runs[ActualQuantity])

// OEE Quality
Quality Rate =
DIVIDE([Good Quantity], [Total Quantity], 0)

// First Pass Yield (no rework, no scrap)
First Pass Yield =
DIVIDE(
    SUM(Production_Runs[GoodQuantity]),
    SUM(Production_Runs[ActualQuantity]),
    0
)

Overall OEE

// Overall Equipment Effectiveness
OEE =
[Availability] * [Performance] * [Quality Rate]

// OEE Status (for conditional formatting)
OEE Status =
SWITCH(TRUE(),
    [OEE] >= 0.85, "World Class",    -- 85%+
    [OEE] >= 0.75, "Good",           -- 75-85%
    [OEE] >= 0.60, "Acceptable",     -- 60-75%
    "Poor"                            -- <60%
)

// OEE Loss Analysis (what is the primary constraint)
Primary OEE Constraint =
SWITCH(TRUE(),
    [Availability] < [Performance] && [Availability] < [Quality Rate], "Availability",
    [Performance] < [Quality Rate], "Performance",
    "Quality"
)

// OEE trend (for sparkline visualization)
OEE Weekly Avg =
CALCULATE(
    [OEE],
    DATESINPERIOD(Date[Date], LASTDATE(Date[Date]), -7, DAY)
)

Downtime Analysis

Downtime KPIs and Pareto

// Total Unplanned Downtime Hours
Unplanned Downtime Hours =
DIVIDE(
    CALCULATE(
        SUM(Downtime_Events[DurationMinutes]),
        Downtime_Events[DowntimeCategory] = "Unplanned"
    ),
    60,
    0
)

// Mean Time Between Failures (MTBF)
MTBF =
DIVIDE(
    [Actual Run Time],
    CALCULATE(COUNTROWS(Downtime_Events),
              Downtime_Events[DowntimeCategory] = "Unplanned"),
    0
)

// Mean Time to Repair (MTTR)
MTTR =
AVERAGEX(
    FILTER(Downtime_Events, Downtime_Events[DowntimeCategory] = "Unplanned"),
    Downtime_Events[RepairTimeMinutes]
)

// Downtime % by reason (for Pareto chart)
Downtime Pareto % =
DIVIDE([Unplanned Downtime Hours],
    CALCULATE([Unplanned Downtime Hours], ALL(Downtime_Events[DowntimeReasonCode])),
    0
)

// Cumulative Downtime % (for Pareto 80/20 line)
Cumulative Downtime % =
DIVIDE(
    SUMX(
        FILTER(
            ALL(Downtime_Events[DowntimeReasonCode]),
            RANKX(ALL(Downtime_Events[DowntimeReasonCode]),
                  [Unplanned Downtime Hours], , DESC) <=
            RANKX(ALL(Downtime_Events[DowntimeReasonCode]),
                  [Unplanned Downtime Hours], , DESC)
        ),
        [Unplanned Downtime Hours]
    ),
    CALCULATE([Unplanned Downtime Hours], ALL(Downtime_Events[DowntimeReasonCode])),
    0
)

Downtime Heatmap

Create a heatmap of downtime by Machine × Time of Day to identify shift-related patterns:

// Downtime by Hour of Day (for heatmap rows)
Downtime by Hour =
CALCULATE(
    SUM(Downtime_Events[DurationMinutes]),
    Downtime_Events[HourOfDay] = SELECTEDVALUE(HourDim[Hour])
)

Quality Analytics: SPC Charts

Statistical Process Control charts monitor whether a process is in control. Power BI builds SPC charts using control limit calculations in DAX.

Control Limits for X-Bar Chart

// Process Mean (X-bar)
Process Mean =
AVERAGE(Quality_Events[MeasuredValue])

// Standard Deviation of measurements
Process StdDev =
STDEV.P(Quality_Events[MeasuredValue])

// Upper Control Limit (UCL = mean + 3σ)
UCL = [Process Mean] + 3 * [Process StdDev]

// Lower Control Limit (LCL = mean - 3σ)
LCL = [Process Mean] - 3 * [Process StdDev]

// Upper Warning Limit (mean + 2σ)
UWL = [Process Mean] + 2 * [Process StdDev]

// Lower Warning Limit (mean - 2σ)
LWL = [Process Mean] - 2 * [Process StdDev]

// Out of Control flag (point outside 3σ limits)
Out of Control =
IF(
    Quality_Events[MeasuredValue] > [UCL] ||
    Quality_Events[MeasuredValue] < [LCL],
    "Out of Control",
    "In Control"
)

// Process Capability Index (Cpk)
Cpk =
MIN(
    DIVIDE([UCL] - [Process Mean], 3 * [Process StdDev], 0),
    DIVIDE([Process Mean] - [LCL], 3 * [Process StdDev], 0)
)

Key Quality KPIs

// Defects per Million Opportunities (DPMO)
DPMO =
DIVIDE(
    SUM(Quality_Events[DefectCount]),
    SUM(Quality_Events[SampleSize]) * [Opportunities per Unit],
    0
) * 1000000

// Sigma Level (from DPMO)
Sigma Level =
SWITCH(TRUE(),
    [DPMO] < 3.4, 6,
    [DPMO] < 233, 5,
    [DPMO] < 6210, 4,
    [DPMO] < 66807, 3,
    [DPMO] < 308537, 2,
    1
)

// Defect Rate %
Defect Rate = DIVIDE(SUM(Quality_Events[DefectCount]), SUM(Quality_Events[SampleSize]), 0)

// Scrap Rate
Scrap Rate =
DIVIDE(
    SUM(Production_Runs[ScrapQuantity]),
    SUM(Production_Runs[ActualQuantity]),
    0
)

// Cost of Poor Quality (COPQ)
COPQ =
SUMX(
    Production_Runs,
    (Production_Runs[ScrapQuantity] + Production_Runs[ReworkQuantity]) *
    RELATED(Dim_Product[StandardCost])
)

Throughput Analysis

Production Throughput KPIs

// Actual Throughput (units per hour)
Throughput =
DIVIDE(
    SUM(Production_Runs[ActualQuantity]),
    SUMX(Production_Runs,
        DATEDIFF(Production_Runs[StartTime], Production_Runs[EndTime], HOUR)
    ),
    0
)

// Theoretical Maximum Throughput
Max Throughput =
SUMX(
    Dim_Machine,
    60 / Dim_Machine[IdealCycleTime]  -- Units per minute × 60
) * 60  -- Per hour

// Capacity Utilization
Capacity Utilization =
DIVIDE([Throughput], [Max Throughput], 0)

// Schedule Attainment (actual vs planned quantity)
Schedule Attainment =
DIVIDE(
    SUM(Production_Runs[ActualQuantity]),
    SUM(Production_Runs[PlannedQuantity]),
    0
)

// Changeover Time (as % of planned time)
Changeover % =
DIVIDE(
    [Changeover Time],
    [Planned Production Time],
    0
)

Line Balancing Analysis

Identify bottleneck machines using throughput comparison:

// Machine Throughput Rate (for bottleneck identification)
Machine Throughput Rate =
DIVIDE(
    CALCULATE(SUM(Production_Runs[GoodQuantity])),
    CALCULATE(
        DATEDIFF(MIN(Production_Runs[StartTime]),
                 MAX(Production_Runs[EndTime]), HOUR)
    ),
    0
)

// Bottleneck indicator (lowest throughput machine in a line)
Is Bottleneck =
IF(
    [Machine Throughput Rate] = MINX(
        FILTER(ALL(Dim_Machine), Dim_Machine[Line] = SELECTEDVALUE(Dim_Machine[Line])),
        [Machine Throughput Rate]
    ),
    "Bottleneck",
    "OK"
)

Manufacturing Dashboard Architecture

Page 1: OEE Summary

  • OEE gauge (current vs world-class 85% target)
  • Availability, Performance, Quality — three KPI cards
  • OEE trend 30 days (line chart)
  • OEE by machine (bar chart, sorted low to high)
  • OEE by shift (bar chart — identify shift performance differences)
  • OEE heatmap (Machine × Day of week)

Page 2: Downtime Analysis

  • Total unplanned downtime hours (KPI card)
  • MTBF and MTTR (two KPI cards)
  • Downtime Pareto (combination bar + line with cumulative %)
  • Downtime by machine (horizontal bar chart)
  • Downtime by shift (grouped bar)
  • Downtime trend 90 days (line chart)
  • Active downtime events (real-time table if streaming)

Page 3: Quality Dashboard

  • First Pass Yield (gauge vs target)
  • DPMO and Sigma Level (KPI cards)
  • Scrap Rate by product (bar chart)
  • COPQ trend (line chart showing cost of quality issues)
  • Defect Pareto by defect code
  • SPC Chart (line chart with UCL, LCL, UWL, LWL reference lines)

Page 4: Throughput and Capacity

  • Schedule Attainment % (gauge)
  • Actual vs Planned production (grouped bar by day)
  • Capacity utilization by machine (heatmap)
  • Changeover time analysis (bar chart by product/machine)
  • Production output trend (area chart, actual vs target)
  • Bottleneck machine highlight table

Frequently Asked Questions

What is OEE and why does it matter for manufacturing?

OEE (Overall Equipment Effectiveness) is the gold standard metric for manufacturing productivity. It combines three factors: Availability (equipment running when it should), Performance (running at the right speed), and Quality (producing good parts). A 60% OEE means you are realizing only 60% of your theoretical capacity — the other 40% is waste. Improving OEE directly increases output without capital investment in new equipment.

Can Power BI connect to MES systems for real-time OEE?

Yes — most MES systems (Ignition SCADA, GE Proficy, Siemens MES, Rockwell FactoryTalk) support database connectivity (SQL Server, Oracle) or REST API access. Power BI connects to these databases and can use streaming datasets for near-real-time updates (every 30 seconds to 1 minute). For true real-time OEE (sub-second), use Azure IoT Hub or Event Hub with Power BI Streaming datasets pushed directly from plant floor sensors.

What data does a factory need to start tracking OEE?

Minimum data requirements for basic OEE: (1) Production count data — when did the machine run and how many units were produced, (2) Downtime events — when did the machine stop and why, (3) Quality counts — how many good vs defective units. This can come from manual operator entry (Excel/paper → Power BI), basic MES, or PLC counter data. Perfect data is not required to start — even imperfect OEE visibility drives improvement.

How do I build an SPC chart in Power BI?

Create a line chart with the measurement values as the main series. Add four additional measures (UCL, LCL, UWL, LWL) as separate line series in the chart. Format UCL/LCL as red dashed lines and UWL/LWL as orange dashed lines. Conditional formatting on data points highlights out-of-control points in red. The built-in SPC custom visual from AppSource provides Western Electric rule detection (runs above/below center, trends, etc.) beyond the basic control limit approach.

What is a realistic timeline to implement a Power BI manufacturing dashboard?

A basic OEE dashboard (single machine, manual data entry via SharePoint list or Excel) can be built in 1-2 weeks. A full manufacturing analytics platform connected to MES and ERP (multi-machine, multi-line, with quality SPC, downtime Pareto, and throughput analysis) typically takes 6-12 weeks. The longest phase is always data integration and data quality — machine timestamps, downtime reason codes, and product changeovers need to be captured consistently before analytics add value.

How does ECOSIRE connect Power BI to Odoo Manufacturing?

Odoo Manufacturing stores production work orders, materials consumption, quality checks, and maintenance requests in PostgreSQL. ECOSIRE connects Power BI directly to Odoo's PostgreSQL database (on a read replica) and models the manufacturing tables (mrp.production, mrp.workcenter, quality.check, maintenance.request) into the OEE data model described in this guide. We handle the work center-level capacity planning and quality integration as part of our Odoo ERP integration practice.


Next Steps

Manufacturing analytics in Power BI — when connected to your production floor data — provides the real-time visibility that separates world-class manufacturers from average performers. OEE, downtime root cause analysis, and quality SPC charts give operations teams the information to improve before problems compound.

ECOSIRE builds manufacturing dashboards connected to MES systems, ERP platforms (Odoo, SAP, Dynamics 365), and IoT data streams. Our Power BI dashboard development services cover the full manufacturing analytics stack from data model design to production-ready dashboards.

Contact our manufacturing analytics team to discuss your plant floor data sources and design a Power BI analytics platform that drives measurable OEE improvement.

E

Written by

ECOSIRE Team

Technical Writing

The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.

ECOSIRE

Unlock Data-Driven Decisions

Custom Power BI dashboards, data modeling, and embedded analytics solutions.