Tämä esimerkki luo Access tietokannan suoraan koodista sekä siihen voidaan lisätä uusia tietueita ja päivittää sitä.
Koodissa käytetty ADOa tietojen hallintaan ja ADOX tietokannan luontiin.
Tarvinnee nähtävästi MDAC 2.8 paketin sekä SP5. Koodissa myös käytetty FlexGrid komponenttia.
Formi
'Tekijä: Wizard 2004; FileExists funktio: Antti Laaksonen
'Tämä malli luo tietokannan kahdella taululla joista toisessa on asiakasrekisteritiedot sekä toisessa kaupunkien nimiä.
'Tietokannan perusteet kannattaa olla hallussa jotta ymmärtää toisen taulun idean mallissa.
'Muokkaamalla tätä mallia ja lisäämällä pieniä toimintoja, saadaan yksinkertainen toimiva asiakasrekisteri.
'Malli ei toimi aivan täydellisesti eikä ole "tehokas" ratkaisu, mutta toimii jotenkin ja on suuntaa antava
Dim strConnection As String
Dim tblKaupunki() As String
Dim tblAsiakas() As String
Dim intKaupunkiLkm As Integer
Dim intAsiakasLkm As Integer
Private Sub cmdLisaa_Click()
TarkistaKentat
End Sub
Sub TarkistaKentat()
'Koska tietokanta ei hyväksy kenttiin nolla-arvoja, niin tarkistetaan, että jokaisessa kentässä on jokin tieto.
'Jos hyväksyt tietokannassa nolla-arvoja, niin joudut ottamaan tämän huomioon VB koodissa, koska VB kaatuu aina kun kentässä ei ole mitään arvoa eli null.
'Kierrän tämän ongelma sillä, että vaadin jokaiseen kenttään tässä jonkin arvon.
If txtAsiakasID.Text = "" Then
MsgBox ("Anna asiakasnumero")
txtAsiakasID.SetFocus
GoTo Loppu
ElseIf txtNimi.Text = "" Then
MsgBox ("Anna nimi")
txtNimi.SetFocus
GoTo Loppu
ElseIf txtOsoite.Text = "" Then
MsgBox ("Anna osoite")
txtOsoite.SetFocus
GoTo Loppu
ElseIf txtPonro.Text = "" Then
MsgBox ("Anna postinumero")
txtPonro.SetFocus
GoTo Loppu
ElseIf cboKaupunki.Text = "Valitse kaupunki" Then
MsgBox ("Valitse kaupunki")
cboKaupunki.SetFocus
GoTo Loppu
End If
TallennaAsiakasrekisteri
Loppu:
End Sub
Sub PaivitaAsiakasrekisteri()
Dim strKaupunkiID As Integer
For i = 1 To intKaupunkiLkm
If tblKaupunki(2, i) = cboKaupunki.Text Then
strKaupunkiID = tblKaupunki(1, i)
Exit For
End If
Next i
AvaaYhteys
Set adTietue = myYhteys.Execute("Update Asiakasrekisteri Set nimi = '" & txtNimi.Text & "', osoite = '" & txtOsoite.Text & "', ponro = '" & txtPonro.Text & "', kaupunkiID = '" & strKaupunkiID & "' where AsiakasID = " & txtAsiakasID.Text & "")
SuljeYhteys
MsgBox ("Tiedot päivitetty")
LueTiedot
End Sub
Sub TallennaAsiakasrekisteri()
Dim strKaupunkiID As Integer
For i = 1 To intKaupunkiLkm
If tblKaupunki(2, i) = cboKaupunki.Text Then
strKaupunkiID = tblKaupunki(1, i)
Exit For
End If
Next i
'Avataan tietokantayhteys
AvaaYhteys
Set adTietue = myYhteys.Execute("insert into Asiakasrekisteri values('" & txtAsiakasID.Text & "', '" & txtNimi.Text & "', '" & txtOsoite.Text & "', '" & txtPonro.Text & "', '" & strKaupunkiID & "')")
'Suljetaan tietokantayhteys
SuljeYhteys
MsgBox ("Tiedon lisätty ja tallennettu.")
txtAsiakasID.Text = ""
txtNimi.Text = ""
txtOsoite.Text = ""
txtPonro.Text = ""
cboKaupunki.Text = "Valitse kaupunki"
LueTiedot
End Sub
Sub LataaTiedot()
ReDim tblKaupunki(2, 1)
'Avataan tietokantayhteys
AvaaYhteys
Set adTietue = myYhteys.Execute("select KaupunkiID, Kaupunki from Kaupunki order by Kaupunki")
i = 0
Do While adTietue.EOF = False
i = i + 1
ReDim Preserve tblKaupunki(2, i)
tblKaupunki(1, i) = adTietue("KaupunkiID")
tblKaupunki(2, i) = adTietue("Kaupunki")
cboKaupunki.AddItem adTietue("Kaupunki")
adTietue.MoveNext
Loop
intKaupunkiLkm = i
'Suljetaan tietokantayhteys
SuljeYhteys
End Sub
Sub MuotoileGrid()
'Muotoillaan flexgrid komponenttia sekä asetetaan / jätetään siihen vain otsikkorivi
flexRekisteri.Clear
With flexRekisteri
.TextMatrix(0, 0) = "AsiakasID"
.TextMatrix(0, 1) = "Nimi"
.TextMatrix(0, 2) = "Osoite"
.TextMatrix(0, 3) = "Ponro"
.TextMatrix(0, 4) = "Kaupunki"
.ColWidth(0) = 800
.ColWidth(1) = 2000
.ColWidth(2) = 2000
.ColWidth(3) = 800
.ColWidth(4) = 1500
.CellAlignment = flexAlignLeftBottom
End With
flexRekisteri.Rows = 1
End Sub
Private Sub cmdLueTiedot_Click()
LueTiedot
End Sub
Sub LueTiedot()
MuotoileGrid
Dim intHaku As Integer
Dim strLisaarivi As String
ReDim tblAsiakas(5, 1)
'Avataan tietokantayhteys
AvaaYhteys
Set adTietue = myYhteys.Execute("select AsiakasID, Nimi, Osoite, Ponro, KaupunkiID from Asiakasrekisteri")
'Haetaan asiakasrekisrin tiedot tietokannasta
i = 0
Do While adTietue.EOF = False
i = i + 1
ReDim Preserve tblAsiakas(5, i)
tblAsiakas(1, i) = adTietue("AsiakasID")
tblAsiakas(2, i) = adTietue("Nimi")
tblAsiakas(3, i) = adTietue("Osoite")
tblAsiakas(4, i) = adTietue("Ponro")
tblAsiakas(5, i) = adTietue("KaupunkiID")
adTietue.MoveNext
Loop
intAsiakasLkm = i
'Suljetaan tietokantayhteys
SuljeYhteys
'Koska asiakasrekisterissä on vain kaupungin numero, niin haetaan numeroa vastaava nimi ja vaihdetaan nimi numeron paikalle
For i = 1 To intAsiakasLkm
intHaku = tblAsiakas(5, i)
For j = 1 To intKaupunkiLkm
If tblKaupunki(1, j) = intHaku Then
tblAsiakas(5, i) = tblKaupunki(2, j)
Exit For
End If
Next j
Next i
'Lisätään asiakas taulusta data flexgridiin
For i = 1 To intAsiakasLkm
strLisaarivi = tblAsiakas(1, i) & vbTab & tblAsiakas(2, i) & vbTab & tblAsiakas(3, i) & vbTab & tblAsiakas(4, i) & vbTab & tblAsiakas(5, i)
flexRekisteri.AddItem strLisaarivi
Next i
End Sub
Private Sub cmdLuoTietokanta_Click()
'Testataan onko tietokanta jo olemassa
If FileExists(App.Path & "Malli.mdb") = True Then
MsgBox ("Tietokanta on jo olemassa")
cmdLuoTietokanta.Enabled = False
frmMalli.Enabled = True
GoTo Loppu
Else
'Tietokannan nimi ja sijainti
strConnection = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & App.Path & "\Malli.mdb"
'Luodaan muuttujat
Dim objCat As ADOX.Catalog
Dim objAsiakasrekisteri As New ADOX.Table
Dim objKaupunki As New ADOX.Table
Set objCat = New ADOX.Catalog
objCat.Create strConnection
objCat.ActiveConnection = strConnection
'Määritellään taulut
With objAsiakasrekisteri
.Name = "Asiakasrekisteri"
Set .ParentCatalog = objCat
With .Columns
.Append "AsiakasID", adInteger
.Append "Nimi", adVarWChar, 75
.Append "Osoite", adVarWChar, 75
.Append "Ponro", adVarWChar, 5
.Append "KaupunkiID", adInteger
End With
.Keys.Append "AsiakasID", adKeyPrimary, "AsiakasID"
End With
With objKaupunki
.Name = "Kaupunki"
Set .ParentCatalog = objCat
With .Columns
.Append "KaupunkiID", adInteger
.Append "Kaupunki", adVarWChar, 50
End With
.Keys.Append "KaupunkiID", adKeyPrimary, "KaupunkiID"
End With
'Luodaan taulut
objCat.Tables.Append objAsiakasrekisteri
objCat.Tables.Append objKaupunki
Set objAsiakasrekisteri = Nothing
Set objKaupunki = Nothing
MsgBox ("Tietokanta luotu onnistuneesti.")
'Lisätään data. Ennen datan lisäystä kannattaa olla pieni tauko, koska kone tarvitsee hieman aikaa luodakseen tietokannan levylle.
'Jos alat liian nopeasti lisäämään dataa tietokantaan, niin osa datasta ei mene tietokantaan.
'Käytän tässä vain yksinkertaista msgbox johon käyttäjä joutuu reagoimaan ja kone kerkiää luomaan tietokannan.
LisaaData
MsgBox ("Data lisätty onnistuneesti.")
'Ladataan kaupunkien tiedot tietokannasta Comboboxiin
LataaTiedot
frmMalli.Enabled = True
cmdLueTiedot.Enabled = True
cmdLuoTietokanta.Enabled = False
End If
Loppu:
End Sub
Sub LisaaData()
'Avataan tietokantayhteys
AvaaYhteys
Set adTietue = myYhteys.Execute("insert into Kaupunki Values('1', 'Lappeenranta')")
Set adTietue = myYhteys.Execute("insert into Kaupunki Values('2', 'Helsinki')")
'Suljetaan tietokantayhteys
SuljeYhteys
End Sub
Private Sub cmdPaivita_Click()
PaivitaAsiakasrekisteri
End Sub
Private Sub cmdUusi_Click()
cmdPaivita.Enabled = False
cmdLisaa.Enabled = True
'Avataan tietokantayhteys
AvaaYhteys
Set adTietue = myYhteys.Execute("select max(asiakasID) as SuurinAsiakasID from asiakasrekisteri")
txtAsiakasID.Text = adTietue("SuurinAsiakasID") + 1
'Suljetaan tietokantayhteys
SuljeYhteys
txtNimi.Text = ""
txtOsoite.Text = ""
txtPonro.Text = ""
cboKaupunki.Text = "Valitse kaupunki"
End Sub
Private Sub flexRekisteri_DblClick()
If flexRekisteri.Text = "AsiakasID" Then
GoTo Loppu
Else
For i = 1 To intAsiakasLkm
If tblAsiakas(1, i) = flexRekisteri.Text Then
txtAsiakasID.Text = tblAsiakas(1, i)
txtNimi.Text = tblAsiakas(2, i)
txtOsoite.Text = tblAsiakas(3, i)
txtPonro.Text = tblAsiakas(4, i)
cboKaupunki.Text = tblAsiakas(5, i)
Exit For
End If
Next i
End If
cmdLisaa.Enabled = False
cmdPaivita.Enabled = True
cmdUusi.Enabled = True
Loppu:
End Sub
Private Sub Form_Load()
'Testataan onko tietokanta jo olemassa
If FileExists(App.Path & "\Malli.mdb") = True Then
frmMalli.Enabled = True
cmdLuoTietokanta.Enabled = False
LataaTiedot
Else
frmMalli.Enabled = False
cmdLueTiedot.Enabled = False
End If
MuotoileGrid
cmdLisaa.Enabled = False
cmdUusi.Enabled = True
cmdPaivita.Enabled = False
End Sub
Private Sub mnuSulje_Click()
Unload Me
End SubModuli
Public myYhteys As ADODB.Connection
Function FileExists(nimi As String) As Boolean
If Dir(nimi) = "" Then
FileExists = False
Else
FileExists = True
End If
End Function
Sub AvaaYhteys()
Set myYhteys = New ADODB.Connection
myYhteys.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & App.Path & "\Malli.mdb;"
'Avataan tietokantayhteys
myYhteys.Open
End Sub
Sub SuljeYhteys()
'Suljetaan tietokantayhteys
myYhteys.Close
End SubHyvä, että tämmöistä saatiin tänne päin! Tarvitsen joitain kohtia tästä omassa ohjelmassani, kiitos siitä Wizardille :P. Kun tuo normaali ADO-komponentin kautta käsiteltävä tietokanta on perseestä, se bugaa jotenki, eikä aina ees tallennaa tietoja, vinee kaikesta jne.
Hyvä esimerkki kaikinpuolin!
Jos halutaan käyttää RecordSettiä, niin koodin moduli osaan pitää lisätä myYhteys.ConnectionString rivin jälkeen seuraavanlainen rivi:
myYhteys.CursorLocation = adUseClient
Sen jälkeen pystyy itse koodissa kirjoittamaan seuraavan rivin:
set adTietue = New ADODB.Recordset
Ja sitten vain kyselyrivin perään kursorin tyyppi esim.
set adTietue = myYhteys.execute("select_kysely", adLockOptimistic)
Tosin en itse käytä cursoria, koska en ole tarvinnut sitä. ADOssa vaihtoehtoisesti monesti käytetty .AddNew ja .Update pystyy korvaamaan tuolla .execute("insert...") tai .execute("update...") käskyillä. Jälkimmäiset ovat myös luotettavampia, koska uuden rivin lisääminen ensin ja datan tallentaminen sitten joskus eivät ole kovin soveliaita tapoja jos tietokantaa käyttää useampi kuin yksi henkilö tai useampi sovellus samaan aikaan. Eli mitä lyhyemmän aikaa pidät tietokantaa varattuna ja yhteyksiä auki, niin sitä parempi.
Mitäs tähän pitää lisätä jos halutaan tuoda vain esim Turkulaiset. Entäs, jos halutaan vain kaupunki ja nimi. Voiko nämä antaa SQL:llä ja/tai ComboBox:lla??
'Haetaan asiakasrekisrin tiedot tietokannasta
i = 0
Do While adTietue.EOF = False
i = i + 1
ReDim Preserve tblAsiakas(5, i)
tblAsiakas(1, i) = adTietue("AsiakasID")
tblAsiakas(2, i) = adTietue("Nimi")
tblAsiakas(3, i) = adTietue("Osoite")
tblAsiakas(4, i) = adTietue("Ponro")
tblAsiakas(5, i) = adTietue("KaupunkiID")
adTietue.MoveNext
Loop
intAsiakasLkm = iLisäämällä Etsi -tekstikentän tai sitten Combobox. Sitten yksi button joka etsii haetuilla arvoilla tietokannasta tulosjoukon ja tulostaa sen ruudulle. Comboboxilla saadaan esim. oikeinkirjoitettu kaupungin nimi jolloin SQL kyselyssä voidaan käyttää = operaattoria. Mutta jos haetaan merkkijonolla, niin kannattaa käyttää SQL kyselyssä like '%haettava_merkkijono%' muotoa.
Jos SQL ei ole hallussa, niin tässä esimerkki turkulaisista Virtasista SQL kyselynä:
select AsiakasID, Nimi, Osoite, Ponro, KaupunkiID from Asiakasrekisteri where kaupunkiID = 'Turku' and nimi like '%virtanen%'
Itse käytän hakusysteemeissä sekä Comboa että tekstikenttää. Comboon vain pitää lomakkeen latauksen yhteydessä ladata kaikki mahdolliset arvot.
Kiitokset SQL-mallista, sain edes vähän haltuun.
Ajattelin käyttää DataComboja, mutta avittaisitko vielä, miten sen arvo tuodaan tuohon SQL-lauseeseen.
Aihe on jo aika vanha, joten et voi enää vastata siihen.