Building Material Distributors, Inc. · Prepared for Jay Carter & Mary Nail · March 2026

Your analytics, modernized
for the decade ahead

Real Power BI reports live in 1–2 weeks — same data, same measures, same divisions. Eliminates manual refresh, unlocks mobile and Teams, and gets your team off end-of-life infrastructure for good.

272 active thin Excel files
20–28 Power BI reports (target)
POC / Stage 0 live in 1–2 weeks
~3 years past Microsoft EOL
Schedule a scoping call → ↓ Download full proposal (PDF)
Where You Are

A platform built to last — that outlasted its era

The BMD BI portal is a real engineering achievement: a 473 MB Power Pivot model driving 272 active thin Excel reports across 27 divisions. It works. The problem is the foundation it runs on.

Current Architecture

End of Life — April 2023
flowchart TD A["🗄️ SQL Server\n(PFBMDSQL01)"] -->|manual refresh| B["📊 SSAS Tabular\n(BMDSSAS01)"] B -->|export + publish| C["📁 BMD_Core.xlsx\n473 MB Power Pivot · compat 1100"] C -->|MSOLAP connection| D["📑 272 Thin Excel Files\n215 Daily · 26 Weekly · 31 Monthly"] D -->|Excel Services REST| E["🌐 SharePoint 2013\nbmdbi.portalfront.com"] E --> F["👥 End Users"]

The Real Pain Points

What's holding you back
  • SharePoint 2013 support ended April 2023 — no security patches, no vendor support, no recovery path
  • Running on EOL infrastructure now triggers active claim denials — insurers are refusing payouts for breaches involving unpatched systems, and some policies explicitly exclude losses from CVEs left unpatched for 3+ weeks. "Coverage at risk" has become "claims denied."
  • Manual refresh cycle: SQL → SSAS → Core.xlsx → 272 files. One failure = stale data everywhere
  • 272 thin files to maintain — any path change breaks them all simultaneously
  • No mobile access, no Teams integration, no modern sharing or collaboration
  • DAX at compatibility level 1100 — first-generation DAX, SQL Server 2012 era. Predates local variables (VAR, added 2016) and calculation groups (added 2019). Direct result: 403 measures where ~175 would do the same analytical work — and every new metric means 8 hand-written variants instead of one.
  • No row-level security — every user with portal access sees all division data

Confirmed component versions — verified from live server and model file

Component Version in Use Support Status
SharePoint Server 2013 · v15.0.0.4641 EOL April 11, 2023
Web Server IIS 8.0 · Windows Server 2012 EOL October 9, 2023
Analysis Services SQL Server 2012 · v11.0 · MSOLAP.5 EOL July 12, 2022
DAX / Power Pivot Compatibility Level 1100 — SQL Server 2012 era First-generation DAX · no VAR · no calc groups
Target Compat Level 1500 · Microsoft Fabric Current · fully supported

Versions confirmed March 2026 from live server response headers (MicrosoftSharePointTeamServices: 15.0.0.4641) and BMD_Core.xlsx model file (CompatibilityLevel: 1100, ConnectTo: 11.0).

The risk isn't theoretical — it's a question of when, not if

The SharePoint server, the SSAS Tabular service, the PortalFront hosting contract — any one of these can fail without a Microsoft-supported recovery path. The system is currently stable, but stability isn't safety. Nearly three years of unpatched vulnerabilities accumulate silently. And insurance won't absorb the damage: cyber insurers are now actively denying claims for breaches where unpatched EOL systems were involved — not adjusting premiums, denying claims. The cost of a forced migration after a failure is dramatically higher than a planned one now.

473 MBCore model file size
272Active thin Excel files
403DAX measures in model
~3 yrsPast Microsoft end-of-life
291Stale/archived files (skip)

Where You're Going

The same data. A modern platform.

Microsoft Fabric + Power BI is the natural successor to this stack — built specifically to absorb SSAS Tabular models and Power Pivot logic without starting from scratch.

Target Architecture

Modern · Supported · Scalable
flowchart TD A["🗄️ SQL Server\n(on-prem or Azure SQL)"] -->|ADF pipeline| B["🏗️ Fabric Lakehouse\n(cloud-managed)"] B -->|DirectLake| C["📊 Power BI Semantic Model\nModern DAX · calc groups · WINDOW"] C --> D["📱 20–28 Power BI Reports\nSlicers replace 272 thin files"] D --> E["🌐 Power BI App\nCentral portal option"] D --> F["📋 BMD SharePoint Intranet\nReports embedded on division pages\n(Power BI web part)"] E --> G["👥 Users · Web · Mobile · Teams"] F --> G

What You Gain

The upside
  • 272 thin Excel files collapse to 20–28 Power BI reports — division and period slicers replace separate files
  • Reports embedded directly in your existing SharePoint intranet — division teams see their reports on the pages they already use, not in a separate portal
  • Automatic scheduled refresh — no manual cycle, monitored, alertable on failure
  • Full mobile experience — sales reps access live data on their phone before a customer visit
  • Microsoft Teams integration — reports embedded in channels, discussed in context
  • Row-level security — division managers see their division; leadership sees everything
  • Copilot / AI — ask questions in plain English, get instant visual answers without IT
  • Full Microsoft support — Fabric is the current strategic platform, not a dead end

On the compatibility question — your concern is the right instinct

A prior Excel 2013 upgrade attempt failed because SSAS version-to-version upgrades were notoriously brittle. Power BI's XMLA import path is fundamentally different — it reads the model directly rather than stepping through compatibility levels. Your existing DAX at compat 1100 (SQL Server 2012) is additive-compatible upward: every measure that works today is expected to keep working in Power BI. The jump to compat 1500 is a one-way upgrade — Stage 2 includes a formal BPA compatibility pass and side-by-side regression validation before anything is decommissioned. Stage 3 then layers in VAR rewrites and calculation groups to rationalize the 403 measures down to ~175 genuine business measures — eliminating ~210 structural variants (time duplicates, GL parallel pairs, intermediate helpers, junk) without touching any business logic. That's modernization on your schedule, not a prerequisite for going live.

Continuity

What doesn't change

The migration modernizes the platform, not the business logic. Everything your users depend on is preserved — validated side-by-side in Stage 0 before anything is decommissioned.

📐

The Data Model

All 64 tables, 67 relationships, and the full measure library migrate intact. The numbers users see today are the same numbers they'll see in Power BI — validated side-by-side in Stage 0 before anything is decommissioned.

🗂️

Report Navigation

The Power BI App mirrors the current portal's report structure — Flash Reports, Category Sales, Booked Orders, Budget. Division-level groupings preserved. Users find the same things in the same places from day one.

🔒

Data Access Control

Restricted reports (commission data, proprietary) become Power BI row-level security roles. The same people see the same data — enforced automatically at the model level rather than by folder ACLs.

📅

Refresh Cadence

Daily, weekly, and monthly data on the same schedule — just automated. No one triggers the refresh manually. Failures send alerts rather than going unnoticed until someone opens a stale report.

📊

All Business Logic

Every DAX measure, KPI definition, and calculation that works today works correctly in Fabric. Stage 3 adds modern capabilities on top — it doesn't replace what's already right.

🏢

Division Structure

All 27 division codes (AL, ACT, BMD, BP, BR, BSI, BT, CH, DFB, Dunn, FP…) carry through. Marvin Windows, intercompany actuals, budget tracking — all preserved in the migrated model.


What this migration actually buys you

These aren't marketing claims — they're capabilities the current stack structurally cannot deliver, regardless of how well it's maintained. Microsoft Power BI has been named a Gartner Magic Quadrant Leader for 18 consecutive years — furthest right in Vision for seven straight. A Forrester study found Microsoft Fabric delivers 379% ROI over three years, with organizations saving 125 hours per BI user per year through self-service alone.

⏱️

Automated Refresh — Zero Manual Work

The current manual SQL → SSAS → Core.xlsx → 272 files cycle is someone's daily job. At roughly 1 hour/day, that's 250+ hours of labor per year — recovered entirely in Stage 1. Power BI replaces it with scheduled, monitored refresh up to 48× per day. Failures trigger alerts, not silence.

Operational
📱

Field Teams Get Real Data — Anywhere

Sales reps pull live division performance, top customers, and booked orders on their phone before walking into a meeting. GPS location filtering auto-scopes reports to the territory or site they're standing in. NFC tags on equipment or shelves instantly open the relevant Power BI report — tap and see. Copilot is available straight from the mobile homepage: ask "show me BP's top customers this quarter" and get a visual answer on the spot. The current portal has no mobile story whatsoever.

Sales Enablement
🔒

Row-Level Security Built In

Division managers see their division. Territory reps see their territory. Leadership sees everything. One report, enforced automatically at the model level — no separate file per role, no ACL spreadsheet to maintain.

Security
🤖

AI / Copilot — Plain English Queries

Business users ask questions in natural language: "What were BP's top 10 customers this quarter?" and get an instant, visualized answer. No DAX, no pivot tables, no IT request. New metrics generate themselves. Available on desktop, browser, and mobile.

Requires F2 Fabric capacity (~$262/mo minimum — no F64 required). PPU users can add F2 Copilot Capacity to unlock it without upgrading their full license. Not available during the free trial.

AI
💬

Teams Integration — Full Portal in Teams

Entire Power BI organizational apps — not just individual reports, but the full BMD portal with navigation, scorecards, and dashboards — embed directly into Teams tabs. The whole team reviews the same live data in a meeting, drills together, annotates visuals, and chats in context. No app-switching. The portal lives where the work already happens.

Collaboration
📊

Self-Service Analytics

Division leaders build their own views — filtering, drilling, slicing — without filing an IT request. The 272-thin-file model exists because Power Pivot required a separate file per pivot configuration. Slicers eliminate that entirely.

Self-Service
🏢

Reports Live on Your Intranet Pages

Power BI's SharePoint web part embeds any report directly into a SharePoint Online page. BP division gets their reports on the BP intranet page. Booked orders live where the operations team already works. No separate portal to navigate to — the data is already there.

SharePoint
📄

Paginated Reports — Print-Ready Output

Power BI Premium includes paginated reports: pixel-perfect, multi-page formatted output for printing, PDF export, or scheduled email delivery. If any of BMD's 272 thin files are used for formal distribution, executive packets, or regulatory reporting, paginated reports handle that natively — no Excel required.

Distribution
Data Model

403 measures. The same insight. Half the code.

We read every measure in BMD_Core.xlsx — all 403. The model is sound. But compat 1100 predates the two most impactful DAX features ever shipped: local variables (VAR, added 2016) and calculation groups (added 2019). Without them, every time-period variant had to be written by hand — and that accumulated over 14 years.

Not a DAX person? Here's what matters.

The numbers don't change. The reports don't change. Stage 3 cleans up 14 years of technical debt in the underlying code — same analytical output, half the maintenance overhead. It's optional, and nothing before it depends on it.

403
Measures today
~100 time-intelligence variants (SEL / YAG / YTD / QTD / Per Day...)
~62 GL Actual + Budget parallel pairs
~20 intermediate helper measures (pre-VAR workarounds)
~29 junk / test / auto-generated — deleted
~192 genuine business logic — kept

Why so many? Every time-period variant (SEL, YAG, YTD, QTD, Per Day, Projected) is a separate hand-written measure at compat 1100. Adding one new base metric means writing eight new measures manually — that's the only way to do it in this version.

~175
Genuine business measures + 3 calculation groups
~175 real business measures — all logic preserved, no variants, no junk
Time Intelligence SEL · YAG · YTD · QTD · Per Day · Projected · Running Total — auto-applied to every base measure
GL Scenario Actual · Budget · Variance · Var% · vs LY — replaces ~62 parallel GL measure pairs
Budget vs Actual Actual · Budget · Variance · Var% — replaces parallel sales budget sets

Same analytical output. Same numbers. Adding a new base metric costs one measure — the Time Intelligence calc group gives it all nine time comparisons automatically.

Where the 403 measures go

Every subject area keeps all its business logic. The structural overhead — variants, parallels, helpers, junk — is what disappears.

Subject Area Before After What changes
Invoiced Sales (InvSalesStats) 159 ~35 Time Intelligence calc group replaces ~120 SEL/YAG/YTD/QTD/Projected variants; 5 base metrics + ~30 other measures (variance, yesterday, counts, Marvin, list price) remain
GL / P&L (GLActual + GLBudget) 62 ~30 GL Scenario calc group handles Actual/Budget/Variance switching; ~30 P&L line base measures (Sales, COS, GM$, OPEX, EBITDA, ROIC, DSO...) remain
Budget (SalesBudget + InventoryBudget) 42 ~22 Budget vs Actual calc group handles variants; to-date proration logic rewritten with VAR into a single clean measure
Balance Sheet 28 ~14 GL Scenario calc group handles Actual/Budget switching; ~14 balance sheet line items remain
Booked Orders 24 ~18 Minor cleanup; duplicate raw measures removed
Marvin / Hanley Wood 20 ~15 Dead relationship (MW ICM Ref) removed — confirmed unused via live DAX audit; measures unchanged
Calendar + Period utilities 22 ~15 Auto-generated junk removed; time boundary anchors (SEL Start/End, YAG Start/End) kept — used inside the calc group
Inventory 11 ~9 Stale 2011 benchmark measure removed
Headcount 11 ~8 Auto-generated SUM wrappers removed; actual Headcount measures kept
Purchasing 8 ~7 Minimal change
Junk / orphan / test 29 0 [DeleteMe countrows periods], [Measure 1], [Blank], and 26 auto-generated [Sum of X] measures across 12 tables — deleted outright
Total 403 ~175 Plus 3 calculation groups providing time variants, GL scenario switching, and budget comparisons dynamically

What this means for your reports

Today the model has separate named measures for Sales SEL, Sales YAG, Sales YAG as of Date, Sales YTD, Sales QTD, Sales per Day, Sales Projected — seven individually hand-written measures for one concept. That pattern repeats for GM$, GM%, Qty, and COGS. After modernization: five base measures and one Time Intelligence calculation group. A period slicer on the report replaces seven separate file tabs. The same analytical depth — a fraction of the maintenance overhead. And adding a new metric costs one measure, not eight.


POC first. Then stages. Each one stands alone.

Stage 0 is the paid proof of concept — one division, real data, embedded in your SharePoint intranet. Evaluate it before committing to anything. Each subsequent stage delivers value independently and decommissions one piece of the old stack. Stage 4 is optional — the gateway refresh works indefinitely.

POC · Stage 0

Gateway Bridge

One division. Two to three Power BI reports connected to your existing SSAS server via gateway. Numbers validated side-by-side with the current portal. Reports embedded in a BMD SharePoint intranet page. Evaluate the experience before committing to anything.

1–2 weeks 8–12 hrs
Nothing decommissioned — pure evaluation
Stage 1

Off PortalFront

272 active thin files replaced by 20–28 Power BI reports with slicers. Users move to the Power BI App. bmdbi.portalfront.com and SharePoint 2013 decommissioned. PortalFront contract ends.

4–6 weeks 80–120 hrs
Decommissions: PortalFront, SharePoint 2013
Stage 2

Model to Azure

SSAS Tabular model exported via XMLA and deployed to Microsoft Fabric. Compatibility level upgraded to 1500. Power BI connects to Fabric instead of on-prem SSAS — users see nothing change.

3–4 weeks 20–30 hrs
Decommissions: BMDSSAS01, POWERPIVOT2013
Stage 3

Modern DAX

Calculation groups replace ~210 structural variants (time duplicates, GL parallels, intermediate helpers). 403 legacy measures rationalized to ~175 genuine business measures. User-defined functions (UDFs) establish reusable DAX logic patterns going forward. Semantic model placed under source control via TMDL. WINDOW functions, field parameters, and dynamic dimensions unlock new report capabilities.

2–4 weeks 20–40 hrs
Decommissions: Redundant legacy measures
Stage 4

Data to Azure

SQL Server data moved to Fabric Lakehouse via Azure Data Factory pipeline. DirectLake replaces the gateway. Monitored refresh with alerting. Fully cloud-native. Optional — gateway refresh works indefinitely.

4–8 weeks 20–40 hrs
Decommissions: On-prem data gateway (optional)
Total Effort Estimate
128–202 hours
Stages 0–3 · from POC to modern DAX · all stages deliver value independently
Stage 0: 8–12 hrs Stage 1: 80–120 hrs (largest — 272 thins) Stage 2: 20–30 hrs Stage 3: 20–40 hrs
Stage 4 (data to Azure) adds 20–40 hrs — optional; gateway refresh works indefinitely
Licensing & Cost

Start free. Decide after you've seen it work.

The 60-day Microsoft Fabric trial is free and covers enough capacity to complete Stages 0 and 1 and validate the Stage 2 model migration — before any licensing commitment. The trial starts at F4 capacity; eligible tenants can request an upgrade to F64 at no extra cost.

Fabric Trial

$0 / 60 days
Start here. Covers Stages 0–2 validation. Begins at F4 capacity; eligible tenants can upgrade to F64. Note: Copilot and Trusted Workspace Access are not available in trial capacity.

PPU + F2 Copilot Capacity

$24 / user / mo + $262/mo
PPU for all Premium features, plus an F2 Fabric Copilot Capacity (~$262/mo flat) to unlock Copilot for the whole organization. Best of both: per-user scaling with AI capability, no $5K/mo F64 commitment. Requires Stages 0–1 complete before adopting.

Fabric F64 Capacity

~$5,000 / month (1-yr reservation)
Required for Lakehouse, DirectLake (Stage 4). ~$8,300/mo pay-as-you-go; ~$5,000/mo with 1-year reservation. Capacity can be paused when idle to reduce costs. All M365 users view reports at no extra per-seat cost.

The recommended path

Start the free Fabric trial (begins at F4; upgrade to F64 if eligible). Complete Stage 0 and Stage 1. Count how many people actively use the new portal. If under ~40 active users and the solution stays Power BI-focused, PPU at $24/user/mo is likely the right answer — no capacity overhead, scales with actual usage. Want Copilot on the PPU path? Add an F2 Fabric Copilot Capacity (~$262/mo flat) alongside PPU — that unlocks Copilot for the entire organization without an F64. If Stage 4 (Lakehouse/DirectLake) becomes real, an F SKU is required regardless of user count.

Risk Management

What could go wrong — and how we handle it

Every migration carries risk. These are the six real ones, with the mitigation built into the stage design.

Risk Mitigation Stage
Compat upgrade breaks deprecated DAX Run Tabular Editor Best Practice Analyzer before upgrading — flags every deprecated pattern first. Fix before the upgrade, not after. Pre-Stage 2
Measure behavior differences after compat upgrade Stage 2 runs Fabric and on-prem SSAS side-by-side for 1–2 weeks. Identical DAX queries, compared numerically. Nothing is decommissioned until the numbers match. Stage 2
More active thins than expected SharePoint audit log analysis before Stage 1 scope is confirmed — actual open counts per file. Build the right 20 reports first; the rest can wait. Pre-Stage 1
User adoption — people are used to Excel Parallel run period (2–4 weeks): both systems live, users compare. Power BI App mirrors the current portal's navigation — users find the same things in the same places from day one. Stage 1
Data refresh gaps during migration Gateway-based refresh continues uninterrupted until Stage 4 replaces it. At no point is the refresh path removed before a replacement is validated. Stages 0–4
Scope creep on report redesign Migrate existing report logic first — exact same output, Power BI format. Visual polish (themes, branding, new visuals) is additive in a separate pass after validation. Stage 1

The design principle behind all of it

Each stage has a gate — a checklist of conditions that must be true before the next stage begins. Nothing is decommissioned until its replacement is validated side-by-side. The project can pause after any stage and BMD keeps the value delivered so far. Risk is sequenced, not eliminated — which means it's manageable.

Scoping Inputs

What we'll cover on the scoping call

A 45-minute call is all it takes to scope Stage 1 accurately. Here's what we'll work through together — none of it blocks Stage 0, which can start this week.

Division Clarity

Are FR, OS, SI, SP, TD distinct business divisions — or are some rep territories or report categories? This determines how we structure the Power BI App navigation and row-level security roles.

Marvin Scope

Marvin Windows & Doors has 6 dedicated model tables and active reports across Daily + Tabular folders. Dealer tracking, vendor program, or both? Determines the Marvin report set and whether the Hanley Wood market data migrates.

Refresh Ownership

Who runs the current manual SQL → SSAS → Core.xlsx cycle today? How often, and what happens when it doesn't run? This informs gateway placement and the Stage 0 scheduled refresh setup.

Naughty Folder Access

Who currently has access to the commission and proprietary data reports (PY Commission, Sales_by_Metro_Region)? Current ACL becomes the Power BI row-level security role definition.

Active User Count

How many people actively log into bmdbi.portalfront.com? The single biggest licensing input — under ~40 active users on a Power BI-only path, PPU ($24/user/mo) is likely the right answer. If Stage 4 (Lakehouse/DirectLake) is in scope, F64 capacity is required regardless of user count.

Usage Data

The SharePoint audit logs (BMD_BI_Audit_Log_*.xlsx) show which of the 272 thin files are actually opened. Pulling these before Stage 1 scope is confirmed lets us build the right 20 reports first and confidently skip the rest.