run time error 3709

  • Onderwerp starter Onderwerp starter scw
  • Startdatum Startdatum
Status
Niet open voor verdere reacties.

scw

Gebruiker
Lid geworden
5 jun 2009
Berichten
530
Goedendag,

Ik probeer een label op een formulier een variabele mee te geven, als volgt:

Code:
Dim Con As Object
Dim Rf, Rg As Object
Dim stSql As String

stSql = "SELECT * FROM tblVerantwoordelijke"
Set Rf = CreateObject("ADODB.Recordset")
Rf.Open stSql, Con, 1
stSql = "SELECT [Naam] FROM tblMedewerkers "
stSql = stSql & "WHERE [MedewerkerID] = " & Rf!Verantwoordelijke
Set Rg = CreateObject("ADODB.Recordset")
Rg.Open stSql, Con, 1

Bijschrift68.Caption = "In te vullen door" & Rf!Verantwoordelijke

Rf.Close
Rg.Close

Set Con = Nothing
Set Rf = Nothing
Set Rg = Nothing

Het is de bedoeling dat hij het MedewerkerID (nummer) pakt uit tblVerantwoordelijke en deze vervolgens vertaald in de bijbehorende Naam in tblMedewerkers en dat deze Naam dan in het label komt te staan: In te vullen door [Naam].

Echter, Access geeft een run time error 3709. The connection cannot be used to perform this operation. It is either closed or invalid in this context.

Vervolgens komt de (geel gekleurde) focus op:
Code:
Rf.Open stSql, Con, 1
te staan.

Kan dit veroorzaakt worden doordat ik stSql verder op in de code ook al gebruik?? Zo ja, waar kan ik dit door verplaatsen? Kan ik zoiets als saSql doen of sbSql? Excuses, maar mijn kennis van VB reikt nog niet zo ver...:(
 
Die melding verbaast me inderdaad niet; je opent wel een Recordset, maar doet daar vervolgens niks mee. Je verwacht dat Access het juiste MedewerkerID ophaalt, maar daarvoor zul je dus per record door de geopende Recordset moeten lopen tot je de juiste gevonden hebt. En daar zit een ander probleem: je hebt geen waarde om op te zoeken. Je kunt in je recordset Rf (overigens: waarom als object gedefinieerd, en niet als Recordset? Geldt ook voor Con: waarom niet als Connection?) wel een waarde opzoeken maar die komt (vermoed ik) uit je formulier. Dus je moet eerst door de recordset lopen om de juiste MedewerkerID op te zoeken en in een variabele te zetten, en daarna kun je de recordset sluiten, en de tweede openen. Daar kun je dan dezelfde Recordset voor gebruiken, dus je hoeft er geen twee te definieren...
 
OK duidelijk dat dit niet gaat werken dan. Maar hoe zet ik het dan wel precies neer? Het gaat me namelijk boven de pet :(

In de tblVerantwoordelijke staat de MedewerkerID in het veld Verantwoordelijke overigens.
 
Ik heb een voorbeeldje gemaakt, met een keuzelijst waarin je de Medewerker selecteert. Deze keuzelijst wordt dan gebruikt om een Verantwoordelijke op te halen uit de tabellen:

Code:
Private Sub cboMedewerker_AfterUpdate()
Dim iChef As Integer
strSQL = "Select VerantwoordelijkeID From tbl_Medewerker WHERE Medewerker_ID=" & Me.cboMedewerker.Value
With CurrentDb.OpenRecordset(strSQL)
    If .RecordCount > 0 Then
        iChef = .Fields("VerantwoordelijkeID").Value
        .Close
    End If
End With
strSQL = "Select Naam From tbl_Verantwoordelijke WHERE Verantwoordelijke_ID=" & iChef
With CurrentDb.OpenRecordset(strSQL)
    If .RecordCount > 0 Then
        Me.lblVerantwoordelijke.Caption = .Fields("Naam").Value
        .Close
    End If
End With
End Sub
 
Excuses,

De Verantwoordelijke wordt niet in het desbetreffende formulier geselecteerd, maar deze wordt op een ander formulier 'frmInstellingen' geselecteerd inderdaad dan wel uit een dropdown. Vervolgens wordt deze bijgewerkt in een tabel (tblVerantwoordelijke), waarin slechts 1 record staat met het MedewerkerID dan.
 
Maakt niet zoveel uit, denk ik.... Het was ook maar een voorbeeldje ;)
Als het formulier 'frmInstellingen' geopend is, kun je de code Me.cboMedewerker vervangen door: Forms!frmInstellingen.cboMedewerker.
Of iets dergelijks... De syntaxis kan licht afwijken.
 
Hoi Michel,

Ik heb hem nu zo:

Code:
Dim iChef As Integer
strSQL = "Select VerantwoordelijkeID From tblMedewerkers WHERE MedewerkerID="
With CurrentDb.OpenRecordset(strSQL)
    If .RecordCount > 0 Then
        iChef = .Fields("VerantwoordelijkeID").Value
        .Close
    End If
End With
strSQL = "Select Naam From tblVerantwoordelijke WHERE VerantwoordelijkeID=" & iChef
With CurrentDb.OpenRecordset(strSQL)
    If .RecordCount > 0 Then
        Me.Bijschrift68.Caption = "In te vullen door" & .Fields("Naam").Value
        .Close
    End If
End With

Maar hij blijft een Run-Time error 3075 geven "Syntax error (missing operator) in query expression 'Medewerker ID='. :eek:

Overigens is frmInstellingen nooit geopend als dit formulier geopend is. Het MedewerkerID zou puur uit het veld Verantwoordelijke gehaald moeten worden in de tabel tblVerantwoordelijke...

Is
Code:
 "Select VerantwoordelijkeID From tblMedewerkers WHERE MedewerkerID="
Dan nog goed?

Of moet het zijn:

Code:
 "Select Verantwoordelijke From tblMedewerkers WHERE MedewerkerID="
???

Dank voor alle hulP!! :)
 
Je was ook iets vergeten....

Code:
Dim iChef As Integer
strSQL = "Select VerantwoordelijkeID From tbl_Medewerker WHERE Medewerker_ID=" & Me.cboMedewerker.Value

 
OK maar is die dan echt noodzakelijk... want ik doe namelijk niets met die combobox; het desbetreffende formulier waar de verantwoordelijke wordt ingesteld staat op dat moment nooit open en het ID staat opgeslagen in de tabel :rolleyes:
 
Ik heb je db niet, dus ik weet uiteraard niet hoe je procedure er precies uitziet. Wat ik met mijn voorbeeld probeerde aan te geven is, dat je het gewenste label in twee stappen moet ophalen. Daarvoor gebruik ik dus een keuzelijst op een denkbeeldig formulier. Als je een VerantwoordelijkeID wilt opzoeken in een niet-geopende tabel, moet dat uiteraard via een Recordset, zoals in het voorbeeld. Maar je zult toch een criterium mee moeten geven, want hoe wil je anders één record opzoeken? Kortom: welk gegeven of formulierveld kun je dan wèl gebruiken als criterium?
 
OK (ongeveer) duidelijk voor mij, maar wel nog de volgende vragen:

Maar zelfs als er altijd maar één record in het tabel staat moet je toch altijd nog een criterium meegeven dus? Want de eerste record heet VerantwoordelijkeID 1, welke dus altijd constant blijft. Het volgende tabelveld heet MedewerkerID waar dus het getal staat voor de verantwoordelijke, welke wel kan variëren.

Graag zou ik het gegeven op willen halen in een niet geopende tabel, maar heb je dan écht nog steeds twee stappen nodig om het label te vullen? Zo ja, zou ik een niet-zichtbaar tekstvak kunnen plaatsen op het desbetreffende form en vervolgens het label de naam uit dat tekstvak laten plukken. Maar fraaier is natuurlijk als het meteen direct naar het label kan...

Ik waardeer je hulp, erg bedankt.
 
Nu heb je mij toch weer op het verkeerde been gezet, want ik ga er toch van uit dat je meerdere records hebt om uit te selecteren. Nu zeg je dat er altijd maar één record in je tabel staat.... Waarom dan niet de waarde gelijk ingetypt, of als constante gebruikt?
 
Excuus, excuus... maar ik denk wanneer je goed leest het toch wel duidelijk zou moeten zijn:

Want de eerste record heet VerantwoordelijkeID 1, welke dus altijd constant blijft. Het volgende tabelveld heet MedewerkerID waar dus het getal staat voor de verantwoordelijke, welke wel kan variëren (d.m.v. combobox op frmInstellingen (iets wat ik al gerealiseerd heb).

Dus recapitulatie:

- ik heb een tblMedewerkers: met alle MedewerkersID's erin

- ik heb een tblVerantwoordelijke met:
veld 1) VerantwoordelijkeID erin (er staat altijd één record in de tabel)
veld 2) Verantwoordelijke (hier staat één MedewerkerID in)

- ik heb een apart te openen frmInstellingen met een combobox welke de verantwoordelijke (=MedewerkerID) opslaat in tblVerantwoordelijke. Hier kunnen deze verschillende medewerkers gekozen worden, echter in de praktijk blijft het er maar altijd ééntje. Dus mogelijk ooit... veranderd de verantwoordelijke, en dan heeft de gebruiker een gebruiksvriendelijke mogelijkheid om dat om te zetten in frmInstellingen ;)

- ik heb een aparte form waar ik dus dat label op wil maken, welke nooit tegelijkertijd geopend is met frmInstellingen.



Dus de label moet opzoeken welk nummer in tblVerantwoordelijke staat, bijv. 5. En dan kijken welke naam bij MedewerkerID 5 hoort in tblMedewerkers

:d Hopelijk heb ik het zo duidelijk uit kunnen leggen, zo niet... dan beantwoord ik graag weer, geen probleem.
 
Ik denk toch dat ik het goed heb gelezen:
- ik heb een tblVerantwoordelijke met:
veld 1) VerantwoordelijkeID erin (er staat altijd één record in de tabel)
veld 2) Verantwoordelijke (hier staat één MedewerkerID in)
De oplossing blijft dus nog steeds: open via een Recordset de tabel tblVerantwoordelijke, lees de waarde uit het veld Verantwoordelijke en sla die op in een variable.
Open vervolgens een nieuwe recordset, waarin je de naam van de medewerker opzoekt m.b.v. de variabele die je net hebt gevuld. Redelijk rechttoe-rechtaan, eigenlijk...
Als je een query gebruikt voor het formulier waarop je het label wilt vullen, dan kun je zelfs (als de tblVerantwoordelijke inderdaad maar één record bevat) die tabel toevoegen aan de query en het veld Verantwoordelijke toevoegen aan de query. Het zal dan voor alle records in de dynaset dezelfde naam geven. En dat is prima, want die koppel je dan bij de <Bij Laden> gebeurtenis aan het label. Of nog simpeler: maak er een tekstveld van, en koppel dat aan het veld Verantwoordelijke uit de query. Hoef je volgens mij niks meer te programmeren...
 
Laatst bewerkt:
OK duidelijk:

Graag zou ik de eerste optie willen toepassen (toch voor het programmeren, staat toch iets strakker, zeker ook omdat het formulier al een behoorlijk aantal velden bevat namelijk ook). Maar is jou eerdergenoeme code met recordset dan nog steeds van toepassing, ik bedoel omdat ik die combobox eigenlijk niet toepas op het desbetreffende formulier, maar omdat deze op frmInstellingen staat? Of moet er toch nog iets anders aan deze code om het te laten werken??

Dank!
 
Ik denk dat je via OpenRecordset dus de tabel tblVerantwoordelijke kunt openen, en het veld Verantwoordelijke kunt uitlezen.

Code:
Dim iChef As Integer
strSQL = "Select Verantwoordelijke From tblVerantwoordelijke" 
With CurrentDb.OpenRecordset(strSQL)
    If .RecordCount > 0 Then
        iChef = .Fields("Verantwoordelijke").Value
        .Close
    End If
    Else
        Exit Sub
    End If
End With
strSQL = "Select Naam From tblVerantwoordelijke WHERE VerantwoordelijkeID=" & iChef
With CurrentDb.OpenRecordset(strSQL)
    If .RecordCount > 0 Then
        Me.Bijschrift68.Caption = "In te vullen door" & .Fields("Naam").Value
        .Close
    End If
End With
 
Hoi goedemorgen,

Het lukt nog niet erg: hierbij plaats ik even een voorbeeldje, uiteindelijk misschien toch het handigst. :D

Bedankt en groet scw :thumb:
 

Bijlagen

Bijna goed...
Code:
Private Sub Form_Open(Cancel As Integer)
Dim iChef As Integer
strSQL = "Select Verantwoordelijke From tblVerantwoordelijke"
With CurrentDb.OpenRecordset(strSQL)
    If .RecordCount > 0 Then
        iChef = .Fields("Verantwoordelijke").Value
        .Close
    End If
End With
strSQL = "Select Naam From tblMedewerkers WHERE MedewerkerID=" & iChef
With CurrentDb.OpenRecordset(strSQL)
    If .RecordCount > 0 Then
        Me.Bijschrift68.Caption = "In te vullen door" & .Fields("Naam").Value
        .Close
    End If
End With
End Sub
 
Bedankt!

:D:D:D Jah het werkt, geweldig!!! Eindelijk voor elkaar, wat een gepuzzel.

Heb ik nog een afsluitend vraagje: wanneer ik me.Bijschrift68.SizeToFit doe, geeft Access aan
"The property is only available in design view" Run time error '2187'. Is er wel nog een andere mogelijkheid om het label te 'resizen'? Dit omdat de ene naam langer is dan de andere natuurlijk; is het label te lang staat het niet mooi, is die te kort, dan zie je maar een gedeelte van de naam... Mogelijk weet je dit toevallig, maar in ieder geval erg bedankt voor het oplossen.

Gr scw :thumb:
 
Blijkbaar kun je niet uit de voeten met een vaste lengte voor je label, want dat zou ik toch als eerste gebruiken: het vak groot genoeg maken dat de langste naam er in past.
Je kunt wel iets doen met VBA, door de Caption.Width in te stellen. Dat is niet geheel foutloos, omdat je waarschijnlijk een proportioneel lettertype gebruikt, maar een grove indicatie heb je dan wel.
Wat je moet doen:
1. een Constante declareren voor de gemiddelde letterbreedte (Const Letter =12)
2. de lengte van de Caption van het label in een variable vastleggen met Len(Me.lblMedewerker) (mag toch een fatsoenlijke naam voorstellen, want je komt geheid in de problemen met namen als Bijschrift37... )
3. Op basis van het gevonden aantal tekens vermenigvuldig je het aantal x de Constante Letter. Daar rolt een getal uit.
4. Deze waarde gebruik je om de Caption.Width in te stellen.

Zoals gezegd, het is een grove methode, omdat je met verschillende tekenbreedtes te maken hebt. Kies je voor een Courier als letter, dan is elke letter even breed, en kun je het wel exact instellen.
Met een loopje kun je overigens wel verschillende waarden gebruiken voor elke aparte letter, maar dat is wat meer werk.
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan