Postcodes op de kaart zetten

Je klanten of je storingen op een landkaart, gekleurd naar wat je wilt weten. Daar heb je geen kaartdienst en geen abonnement voor nodig: in de postcodetabel staan bij elke rij al coördinaten. Hieronder lees je hoe je die gebruikt in Power BI, Excel en QGIS, hoe je zelf een kaart in HTML bouwt, en wat je met de pandvormen uit de postcode database kunt. Inclusief de fouten die iedereen één keer maakt.

Liever zonder kaartprogramma? Met de kaartmaker maak je een postcodekaart van Nederland in je browser, ingekleurd op je eigen cijfers of op CBS-cijfers.

Een postcode is geen plek op de kaart

Dit is waar de meeste kaarten stranden. 3992 DG is een code, geen positie. Je kaartprogramma weet niet waar dat ligt, tenzij je het erbij levert. Wat je nodig hebt zijn coördinaten: twee getallen per rij.

In de postcodetabel van Brons en in de postcode database van Zilver en Goud staan die getallen al in vier kolommen:

  • Latitude en Longitude: graden, het stelsel van Google Maps, Power BI en elke webkaart (WGS84).
  • XCoordinaat en YCoordinaat: Rijksdriehoek, het Nederlandse stelsel in meters. Handig als je met afstanden rekent.

Je hoeft dus niets op te zoeken en niets te geocoderen. Je sleept twee kolommen naar je kaart en klaar. Wie een lijst postcodes zonder coördinaten heeft, koppelt die eerst op postcode aan de tabel; dat is één VLOOKUP of één JOIN.

De data komt uit de BAG van het Kadaster en bevat alleen fysieke verblijfsobjecten. Postbussen zitten er niet in, dus die verschijnen ook niet op je kaart.

Geen zin in een kaartprogramma? Met de kaartmaker voor adressen op kaart plak je je lijst uit Excel en download je een kaart als afbeelding. Gratis tot 250 adressen.

Punten of vlakken: kies dit eerst

Postcodekaarten komen in twee soorten, en ze vragen om verschillende data. Kies verkeerd en je bent een middag kwijt.

Stippen (punten)

Elk adres of elke postcode wordt een bolletje op de kaart. Je hebt alleen coördinaten nodig, dus dit werkt meteen met onze bestanden. Goed voor de vraag waar je klanten wonen, of waar de storingen vandaan komen.

Gekleurde gebieden (vlakken)

Nederland opgedeeld in postcodegebieden, elk met een kleur naar omzet of aantal klanten. Dit heet een choropleet. Hiervoor heb je naast je cijfers ook de vórm van elk postcodegebied nodig — zie "Het officiële postcodegebied" hieronder voor waar die vandaan komt en welke cijfers erbij horen.

Een tussenweg die vaak genoeg is: tel je adressen per PC4 en zet één bolletje per postcodegebied, met de grootte naar aantal. Dat leest bijna net zo goed en kost je geen grensbestand.

Heb je een eigen indeling — welk kantoor welke postcodes bedient — dan is er nog een derde weg, zonder los grensbestand: het gebied tekenen uit je eigen adressen. Zie "Dekkingsgebied tekenen" verderop.

PC4 of PC6

PC4 zijn de vier cijfers (3992). Ruim 4.000 gebieden, ter grootte van een wijk of dorp. Rustig op een landkaart en genoeg voor een overzicht per regio. PC6 is de volledige postcode (3992 DG): meestal één straat of een stuk daarvan. Dat zijn er ruim 450.000, dus op een kaart van heel Nederland wordt het één vlek. Gebruik PC6 als je op wijkniveau inzoomt, PC4 als je het hele land laat zien.

Het officiële postcodegebied

De vórm van elk postcodegebied — de echte grens, zoals het CBS hem vaststelt — staat in ons bestand Postcodegebieden, samen met 136 kolommen cijfers per gebied: bevolking, woningen, inkomen, WOZ-waarde en de afstand tot voorzieningen.

Niet elk cijfer staat er meteen bij. CBS publiceert inkomen, WOZ-waarde en energieverbruik met twee jaar vertraging en de afstand tot voorzieningen met één jaar vertraging: in de nieuwste editie (2024) staan die kolommen bij alle 4.071 gebieden leeg, ook bij de grote steden. Ons bestand neemt per kolom en per postcodegebied de nieuwste jaargang die wél een cijfer geeft. Leeg blijft alleen een cel waar het CBS het cijfer geheimhoudt, omdat er te weinig mensen wonen.

Actiepunt. Wil je je eigen klanten op de kaart zetten, dan heb je aan alleen de vorm niet genoeg. Die vertelt je waar postcodegebied 3011 begint en eindigt, niet waar in dat gebied een klant precies woont. Wil je dat wél laten zien — bolletjes op de echte plek van elke klant — dan heb je coördinaten per adres nodig, zoals in de postcodetabel hierboven. Wil je alleen tellen of vergelijken per postcodegebied ("hoeveel klanten per PC4", "omzet per regio"), dan is het Postcodegebieden-bestand genoeg: koppel de vier cijfers van elke klant aan het bestand en je bent klaar.

Hieronder het bewijs dat het echt werkt: 45 echte postcodegebieden van centraal Rotterdam, met hun officiële vorm en het echte inwonertal van het CBS, getekend op een kaart.

De kaart laadt zodra je hem in beeld scrolt.

Inwoners per postcodegebied:tot 2.000tot 5.000tot 9.000tot 14.000vanaf 14.000

45 echte postcodegebieden (PC4) van centraal Rotterdam, met de officiële vorm en het echte inwonertal. Bron: CBS, licentie CC BY 4.0.

Koop het volledige bestand — € 49: alle 4.071 gebieden, alle 136 kolommen, en een echt cijfer waar de nieuwste CBS-editie nog leeg is.

Zo ziet een hele provincie eruit

Rotterdam hierboven is 45 gebieden. Hieronder de provincie Utrecht: 231 gebieden, ingekleurd op inwoners, gemiddeld inkomen of gemiddelde WOZ-waarde — kies zelf.

De kaart laadt zodra je hem in beeld scrolt.

Inwoners:tot 3.000tot 6.000tot 10.000tot 15.000vanaf 15.000

Alle postcodegebieden (PC4) van de provincie Utrecht, met de officiële vorm en drie echte cijfers per gebied — uit ons eigen, aangevulde bestand. Grijs is een gebied waar het CBS het cijfer geheimhoudt omdat er te weinig mensen wonen. Zoom in voor meer postcodes.

Postcodes op de kaart in Power BI

Power BI tekent de kaart voor je, maar het moet wel weten dat jouw getallen coördinaten zijn. Doe je dat niet, dan ziet het twee gewone getallen, telt ze op en zet één bolletje midden in de oceaan. Het is de fout die iedereen één keer maakt.

Stap voor stap

  1. Laad het CSV-bestand: Gegevens ophalen › Tekst/CSV. Zet het scheidingsteken op puntkomma en de bestandsoorsprong op UTF-8, anders lopen straatnamen met accenten in de war.
  2. Controleer het kolomtype van Latitude en Longitude. Die moeten Decimaal getal zijn, niet Tekst en niet Geheel getal. Staat er tekst, dan komt dat meestal door een komma als decimaalteken; zet de landinstelling van die stap op Engels (Verenigde Staten).
  3. Selecteer de kolom Latitude, ga naar het tabblad Kolomhulpmiddelen en zet Gegevenscategorie op Breedtegraad. Doe hetzelfde voor Longitude met Lengtegraad. Sla je dit over, dan klopt er niets van je kaart.
  4. Zet de visual Kaart op je rapport. Sleep Latitude naar Breedtegraad en Longitude naar Lengtegraad, niet naar Locatie.
  5. Sleep een getal naar Grootte, bijvoorbeeld het aantal adressen of je omzet. Nu zie je in één oogopslag waar het zwaartepunt ligt.

Waarom niet gewoon de postcode in Locatie slepen

Dat kan, en soms werkt het. Power BI stuurt die postcode dan naar Bing om er een plek van te maken. Drie bezwaren. Het is traag bij duizenden rijen. Het raadt er soms naast, want 1000 AA bestaat ook in andere landen. En je stuurt je adreslijst naar een dienst buiten je eigen omgeving, wat bij klantgegevens een gesprek met je privacyfunctionaris oplevert. Met eigen coördinaten gebeurt het rekenwerk gewoon op je eigen scherm.

Wil je toch gebieden inkleuren, dan is Vormkaart de visual die je zoekt. Die vraagt om een TopoJSON-bestand met de postcodegrenzen; dezelfde grenzen als hierboven, en dus niet iets wat in onze bestanden zit.

Het volledige bestand van Zilver en Goud telt ruim negen miljoen adressen. Dat past niet in Excel en het is ook zwaar voor één kaart. Filter eerst op de gemeente of de provincie die je wilt zien, of tel samen per postcode. Negen miljoen bolletjes worden één grote vlek.

Zelf een kaart bouwen in HTML

Je hebt geen dure kaartdienst nodig om adressen op een webpagina te zetten. Een kaart is niet meer dan een raster van plaatjes met jouw stippen eroverheen. Twee routes.

Met een bibliotheek: Leaflet

De makkelijkste weg. Leaflet is gratis, klein en werkt met kaarttegels van OpenStreetMap. Onderstaand voorbeeld zet een handvol adressen op de kaart; vervang de lijst door je eigen rijen uit de postcodetabel en je bent klaar.

Adressen op een kaart met Leaflet
<!-- Zet er een vast versienummer bij. Zonder nummer krijg je altijd de
     nieuwste, en breekt je kaart op een dag zonder dat je iets wijzigde. -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<div id="kaart" style="height: 500px"></div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
  // Rijen uit de postcodetabel: [latitude, longitude, label]
  const adressen = [
    [52.0907, 5.1214, "3511 LN Utrecht"],
    [51.9244, 4.4777, "3011 AA Rotterdam"],
    [52.3676, 4.9041, "1011 AB Amsterdam"],
  ];

  const kaart = L.map("kaart").setView([52.1, 5.1], 8);
  L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
    attribution: "&copy; OpenStreetMap-bijdragers",
    maxZoom: 19,
  }).addTo(kaart);

  for (const [lat, lon, label] of adressen) {
    L.circleMarker([lat, lon], { radius: 6 }).addTo(kaart).bindPopup(label);
  }
</script>

Zonder bibliotheek

Het kan ook kaal, met gewone plaatjes. Een kaarttegel is een plaatje van 256 bij 256 pixels op een vast adres: zoom, kolom, rij. Het rekenwerk van een coördinaat naar een tegelnummer past in vier regels.

Van coördinaat naar tegelnummer
function tegelX(lon, zoom) {
  return ((lon + 180) / 360) * 2 ** zoom;
}

function tegelY(lat, zoom) {
  const rad = (lat * Math.PI) / 180;
  return ((1 - Math.log(Math.tan(rad) + 1 / Math.cos(rad)) / Math.PI) / 2) * 2 ** zoom;
}

// De tegel waarin een adres valt, op zoomniveau 17:
const x = Math.floor(tegelX(5.9512, 17));
const y = Math.floor(tegelY(52.0043, 17));
const url = `https://tile.openstreetmap.org/17/${x}/${y}.png`;

Het niet-hele deel van die uitkomst vertelt je waar in de tegel het punt ligt: vermenigvuldig met 256 en je hebt de pixel. Zo tekenen wij de kaart op onze eigen demopagina, zonder kaartbibliotheek. Bekijk hem gerust en haal de aanpak eruit.

Tegels van OpenStreetMap zijn gratis, maar niet onbeperkt. Hun gebruiksvoorwaarden staan zwaar geautomatiseerd verkeer niet toe. Bouw je iets dat druk bezocht wordt, neem dan een betaalde tegeldienst of draai je eigen tegelserver. Vermeld altijd © OpenStreetMap-bijdragers.

Bekijk de werkende kaart op de demopagina: alle panden van één gemeente, gekleurd op woningtype, getekend met de techniek hierboven.

Dekkingsgebied tekenen: van postcode naar rayon

Een andere vraag dan een landkaart met stippen: welk gebied bedient kantoor A? Je hebt een eigen tabelletje — kantoor, en de postcodes die erbij horen — en je wilt dat als gekleurd vlak zien, in je eigen Power BI-rapport, met volle controle over het uiterlijk. Niet de ingebouwde kaartvisual, en niet Vormkaart: een eigen HTML-visual, met precies de techniek van de vorige sectie, maar dan binnen Power BI.

Waarom geen postcodegrenzenbestand

Kan wel (zie hierboven), maar het is een los bestand om te downloaden, te onderhouden en aan je eigen indeling te koppelen. En je eigen rayons volgen zelden precies de officiële postcodegrens. Er is een weg zonder dat bestand: het gebied tekenen uit de adressen die je toch al hebt.

Het gebied uit je eigen adressen

Filter de postcodetabel op de postcodes van één kantoor. Je houdt een lijst adressen over, elk met Latitude en Longitude. Span daar een elastiekje omheen — een vlak dat precies om de buitenste punten sluit — en je hebt een gebied, zonder ergens een grenzenbestand voor te downloaden. Dat elastiekje heet een convex hull, en de code past in dertig regels, zonder bibliotheek.

Een vlak om een groep adrespunten heen
type Punt = { lat: number; lon: number };

function kruisProduct(o: Punt, a: Punt, b: Punt): number {
  return (a.lon - o.lon) * (b.lat - o.lat) - (a.lat - o.lat) * (b.lon - o.lon);
}

// De convex hull: het kleinste vlak dat alle punten omvat (monotone chain).
function convexeHull(punten: Punt[]): Punt[] {
  const uniek = [...new Map(punten.map((p) => [`${p.lon},${p.lat}`, p])).values()]
    .sort((a, b) => a.lon - b.lon || a.lat - b.lat);
  if (uniek.length < 3) return uniek;

  const onder: Punt[] = [];
  for (const p of uniek) {
    while (onder.length >= 2 && kruisProduct(onder.at(-2)!, onder.at(-1)!, p) <= 0) onder.pop();
    onder.push(p);
  }
  const boven: Punt[] = [];
  for (let i = uniek.length - 1; i >= 0; i--) {
    const p = uniek[i];
    while (boven.length >= 2 && kruisProduct(boven.at(-2)!, boven.at(-1)!, p) <= 0) boven.pop();
    boven.push(p);
  }
  onder.pop();
  boven.pop();
  return [...onder, ...boven];
}

Wil je een vlak dat dichter tegen de straten aan ligt in plaats van een grove bol, gebruik dan een concave hull. Het pakket concaveman doet dat in een paar regels meer; voor de meeste rayons is de gewone convex hull hierboven al genoeg.

Een eigen HTML-visual in Power BI

De visual die dit mogelijk maakt heet HTML Content, te vinden in AppSource, gebouwd door dm-p. Die rendert gewone HTML, CSS en JavaScript in je rapport, en leest daarbij Power BI's eigen gegevens: verandert een filter of een slicer, dan verandert de data die de visual ziet mee, en teken je opnieuw.

  1. Maak in Power Query een tabel kantoor-postcode: welk kantoor welke postcodes bedient. Eén regel per postcode.
  2. Koppel die tabel aan de postcodetabel op de kolom Postcode (of PC4, als je op vier cijfers werkt). Elke rij krijgt nu een kantoornaam, plus Latitude en Longitude.
  3. Installeer HTML Content vanuit AppSource en zet 'm op je rapport.
  4. Geef de visual de velden Kantoor, Latitude en Longitude mee.
  5. Zet in het HTML-veld van de visual een kaart neer (Leaflet werkt hier het makkelijkst, zie de vorige sectie) die de binnenkomende rijen groepeert per kantoor, per groep de convexeHull-functie hierboven aanroept, en het resultaat als polygoon tekent.

Dit is geen officiële postcodegrens. Het is de vorm die om je eigen punten past — bij een kantoor met veel adressen ziet dat er redelijk uit, bij een postcode met maar twee of drie adressen wordt het een grove driehoek. Presenteer het als een praktische eigen weergave van je dekking, niet als een juridische grens.

Hieronder een werkend voorbeeld met de techniek hierboven: twee fictieve kantoren, elk met een handvol vaste voorbeeldpunten, en het vlak dat de code hierboven eromheen tekent.

De kaart laadt zodra je hem in beeld scrolt.

Kantoor NoordKantoor Zuid

Verzonnen voorbeeld met vaste punten rond Utrecht, geen echte klantgegevens. Elk vlak is een convex hull om de eigen punten van dat kantoor — geen officiële postcodegrens.

Van stip naar gebouw: Panden Plus

Een stip zegt dat er iets staat. Een pandvorm laat zien wát er staat. Panden Plus bevat de omtrek van elk gebouw in Nederland als polygoon. Ruim 12,7 miljoen panden, met het woningtype dat uit die vorm volgt: vrijstaand, hoekwoning, twee-onder-een-kap, tussenwoning of appartement.

Op een kaart is het verschil meteen zichtbaar. In plaats van bolletjes op een straat zie je de daken zelf, en kun je ze kleuren op bouwjaar, oppervlakte of woningtype. Een wijk uit de jaren dertig ziet er dan anders uit dan een nieuwbouwplan, zonder dat je één cijfer hoeft te lezen.

Wat je ermee doet

  • Oppervlakte rechtstreeks uit de vorm rekenen, in plaats van schatten.
  • Controleren of een punt binnen een pand valt, handig om losse data zoals een energielabel aan het juiste gebouw te hangen.
  • Filteren op vorm en grootte: alle vrijstaande woningen van vóór 1990 in één gemeente, voor een isolatie- of zonnepanelenactie.
  • Risico inschatten per pandtype, zoals verzekeraars doen: een vrijstaand pand brandt anders dan een rij tussenwoningen.
  • De woningmix van een wijk in kaart brengen, voor beleid of voor een haalbaarheidsstudie.
  • Kabels, leidingen of bezorgroutes plannen op de echte pandvorm in plaats van op een adrespunt.

In welke vorm het komt

Eén zip met twee bestanden die dezelfde panden bevatten. Een CSV met de vorm als WKT-tekst, voor Excel, SQL Server of Power BI. En een GeoPackage (.gpkg) waarin de vorm al echte geometrie is: die sleep je zo in QGIS of ArcGIS, en met ogr2ogr laad je hem in PostGIS of SQL Server. Er zit een leesmij bij met alle kolommen.

Bekijk de werkende kaart op de demopagina: alle panden van één gemeente, gekleurd op woningtype, getekend met de techniek hierboven.

Postcodes op de kaart in Excel

Excel heeft 3D-kaarten ingebouwd, onder Invoegen › 3D-kaart. Selecteer je tabel, open 3D-kaarten en sleep Latitude en Longitude naar Locatie; geef bij elk veld aan welke het is. Je kunt de hoogte of kleur van de staafjes op een getal zetten.

Twee grenzen om vooraf te kennen. Een werkblad houdt op bij ruim een miljoen rijen, dus Zilver en Goud passen er niet in; Brons met ruim 600.000 rijen wel. En 3D-kaarten zit alleen in de Windows-versies van Microsoft 365 en Office, niet in Excel voor het web en niet op een Mac. Werk je daarop, gebruik dan Power BI of de HTML-route hierboven.

Werk je op een Mac of in Excel voor het web? Plak je lijst dan in de kaartmaker: die zet je adressen op de kaart zonder 3D-kaarten, en geeft een PNG voor je presentatie.

Postcodes op de kaart in QGIS

QGIS is gratis, en het is de enige route hier waarmee je echt met vormen kunt rekenen: snijden, bufferen, tellen binnen een gebied. Voor Panden Plus is het de kortste weg, want daar sleep je het .gpkg-bestand zo in.

Een CSV met coördinaten inladen

  1. Laag › Laag toevoegen › Tekstbestand met scheidingstekens toevoegen.
  2. Kies het bestand, zet het scheidingsteken op puntkomma en de codering op UTF-8.
  3. Bij Geometriedefinitie: X-veld op Longitude, Y-veld op Latitude. Let op de volgorde: X is de lengtegraad, niet de breedtegraad.
  4. Zet het coördinaatstelsel op EPSG:4326 (WGS84). Gebruik je liever XCoordinaat en YCoordinaat, kies dan EPSG:28992.
  5. Voeg toe. Een achtergrondkaart krijg je met de plug-in QuickMapServices, of via XYZ Tiles › OpenStreetMap.

Kleuren op een kolom doe je via Eigenschappen › Symbologie › Gecategoriseerd. Kies bijvoorbeeld het veld woningtype en klik op Classificeren.

Rijksdriehoek of WGS84: het verschil dat kaarten sloopt

Nederland heeft een eigen coördinaatstelsel: Rijksdriehoek, kortweg RD, ook bekend als EPSG:28992. Het rekent in meters vanaf een nulpunt bij Amersfoort. De rest van de wereld gebruikt WGS84 (EPSG:4326), dat in graden rekent: de breedte- en lengtegraden die je van Google Maps kent.

Je herkent ze meteen aan de getallen. Een RD-coördinaat in Nederland ziet eruit als 155000 en 463000. Een WGS84-coördinaat als 52,09 en 5,12. Haal je ze door elkaar, dan verdwijnt je kaart: RD-getallen in een webkaart plaatsen je punt ergens ver buiten de aarde, en dan zie je niets.

  • Webkaart, Power BI, Google Maps, Leaflet: gebruik Latitude en Longitude (WGS84).
  • Afstanden en oppervlaktes in meters: gebruik XCoordinaat en YCoordinaat (RD). In graden rekenen levert scheve uitkomsten, want een graad lengte is in Nederland korter dan een graad breedte.

Omzetten kan altijd. In PostGIS is dat ST_Transform(geom, 4326), en met ogr2ogr zet je er -t_srs EPSG:4326 achter. De geometrie van Panden Plus staat in RD; de kolommen Latitude en Longitude staan er voor het gemak al naast.

Wat er in de praktijk misgaat

Alle punten liggen op één hoop bij Afrika

Coördinaat 0,0 ligt in de Golf van Guinee. Zie je daar een stapel punten, dan heeft je import lege coördinaten op nul gezet. Filter rijen zonder coördinaat eruit voordat je tekent.

Nederland ligt ineens in Somalië

Breedte- en lengtegraad omgewisseld. 52,09 en 5,12 is Utrecht; 5,12 en 52,09 is de Indische Oceaan. In QGIS is X de lengtegraad, in Power BI hoort Latitude in Breedtegraad. Draai ze om en je punt verhuist.

Eén bolletje in plaats van duizend

Power BI telt je coördinaten op in plaats van ze te tonen. De kolom staat op Som. Zet hem op Niet samenvatten, en zet de gegevenscategorie op Breedtegraad en Lengtegraad.

De komma

52,0907 is voor een Nederlandse computer een getal en voor een Engelse twee kolommen. Loopt je import scheef of worden coördinaten tekst, kijk dan naar het decimaalteken en naar de landinstelling van de importstap.

Het is traag

Negen miljoen punten tekenen kost tijd, ook op een snelle machine. Tel samen per PC4 of per gemeente, of filter op het gebied dat je nodig hebt. Voor een landkaart is één punt per postcodegebied bijna altijd genoeg.

Vragen over postcodes op een kaart

Eerst zien of het past?Download een demobestand van 1.000 rijen, met dezelfde kolommen als het volledige bestand.