I have a program for advanced VB in which we are to create a Struct of account records that are in a Text file and close the text file after opening and read the file in to the form window from the Struct and be able to edit the data and save it back to the text file when the program exits. The red entry code is where i am confused as to what i should be writing. Each entry i put in the ACWriter it overwrites the existing textfile with the current record displayed and deletes all other records. How do i write the code to write the records that are in the struct to include the updated data, so that when the program reopens the updated records data displays properly. Thanks

Option Strict On

Public Class frmMain

    'Globals
    'User defined structure for Account Records
    Public Structure AccountRecords
        Dim LastName As String
        Dim FirstName As String
        Dim CustNum As Integer
        Dim Address As String
        Dim City As String
        Dim State As String
        Dim ZipCode As String
        Dim TelephoneNum As String
        Dim AccountBal As Decimal
        Dim DateLastPay As String
    End Structure


    'Opens the Records window and displays the first record in the Account Struct file
    ' Create an instance of AccountRecords
    Public myAccountRecords(25) As AccountRecords
    ' Create a variable that defines the maximum size of AccountRecords
    Private sizeAccountRecords As Integer = 24
    ' Create a variable that counts number of 'Active Records' in AccountRecords
    Private activeAccountRecordsCount As Integer = 0
    ' Create a variable that indicates which record is currently active / displayed
    Public currentRecordNumber As Integer = 0

    Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' Load all file data into array of structs "myAccountRecords"
        loadArray()
        ' Now that all file data is loaded, let's setup the GUI to view the first record.
        initfrmMain()

    End Sub

    ' Loads the structure with file data
    Private Sub loadArray()
        ' Declare structure index variable
        Dim thisAccountRecordsNum As Integer = 0
        ' Declare StreamReader
        Dim ACReader As IO.StreamReader
        ' Read file data into Struct 'myAccountRecords' until end of file
        Dim userReply As DialogResult

        Try
            ' Try to open the data file "AccountRecords.txt"
            ACReader = IO.File.OpenText("AccountRecords.txt")
            ' Read first record of "AccountRecords.txt" IF it exists.
            Do While ACReader.Peek <> -1
                myAccountRecords(thisAccountRecordsNum).LastName = ACReader.ReadLine
                myAccountRecords(thisAccountRecordsNum).FirstName = ACReader.ReadLine
                myAccountRecords(thisAccountRecordsNum).CustNum = CInt(ACReader.ReadLine)
                myAccountRecords(thisAccountRecordsNum).Address = ACReader.ReadLine
                myAccountRecords(thisAccountRecordsNum).City = ACReader.ReadLine
                myAccountRecords(thisAccountRecordsNum).State = ACReader.ReadLine
                myAccountRecords(thisAccountRecordsNum).ZipCode = ACReader.ReadLine
                myAccountRecords(thisAccountRecordsNum).TelephoneNum = ACReader.ReadLine
                myAccountRecords(thisAccountRecordsNum).AccountBal = CDec(ACReader.ReadLine)
                myAccountRecords(thisAccountRecordsNum).DateLastPay = ACReader.ReadLine

                ' Record loaded: increment the record counter
                thisAccountRecordsNum += 1
                
                ' Is the Account Records full?
                ' Can any more records be read from file & loaded into struct myAccountRecords? 
                If thisAccountRecordsNum > sizeAccountRecords Then
                    MsgBox("Account Records is Full! " & vbCrLf & _
                           "No More Data Can Be Added. ", MsgBoxStyle.Critical, _
                           "Account Records Capacity Warning")
                    Exit Do
                End If
            Loop

        Catch ex As Exception
            ' Error: No external file exists.
            userReply = MessageBox.Show("No Account Records File Exists." & vbCrLf & "Do you wish to create the file?", "File Error", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation)

            If userReply = Windows.Forms.DialogResult.Yes Then
                ' Create a blank 'AccountRecords.txt' file using the StreamWriter. Be sure to use the "Append" option.
                MessageBox.Show("Create a blank 'AccountRecords.txt' file in the 'bin\Debug' directory." & vbCrLf & "Close the data file.", "Procedure Hint")
                ' A blank "AccountRecords.txt" file now exists BUT NO records exist: 

            Else
                ' File DOES NOT EXIST: close the "View" operation
                MessageBox.Show("Cannot continue without program data file.", "Fatal Read Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
                Me.Close()
            End If
        End Try
        ACReader.Close()
        ' Update the number of active Account records counted during the loading process
        activeAccountRecordsCount = thisAccountRecordsNum
        ' Display active record count in lblRecords
        lblRecords.Text = CStr(activeAccountRecordsCount)

    End Sub

    Private Sub initFrmMain()
        ' First record is displayed
        currentRecordNumber = 0

        ' Lets initialize frmMain for Viewing the available records in struct myAccountRecords()
        btnPrev.Enabled = False

        ' Since we are viewing the first record IF IT EXISTS
        If activeAccountRecordsCount > 1 Then
            btnNext.Enabled = True
            txtLastName.Text = myAccountRecords(currentRecordNumber).LastName
            txtFirstName.Text = myAccountRecords(currentRecordNumber).FirstName
            txtCustNum.Text = CStr(myAccountRecords(currentRecordNumber).CustNum)
            txtAddress.Text = myAccountRecords(currentRecordNumber).Address
            txtCity.Text = myAccountRecords(currentRecordNumber).City
            txtState.Text = myAccountRecords(currentRecordNumber).State
            txtZipCode.Text = myAccountRecords(currentRecordNumber).ZipCode
            txtPhoneNum.Text = myAccountRecords(currentRecordNumber).TelephoneNum
            txtAcctBal.Text = CStr(myAccountRecords(currentRecordNumber).AccountBal)
            txtDate.Text = myAccountRecords(currentRecordNumber).DateLastPay
            'if no other records exist
        ElseIf activeAccountRecordsCount = 1 Then
            btnNext.Enabled = False
            txtLastName.Text = myAccountRecords(currentRecordNumber).LastName
            txtFirstName.Text = myAccountRecords(currentRecordNumber).FirstName
            txtCustNum.Text = CStr(myAccountRecords(currentRecordNumber).CustNum)
            txtAddress.Text = myAccountRecords(currentRecordNumber).Address
            txtCity.Text = myAccountRecords(currentRecordNumber).City
            txtState.Text = myAccountRecords(currentRecordNumber).State
            txtZipCode.Text = myAccountRecords(currentRecordNumber).ZipCode
            txtPhoneNum.Text = myAccountRecords(currentRecordNumber).TelephoneNum
            txtAcctBal.Text = CStr(myAccountRecords(currentRecordNumber).AccountBal)
            txtDate.Text = myAccountRecords(currentRecordNumber).DateLastPay
            'the only record
        Else
            btnNext.Enabled = False
        End If

    End Sub

    Private Sub btnPrev_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrev.Click
        'To display previous record
        'determine current record
        currentRecordNumber -= 1

        If currentRecordNumber > 0 Then
            btnPrev.Enabled = True
            btnNext.Enabled = True
            txtLastName.Text = myAccountRecords(currentRecordNumber).LastName
            txtFirstName.Text = myAccountRecords(currentRecordNumber).FirstName
            txtCustNum.Text = CStr(myAccountRecords(currentRecordNumber).CustNum)
            txtAddress.Text = myAccountRecords(currentRecordNumber).Address
            txtCity.Text = myAccountRecords(currentRecordNumber).City
            txtState.Text = myAccountRecords(currentRecordNumber).State
            txtZipCode.Text = myAccountRecords(currentRecordNumber).ZipCode
            txtPhoneNum.Text = myAccountRecords(currentRecordNumber).TelephoneNum
            txtAcctBal.Text = CStr(myAccountRecords(currentRecordNumber).AccountBal)
            txtDate.Text = myAccountRecords(currentRecordNumber).DateLastPay
        Else
            btnPrev.Enabled = False
            btnNext.Enabled = True
            txtLastName.Text = myAccountRecords(currentRecordNumber).LastName
            txtFirstName.Text = myAccountRecords(currentRecordNumber).FirstName
            txtCustNum.Text = CStr(myAccountRecords(currentRecordNumber).CustNum)
            txtAddress.Text = myAccountRecords(currentRecordNumber).Address
            txtCity.Text = myAccountRecords(currentRecordNumber).City
            txtState.Text = myAccountRecords(currentRecordNumber).State
            txtZipCode.Text = myAccountRecords(currentRecordNumber).ZipCode
            txtPhoneNum.Text = myAccountRecords(currentRecordNumber).TelephoneNum
            txtAcctBal.Text = CStr(myAccountRecords(currentRecordNumber).AccountBal)
            txtDate.Text = myAccountRecords(currentRecordNumber).DateLastPay
        End If

    End Sub

    Private Sub btnNext_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNext.Click
        'Displays if additional records are available
        currentRecordNumber += 1

        If currentRecordNumber < activeAccountRecordsCount - 1 Then
            btnNext.Enabled = True
            txtLastName.Text = myAccountRecords(currentRecordNumber).LastName
            txtFirstName.Text = myAccountRecords(currentRecordNumber).FirstName
            txtCustNum.Text = CStr(myAccountRecords(currentRecordNumber).CustNum)
            txtAddress.Text = myAccountRecords(currentRecordNumber).Address
            txtCity.Text = myAccountRecords(currentRecordNumber).City
            txtState.Text = myAccountRecords(currentRecordNumber).State
            txtZipCode.Text = myAccountRecords(currentRecordNumber).ZipCode
            txtPhoneNum.Text = myAccountRecords(currentRecordNumber).TelephoneNum
            txtAcctBal.Text = CStr(myAccountRecords(currentRecordNumber).AccountBal)
            txtDate.Text = myAccountRecords(currentRecordNumber).DateLastPay
            'Display next button if additional record exists
        Else
            btnNext.Enabled = False
            txtLastName.Text = myAccountRecords(currentRecordNumber).LastName
            txtFirstName.Text = myAccountRecords(currentRecordNumber).FirstName
            txtCustNum.Text = CStr(myAccountRecords(currentRecordNumber).CustNum)
            txtAddress.Text = myAccountRecords(currentRecordNumber).Address
            txtCity.Text = myAccountRecords(currentRecordNumber).City
            txtState.Text = myAccountRecords(currentRecordNumber).State
            txtZipCode.Text = myAccountRecords(currentRecordNumber).ZipCode
            txtPhoneNum.Text = myAccountRecords(currentRecordNumber).TelephoneNum
            txtAcctBal.Text = CStr(myAccountRecords(currentRecordNumber).AccountBal)
            txtDate.Text = myAccountRecords(currentRecordNumber).DateLastPay
        End If
        'Display previous button if records greater than zero
        If currentRecordNumber > 0 Then
            btnPrev.Enabled = True
        End If

    End Sub

    Private Sub PrintPreviewToolStripMenuItem_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintPreviewToolStripMenuItem.Click
        'Allows the user to Print Preview the current document or record
        'PrnPreviewDialog.Document = PrnDocument
        'PrnPreviewDialog.ShowDialog()
    End Sub

    Private Sub PrintToolStripMenuItem_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintToolStripMenuItem.Click
        'Allows the user to print the current document to a printer
        'PrnDocument.Print()
    End Sub

    Private Sub ExitToolStripMenuItem_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExitToolStripMenuItem.Click
        'Create Record Counter
        Dim RecordCount As Integer
        'Open StreamWriter
        Dim ACWriter = IO.File.CreateText("AccountRecords.txt")

        'Write to file.
        For RecordCount = 0 To activeAccountRecordsCount
            ACWriter.WriteLine(txtLastName.Text)


            RecordCount += 1
        Next RecordCount
        'Close the writer
        ACWriter.Close()



        'Closes the application
        Me.Close()
    End Sub    
Private Sub AddRecordToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AddRecordToolStripMenuItem.Click
        'Displays the Add New Record Window and allows the user to add a new account to the struct file
        Dim frmAdd As New frmAdd

        frmAdd.ShowDialog()
    End Sub

    Private Sub EditRecordToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles EditRecordToolStripMenuItem.Click
        'Displays the Edit Account Record Window and allows the user to edit the current record data in the struct file
        Dim frmEdit As New frmEdit
        'Display the text information in the edit record window
        frmEdit.txtLastName.Text = myAccountRecords(currentRecordNumber).LastName
        frmEdit.txtFirstName.Text = myAccountRecords(currentRecordNumber).FirstName
        frmEdit.txtCustNum.Text = CStr(myAccountRecords(currentRecordNumber).CustNum)
        frmEdit.txtAddress.Text = myAccountRecords(currentRecordNumber).Address
        frmEdit.txtCity.Text = myAccountRecords(currentRecordNumber).City
        frmEdit.txtState.Text = myAccountRecords(currentRecordNumber).State
        frmEdit.txtZipCode.Text = myAccountRecords(currentRecordNumber).ZipCode
        frmEdit.txtPhoneNum.Text = myAccountRecords(currentRecordNumber).TelephoneNum
        frmEdit.txtAcctBal.Text = CStr(myAccountRecords(currentRecordNumber).AccountBal)
        frmEdit.txtDate.Text = myAccountRecords(currentRecordNumber).DateLastPay
        'Display the Edit Customer Record form
        frmEdit.ShowDialog()

    End Sub

    Private Sub ByNameToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ByNameToolStripMenuItem.Click
        'Displays to allow the user to search the file for a specific Last Name
        Dim frmName As New frmName

        frmName.ShowDialog()
    End Sub

    Private Sub ByCustormerNumberToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ByCustormerNumberToolStripMenuItem.Click
        'Displays to allow the user to search the file for a specific Account Number
        Dim frmAcct As New frmAcct

        frmAcct.ShowDialog()
    End Sub

    Private Sub AboutToolStripMenuItem_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AboutToolStripMenuItem.Click
        'Displays the About form window
        Dim frmAbout As New frmAbout

        frmAbout.ShowDialog()
    End Sub



    
End Class

Each time you enter the sub you Dim ACWriter = IO.File.CreateText("AccountRecords.txt") which (at my best guess) creates a new text file, wiping out the old. I think you need to look into "append" when opening a file and wanting to add data to the end.

Edgar5, What i need the ACWriter to do is write the current data from the struct to the file with the edited data, not add to the end of the existing data. Sorry if i did not explain properly, ( i do not want to append the text) i want to write over the existing text with all the records in the struct to included the unedited original data.

I see. I am facing exactly the same situation here. I have an MP4 file which has meta-data embedded (tags--things like track title, artist etc.) and I want to remove one of the old tags and replace it with a new one.

The only way I have found (so far) is to copy the file into a buffer, up to the portion I want to edit then put the new data in the buffer, then skip past the old data with the stream reader and continue writing the old data into the buffer. Finally, write the buffer out in place of the old file.

All this is necessary because the old data and the new data is not always going to be the same byte length. If your structure is always the same length, you could stream read to the start of the structure, write the new struct over the old and be done. If this were the case, I would put a method in the struct which, when passed a stream writer would know how to write itself to file (unless VB allows StreamWriter.WriteByte(pointerToCurrentRecord, sizeof(AccountRecords)) like C++ does). Keep me posted on your solution, please.

This article has been dead for over six months. Start a new discussion instead.