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 SubSikä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)
NextEdit: 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 FunctionVoit 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 SubJa 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.