Ongelmani on se, että ohjelmani hävittää käynnistyksessä vähän väliä oletusasetukset. Kun pitäisi sijoittaa tekstikenttään esimerkiksi lämpötilaksi 22, silloin tällöin siihen ilmaantuu tyyliin "102011356". Eräät kolme single-muuttujaa latautuvat usein nollina. Missä on vika?
Olen tallentanut kaiken "tiedot"-nimiseen luokkaan esim. näin:
'OK-nappia painettaessa tiedot.Aikavali = Int(aikatext.text) Call AloitusForm.TallenaTiedostoon
Ohjelman käynnistyessä tekstikentät täytetään vastaavalla tavalla, esim. aikatext.text = tiedot.Aikavali. Tiedot tallennetaan seuraavanlaiseen luokkaan, joka on globaalisti käytettävissä moduulissa:
Type Tallennustiedot Aikavali as Integer Raakadata(27,27,5) As Double Temp As Single Raja1 As Single Raja2 As Single 'jne. End Type Public tiedot As Tallennustiedot
Oletusasetukset haetaan binääritiedostosta alustukset.dat seuraavalla koodilla:
Public Sub HaeTiedotTiedostosta() Dim nAvaus As Integer nAvaus = FreeFile 'avataan Open App.path & "\alustukset.dat" For Binary As #nAvaus 'sama luokka "tiedot" sisältää kaiken datan Get #nAvaus, , tiedot Close #nAvaus End sub
Tallennus taas menee vastaavasti:
Public Sub TallennaTiedostoon() Dim nAvaus As Integer nAvaus = FreeFile 'avataan Open App.path & "\alustukset.dat" For Binary As #nAvaus 'sama luokka "tiedot" sisältää kaiken datan Put #nAvaus, , tiedot 'suljetaan Close #nAvaus End sub
Moi taas kisahalo!
Aluksi, olet pukannut kaman 'tiedot' nimiseen muuttujaan, joka on ilmentymä oliosta, jonka olet nimennyt nimellä 'Tallennustiedot'.
Nyt on niin, että kun pukkaat uutta kamaa binaaritiedostoon niin tiedostoa ei luoda enää uudestaan vaan se kirjoitetaan vanhan tiedon päälle alkaen tiedoston alusta jos kohdistinta ei erikseen siirretä osoittamaan esim. tiedoston loppua. Nyt jos dataputki on pidempi, kuin edellisellä kerralla, esim. joku luku on vaikkapa 1000 ja oli edellisellä tallennuskerralla 100 ja muu tallennettava tieto on pysyy ennallaan niin tiedoston pituus kasvaa hieman verrattuna edelliseen tallennuskertaan. Mutta jos jutska onkin toisin päin eli luku oli edellisellä kerralla 1000 ja nyt 100 niin tiedoston pituus ei lyhene.
Tämä on helppo ratkaista siten , että tuhoaa vanhan tiedoston ennen uuden tallentamista.
Toinen jutska joka auttaa on, että käyttää datan erotteluun jotain erotinmerkkiä/merkkijonoa jolloin se on kätevästi splitattavissa taulukkoon eikä 'kenttien' merkkimäärien muutoksilla ole enää mitään vaikutusta.
Lopuksi, jätä FreeFile-funktion käyttö ja käytä määrittelyyn yksinkertaista: As #1 määrittelyä...
Kiitos vastauksesta, Nea. Miten minun pitäisi tuo tallennus tehdä, jotta se tuhoaisi edellisen tiedon (vaikka tiedostonkin) kokonaan ja kirjoittaisi uuden? Olisiko jokin muu tallennusmuoto parempi? Pahoitteluni että olen nyyppä tässä.
Minulle on joka tapauksessa tärkeintä, että voin tallettaa tiedot tuollaisena oliona, ettei tarvitsisi 3-ulotteisten matriisien dataa parsea tekstitiedostosta.
Toiseksi tuo FreeFile tuli käyttöön siksi, että ohjelma valitti toistuvasti, että käytetty numero on käytössä, vaikka mielestäni olin sulkenut sen. Onko FreeFilessa jotain pahaa? Ajattelin, että se kävisi hyvin kun kerran tiedosto avataan ja suljetaan samassa aliohjelmassa.
Moi taas kisahalo!
esim näin...
Private Type AsetusTiedot asetus() As Variant End Type Private asetukset As AsetusTiedot Private Sub Form_Load() If Dir("C:\polku\asetukset.dat") <> "" Then Dim fileContent As Variant, i As Integer Dim fileData() As String Open "C:\polku\asetukset.dat" For Binary Access Read As #1 Get #1, , fileContent: Close #1 fileData = Split(fileContent, "|"): Close #1 Redim asetukset.asetus(UBound(fileData)) For i = 0 To UBound(fileData) asetukset.asetus(i) = fileData(i) End Select Next i End If End Sub Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) If Dir("C:\polku\asetukset.dat") <> "" Then Kill("C:\polku\asetukset.dat") End If Dim fileData As Variant, i As Integer For i = 0 To UBound(asetukset.asetus) fileData = fileData & asetukset.asetus(i) If i < UBound(asetukset.asetus) Then fileData = fileData & "|" End If Next i Open "C:\polku\asetukset.dat" For Binary Access Write As #1 Put #1, , fileData: Close #1 End Sub
Moi taas kisahalo!
tutki myös oheista esimerkkiä...
Private Type AsetusTiedot asetus As Variant End Type Private asetukset(2) As AsetusTiedot Private kokoPolku As String Private table(1, 1, 1) Private Sub Form_Load() kokoPolku = Environ("userprofile") & "\Työpöytä\asetukset.dat" If Dir(kokoPolku) <> "" Then Open kokoPolku For Binary Access Read As #1 Get #1, , asetukset: Close #1 MsgBox asetukset(0).asetus(1, 0, 0) MsgBox asetukset(1).asetus MsgBox asetukset(2).asetus End If table(0, 0, 0) = 1 table(0, 0, 1) = 2 table(0, 1, 0) = 3 table(0, 1, 1) = 4 table(1, 0, 0) = 5 table(1, 0, 1) = 6 table(1, 1, 0) = 7 table(1, 1, 1) = 8 End Sub Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) If Dir(kokoPolku) <> "" Then Kill kokoPolku End If asetukset(0).asetus = table asetukset(1).asetus = 1000000000# asetukset(2).asetus = 100.01! Open kokoPolku For Binary Access Write As #1 Put #1, , asetukset: Close #1 End Sub
Terve taas Nea. Katsotaan ymmärsinkö oikein jälkimmäisen esimerkin:
Ilmeisesti teet luokan, jonka ominaisuuksiin voi lisätä mitä vain. Sitten teet taulukkotyyppisen muuttujan juuri luodusta luokasta, ja lisäät muuttujaan uusia ominaisuuksia taulukon soluina. Mutta onko tuossa jokin etu siihen nähden, että lisäisi vain ominaisuuksia itse luokkaan?
Edellistä esimerkkiä en oikein ymmärrä. Onko kyseessä juuri jonkinlainen tekstin parseminen? Ilmeisesti talletat tiedot pitkänä merkkijonona, jossa erottimena on "|" ja sitten luet ne avattaessa samalla tavalla. En oikein näe, mitä matriisit tykkää tuollaisesta. :)
Kokeilin jälkimmäistä, se ei toimi. Ongelma on tuossa matriisien siirtelyssä, tulee vain "can't assign to array". Pitää kokeilla seuraavaksi edellistä esimerkkiä.
Äh, ongelma muuntui nyt täysin toiseksi:
Jälkimmäinen esimerkkisi näyttää toimivalta, mutta ongelmia tulee Variant-muuttujan kanssa. Logiikkani on seuraava: yritän säilyttää määrittelemäni Tiedot-olion ennallaan siksi, että dataa on niin paljon, että sen säilöminen pelkkiin asetukset()-taulukon indekseihin aiheuttaisi harmaita hiuksia. Siksi ajattelin käyttää asetukset()-taulukkoa tallennukseen ja siirtää dataa Tiedot-olion ja sen välillä. Esimerkki:
Public Sub Tallennatiedostoon() '(tiedoston avaaminen jne.) 'sijoitetaan taulukko asetukset(0).asetus = Tiedot.Isodoosiarvot 'sijoitetaan integer asetukset(1).asetus = Tiedot.Raja1 'jne End Sub Public Sub HaeTiedotTiedostosta() '(tiedoston avaaminen jne.) Tiedot.Isodoosiarvot = asetukset(0).asetus End Sub
Nyt ongelmaksi tulee se, että Tiedot.Isodoosiarvot on Double, eli sijoitus ei onnistu. Pitäisi ilmeisesti sijoittaa yksi kerrallaan kaikki arvot tai muuttaa Isodoosiarvot Variant-tyypiksi. Kun yritän muuttaa Variantiksi, kääntäjä valittaa, että moduuliin määritellyn olion koko on yli 64K. :/
Kysymys kuuluu: onko tähän olemassa jonkinlaista fiksua ratkaisua, vai pitääkö minun vaihtoehtoisesti A) siirrellä matriisitiedot yksi kerrallaan tai B) vain hyväksyä tuo asetukset()-taulukon indekseihin tallettaminen?
Moi taas kisahalo!
kisahalo kirjoitti:
...Ilmeisesti teet luokan, jonka ominaisuuksiin voi lisätä mitä vain...
En oikein käsitä tarvettasi inttää jostain luokan luomisesta, kun sellaista ei missään vaiheessa luoda. Type-määritteellä alustetaan olio, joka voi sisältää vain muuttujia tai toisia olioita (jotka voivat sisältää vain muuttujia tai jne.). Luokka taas voi sisältää mm. aliohjelmia (sub programs), funktioita (functions), ominaisuuksia (properties), ja esim em. oliorakenteita (structures) jne.
Ja jotta kaikki menisi vieläkin epäselvemmäksi niin...olion jäsenen arvoiksi voidaan sijoittaa objektiviittaus luokkaan. Mikäli sijoitat objektiviittauksen olioon niin VB6 ei suostu tallentaamaan oliotasi binaaritiedostoon.
mutta kaikessa yksinkertaisuudessaan jutska menee näin...
'Module1 Private Type AsetusTiedot taulu(10, 10, 5) As Double 'esim. int1 As Integer 'esim. sng1 As Single 'esim. 'jne. End Type Public asetukset As AsetusTiedot
'Form1 Private tiedostopolku As String Private Sub Form_Load() 'Ladattaessa ohjelman päälomaketta: 'asetetaan merkkijonomuuttujan arvoksi tiedostopolku tiedostopolku = "c:\asetukset.dat" 'tutkitaan ehtolauserakenteessa lytykö määritetyn 'tiedostopolun takaa määritetty tiedosto... If Dir(tiedostopolku) <> "" Then 'ja jos löytyy niin avataan ko. tiedosto 'lukuoikeuksin, luetaan tiedoston data 'oliomuuttujan arvo(i)ksi ja suljetaan tiedosto. Open tiedostopolku For Binary Access Read As #1 Get #1, , asetukset: Close #1 'tähän koodia jolla haet arvoja oliomuuttujasta 'ja sijoittelet haluamiesi muuttujien arvoiksi... End If End Sub Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) 'Ohjelman päälomaketta suljettaessa: 'jos määritetyn tiedostopolun päästä 'löytyy polussa määritetty tiedosto niin... If Dir(tiedostopolku) <> "" Then 'tapetaan ko. tiedosto! Kill tiedostopolku End If 'luodaan uusi binaaritiedosto merkkijonomuuttujassa 'tiedostopolku' määritettyyn hakemistoon samaisessa 'muuttujassa määritetyllä tiedostonimellä... Open tiedostopolku For Binary Access Write As #1 'ja kirjoitetaan 'tämänhetkiset' asetukset 'nyt luotuun tiedostoon ja suljetaan tiedosto. Put #1, , asetukset: Close #1 End Sub
"vähän lisävalaistusta..?"
Private Type OlioTyyppi kama As Variant nimi As String End Type Private oliot() As OlioTyyppi Private arvotosi As Boolean Private luotu As Boolean Private Sub Command1_Click() If arvotosi Then Exit Sub Dim Bytes() As Byte Open "c:\windows\system32\notepad.exe" _ For Binary Access Read As #1 Get #1, , Bytes: Close #1 Dim ub As Integer On Error Resume Next ub = UBound(oliot) If Err <> 0 Then Err.Clear On Error GoTo o ReDim oliot(0) Else ReDim Preserve oliot(UBound(oliot) + 1) End If oliot(UBound(oliot)).kama = Bytes: Erase Bytes oliot(UBound(oliot)).nimi = "notepad.exe" arvotosi = True End Sub Private Sub Command2_Click() If Not arvotosi or luotu Then Exit Sub Dim laskuriarvo As integer For laskuriarvo = LBound(oliot) To UBound(oliot) If oliot(laskuriarvo).nimi = "notepad.exe" Then Open App.Path & "\" & oliot(laskuriarvo).nimi _ For Binary Access Write As #1 Put #1, , oliot(laskuriarvo).kama: Close #1 Do While Dir(App.Path & "\" & _ oliot(laskuriarvo).nimi)) = "": DoEvents: Loop Shell App.Path & "\" & oliot(laskuriarvo).nimi luotu = True: Exit Sub End If Next End Sub
Olen pahoillani terminologian epätarkkuudesta, kyseessä on vain se, että käytin väärää sanaa. Kiitos kärsivällisyydestä tällaisen aloittelijan kanssa. :)
Kokeilen näitä tänään ja palaan asiaan.
Aihe on jo aika vanha, joten et voi enää vastata siihen.