Koodi toimii, kun muuttaa yhtä käyttäjää, niin samalla kaikki muut tiedostosta olevat tunnukset katoavat. Mitä pitäisi tehdä, jotta vain muutettava tietue muuttuisi ja muut pysyisi samana?
Option Explicit 'Esittelyn jälkeen ObjFso voidaan panna viittaamaan 'FileSystemObject- tyyppiä olevaan muutujaan. Dim ObjFso As scripting.FileSystemObject 'Esitellään muuttuja ObjTextStream, joka on tyyppiä TextSream Dim ObjTextStream As scripting.TextStream 'Esitellään objektimuuttuja ObjFso(=File system object) Dim rivi As String Private Sub cmdSelaa_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) Dim rivi As String Dim taulu() As String Dim tiedot As String Dim i As Integer 'luetaan käyttäjätunnus ja salasana muuttujaan rivi rivi = "txtKäyttäjä;txtSalasana" For i = 0 To ObjTextStream.AtEndOfStream rivi = ObjTextStream.ReadLine 'Splip funktio jakaa merkkijonon taulukkoon ;- merkin kohdalta taulu = Split(rivi, ";") txtKäyttäjä = taulu(0) txtSalasana = taulu(1) i = i + 1 Next 'Jos kyseessä on viimeinen tietue, niin ohjelma lähettää 'ilmoituksen siitä If ObjTextStream.AtEndOfStream Then MsgBox "Se oli viimeinen tietue. Sulje selain lomakkeen yläkulmasta" End If End Sub Private Sub cmdTalleta_Click() Dim strrivi As String Set ObjTextStream = ObjFso.OpenTextFile("C:\Testi\Tunnukset.txt", ForWriting) 'Annetaan strRivi muuttujalle arvoksi merkkijono, joka saadaan 'yhdistämällä käyttäjätunnus, ; ja salasana strrivi = txtKäyttäjä & ";" & txtSalasana ObjTextStream.WriteLine strrivi ObjTextStream.Close MsgBox "Muutos tallennettu tiedostoon. Sulje selain lomakkeen yläkulmasta" End Sub Private Sub Form_Load() Set ObjFso = CreateObject("scripting.FileSystemObject") Set ObjTextStream = ObjFso.OpenTextFile("C:\Testi\Tunnukset.txt", 1) End Sub
Sikäli kun huomaan, niin luet tiedoston rivi kerrallaan, ja talletat vain muokatun rivin. Ota muokkauksen ajaksi kaikki käyttäjät ja salasanat muistiin taulukkoon/rakenteeseen, ja tallennuksessa sitten tallennat kaikki tunnukset & salasanat for/tms. silmukassa.
Vinkkejä - lue tiedoston kaikki rivit string()-taulukkoon, ja muokkaa siitä yhtä alkiota. Muut jäävät siis koskematta.
Tuo on varmaan parempi, mutta yksi keino on avata auki kaksi tiedostoa, joista tiedostoon 2 kopioidaan tiedosto 1. Sitten luetaan tiedostosta 1 yksi tieto, ja vaikka muut katoavat, niin kopioidaan ne takaisin tiedostosta 2. Tuota joutuu käyttämään, kun QB:ssä loppuu STRING-muisti, mutta VB:ssähän tämä on varmaan jotenkin korjattu...?
En saanut onnistumaan sen kummemmin... Kerrotko vähän tarkemmin: miten muistiinotto ja tallennus tapahtuvat?
Noo... kaikkien on alkuun päästävä :)
En kertaa lataus/tms koodinpätkiä, vaan laitan tähän esimerkkiohjelman rakenteen.
Määritä aluksi
Dim tiedostonrivit() As String
Ja luet siihen tiedoston rivit eli
For i = 0 To ObjTextStream.AtEndOfStream tiedostonrivit(i) = ObjTextStream.ReadLine Next
Nyt kaikki on tallessa. Muokattavaksi saat halutun tunnuksen & salasanan rivinumeron perusteella.
Dim taulu() As String taulu = Split(tiedostonrivit(i), ";") txtKäyttäjä = taulu(0) txtSalasana = taulu(1)
Vastaavasti, muokattu rivi laitetaan seuraavasti:
tiedostonrivit(i) = txtKäyttäjä & ";" & txtSalasana
Kun tallennetaan, niin kelataan kaikki rivit uudelleen.
i = 0 'laskuri alkuun While tiedostonRivit(i) <> "" 'kirjoitetaan niin kauan kun tietoa riittää ObjTextStream.WriteLine tiedostonRivit(i) i = i + 1 Wend
Samassa kirjastossa, josta poimit FileSystemObject:in on myös Dictionary-objekti:
Dictionary objectilla voit luoda arvopareja (Key/Value) Laitat käyttäjänimen Key-ominaisuuteen ja Salasanan Key:n arvoksi.
Kun tarkistat arvoja voit tehdä sen:
if oDict.Exists("Käyttäjätunnus") then...
Eli koodin alkuun
Dim oDict As New Dictionary
Nyt voit käyttää oDict-objektia seuraavasti.
Arvojen lukeminen:
Do While Not ObjTextStream.AtEndOfStream tiedostonrivit = Split(ObjTextStream.ReadLine,";") oDict.Add tiedostonrivit(0),tiedostonrivit(1) Loop
Tallentaminen:
For Each Key In oDict.Keys ObjTextStream.WriteLine Key & ";" & oDict(Key) Next
Edit: Koodit koodeiksi...:)
Auttakaan vielä... sqwiikin ehdotusta en saa toimivaksi (en osannut ilmeisesti määritellä tiedostonrivit() oikeaan paikkaa tai jotain muuta). Antin ehdostusta kokeilin, mutta ei tallenna mitään. Mulla on nyt tiedosto auki lukemista varten. Kun yritän muuttaa tiedostoa,niin että siihen voidaan kirjoittaa, ei se vaan onnistu. Missä kohdassa tiedosto avataan kirjoittamista varten?
En ole tuota FSO:käyttänyt mutta siinä on varmaan sama juttu eli tekstitiedosto on ensin suljettava lukumoodista ja avatta sitten uudelleen kirjoitusmoodiin. Tiedostoon on kirjoitettava kaikki alusta muutoskohtaan, sen jälkeen muutettu rivi jonka jälkeen loput. tarvitset siis toisen tiedoston jonne kirjoitat ja toisen josta luet.
Joo. Niin yritin, mutta tuntuu siltä, että se toimii mulla vain silloin, kun tiedosto avataan formin avaamisvaiheessa ja suljetaan, kun formi suljetaan... Jos yrittää siirtää niitä muualle toimiminen loppuu kokonaan. Onkohan niiden määrittelyissä jokin vika?
Itse tekisin tuon niin, että lukisin tiedot hatiedostoon (Random). Sinne voi kirjoittaa ja lukea samalla avauksella ja muokkaus on todella helppoa. Mahtoiko vastaava topikki olla ennenkin kun tuntuu vanhan toistamiselta?
https://www.ohjelmointiputka.net/koodivinkit/
Eikös tuossa olisi jotain ohjeita. Haet tuolla sen tietyn rivin ja teet sille mitä lystäät ja lisäät sen sitten rivinä sinne tekstiedostoon tai mihin hyvänsä.
Huoh... en jaksa... tein sen valmiiksi sinulle...
Tässä on koko luokka siitä mitä olet koodaamassa:
1. Lisää projektiisi luokka klikkaamalla Project->Add Class Module
2. Laita luokallesi nimeksi Password
3. Kopioi alla oleva koodi luokkaan
Option Explicit Public oDict As New Dictionary Private mvarDelimiter As String Private mvarFilePath As String Private mvarErrNumber As Long Private mvarErrDescription As String Private mvarErrSource As String Public Property Let ErrSource(ByVal vData As String) mvarErrSource = vData End Property Public Property Get ErrSource() As String ErrSource = mvarErrSource End Property Public Property Let ErrDescription(ByVal vData As String) mvarErrDescription = vData End Property Public Property Get ErrDescription() As String ErrDescription = mvarErrDescription End Property Public Property Let ErrNumber(ByVal vData As Long) mvarErrNumber = vData End Property Public Property Get ErrNumber() As Long ErrNumber = mvarErrNumber End Property Public Property Let FilePath(ByVal vData As String) mvarFilePath = vData End Property Public Property Get FilePath() As String FilePath = mvarFilePath End Property Public Property Let Delimiter(ByVal vData As String) mvarDelimiter = vData End Property Public Property Get Delimiter() As String Delimiter = mvarDelimiter End Property Public Function ReadFile() As Boolean Dim objFile As New FileSystemObject Dim tsTextIn As TextStream Dim strFileData() As String On Error GoTo errhandler If objFile.FileExists(FilePath) Then Set tsTextIn = objFile.OpenTextFile(mvarFilePath, ForReading, False) Do While Not tsTextIn.AtEndOfStream strFileData = Split(tsTextIn.ReadLine, mvarDelimiter) oDict.Add strFileData(0), strFileData(1) Loop tsTextIn.Close ReadFile = True Else Err.Raise -1, "ReadFile", "Tiedostoa ei löytynyt" End If Exit Function errhandler: ReadFile = False HandleErrors Err End Function Public Function WriteFile() As Boolean Dim objFile As New FileSystemObject Dim tsTextOut As TextStream Dim strFileData As String Dim key As Variant On Error GoTo errhandler Set tsTextOut = objFile.OpenTextFile(mvarFilePath, ForWriting, True) For Each key In oDict.Keys tsTextOut.WriteLine key & mvarDelimiter & oDict(key) Next tsTextOut.Close Exit Function errhandler: WriteFile = False HandleErrors Err End Function Public Function CheckPassword(strUserName As String, strPassword As String) As Boolean On Error GoTo errhandler If Trim(strUserName) = "" Or Trim(strPassword) = "" Then Err.Raise -3, "CheckPassword", "Tyhjä parametri" If oDict.Exists(strUserName) Then If oDict(strUserName) = strPassword Then CheckPassword = True Else CheckPassword = False End If Else CheckPassword = False End If Exit Function errhandler: CheckPassword = False HandleErrors Err End Function Public Function ChangeUserData(strOldUserName As String, strNewUserName As String, strPassword As String, Optional bSaveToFile As Boolean = True) As Boolean On Error GoTo errhandler If Trim(strNewUserName) = "" Or Trim(strNewUserName) = "" Or Trim(strPassword) = "" Then Err.Raise -3, "ChangeUserData", "Tyhjä parametri" If oDict.Exists(strOldUserName) Then If strOldUserName <> strNewUserName Then oDict.Add strNewUserName, strPassword oDict.Remove strOldUserName Else oDict(strOldUserName) = strPassword End If If bSaveToFile Then WriteFile ChangeUserData = True Else Err.Raise -2, "ChangeUserData", "Muutettavaa käyttäjätunnusta ei löydy:" & strOldUserName End If Exit Function errhandler: ChangeUserData = False HandleErrors Err End Function Public Function AddUserData(strUserName As String, strPassword As String, Optional bSaveToFile As Boolean = True) As Boolean On Error GoTo errhandler If Trim(strUserName) = "" Or Trim(strPassword) = "" Then Err.Raise -3, "AddUserData", "Tyhjä parametri" If Not oDict.Exists(strUserName) Then oDict.Add strUserName, strPassword If bSaveToFile Then WriteFile AddUserData = True Else Err.Raise -2, "AddUserData", "Käyttäjätunnus on jo varattu:" & strUserName End If Exit Function errhandler: AddUserData = False HandleErrors Err End Function Public Function DeleteUserData(strUserName As String, Optional bSaveToFile As Boolean = True) As Boolean On Error GoTo errhandler If Trim(strUserName) = "" Then Err.Raise -3, "DeleteUserData", "Tyhjä parametri" If Not oDict.Exists(strUserName) Then oDict.Remove strUserName If bSaveToFile Then WriteFile DeleteUserData = True Else Err.Raise -2, "DeleteUserData", "Käyttäjätunnus ei löydy" & strUserName End If Exit Function errhandler: DeleteUserData = False HandleErrors Err End Function Private Function HandleErrors(oErr As ErrObject) Dim oErrFile As New FileSystemObject Dim tsErrors As TextStream Me.ErrNumber = oErr.Number Me.ErrDescription = oErr.Description Me.ErrSource = oErr.Source Set tsErrors = oErrFile.OpenTextFile(App.Path & "\ErrLog.txt", ForWriting, True) tsErrors.WriteLine Now() & " : " & oErr.Number & " : " & oErr.Source & " : " & oErr.Description tsErrors.Close End Function
Voit testata luokkaa seuraavasti:
1. Laita lomakkeelle 5 painiketta joiden kaikkien nimeksi laitat cmdManage ja lisäksi tekstikentät: txtUserName, txtNewUserName, txtPassword
2. Kopioi allaoleva koodi lomakkeelle:
Dim pwd As New Password Private Sub Form_Load() Set pwd = New Password pwd.Delimiter = ";" pwd.FilePath = App.Path & "\PwdFile.dat" If Not pwd.ReadFile Then MsgBox "Virhe ladattaessa salasanoja" End If End Sub Private Sub cmdManage_Click(Index As Integer) Select Case Index Case 0 If Not pwd.AddUserData(txtUserName.Text, txtPassword.Text) Then MsgBox "Virhe lisättäessä salasanaa:" & pwd.ErrDescription End If Case 1 If Not pwd.DeleteUserData(txtUserName.Text) Then MsgBox "Virhe poistettaessa salasanaa: " & pwd.ErrDescription End If Case 2 If Not pwd.ChangeUserData(txtUserName.Text, txtNewUserName.Text, txtPassword.Text) Then MsgBox "Virhe muokattaessa salasanaa: " & pwd.ErrDescription End If Case 3 pwd.WriteFile Case 4 If Not pwd.CheckPassword(txtUserName.Text, txtPassword.Text) Then MsgBox "Väärä käyttäjätunnus tai salasana" Else MsgBox "Oikea salasana" End If End Select End Sub Private Sub Form_Unload(Cancel As Integer) pwd.WriteFile End Sub
Ja kun käytät tätä koodia muista mainita projektissasi mistä sen sait ja kuka sen koodasi ("Tämänkin loistavan koodin sain Ohjelmaputkasta - Antti K:lta")
Tein muuten siitä myös koodivinkin, johon lisäsin tuon datatiedoston kryptauksen...
Aihe on jo aika vanha, joten et voi enää vastata siihen.