Van workspace setup tot gepubliceerd dashboard: een praktische handleiding voor het bouwen van professionele Power BI rapporten met DAX, Power Query en Row Level Security.
Power BI bestaat uit twee onderdelen: Power BI Desktop (gratis, voor ontwikkeling) en de Power BI Service (cloud, voor publiceren en delen).
| Licentie | Kosten | Delen | Gebruik |
|---|---|---|---|
| Free | Gratis | Alleen met jezelf | Persoonlijk gebruik, leren |
| Pro | ~€9/gebruiker/maand | Met Pro gebruikers | Teams, zakelijk gebruik |
| Premium Per User | ~€18/gebruiker/maand | Met gratis gebruikers | Grote organisaties |
| Premium Capacity | Vanaf ~€4.000/maand | Iedereen in org | Enterprise, embedded |
Power Query (ook wel de M engine) is de ETL laag van Power BI. Je gebruikt het om data te importeren, transformeren en combineren voordat het in het datamodel komt.
Ga naar Start → Gegevens ophalen en kies je bron. Power BI ondersteunt 100+ connectoren: SQL Server, Azure, SharePoint, Excel, REST API's, en meer.
let // Stap 1: verbinding maken met SQL Server Bron = Sql.Database("server.database.windows.net", "AdventureWorks"), // Stap 2: tabel selecteren dbo_Sales = Bron{[Schema="dbo", Item="Sales"]}[Data], // Stap 3: kolommen filteren Gefilterd = Table.SelectColumns(dbo_Sales, {"OrderID", "OrderDate", "Amount", "CustomerID"}), // Stap 4: rijen filteren (query folding!) Actief = Table.SelectRows(Gefilterd, each [OrderDate] >= #date(2024, 1, 1)), // Stap 5: datumkolom omzetten naar datum type TypeKorrect = Table.TransformColumnTypes(Actief, {{"OrderDate", type date}, {"Amount", type number}}) in TypeKorrect
let StartDatum = #date(2020, 1, 1), EindDatum = Date.From(DateTime.LocalNow()), AantalDagen = Duration.Days(EindDatum - StartDatum) + 1, DatumLijst = List.Dates(StartDatum, AantalDagen, #duration(1, 0, 0, 0)), DatumTabel = Table.FromList(DatumLijst, Splitter.SplitByNothing(), type table [Datum = date]), Verrijkt = Table.AddColumn(DatumTabel, "Jaar", each Date.Year([Datum]), Int32.Type), MetKwartaal = Table.AddColumn(Verrijkt, "Kwartaal", each "Q" & Text.From(Date.QuarterOfYear([Datum])), type text), MetMaand = Table.AddColumn(MetKwartaal, "Maand", each Date.Month([Datum]), Int32.Type), MetMaandNaam = Table.AddColumn(MetMaand, "MaandNaam", each Date.MonthName([Datum], "nl-NL"), type text) in MetMaandNaam
Een goed datamodel is het fundament van een snel en correct Power BI rapport. Gebruik altijd een ster-schema: één feitentabel in het midden, omringd door dimensietabellen.
| Do | Don't |
|---|---|
| Ster-schema met aparte datumtabel | Platte tabel met alle kolommen samen |
| Integer surrogate keys | Tekst als join-kolom |
| Eén actieve relatie per tabelpaar | Bidirectionele filters standaard |
| Datumtabel gemarkeerd als datumtabel | Datum uit feitentabel gebruiken |
TOTALYTD, DATEADD en SAMEPERIODLASTYEAR.
DAX (Data Analysis Expressions) is de formuletaal van Power BI. Het werkt met tabellen en kolomcontext — fundamenteel anders dan Excel formules.
-- Eenvoudige aggregatie Totale Omzet = SUM(fct_Orders[Amount]) -- Aantal unieke klanten Unieke Klanten = DISTINCTCOUNT(fct_Orders[CustomerID]) -- Gemiddelde orderwaarde Gem. Orderwaarde = DIVIDE([Totale Omzet], COUNTROWS(fct_Orders))
-- Omzet alleen voor categorie "Electronics" Omzet Electronics = CALCULATE( SUM(fct_Orders[Amount]), dim_Product[Category] = "Electronics" ) -- Omzet vorig jaar (time intelligence) Omzet Vorig Jaar = CALCULATE( [Totale Omzet], DATEADD(dim_Datum[Datum], -1, YEAR) ) -- Jaar-op-jaar groei % YoY Groei % = DIVIDE( [Totale Omzet] - [Omzet Vorig Jaar], [Omzet Vorig Jaar] ) -- Cumulatief jaar tot datum Omzet YTD = TOTALYTD([Totale Omzet], dim_Datum[Datum])
-- SUMX: bereken per rij en sommeer Omzet Excl. BTW = SUMX( fct_Orders, fct_Orders[Amount] * (1 - fct_Orders[BTW_Rate]) ) -- RELATED: waarde ophalen uit gerelateerde tabel Omzet Premium Klanten = CALCULATE( SUMX( fct_Orders, fct_Orders[Amount] ), RELATED(dim_Customers[Segment]) = "Premium" ) -- Moving average 3 maanden Omzet 3M MA = AVERAGEX( DATESINPERIOD( dim_Datum[Datum], LASTDATE(dim_Datum[Datum]), -3, MONTH ), [Totale Omzet] )
Een goed dashboard communiceert snel en duidelijk. Design is geen bijzaak — het bepaalt of gebruikers het rapport begrijpen en vertrouwen.
| Doel | Visual | Wanneer |
|---|---|---|
| Vergelijken | Staafdiagram (horizontaal) | Categorieën vergelijken |
| Trend over tijd | Lijndiagram | Tijdreeksen |
| Aandeel | Ringdiagram (donut) | Max 5 categorieën |
| KPI | Kaartvisual of KPI-visual | Enkelvoudige meting |
| Geografisch | Kaart (ArcGIS/Bing Maps) | Regionale analyses |
| Detail | Tabelvisual of Matrix | Drilldown data |
Met RLS zorg je dat gebruikers alleen de data zien die ze mogen zien. Elke gebruiker gebruikt hetzelfde rapport, maar ziet gefilterde data op basis van hun identiteit.
-- Rol: Nederland medewerker -- DAX filter op dim_Regio tabel: [Land] = "Nederland" -- Rol: Manager (ziet alles) -- Geen filter — laat dit veld leeg
-- Filter op dim_Medewerkers tabel: -- Toont alleen data waar het e-mailadres overeenkomt [Email] = USERPRINCIPALNAME() -- Of via een mapping tabel (aanbevolen voor complexe structuren): -- dim_Medewerkers[Email] = USERPRINCIPALNAME() -- Gerelateerde tabellen filteren automatisch mee
Trage rapporten frustreren gebruikers. Met de juiste aanpak laad een dashboard in seconden, ook bij miljoenen rijen data.
| Modus | Voordeel | Nadeel | Wanneer |
|---|---|---|---|
| Import | Snel, volledige DAX ondersteuning | Data niet real-time, geheugen limiet | Standaard keuze |
| DirectQuery | Real-time, geen geheugen limiet | Trager, beperkte DAX | Grote live datasets |
| Dual | Flexibel (import + DQ) | Complex te beheren | Hybride scenario's |
VAR) om herhaalde berekeningen te cachenFILTER(ALL(Tabel), ...) — gebruik KEEPFILTERS of directe kolomfiltersDIVIDE() in plaats van / voor deling-door-nul beveiligingSUMX) op grote tabellen zonder noodzaak-- Slecht: OmzetVorig twee keer berekend Groei Slecht = DIVIDE( [Totale Omzet] - CALCULATE([Totale Omzet], DATEADD(dim_Datum[Datum], -1, YEAR)), CALCULATE([Totale Omzet], DATEADD(dim_Datum[Datum], -1, YEAR)) ) -- Goed: VAR vermijdt herhaalde berekening Groei Goed = VAR HuidigJaar = [Totale Omzet] VAR VorigJaar = CALCULATE([Totale Omzet], DATEADD(dim_Datum[Datum], -1, YEAR)) RETURN DIVIDE(HuidigJaar - VorigJaar, VorigJaar)
Na het bouwen publiceer je het rapport naar de Power BI Service voor geautomatiseerde vernieuwen en eenvoudig delen met collega's.
Apps zijn de aanbevolen manier om rapporten met eindgebruikers te delen.