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 ClassEDIT:
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.DisposeSijoita 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 SubLisää 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.