Om bij het begin te beginnen: hier een uitgebreider voorbeeldje.
Code:
For Each ctl In Controls
With ctl
Select Case .ControlType
Case acTextBox
If Left(.Name, 5) = "Tekst" Then
sVeld = .Tag
.Value = Nz(Me(sVeld).Value, "")
End If
On Error GoTo 0
Case acComboBox
If Left(.Name, 10) = "Keuzelijst" Then
sVeld = .Tag
.Value = Me(sVeld).Value
End If
Case acCheckBox
If Left(.Name, 3) = "chk" Then
sVeld = .Tag
.Value = Me(sVeld).Value
Exit For
End If
End Select
End With
Next ctl
Eigenlijk is de procedure voor elk object hetzelfde: je leest de tag uit, en stelt een waarde in. Waarom dan toch verschillende? Dat komt doordat de
naamgeving van de objecten bij elk objecttype anders is. Dat hoeft overigens niet; als je een naamgeving hanteert die voor elk object dezelfde naamstructuur heeft, dan ben je er ook. Krijg je iets als:
Code:
For Each ctl In Controls
With ctl
Select Case .ControlType
Case acTextBox, acComboBox, acCheckBox
If LCase(Left(.Name, 5)) = "nieuw" Then
sVeld = .Tag
.Value = Nz(Me(sVeld).Value, "")
End If
End Select
End With
Next ctl
Het hele principe is gebaseerd op het idee dat je speciale objecten (tekstvakken, keuzelijsten, selectieveldjes) hebt die
alleen uitgelezen moeten worden. De
For Each ctl In Controls regel zorgt ervoor dat
alle objecten op een formulier worden geëvalueerd. Dus ook labels, lijnen, knoppen etc. Die kun je uiteraard niet allemaal gebruiken; een knop
heeft nu eenmaal geen waarde. Je moet dus, als je alle objecten doorloopt, onderscheid maken in welke objecten wél, en welke níet. Dat doe je dus met
ControlType.
Daarnaast is niet elk tekstvak of selectievakje geschikt; je wilt alleen die objecten gebruiken die daarvoor bedoeld zijn. Daarom moet je onderscheid maken in die objecten. Vroeger, toen ik deze techniek nog niet gebruikte, was ik van mening dat een object een logische, verklarende naam moet hebben. In beginsel vind ik dat nog steeds. Om nu onderscheid te maken tussen het oude veld txtAchternaam en het nieuwe tekstveld, geef ik dat laatste dus bijvoorbeeld de naam nieuwAchternaam. En het veld txtAdres kent een broertje met de naam nieuwAdres. De code moet dus, om te weten welk tekstveld wel en welke nieuw, kijken naar de
naam van het object, meer specifiek naar de beginletters ervan. Doe je dat consequent, dan pak je nooit verkeerde velden op en schrijf je dus ook nooit verkeerde velden weg.
Dat lost hopelijk dit probleem op:
Na het tonen van een msgbox waarin staat Tekst350 (naam van een tekstveld waarin ik een expressie heb staan die de "contactpersoon 1 van x" toont) en ik op OK klik, stopt de code met melding:
"Fout 2465 tijdens uitvoering. Kan het veld niet vinden waarnaar wordt verwezen in de expressie".
Standaard krijgen objecten een naam volgens een vast patroon: tekstvakken de naam Teksvak12, Teksvak14, keuzelijsten de naam Keuzelijst89 etc. Als ik een 'normaal' tekstvak, zoals in jouw voorbeeldje, zou dat bij mij zonder meer, en vrijwel gelijk, een naam krijgen als: txtContactPersoon. Een normale keuzelijst geef ik gelijk een naam als cboLand, en ga zo maar door. De belangrijkste reden? Als ik formules ga maken met de functie Opbouwen, dan wil ik niet objecten zien met de namen Teksvak12, Teksvak14 en Tekstvak350, want die zeggen mij helemaal niks. Ik wil snel en foutloos kunnen zien waar dat object voor staat. Dus: altijd een logische naam!
Met dus de uitzondering voor objecten die ik juist wél op basis van standaardnamen wil verwerken, zoals in deze routine. Dat brengt mij bij het laatste stukje van de puzzel: hoe weet ik nu welk veld met welke waarde waar moet worden weggeschreven? Op het formulier is het duidelijk: de velden met de oude en nieuwe waarde staan waarschijnlijk naast of onder elkaar. Makkelijk zat. Maar waar het veld [Achternaam] niet alleen een herkenbare naam heeft, maar ook is gekoppeld aan het
veld [Achternaam], is [Tekstveld16] dat niet. Maar dat bevat dus wél de nieuwe waarde.... En hier komt dus de eigenschap <Extra Info> (of Tag) om de hoek kijken.
Bij het maken van het formulier zet ik dus de origine velden op hun plek, de nieuwe niet-gebonden tekstvelden er naast, en kopieer ik de
Besturingselementbron uit het oorspronkelijke object en plak ik dat in de eigenschap <Extra Info> van het nieuwe tekstveld. En dat herhaal je voor alle velden. Is meestal niet meer dan een half uurtje werk.
Goed, ik heb dus (voorbeeldje) 20 originele velden, en 20 velden voor de nieuwe waarden. Die 20 hebben allemaal een veldnaam in de <Extra Info> staan, en een naam als Tekstvak23. (Of Nieuw01, Nieuw02 etc als je niet lui bent

). Ik heb er voor gezorgd
dat er geen enkel ander tekstveld is waarvan de naam met 'Tekst' begint, want zoals je al gemerkt hebt: die mogen dus niet meedoen in de procedure. Niet alleen bevatten ze niet de juiste informatie (nieuwe waarden voor je tabel), je hebt er vast ook geen <Extra Info> ingevuld. En dat
is verplicht, want anders kan de procedure daar op vastlopen.
Ik hoop dat de procedure zo wat duidelijker is

.
Eén opmerking nog: het uitlezen is voor de meeste objecten identiek, behalve bij
keuzelijsten waar je meerdere waarden kunt selecteren. Die moet je anders uitlezen. Je moet dan namelijk door alle geselecteerde waarden heenlopen en die ofwel samenvoegen in één string, ofwel apart opslaan. Maar dat speelt geloof ik niet nu.