Adres splitsen

Dat zal je altijd zien! Krijg je een adressenbestand aangeleverd, staat het adres (straat, huisnummer en toevoeging) in één veld. En in jouw database wil je dat nu juist in drie aparte velden opslaan. In dit voorbeeld laat ik zien hoe je met behulp van drie functies respectievelijk de straatnaam, het huisnummer en de toevoeging bij het huisnummer uit dat ene veld kunt peuteren.

Een eerste uitdaging waar we tegenaan lopen is de vraag waar staat het huisnummer?. Probleem is dat straatnamen ook getallen kunnen bevatten en het dus niet per definitie zo is dat een getal in een adres het huisnummer is. Voorbeelden van zulke straatnamen zijn: 1940-45 Laan, 2e Zuider Pierkesmarsweg, Apollo 11-Laan, Laan der 4 Heemskinderen, Plein 1813 en Plein '40-'45. Deze voorbeelden laten zien dat getallen op allerlei plaatsen in een straatnaam kunnen staan en dat er ook meerdere getallen in kunnen staan.
De functies zijn gebaseerd op de aanname dat het laatste getal in het samengestelde veld het huisnummer is (uitgaande van de in Nederland gebruikelijke schrijfwijze voor adressen). Alles dat voor het getal staat is de straatnaam, wat er achter staat is de toevoeging bij het huisnummer. Met deze aanpak kunnen we al dit soort straatnamen aan.
De functies zijn zo gemaakt dat ze zoveel mogelijk foutbestendig zijn, maar er zijn natuurlijk grenzen. Het gaat bijvoorbeeld fout als bij een adres op de Laan der 4 Heemskinderen het huisnummer ontbreekt. Dan zien de functies de 4 als huisnummer en 'Heemskinderen' als toevoeging bij het huisnummer.

Een ander lastig punt is de manier waarop toevoegingen bij het huisnummer genoteerd (kunnen) zijn. Staat de toevoeging vast aan het nummer of staat er iets tussen (een spatie, een - of wellicht een /)?
Ik heb het nu zo opgelost dat de positie na het huisnummer genegeerd wordt indien op die positie geen letter (a-z of A-Z) staat. Dus als het samengestelde adres eindigt op '30 B', dan wordt de toevoeging 'B' (want na de 30 geen letter maar een spatie). Evenzo wordt bij '30-B' de toevoeging eveneens 'B' (want geen letter maar een streepje na de 30). Ook bij '30B' wordt de toevoeging 'B' (want wel een letter na de 30).

Onderstaand vind je de uitwerking van de functies om de onderdelen uit het samengestelde adres te halen. Je kan de functies bijvoorbeeld gebruiken in een bijwerkquery:
   UPDATE Adrestabel
    SET Straat = ZoekStraat(SamengesteldAdres),
    SET Huisnummer = ZoekHuisnummer(SamengesteldAdres),
    SET Toevoegsel = ZoekToevoegsel(SamengesteldAdres)

Ik heb voorbeelddatabase gemaakt (hoewel, een database mag je het bij gebrek aan tabellen nauwelijks noemen) waarin je op een formulier een te splitsen adres in kunt geven en kunt zien hoe de functies het uitsplitsen.


Straatnaam
Function ZoekStraat(Adres As Variant) As String
Dim Teller As Byte
Dim AantalTekens As Byte
Dim StartLtstNum As Byte
Dim VorigTeken As String
Dim Teken As String

If IsNull(Adres) Then
   AantalTekens = 0
Else
   AantalTekens = Len(Adres)
End If

StartLtstNum = 0
VorigTeken = "X"

If AantalTekens > 0 Then
   For Teller = 1 To AantalTekens
      Teken = Mid(Adres, Teller, 1)
      If IsNumeric(Teken) And Not IsNumeric(VorigTeken) Then StartLtstNum = Teller
      VorigTeken = Teken
   Next

   If StartLtstNum > 1 Then
      ZoekStraat = Trim(Mid(Adres, 1, StartLtstNum - 1))
   Else
      ZoekStraat = Adres
   End If
Else
   ZoekStraat = ""
End If
End Function

Huisnummer
Function ZoekHuisnummer(Adres As Variant) As Variant
Dim Teller As Byte
Dim AantalTekens As Byte
Dim StartLtstNum As Byte
Dim StartLtstTxt As Byte
Dim VorigTeken As String
Dim Teken As String

If IsNull(Adres) Then
   AantalTekens = 0
Else
   AantalTekens = Len(Adres)
End If

StartLtstNum = 0
StartLtstTxt = 0
VorigTeken = "X"

If AantalTekens > 0 Then
   For Teller = 1 To AantalTekens
      Teken = Mid(Adres, Teller, 1)
      If IsNumeric(Teken) And Not IsNumeric(VorigTeken) Then StartLtstNum = Teller
      If Not IsNumeric(Teken) And IsNumeric(VorigTeken) Then StartLtstTxt = Teller
      VorigTeken = Teken
   Next

   If StartLtstNum > 1 Then
      If StartLtstTxt > StartLtstNum Then
         ZoekHuisnummer = Mid(Adres, StartLtstNum, StartLtstTxt - StartLtstNum)
      Else
         ZoekHuisnummer = Mid(Adres, StartLtstNum)
      End If
   Else
      ZoekHuisnummer = Null
   End If
Else
   ZoekHuisnummer = Null
End If
End Function

Toevoeging huisnummer
Function ZoekToevoegsel(Adres As Variant) As String
Dim Teller As Byte
Dim AantalTekens As Byte
Dim StartLtstNum As Byte
Dim StartLtstTxt As Byte
Dim VorigTeken As String
Dim Teken As String
Dim AW As Integer

If IsNull(Adres) Then
   AantalTekens = 0
Else
   AantalTekens = Len(Adres)
End If

StartLtstNum = 0
StartLtstTxt = 0
VorigTeken = "X"

If AantalTekens > 0 Then
   For Teller = 1 To AantalTekens
      Teken = Mid(Adres, Teller, 1)
      If IsNumeric(Teken) And Not IsNumeric(VorigTeken) Then StartLtstNum = Teller
      If Not IsNumeric(Teken) And IsNumeric(VorigTeken) Then StartLtstTxt = Teller
      VorigTeken = Teken
   Next

   If StartLtstNum > 1 Then
      If StartLtstTxt > StartLtstNum Then
         ZoekToevoegsel = Trim(Mid(Adres, StartLtstTxt))
         AW = Asc(ZoekToevoegsel)
         If AW < 65 Or (AW > 90 And AW < 97) Or AW > 122 Then ZoekToevoegsel = Mid(ZoekToevoegsel, 2)
      Else
         ZoekToevoegsel = ""
      End If
   Else
      ZoekToevoegsel = ""
   End If
Else
   ZoekToevoegsel = ""
End If
End Function