Minulla on tietokannassa Lukuvuosi, Luokka, Oppilas, Poissaoloseuranta ja Paiva taulut. Päälomakkeella on lstluokka, lstoppilas ja oppilasId listat. Päälomakkeella on listassa kaikki luokat, kun klikkaa luokkaa tulevat kyseisen luokan oppilaiden nimet lstOppilas- listaan ja jokaisen oppilaan oppilastunnus lstOppId-listaan. Nyt en saa tallennettua OppilasId:tä Poissaoloseutanta taulukkoon. Ohjelma antaa virheen rivillä: rsPoissa.Fields(1) = lstOppID.Text ja syyksi: tyypit eivät ole yhteensopivia. Muut tiedot tallentuvat Poissaoloseuranta taulukkoon. Tuntien tallennus koodi alla. Missähän vika?
Private Sub cmdTunnit_Click() ' määritellään muuttuja Dim i As Integer ' mennään poissaolotietojen viimeiseen tietueeseen rsPoissa.MoveLast ' käydään läpi kaikki txtPoissa kentät, joissa on merkitty poissaolotunnit For i = 0 To txtLuku - 1 ' jos poissaolotunnit eivät ole tyhjiä, niin lisätään ne poissaoloseuranta ' tietokantaan If txtTunnit(i) <> "" Then ' avataan uusi poissaolo lomake rsPoissa.AddNew rsPoissa.Fields(1) = lstOppID.Text rsPoissa.Fields(2) = DTPicker1.DayOfWeek rsPoissa.Fields(3) = DTPicker1.Value rsPoissa.Fields(4) = txtTunnit(i) rsPoissa.Update End If Next MsgBox "Poissaolotunnit lisätty!" End Sub
Menee vähän arvailuks kun en tiedä mitä tyyppiä mikin on, mutta kokeileppa muuttaa kyseinen virherivi muotoon:
rsPoissa.Fields(1) = Val(lstOppID.Text)
Edit: tekstiä ei voi tallentaa lukumuuttujaan vaan se pitää ensin konvertoida luvuksi Val()-funktiolla.
Muutoksen jälkeen virheilmoitus: Tietuetta ei voi lisätä tai muuttaa, koska tähän tietuseen liittyvän on oltava taulukossa öoppilasö. Taulukossa oppilas ovat kentät: OppilasId, Nimi ja luokkaId ja vastaavasti Poissaoloseuranta taulukossa ovat kentät: SeurantaId, OppilasID, PoissaPaiva, PoissaPVM, PoissaTunnit ja PoissaoloSyy. (Luokka taulukossa: LuokkaId, LuokanNimi,LukuvuosiId ja Lukuvuositaulukossa:LukuvuosiId ja Lukuvuosi)
rsPoissa.Fields(1) = lstOppID.Text
Onko tuo rsPoissa.Fields todellakin indeksoitu ykköseksi vai onko se numero 0? On myös vaikea käsittää, että miksi ID-numero olisi Text-arvolla.. hmm
Kyseessä on Poissaoloseuranta taulukon toinen kenttä, ensimmäinen on rsPoissa.fields(0). ID-numero on tietenkin numero, mutten osannut sitä laittaa...
Mikä kontrolli on tuo rsPoissa?
moduulissa määritelty: Global rsPoissa As ADODB.Recordset
Liisapu kirjoitti:
moduulissa määritelty: Global rsPoissa As ADODB.Recordset
Global? Neverheard... tuskin auttaa mutta korvaa se Public -muuttujalla.
Ja eikös ID-numeron (jossa on varmaan myös perusavain määriteltynä? Siis, jos käytät accessia tietokannan rakentamiseen) ole syytä olla se eka kenttä eli rsPoissa.fields(0).
Mitä muuten yleensä käytät tietokantayhteyden muodostamiseen? ADOa? DAOa? Entä mitä "tietokantaengineä"?
Yhteys ADOlla, koodi alla. Taulukossa Oppilas on OppilasId perusavain ja Poissaolotaulussa on perusavaimena SeurantaId ja viiteavaimena OppilasId.
Public Function avaaYhteys() 'Yhteyden alustaminen kohde = "Poissaolo.mdb" Set cn = New ADODB.Connection 'Jos kantaan ei saada yhteyttä, niin ilmoitetaan siitä käyttäjälle 'provider ominaisuus viittaa OLEDB:n tietokantatyyppiin cn.Provider = "Microsoft.Jet.OLEDB.4.0" 'yhteyden asentaminen cn.ConnectionString = App.Path + "\" + kohde 'avataan yhteys cn.Open End Function
Liisapu kirjoitti:
Yhteys ADOlla, koodi alla. Taulukossa Oppilas on OppilasId perusavain ja Poissaolotaulussa on perusavaimena SeurantaId ja viiteavaimena OppilasId.
Public Function avaaYhteys() 'Yhteyden alustaminen kohde = "Poissaolo.mdb" Set cn = New ADODB.Connection 'Jos kantaan ei saada yhteyttä, niin ilmoitetaan siitä käyttäjälle 'provider ominaisuus viittaa OLEDB:n tietokantatyyppiin cn.Provider = "Microsoft.Jet.OLEDB.4.0" 'yhteyden asentaminen cn.ConnectionString = App.Path + "\" + kohde 'avataan yhteys cn.Open End Function
Miten olisi
Set cn = New ADODB.Connection 'Asettaa cn -metodin uudeksi ADO-tietokantayhteydeksi cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & App.Path & "\TIETOKANNAN NIMI.mdb" cn.Open 'Avataan tietokantayhteys Set JOKU = New ADODB.Recordset 'Asetetaam Tietokanta -metodi uudeksi ADO-recordsetiksi ( JOKU.Open "TIETOKANTATAULUN NIMI TÄHÄN", myYhteys, adOpenKeyset, adLockPessimistic, adCmdTable
Ehkä? Sitten siihen vielä... e h k ä
Liisapu kirjoitti:
Muutoksen jälkeen virheilmoitus: Tietuetta ei voi lisätä tai muuttaa, koska tähän tietuseen liittyvän on oltava taulukossa öoppilasö.
Sinulla on relaatio poissaolo-taulun ja oppilas-taulun välillä ja kyseessä on relaatiovirhe. Lisätessäsi poissaolo tauluun rivin ei vastaavaa oppilasta löydy oppilas-taulusta.
Ongelma syntyy tarkalleen ottaen lisättäessä tekstiä numeeriseen kenttään. Kenttään lisättävä arvo pitää tyypittää tarkalleen sarakkeen tyypiksi: CInt(Tekstiarvo); ja vastaavan tulee löytyä oppilastaulusta.
Syytä olisi varmaan myös ennen lisäämistä tarkistaa arvon olemassaolo ja tyyppi.
Edit: Typoja
Tarkistin kannan ja Poissaoloseuranta taulukossa OppilasId on pitkä kokonaisluku. OppilasId on Oppilas taulukossa perusavain ja laskuri tyyppinen. Millä konvertoidaan testi pitkäksi kokonaisluvuksi? (CInt antaa tyyppivirheen)
öööh... pitääkö teksti siis konvertoina numeroksi? Tarkennas nyt hieman. Ja pitääkö tuo konvertointi tapahtua tietokannassa (Access?) vai ohjelmakoodissa (Visual Basic)?!
Clng(lstOppID.Text)
Ongelma ilmeisesti ratkennut, kun kerran mitään ei kuulu, mutta kiinnitin vain huomiota noihin lstOppilas- ja lstOppId-listoihin.
Jos listat luodaan "käsin", niin nuo kannattaisi yhdistää käyttämällä ListBox:n ItemData-toimintoa. Kun oppilaiden nimet lisätään listaan, niin nimen ItemDataan tallennetaan samalla kyseisen oppilaan oppilasID.
List1.AddItem [Oppilaan nimi] List1.ItemData(.List1.NewIndex) = [OppilasID]
ItemDataan viitataan samalla tavalla mitä itse Listaankin, eli
MsgBox List1.List(i) & ":n ItemData on " & List1.ItemData(i)
Huomioitavaa on, että ItemDataan voi laittaa ainoastaan numeerisia arvoja, eli juuri jotain ID arvoja.
Edit: tyop, toyp, typo...
Aihe on jo aika vanha, joten et voi enää vastata siihen.