voorbeeldbestand
Vertaal getallen naar tekst

1 Soms moet je getallen als tekst uitschrijven

In het Nederlands is de weergave van getallen in tekst erg regelmatig.
Getallen worden ingedeeld in groepen van drie, voor: eenheden, duizendtallen, miljoenen, miljarden, etc.
Het 1e cijfer in iedere groep van 3 geeft het aantal honderdtallen aan, het 2e cijfer het aantal tientallen en het 3e cijfer het aantal eenheden.

Die worden standaard op de volgende manier aan elkaar verbonden:

7honderd7en7tig

Er is een aantal uitzonderingen:

- sommige tiental-en-eenhedencombinaties hebben een afwijkende (eigen) naam: 11, 12, 13, 14, 20, 30, 40, 80.
- bij getallen tussen 10 en 20 worden eenheden en tientallen niet gekoppeld met 'en' : zeventien (i.t.t zevenenzeventig)
- bij getallen tussen 10 en 20 wordt geen gebruik gemaakt van 'tig' als uitgang, maar van het woord 'tien'
- vóórhonderdenduizendwordt 'een' weggelaten, bij miljoen en miljard niet.

Bij de schrijfwijze heb ik aansluiting gezocht bij de Algemene Nederlandse Spraakkunst en de spreektaal.
Waar in de spreektaal geen tussen 'en' wordt gebruikt ( bijv. 107 honderdzeven), doe ik dat ook niet in deze funktie

Ik heb gezocht naar een methode die geschikt is voor alle programma's die van VBA gebruikmaken.
De onderstaande methode kun je dus in Word, Excel, Access, Powerpoint, Outlook, etc. gebruiken.

Het bestand in de bijlage bevat 3 verschillende funkties: vertaal, vertaal_dec en vertaal_dec_suf.
De funktie vertaal werkt uitsluitend voor gehele getallen.
De funktie vertaal_dec werkt voor gehele getallen en getallen tot twee decimalen.
De funktie vertaal_dec_suf werkt voor gehele getallen, getallen tot 2 decimalen en bevat de optie een préfix, een tussenvoegsel en/of een suffix aan de uitgeschreven tekst toe te voegen.
Iedere funktie maakt gebruik van de funktie 'mats' om teksten op te halen.
Je kunt iedere vertaalfunktie aanroepen met een macro: zie het voorbeeld Sub snb()

In Excel kun je iedere funktie ook als een User Defined Function (UDF) gebruiken.
Daarvoor moet je de funktie in een macromodule zetten.
Aanroepen in een cel, doe je bijv. met =vertaal(rij())

2 Toelichting

2.1 De funktie vertaal

Eerst wordt het uit te schrijven getal aangevuld met nullen totdat de lengte van het getal een veelvoud van 3 is: '4' wordt '004'; '12' wordt '012'; '1230455' wordt '001230455'.

Daarna wordt iedere groep van 3 getallen geanalyseerd met behulp van de funktie'mats'en komen de resultaten in de arrayspterecht.
In de arrayspworden de volgende zaken opgeroepen:
- de tekst voor het aantal hondertallen: het eerste cijfer van de groep van 3
- de tekst voor alle afwijkende tiental-eenheden combinaties: de laatste 2 cijfers van de groep van 3
- de tekst voor de eenheden: het laatste cijfer van de groep van 3
- de tekst voor alle afwijkende tiental-namen (20, 30, 40, 80) voor de combinatie met eenheden: het tweede cijfer van de groep van 3, aangevuld met een "0"
- de tekst voor het tiental: het tweede cijfer van de groep van 3

Daarna worden de resultaten in array sp met elkaar gecombineerd.
- als het 1e getal in de groep van 3 groter is dan 0 voeg aan de cijfertekst in sp(0) het woord 'honderd' toe
- als de groep van 3 geen eenheden en tientallen bevat: klaar

- als de laatste 2 cijfers in de groep van 3 een afwijkende naamgeving hebben voeg die sp(1) dan toe; klaar

- als de laatste 2 cijfers in de groep van 3 geen afwijkende naamgeving hebben voeg dan de cijfertekst van de eenheden toe: sp(2)
- als het 2e cijfer in de groep van 3 '1' is: voeg 'tien' toe; klaar

- als het 2e cijfer in de groep van 3 groter is dan '1', neem de afwijkende tiental-naam: sp(3)
- als het 2e cijfer in de groep van 3 groter is dan '1' en het tiental heeft geen afwijkende naam, neem dan de tekst van het 2e cijfer in de groep van 3: sp(4)

Daarna vindt 'polijsting' plaats:
- tweeen wordt vervangen doortweeën
- drieen wordt vervangen doordrieën
- eenhonderd wordt vervangen doorhonderd
- eenduizend aan het begin van een getal wordt vervangen doorduizend

2.2 De funktie mats

De tekstreeks "__1een_2twee_3drie_4vier....._80tachtig" wordt gesplitst met het te zoeken getal (y), voorafgegaan door een 'underscore': _.
Als het getal 13 wordt gezocht, is het splitsingselement '_13'.
Het tweede element na de splitsing begint met het eerste woord na de splitsing: 'dertien_14veertien_....'
Omdat na een splitsing het eerste element de index (0) heeft, heeft het tweede element de index (1).
Nu splitsen we dit tweede element (1) met de 'underscore'.
Het eerste element na deze splitsing (met de index (0)) bevat het woord 'dertien'.

In VBA kun je deze stappen zo schrijven:
sp=split("__1een_2twee_3drie_4vier....._80tachtig")
sq=split(sp(1),"_")
mats=sq(0)
Je kunt de schrijfwijze ook reduceren tot een oneliner:
mats=split(split("__1een_2twee_3drie_4vier....._80tachtig")(1),"_")(0)

3 De code in de bijlage

Function vertaal(y)
c00 = Format(Val(1 * y), String(3 * ((Len(Format(Val(1 * y))) - 1) \ 3 + 1), "0"))

For j = 1 to Len(c00) \ 3
x = Mid(c00, 3*(j-1) + 1, 3)

sp = Array(mats(Left(x, 1)), mats(Val(Right(x, 2))), mats(Right(x, 1)), mats(Mid(x, 2, 1) & "0"), mats(Mid(x, 2, 1)))
c01 = c01 & IIf(sp(0) = "", "", sp(0) & "honderd") & IIf(Right(x, 2) = "00", "", IIf(sp(1)<>"", sp(1), sp(2) & IIf(Mid(x, 2, 1) = "1", sp(3), "en" & IIf(sp(3) = "", sp(4) & "tig", sp(3))))) & Choose(Len(c00) \ 3 - j + 1, "", "duizend ", " miljoen ", " miljard ")
Next

vertaal = IIf(c01 = "", "nul", Trim(Replace(Replace(Replace(Replace(" " & c01, " eendu", "du"), " eenho", "ho"), "eee", "eeë"), "rieen", "rieën")))
End Function
Function mats(y)
On Error Resume Next

mats = Split(Split("__1een_2twee_3drie_4vier_5vijf_6zes_7zeven_8acht_9negen_10tien_11elf_12twaalf_13dertien_14veertien_20twintig_30dertig_40veertig_80tachtig", "_" & y)(1), "_")(0)
End Function
Sub snb()
MsgBox vertaal(InputBox("voer een getal in zonder scheidingstekens: ", "snb")),,"snb"
End Sub