Hei.
Olen tässä tekemässä tietovisaa Visual Basicilla ja tarkoituksena olisi, että ohjelma hakisi Access-tietokannasta kysymyksen ja vastausvaihtoehdot ja tulostaisi ne vastauslomakkeeseen, joka sisältää labelin kysymykselle ja neljä painiketta vastausvaihtoehdoille.
Olen yrittänyt etsiskellä tietoa tästä, mutta pääosa ohjeista on suunnattu enemmän tiedon viemiseksi tietokantoihin, joten jos joku osaisi neuvoa, millaisella koodilla tuo onnistuisi niin kiitos.
Moi Ati!
Onko kyseessä VB.NET vai VB-classic (VB ../4/5/6)?
Elikä jatkossa: jos kyseessä on esim. Visual Basic 6.0 niin liitä aiheen otsikkoon (VB6) ja jos kyseessä on Visual Basic 2002 - 2010 -> lähitulevaisuus) niin liitä aiheen otsikkoon (VB.NET) syystä, että tiedetään missä mennään.
Oletan nyt kuitenkin, että puhut Visual Basic versiosta, joka vaatii .NET Framework alustan.
Malli tietokannasta (MSAccess)
Tietokannan nimi: Tietovisakanta Taulut Nimi: Tietovisataulu Tietovisataulun kentät Nimi: kysymys Asetukset: teksti, perusavain (kentän indeksi=0) Nimi: vastaus1 Asetukset: teksti, kentän koko 200 Nimi: vastaus2 Asetukset: teksti, kentän koko 200, arvo tarvitaan Nimi: vastaus3 Asetukset: teksti, kentän koko 200, arvo tarvitaan Nimi: vastaus4 Asetukset: teksti, kentän koko 200, arvo tarvitaan Nimi: oikeavastaus Asetukset: teksti, kentän koko 200, arvo tarvitaan Nimi: indksi Asetukset: luku, pitkä kokonaislukuluku, arvo tarvitaan, indeksoitu (aloita kentän numerointi 0:sta 0, 1, 2 jne...
VB.NET WindowsForms-projekti:
'Huom! väännetty SharpDevelop 4.0 Beta 4:lla '(Visual Basic IDE luo oletuksena pääformin nimellä: Form1) 'Lomakkeelle: '5 Labellia (label1 - label5) '5 Painiketta (button1 - button5) 'button1.Text="Uusi kysymys" 'button2.Text="Vaihtoehto 1" '... 'button5.Text="Vaihtoehto 4" 'Aseta kaikki labellit alekkain ja Button1 niiden alle 'loput Buttonit: button2 label2:den viereen jne... 'Tietokannan tulee sijaita samassa kansiossa, jossa 'projektista luotava .exe -tiedosto sijaitsee... 'Designerin debuggerilla ajettaessa: ..\Bin\Debug\ 'tai jos julkaistu: ..\Bin\Release Imports System.Data Imports System.Data.OleDb Public Partial Class MainForm Private yhteys As OleDbConnection = Nothing Private datasetti As DataSet = Nothing Private kysymys As Integer = -1 Private vastaus As String = String.Empty Private tietueet As Integer = 0 Private kysely As String = String.Empty Public Sub New() Me.InitializeComponent() End Sub Sub MainForm_Load(sender As Object, e As EventArgs) Dim kansioPolku As String = Application.StartupPath Dim tiedostoNimi As String = "Tietovisakanta.mdb" 'tai "Tietovisa.accdb" jos tietokanta on luotu 'Access versiolla 12 (Office 2007) -> lähitulevaisuus Dim kokoPolku As String = kansioPolku + "\" + tiedostoNimi Dim yhteysmerkkijono As String = _ "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" _ + kokoPolku + ";Persist Security Info=False;" 'asetetaan SQL kyselylause palauttamaan taulun tietueiden lukumäärä kysely = _ "SELECT COUNT(*) As [RecordCount] FROM [Tietovisataulu]" yhteys = New OleDbConnection(yhteysmerkkijono) yhteys.Open Dim komento As New OleDbCommand komento.Connection = yhteys komento.CommandText = kysely 'palutetaan SQL kyselyn vastausarvo OleDbCommand- 'objektin ExecuteScalar-Metodilla ja asetetaan samalla 'Integer tyyppiin muutettu arvo muuttujan ’tietueet’ arvoksi tietueet = CType(komento.ExecuteScalar, Integer) yhteys.Close: komento.Dispose End Sub Sub Button1_Click(sender As Object, e As EventArgs) Randomize Dim rndkysymys As Integer 'Jos tietokannasta löytyi tietueita niin 'arvotaan tietueiden määrästä palautetusta 'arvosta satunnaisluku 0 - tietueet If tietueet > 0 Then Do 'pyöritään silmukassa ja arvotaan satunnaislukua rndkysymys = CInt(Int(tietueet * Rnd())) 'jos satunnaisluku ei ole sama, kuin edellisen 'arvonnan palauttama luku niin... If rndkysymys <> kysymys Then 'asetetaan muuttujan 'kysymys' 'arvoksi saatu satunnaisluku... 'ja poistutaan silmukasta kysymys = rndkysymys: Exit Do End If Application.DoEvents: Loop End If 'jos muuttujan kysymys arvo on suurempi kuin -1 '(nyt edellä arvottu satunnaisluku) niin... If kysymys > -1 Then 'asetetaan SQL-kysely palauttamaan tietue, jonka indeksi- 'kentän arvo on sama, kuin kysymys (kysymys nro) kysely = _ "Select * From [Tietovisataulu] Where indeksi=" + Cstr(kysymys) 'luodaan DataSet-objektista uusi ilmentymä ja avataan yhteys datasetti = New DataSet: yhteys.Open 'luodaan uusi ilmentymä OleDbDataAdapter-objektista 'ja asetetaan sen SQL-kyselylauseeksi merkkijonon 'kysely' arvo 'ja yhteydeksi OleDbConnection-ilmentymä 'yhteys Dim adapteri As New OleDbDataAdapter(kysely, yhteys) 'täytetään datasetti-objekti adpterin avulla adapteri.Fill(datasetti,"Tietovisataulu") 'tuhotaan adapteri-objekti adapteri.Dispose 'jos datasettiin palautui kyselyn perusteella tietue... If datasetti.Tables("Tietovisataulu").Rows.Count > 0 Then 'niin laskurisilmukan laskuriarvon perusteella... For i As Integer = 0 To 5 Select Case i 'tapauksessa että laskuriarvo on pienempi, kuin 5 Case Is < 5 'asetetaan Formin.Kontrollin(jonka nimi 'on "lablel" + merkkijonoksi muutettu'laskuriarvo). Tekstiarvoksi datasetin("Titovisataulun") 'datasetin ainoan tietueen (rivin) 'laskuriarvoa vastaavan kentän (sarke) arvo Me.Controls("label" & CStr(i + 1)).Text = _ CType(datasetti.Tables("Tietovisataulu"). _ Rows(0)(i), String) 'ja tapauksessa että laskuriarvo on 5 Case 5 'asetetaan koko tällä lomakkeella 'näkyvän muuttujan 'vastaus' arvoksi 'datasetin ainoan tietueen 5. kentän arvo, 'jonka kentän tulisi sisältää oikea vastaus vastaus = CType(datasetti.Tables( _ "Tietovisataulu").Rows(0)(i), String) End Select Next End if datasetti = Nothing: kysely = String.Empty End If End Sub Sub Button2_Click(sender As Object, e As EventArgs) 'Kutsutaan aliohjelmaa ja välitetään kutsussa 'parametri (tässä tapauksessa ~ "label2") VertaaVastausta(2) End Sub Sub Button3_Click(sender As Object, e As EventArgs) VertaaVastausta(3) End Sub Sub Button4_Click(sender As Object, e As EventArgs) VertaaVastausta(4) End Sub Sub Button5_Click(sender As Object, e As EventArgs) VertaaVastausta(5) End Sub Sub VertaaVastausta(indeksi As Integer) 'jos vain koko tällä lomakkeella näkyvän 'muuttujan 'vastaus' arvo on tyhjä merkkijono niin... If vastaus = String.Empty Then 'poistutaan aliohjelmasta Exit Sub End If 'jos painettiin oikeaa vaihtehtoa niin.. If Me.Controls("label" & _ CStr(indeksi)).Text = vastaus Then 'näytetään viesti-ikunnassa: MsgBox("Oikein vastattu") 'muussa tapauksessa... Else 'näytetään viesti-ikunnassa: MsgBox("Väärin vastattu" & _ "Oikea vastaus on: " & vastaus) End if 'asetetaan muuttujan 'vastaus' tyhjä mekkijono... vastaus = String.Empty 'ja asetetaan silmukassa kunkin labellin 'tekstiarvoksi tyhjä mekkijono... For i As Integer = 1 To 5 Me.Controls("label" & _ CStr(i)).Text = String.Empty Next End Sub Sub MainForm_FormClosing(sender As Object, e As FormClosingEventArgs) yhteys = Nothing Me.Dispose End Sub End Class
EDIT:
yllä olevan esimerkin Button1_Click tapahtuman koodista puuttuu...
adapteri.Dispose: yhteys.Close
onnistuin copy/paste-combinoimaan : yhteys.Close pätkän pois
Kiitos pikaisesta vastauksesta.
VB.NET on tosiaan käytössä, mutta tuon koodipätkän kanssa oli jonkinlaista häiriötä, kun kokeilin sitä Visual Studio 2010, niin kääntäjä ei alkanut suorittamaan sitä, enkä ole vielä ehtinyt kokeilemaan johtuiko se jostain omasta virheestä.
Ja miten tuon koodin saisi muutettua siten, että tarkoituksena olisi, että vastausvaihtoehtojen tekstit tulostuvat painikkeisiin ja vain kysymys labeliin ja aina käyttäjän vastattua oikein, lomakkeelle päivittyisi uusi kysymys ilman msgboxeja.
Kiitos.
Morjens taas Ati!
Aluksi: Jos koodi ei käänny tai toimi, niin on SATAVARMAA, että se johtuu omasta mokastasi...
tässä, kuitenkin ehdotus kaipamaasi muutokseen...uusi kysymys päivittyy automaattisesti vastauksen ja vastaustuloksen jälkeen (en näe järkeä siinä, että voi vastailla kunnes osuu oikeaan)
Luo uusi Windows Forms-projekti (nimeksi esim. TietovisaTesti)
Tarkista. että Solution Explorer-ikkunassa näkyvässä References-kansiossa näkyy teksti
System.Data, jos ei näy niin klikkaa samaisen kansion kuvaketta hiiren 2-näppimellä ja valitse: Add Reference , valitse .NET välilehti, selaa listalta teksti System.Data, tuplaklikkaa tekstiä ja kilkkaa OK-nappia.
Sijoita lomakkeelle Form1 1 label-objketi (label1) ja 4 komentopainiketta (Button1 - Button4).
Tupklikkaa lomaketta design-tilassa niin koodi-ikkunaan ilmestyy lomakkeen Load tapahtumakoodi:
Private Sub Form1_Load(sender As Object, e As EventArgs) … ’sijoita aliohjelman koodi tähän… End Sub
Tuplaklikkaa sitten kutakin painiketta design-tilassa niin koodi-ikkunaan ilmestyy kunkin napin Click tapahtumakoodit:
Private Sub Button1_Click(sender As Object, e As EventArgs) … ‘sijoita aliohjelman koodi tähän… End Sub jne.
Kirjoita sitten koodi-ikkunan alkuun seuraavat Imports-lauseet:
Imports System.Data Imports System.Data.OleDb
Ja kirjoita koodirivin: Public Class Form1 jälkeen seuraavat objektimuuttujien alustukset
Private yhteys As OleDbConnection = Nothing Private kysymys As Integer = -1 Private vastaus As String = String.Empty Private tietueet As Integer = 0 Private kysely As String = String.Empty Public Shared viesti As String = String.Empty
Sijoita sitten seuraava koodi Form1_Load tapahtuman koodiksi
Dim kansioPolku As String = Application.StartupPath Dim tiedostoNimi As String = "Tietovisakanta.mdb" Dim kokoPolku As String = kansioPolku + "\" + tiedostoNimi Dim yhteysmerkkijono As String = _ "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" _ + kokoPolku + ";Persist Security Info=False;" kysely = "SELECT COUNT(*) As [RecordCount] FROM [Tietovisataulu]" yhteys = New OleDbConnection(yhteysmerkkijono) yhteys.Open Dim komento As New OleDbCommand komento.Connection = yhteys komento.CommandText = kysely tietueet = CType(komento.ExecuteScalar, Integer) If tietueet > 0 Then kysely="Select * From [Tietovisataulu] Where indeksi=0" komento = New OleDbCommand komento.Connection = yhteys komento.CommandText = kysely Dim lukija As OleDbDataReader = komento.ExecuteReader If lukija.HasRows Then kysymys = 0 While lukija.Read label1.Text = CType(lukija(0), String) For i As Integer = 1 to 4 Me.Controls("button" & Cstr(i)).Text = CType(lukija(i), String) Next vastaus = CType(lukija(5), String) End While lukija.Close: lukija.Dispose End If End if yhteys.Close: komento.Dispose
Sijoita sitten seuraava koodi jokaisen komentopainikkeen Click tapahtuman koodiksi:
TarkistaVastaus(sender)
Copy/Paskanna sitten alla oleva koodi johonkin kohtaan From1-luokan sisälle
(ei kuitenkaan toisen aliohjelman sisälle)
Private Sub TarkistaVastaus(sender As Object) If CType(sender.Button).Text = vastaus Then viesti = "Vastaus on oikein!" Else viesti = "Vastaus on väärin!" _ & Environment.NewLine _ & "Oikea vastaus on: " & vastaus End If Dim frm2 As New Form2 frm2.ShowDialog frm2.Dispose Randomize Dim rndkysymys As Integer If tietueet > 0 Then Do rndkysymys = CInt(Int(tietueet * Rnd())) If rndkysymys <> kysymys Then kysymys = rndkysymys: Exit Do End If Application.DoEvents: Loop End If If kysymys > -1 Then kysely = "Select * From [Tietovisataulu] Where indeksi=" + Cstr(kysymys) Dim datasetti As New DataSet: yhteys.Open Dim adapteri As New OleDbDataAdapter(kysely, yhteys) adapteri.Fill(datasetti,"Tietovisataulu") adapteri.Dispose: yhteys.Close If datasetti.Tables("Tietovisataulu").Rows.Count > 0 Then label1.Text = datasetti.Tables("Tietovisataulu"). Rows(0)(0), String) For i As Integer = 1 To 4 Me.Controls("button" & CStr()).Text = _ CType(datasetti.Tables("Tietovisataulu").Rows(0)(i), String) Next vastaus = datasetti.Tables("Tietovisataulu"). Rows(0)(5), String) End if datasetti = Nothing: kysely = String.Empty End If En Sub
Lisää sitten projektiin uusi tyhjä lomake (Form2) ja lisää lomakkeelle label-objekti (label1)
avaa Form2 koodi-ikkunaan, siirry designer–tilaan ja tuplaklikkaa lomaketta niin koodi-ikkunaan ilmestyy lomakkeen Load tapahtumakoodi:
Private Sub Form2_Load(sender As Object, e As EventArgs) … ’sijoita aliohjelman koodi tähän… End Sub
Copy/Pastea alla oleva koodi Form2_Load tapahtuman koodiksi…
Me.FormBorderStyle = FormBorderStyle.None Me.BackColor = Color.White Me.Size = New System.Drawing.Size(200, 60) label1.Size = New System.Drawing.Size(200, 60) label1.BorderStyle = BorderStyle.FixedSingle Dim fw As Integer = Me.Width Dim fh As Integer = Me.Height Dim sw As Integer = _ Screen.PrimaryScreen.WorkingArea.Width Dim sh As Integer = _ Screen.PrimaryScreen.WorkingArea.Height Dim lw As Integer = CType((label1.Width / 2), Integer ) Dim lh As Integer = CType((label1.Height / 2),Integer) Me.Left = CType((sw / 2) - (fw / 2), Integer) Me.Top= CType((sh / 2) - (fh / 2), Integer) label1.AutoSize = True: label1.Text = MainForm.viesti label1.Left = CType((fw / 2) - lw, Integer) label1.Top = CType((fh / 2) - lh, Integer) Application.DoEvents System.Threading.Thread.Sleep(2000) Me.Close
Aihe on jo aika vanha, joten et voi enää vastata siihen.