Je exporteert een tabel van een Duitse website. De omzetkolom toont "1.234,56 €".
Je plakt het in Excel. Het wordt "1.23456E" of, erger nog, een datum.
Welkom bij het internationale getalnotatie-probleem.
Het Kernprobleem: Wat Betekent "1.234"?
In de VS en het VK: 1.234 = één komma twee drie vier (decimaal)
In Duitsland, Spanje en het grootste deel van Latijns-Amerika: 1.234 = duizend tweehonderdvierendertig
Dezelfde tekens. Totaal verschillende waarden.
Bij het extraheren van data van internationale websites kun je niet aannemen met welk formaat je te maken hebt. En als je het verkeerd hebt, zit je er met ordes van grootte naast.
De Drie-Cijfer-Ambiguïteit
Het lastigste geval is precies drie cijfers na een scheidingsteken.
| Invoer | VS-Interpretatie | EU-Interpretatie |
|---|---|---|
| 1.234 | 1.234 (decimaal) | 1.234 (duizendtallen) |
| 1,234 | 1.234 (duizendtallen) | 1.234 (decimaal) |
| 1.234.567 | Ongeldig | 1.234.567 |
| 1,234,567 | 1.234.567 | Ongeldig |
Met twee cijfers erna is het duidelijk decimaal: "1.23" of "1,23".
Met vier+ cijfers erna is het duidelijk decimaal: "3.14159".
Met drie cijfers? Kan allebei zijn.
Het Detectie-algoritme
Hier is een heuristische aanpak die de meeste real-world gevallen afhandelt:
function normalizeNumberString(value) {
if (typeof value !== "string") return value;
const v = value.trim();
if (!v || !/[0-9]/.test(v)) return value;
// Stap 1: Verwijder valutasymbolen, percentages, witruimte
let cleaned = v
.replace(/ /g, " ")
.replace(/^(USD|EUR|GBP|R\$|MXN)\s*/i, "")
.replace(/[$€£¥₹₽₩]/g, "")
.replace(/%/g, "")
.replace(/\s+/g, "");
// Stap 2: Verwerk mintekens
const isNegative = cleaned.match(/^-/);
if (isNegative) {
cleaned = cleaned.substring(1).trim();
}
// Stap 3: Alleen cijfers? Dan zijn we klaar
if (/^\d+$/.test(cleaned)) {
return isNegative ? `-${cleaned}` : cleaned;
}
// Stap 4: Detecteer scheidingstekens
const hasComma = cleaned.includes(",");
const hasDot = cleaned.includes(".");
// Stap 5: Pas heuristiek toe
let decimalSeparator = ".";
let thousandsSeparator = ",";
if (hasComma && hasDot) {
// Beide aanwezig: de laatste is het decimaalteken
const lastComma = cleaned.lastIndexOf(",");
const lastDot = cleaned.lastIndexOf(".");
if (lastComma > lastDot) {
decimalSeparator = ",";
thousandsSeparator = ".";
}
} else if (hasComma && !hasDot) {
const parts = cleaned.split(",");
if (parts.length === 2 && parts[1].length <= 2) {
// "1,23" → decimaal
decimalSeparator = ",";
} else {
// "1,234" of "1,234,567" → duizendtallen
decimalSeparator = null;
thousandsSeparator = ",";
}
} else if (hasDot && !hasComma) {
const parts = cleaned.split(".");
if (parts.length === 2) {
const afterDot = parts[1];
if (afterDot.length <= 2 || afterDot.length >= 4) {
// "1.23" of "3.14159" → decimaal
decimalSeparator = ".";
} else {
// "1.234" → DUIZENDTALLEN (pragmatische keuze voor tabellen)
decimalSeparator = null;
thousandsSeparator = ".";
}
} else {
// Meerdere punten → duizendtallen
decimalSeparator = null;
thousandsSeparator = ".";
}
}
// Stap 6: Verwijder duizendtallenscheidingstekens
if (thousandsSeparator) {
cleaned = cleaned.replace(new RegExp(`\\${thousandsSeparator}`, "g"), "");
}
// Stap 7: Normaliseer decimaal naar punt
if (decimalSeparator && decimalSeparator !== ".") {
cleaned = cleaned.replace(decimalSeparator, ".");
}
// Stap 8: Valideer
const num = Number(cleaned);
if (!Number.isFinite(num)) return value;
return isNegative ? `-${cleaned}` : cleaned;
}
Waarom Drie Cijfers = Duizendtallen
De kernbeslissing: wanneer we precies drie cijfers na één scheidingsteken zien (zoals "1.234"), interpreteren we het als duizendtallen, niet als decimaal.
Waarom? In HTML-tabellen:
- Financiële data met duizendtallen komt extreem vaak voor: $1.234, €1.234
- Decimalen met precies drie cijfers zijn in de praktijk zeldzaam
- Wetenschappelijke data met drie decimalen (zoals "3.141") wordt meestal geschreven als "3.14159" of gewoon "3.14"
Deze heuristiek is een pragmatische afweging die werkt voor het overgrote deel van real-world tabellen.
De Volledige Formaatmatrix
| Invoer | Interpretatie | Genormaliseerde Output |
|---|---|---|
| 1.234,56 | EU decimaal | 1234.56 |
| 1,234.56 | VS decimaal | 1234.56 |
| 1.234.567,89 | EU duizendtallen + decimaal | 1234567.89 |
| 1,234,567.89 | VS duizendtallen + decimaal | 1234567.89 |
| 1.234 | Duizendtallen | 1234 |
| 1,234 | Duizendtallen | 1234 |
| 3.14 | Decimaal | 3.14 |
| 3,14 | Decimaal | 3.14 |
| 3.14159 | Decimaal (4+ cijfers) | 3.14159 |
| $ 1.200,50 | Valuta + EU | 1200.50 |
| -5.000 | Negatief duizendtallen | -5000 |
| 12.5% | Percentage | 12.5 |
Omgaan met Valutacodes
Internationale data komt met valutaprefixen en -suffixen. Verwijder ze eerst:
// Verwijder valutacodes VOOR symbolen
.replace(/^(USD|EUR|GBP|JPY|CHF|CAD|AUD|CNY|INR|BRL|R\$|MXN|KRW)\s*/i, "")
// Verwijder daarna symbolen
.replace(/[$€£¥₹₽₩₪฿₫₴₦]/g, "")
Volgorde is belangrijk: "R$" (Braziliaanse Real) bevat "$", dus het eerst verwijderen van valutacodes voorkomt gedeeltelijke matches.
Wanneer de Heuristiek Faalt
Geen heuristiek is perfect. Je krijgt onjuiste resultaten wanneer:
- Wetenschappelijke data met precies 3 decimalen: "3.141" wordt "3141"
- Prijzen onder $10 met 3 decimalen: "$1.234" wordt "$1234"
- Gemengde formaten in één kolom: Sommige rijen EU, sommige rijen VS
Voor geval 3 heb je kolomniveau-formaatdetectie nodig:
function detectColumnFormat(values) {
let euIndicators = 0;
let usIndicators = 0;
for (const v of values) {
if (/\d\.\d{3},\d{2}$/.test(v)) euIndicators++;
if (/\d,\d{3}\.\d{2}$/.test(v)) usIndicators++;
}
if (euIndicators > usIndicators) return "eu";
if (usIndicators > euIndicators) return "us";
return "auto"; // Gebruik per-cel heuristiek
}
Exportprofielen voor Verschillende Regio's
Als je het bronland kent, kun je de ambiguïteit volledig vermijden door regiospecifieke profielen te gebruiken:
- Europees formaat: Neemt de komma als decimaalteken, gebruikt puntkomma als CSV-scheidingsteken
- VS/VK-formaat: Neemt de punt als decimaalteken, gebruikt komma als CSV-scheidingsteken
HTML Table Exporter bevat vooraf ingestelde profielen voor beide formaten, plus gespecialiseerde profielen voor tools zoals Pandas en DuckDB.
Veelvoorkomende Valkuilen
Verlies Geen Precisie
// Fout: verliest precisie bij grote getallen
const num = parseFloat("12345678901234567890");
// 12345678901234567000 (JavaScript-limiet)
// Beter: bewaar als string tot de laatste berekening
const cleaned = normalizeNumberString(value);
// Gebruik pas parseFloat wanneer je echt moet rekenen
Let op HTML-Entiteiten
Webtabellen bevatten soms (niet-afbrekende spatie) binnen getallen:
// "1 234 567" moet "1234567" worden
.replace(/ /g, " ")
.replace(/\s+/g, "")
Bewaar het Origineel bij Twijfel
Als de waarde er niet uitziet als een getal, retourneer het dan ongewijzigd:
if (!/[0-9]/.test(v)) return value;
// ...
if (!Number.isFinite(num)) return value;
Beter om "N.v.t." als "N.v.t." te laten dan te proberen het te parsen.
Samenvatting
| Scenario | Detectie | Opmerkingen |
|---|---|---|
| Zowel . als , | Laatste = decimaal | Universeel |
| Alleen komma, ≤2 cijfers erna | Decimaal | "1,23" |
| Alleen komma, 3+ cijfers erna | Duizendtallen | "1,234" |
| Alleen punt, ≤2 of 4+ cijfers | Decimaal | "1.23", "3.14159" |
| Alleen punt, precies 3 cijfers | Duizendtallen | "1.234" |
Het drie-cijfer-geval is de pragmatische afweging. Het werkt voor de meeste real-world data. Bij twijfel, gebruik een exportprofiel dat overeenkomt met je bronregio.
Lees voor meer over het kopiëren van data van websites naar Excel onze gids over de beste Chrome-extensie om tabellen naar Excel te kopiëren.
Wil je schone getalexporten zonder giswerk? Meer informatie op gauchogrid.com/nl/html-table-exporter of probeer het gratis in de Chrome Web Store.
Top comments (0)