Gegevens uit query halen na input in formulier

Status
Niet open voor verdere reacties.

stimmy

Gebruiker
Lid geworden
8 nov 2016
Berichten
33
Voor een uitgebreide database wil in de gebruikers in een formulier gegevens laten invullen. Om mijn vraag te illustreren heb ik hierbij een fictieve database gevoegd.

Gebruikers zullen in formulier "Orders België" een nieuw record beginnen met het invullen van een klantnummer (niet via keuzelijst). Naam, straat en gemeente moeten dan opgehaald worden uit Query "België" en deze gegevens worden dan weggeschreven in tabel "Orders België". Deze velden mogen echter niet gekoppeld zijn aan de gegevens uit de Query (of bijhorende tabel), dus als deze wijzigen mag er in tabel "Orders België" niets wijzigen.

Alvast bedankt voor jullie hulp.

https://1drv.ms/u/s!AoAjO5lMk3N8gXaeMqZ6T0PZTnqZ
 
Gebruikers zullen in formulier "Orders België" een nieuw record beginnen met het invullen van een klantnummer (niet via keuzelijst). Naam, straat en gemeente moeten dan opgehaald worden uit Query "België"
Ik snap je opzet niet, en eigenlijk ook je probleem niet. Om te beginnen: waarom gebruik je geen keuzelijst? En waarom sla je in [Orders België] de complete adresgegevens op en niet alleen het KlantID? Nu krijg je nodeloze dataredundantie.
 
In de eigenlijke database heb ik zo'n 20000 motoren met elk een ID-nummer waarvan ik kenmerken heb (+/-40 kolommen) die automatisch worden opgehaald uit een andere database. Voor deze motoren worden reparatieverslagen gemaakt. Gebruiker heeft bij begin opmaak verslag dan het ID-nummer (aangezien hij het dan al heeft vind ik het makkelijker om dit zo in te geven dan om te werken met keuzelijst). Op basis van ID-nummer worden dan een 40-tal kenmerken opgehaald en op het verslag gezet (en later wordt dan een rapport hiervan afgedrukt). Die verslagen mogen later niet wijzigen mochten er kenmerken gewijzigd zijn (vandaar wil ik ze ophalen uit de query en in een tabel wegschrijven).

In mij voorbeeldfile wil ik dus dat adresgegevens opgehaald worden en in tabel orders worden weggeschreven. Als een adres dan wijzigt, gebeurt dit niet op het originele order.
 
Maar sowieso haal je de gegevens uit je klantentabel... Ik zie nog steeds de noodzaak niet van de redundantie. Als een klant een reparatie laat doen, wil je sowieso de actuele gegevens weten. En met een keuzelijst, waar je ze inzet, kun je ze simpel op je formulier laten zien. Mij lijkt het nauwelijks zinvol om van een klant of een apparaat alle details elke keer opnieuw op te slaan. Dat heeft m.i. alleen zin voor gegevens die van belang zijn voor de transactie. Dus als je een bestelling plaatst voor een specifiek artikel, dan is het artikelID belangrijk (want dat bestel je) maar de artikelnaam niet, de kleur ook niet, maar de artikelprijs weer wel. Dus dan sla je alleen de ArtikelID en de ArtikelPrijs op.
Dat je 40 velden ophaalt uit een tabel, en die op het formulier zet, is dus makkelijk te doen, maar die ga je echt niet alle 40 muteren. Niet voor je reparatieverslag.

Maar goed, het kán natuurlijk allemaal wel. Op twee manieren:
1. vanuit een keuzelijst waar alle velden inzitten die je op het formulier wilt zien. Je vult de tekstvakken dan vanuit de keuzelijst.
Gebruiker heeft bij begin opmaak verslag dan het ID-nummer (aangezien hij het dan al heeft vind ik het makkelijker om dit zo in te geven dan om te werken met keuzelijst).
Kijk, dat snap ik dus niet helemaal: ergens moet de gebruiker op één of ander moment een motor kiezen. Dus waarom niet vanuit je reparatieformulier met die keuzelijst? Dan vul je daarna vanuit die keuzelijst de overige 40 tekstvakken.

2. Met een recordset. Je opent blijkbaar dus een formulier waar het ID al in staat. Dan kun je een recordset maken die op basis van het ID de overige velden uitleest, en je formulier vult.
 
Keuzelijst is inderdaad mogelijk, maar leek me niet zo handig als dit om 20000 records gaat (terwijl ID op motor zelf staat en ze dit dus gewoon kunnen ingeven - slechts 5 digits). Begin is dus een leeg formulier (=nieuw record) waarin ze dat motor ID moeten ingeven en waarvan dan de gegevens moeten gekopieerd worden. Een heel aantal van de kenmerken wijzigen wel eens, maar op het reparatieverslag wil ik dus de kenmerken zien van op het moment dat het verslag gemaakt werd.
 
Als je de keus hebt tussen een tekstvak waarin je altijd alle karakters moet typen, of een keuzelijst waarin je ook alle karakters mag typen, maar er waarschijnlijk minder nodig hebt, dan is de keuze toch niet zo moeilijk? Bovendien vul je vanuit de keuzelijst in één keer de rest van je formulier.
 
Inderdaad, je hebt me overtuigd. Keuzelijst met invoervak is wat ik nodig heb. Ik zal dan een routine moeten gebruiken bij "after update" van dit veld om de andere velden op te vullen vanuit de tabel met kenmerken. Suggesties om dit slim aan te pakken?

Alvast bedankt!
 
Persoonlijk gebruik ik de <Bij klikken> gebeurtenis, want dan trigger je de actie gelijk. Omdat je de overige velden wilt kunnen muteren, moet je ze koppelen aan je tabelvelden. Het vullen doe je dan met iets als:
Code:
For i = 1 to Me.cboMotor.Columns.Count -1
     Me("Tekstveld" & i).Value = Me.cboMotor.Columns(i)
End IF
Enigszins dummy code uiteraard, maar het idee is dat alle tekstvelden de naam Tekstveld# krijgen zodat elke kolom in de keuzelijst wordt gezet in het overeenkomende tekstveld. Zou moeten werken!
 
Mijn idee was om in de keuzelijst enkel de motor-ID te laten zien en dat na selectie dan de velden op het formulier werden ingevuld. Ik hoopte dat het zou werken met dit:

Private Sub MotorID_AfterUpdate()
Me!Equipment = DLookup("[Equipment]", "Q_Eq_27020101", "[Serienummer]=" & Me!MotorID)
End Sub

veld Equipment op formulier zou dan moeten gevuld worden met waarde in kolom Equipment van de query met motorgegevens, waarbij het geselecteerde MotorID daar overeenkomt met waarde in kolom Serienummer.

Helaas krijg ik dan steeds "fout 3464 tijdens uitvoering" met melding "gegevenstypen komen niet overeen in criteriumexpressie (ook al gaat het overal om velden ven type "korte tekst").
 
Dat is zo'n beetje de slechts denkbare optie, omdat DLookup veruit de traagste functie is binnen Access. Nou ja, hij is in goed gezelschap: alle Dfuncties zijn traag. En aangezien je 40 velden wilt vullen, ga je dat dus echt wel merken. Het zou overigens wel moeten werken (toch voor de AfterUpdate gekozen? Waarom?) al geef je aan dat je met tekstwaarden werkt, en dan moet het er dus toch anders uit zien. Zo namelijk:
Code:
Private Sub MotorID_Click()
     With Me
          .Equipment = DLookup("[Equipment]", "Q_Eq_27020101", "[Serienummer]= """ & .MotorID & """")
          .Color = DLookup("[Colour]", "Q_Eq_27020101", "[Serienummer]= """ & .MotorID & """")
          .Height = DLookup("[Height]", "Q_Eq_27020101", "[Serienummer]= """ & .MotorID & """")
          .Weight = DLookup("[Weight]", "Q_Eq_27020101", "[Serienummer]= """ & .MotorID & """")
     End With 
End Sub
Het voordeel van mijn constructie is dus dat je met 'anonieme' tekstvelden kunt werken; je pakt een standaard tekstveld, past het nummer aan zodat je een correct oplopende serie krijgt, en met een lus vul je alle tekstvelden vanuit de keuzelijst. Snel, foutloos. En het is dus meet- en merkbaar sneller.
In deze code heb je dus alle velden in die je wilt zien op je formulier in de keuzelijst staan. Je hoeft ze uiteraard niet te zien, dus bij de opmaak van de keuzelijst maak je de breedte van die velden ocm. De eerste kolommen maak je dan wel zichtbaar. Je typt dan iets als: 3;4;0;0;0;0;0;0;0;0;0 etc. in bij Kolombreedten. Uiteraard stel je ook het Aantal kolommen in op de juiste waarde. Nu heb je dus een normale keuzelijst, met alle info er in. en die lees je dan zo uit
Code:
Private Sub MotorID_Click()
     For i = 1 to Me.cboMotor.Columns.Count -1
          Me("Tekst" & i).Value = Me.cboMotor.Columns(i)
     End IF
End Sub
 
Dit is in elk geval nieuw voor mij... voorlopig geraak ik er nog niet uit. Als de naam van mijn combobox "cboMotor" is veronderstel ik dat ik dus "Me.cboMotor" moet gebruiken. Ik heb nu in combox met 2 kolommen en 1 formulier met de combobox en 1 tekstveld.

Ik heb het geprobeerd met de code hieronder, maar ik krijg een compileerfout waarbij ".Columns" wordt aangeduid(kan de methode of het gegevenslid niet vinden)

Private Sub MotorID_Click()
For i = 1 To Me.cboMotor.Columns.Count - 1
Me("Tekst" & i).Value = Me.cboMotor.Columns(i)
End If
 
Laatst bewerkt:
Klein foutje mijnerzijds. Dat krijg je als je dingen uit je hoofd doet, maar goed, ik noemde het niet voor niets 'dummy' code. Wist alleen niet dat de dummy ondergetekende was :).
Code:
Private Sub MotorID_Click()
     For i = 1 To Me.cboMotor.ColumnCount-1
          Me("Tekst" & i).Value = Me.cboMotor.Columns(i)
     End If
End Sub
Nog even een kleine toelichting op de code: ColumnCount geeft het juiste aantal kolommen weer, dus als je 5 kolommen hebt, komt daar '5' uit. Je zou zeggen: maak een loop van 1-5 en je hebt alle velden te pakken. Nee dus. De opdracht Me.cboMotor.Columns begint namelijk niet bij 1, maar bij 0. Dus de reeks langs alle kolommen loopt van 0-4. Daarom moet je de loop met de waarde 1 verlagen. Waarom dan toch met 1 beginnen? De eerste kolom is doorgaans de gebonden kolom, en die zie je al in de keuzelijst. Dus die hoeft niet ook nog eens naar een tekstveld. Dat mag natuurlijk wel, maar dan moet je daar met je velden rekening mee houden.
 
Status
Niet open voor verdere reacties.
Steun Ons

Nieuwste berichten

Terug
Bovenaan Onderaan