Searching for and deleting data within a text file - vb.net

I am currently working on a Library Inventory System. I wanted it to be able to add, issue, search and delete book records. The records are stored in a text file which looks like this:
(ID), (Name Of Book); (Author); (Price) ; (Book Donor) ; (Language)
E.g.
123 , Journey to the center of the earth ; Jules Verne ; 50 ; Jack ; English
...
This program also works with a datagridview to update to/from the text file, so far my add and issue functions are working but i am having trouble with search and delete.
To search, the user must either enter the ID of the book in a textbox or the language of the book (separate textbox) and it must show the search results in the datagridview.
This is the my attempt for the search function:
Dim line As String
Dim fields(7) As String
Dim found As Boolean = False
Dim inputStream As StreamReader
inputStream = File.OpenText("AddBookScreen.txt")
line = inputStream.ReadLine()
While (line <> Nothing) And found = False
fields = Split(line, ",")
If Trim(fields(0)) = SBidTextbox.Text Then
SBdatagridview.Rows.Add(Trim(fields(1)), Trim(fields(2)), Trim(fields(3)), Trim(fields(4)), Trim(fields(5)), Trim(fields(6)))
found = True
Else
line = inputStream.ReadLine()
End If
End While
If Not found Then
MessageBox.Show(SBidTextbox.Text & " not found")
End If
inputStream.Close()
End Sub
The delete function should be able to find the specific book by id and then delete that record from the text file.
This is my attempt for the delete function:
Dim lines() As String
Dim outputlines As New List(Of String)
Dim searchString As String = DBidTextbox.Text
lines = IO.File.ReadAllLines("AddBookScreen.txt")
For Each line As String In lines
If line.Contains(searchString) = False Then
outputlines.Add(line)
End If
Next
The search and delete methods are meant to search for a specific book in the text file by either the ID of the book or the language and display the results in the datagridview, the delete method is to search for a specific record through ID and delete that record.
Could someone please guide me through these problems, your help would be much appreciated.

If you can change your text file format slightly (Only use one kind of delimiter - either comma or semi-colon), then you can use the Microsoft Text Driver. This allows you to treat the text file like a database table, and you can use SQL statements to SELECT, DELETE, or UPDATE. Below is an example:
Public Sub Delete(ByVal ID As String)
Dim SQL As String = String.Format("DELETE FROM myfile.csv WHERE ID={0}", ID)
Dim conn_str As String = String.Format("Driver={{Microsoft Text Driver (*.txt; *.csv)}};Dbq={0};Extensions=asc,csv,tab,tsv,txt;", folder)
Dim conn As New OdbcConnection(conn_str)
conn.Open()
Dim cmd As New OdbcCommand(sqltxt, conn)
Dim reader As OdbcDataReader = cmd.ExecuteNonQuery()
...
End Sub
If this system has any publicly facing user input, I would definitely recommend using a Parameterized Query to prevent SQL injection attacks.

Related

Saving contents of multiple text boxes and possibly combo boxes

I'm working on a basic application that lets you track experience earned across up to 3 skills. The names of the skills are in a combo box (not sure if the best) and the beginning and ending values are in text boxes.
I want to add a save button that saves the ending values and selected skills, when pressing the load button it would populate the combo boxes with saved skills and input the old ending values into the new beginning ones.
I've been working on this all day, searching for a long time I've come up with similar solutions but nothing seems to work right. I'm still a bit of a beginner so some of the solutions I don't understand. Also, this has to work for VBNet.
The closest solution I've come across is:
File.WriteAllText("C:\Data.txt", String.Join("|", new String({TextBox1.Text, TextBox2.Text, TextBox3.Text}))
I'd like the file to stay with the project in the main directory though. Would this work for combo boxes as well, and how to load the values back in?
I'm still a newbie to VB, hope this question makes sense.
If I get your idea right, please find some functions below if they can help:
One can read (or write) text:
This one can populate the needed string to 3 textboxes txtSkill1, txtSkill2, txtSkill3
Sub ReadTextFile()
Dim lineCount As Integer = 0
Dim rndInstance As New Random
Dim idx As Integer = 0
Dim selectedLine As String = ""
Dim txt As String = "Skills.txt"
If Not File.Exists(txt) Then
File.Create(txt).Dispose()
Dim objWriter As New System.IO.StreamWriter(txt, True)
' 2 sample text lines:
objWriter.WriteLine("Negotiating - Interpersonal - Working independently")
objWriter.WriteLine("Goal oriented - Leadership - Teamwork")
objWriter.Close()
End If
lineCount = File.ReadAllLines(txt).Length
idx = rndInstance.Next(1, lineCount + 1) ' the index can be random if you want, or run from (1 to lineCount)
selectedLine = ReadLineWithNumberFrom(txt, idx)
Dim pattern As String = "-" ' split on hyphens
Dim subStrings() As String = Regex.Split(selectedLine, pattern)
txtSkill1.Text = subStrings(0)
txtSkill2.Text = subStrings(1)
txtSkill3.Text = subStrings(2)
End Sub
One can read a string from a specific line number:
Function ReadLineWithNumberFrom(filePath As String, ByVal lineNumber As Integer) As String
Using file As New StreamReader(filePath)
' Skip all preceding lines:
For i As Integer = 1 To lineNumber - 1
If file.ReadLine() Is Nothing Then
Throw New ArgumentOutOfRangeException("lineNumber")
End If
Next
' Attempt to read the line you're interested in:
Dim line As String = file.ReadLine()
If line Is Nothing Then
Throw New ArgumentOutOfRangeException("lineNumber")
End If
' Succeeded!
Return line
End Using
End Function
Now with the functions allow you to write to any text file, to read from any text file, from any line number, with specific separator (here is the hyphen -- char), you can Save and Load any string you need.

VB.Net Cant create "new line" "string"

I am in need of assistance... i am trying to create a textfile with links in it. the code i have..
dim domain as string = "http://www.mywebsite/"
dim name as string = "username"
Dim link As String = New String("domain" & "name")
TextBox1.AppendText(link & Environment.NewLine)
Msgbox(textBox1.lines(0))
The problem is that MsgBox only shows up as "http://www.mywebsite/". the textbox does show "http://www.mywebsite/username" but when copied to text document it is:
Line0: http://www.mywebsite/
Line1:username
any ideas... tried using
Dim link As String = String.Join(domain & name) but that doesnt work nor does
Dim link As String = new String.Join(domain & name)
i need
Msgbox(textBox1.lines(0)) to display "http://www.mywebsite/username" not one or the other.
That was quick got a message saying to use. Dim link As String = String.Concat(domain & name)
i think you should move to StringBuilder first import Imports System.Text
'create a string with multiple lines
Dim a As New StringBuilder
a.AppendLine("hi")
a.AppendLine("there")
a.AppendLine("this")
a.AppendLine("is")
a.AppendLine("a")
a.AppendLine("test")
'read will makes read line by line
Dim read As String() = a.ToString.Split(vbNewLine)
'count has number of lines
Dim count As Integer = a.ToString().Split(vbNewLine).Length - 1
'lines will be added to combobox one by one
For i As Integer = 0 To count - 1
ComboBox1.Items.Add(read(i))
Next
you just should edit it to suits your needs i didnt understand what you needed exactly

skip first row when reading excel CSV file

I found how to do this in several languages but not in .net (specifically vb.net). I am using OLeDbCommand to read both CSV and Excel files. In case of Excel I can skip first row and select second row onwards by specifying a range of cells. But in case of CSV, I am not sure how to do it.
Current code looks like:
Dim cmd As OleDbCommand = New OleDbCommand("SELECT * FROM [" + Path.GetFileName(FileName) + "]", cn)
Here we give the file, not the sheet. So I am bit stuck.
From my experience reading a text file like this is very restrictive. It only allows you to read the whole file, because you can't specify a table name. You might be better of reading each line and making table rows and adding them to a table. If the first row is headers you can use that to make the columns, otherwise hard code the columns.
Here's a simple little method that fills a datatable with the data from a .csv file, that you should be able to use:
Private Sub GetData(ByRef dt As DataTable, FilePath As String, Optional ByVal Header As Boolean = True)
Dim Fields() As String
Dim Start As Integer = CInt(Header) * -1
If Not File.Exists(FilePath) Then
Return
End If
dt.Clear()
Dim Lines() As String = File.ReadAllLines(FilePath)
If CBool(Start) AndAlso dt.Columns.Count = 0 Then
Lines(0) = Lines(0).Replace(Chr(34), "")
For Each h As String In Lines(0).Split(",")
dt.Columns.Add(h)
Next
End If
For I = Start To Lines.Count - 1
Fields = Lines(I).Split(",")
dt.Rows.Add(Fields)
Next
End Sub

VBNET Reading a specific column on a line in a text file

I have saved written a text file and it currently reads:
"first","surname","pass"
I want to read the password column so the 3rd one and define that as a variable. Its basically for a login, if pass in text file matches the entered pass (from user).
I have searched for about an hour now and no luck. Could someone guide me to a correct path.
Thanks.
Simple example of reading a small file line by line and splitting each one into fields:
' get the values from the user somehow:
Dim first As String = "James"
Dim surname As String = "Bond"
Dim pass As String = "007"
Dim validated As Boolean = False ' assume wrong until proven otherwise
' check the file:
Dim fileName As String = "c:\some folder\path\somefile.txt"
Dim lines As New List(Of String)(System.IO.File.ReadAllLines(fileName))
For Each line As String In lines
Dim values() As String = line.Split(",")
If values.Length = 3 Then
If values(0).Trim(Chr(34)) = first AndAlso
values(1).Trim(Chr(34)) = surname AndAlso
values(2).Trim(Chr(34)) = pass Then
validated = True
Exit For
End If
End If
Next
' check the result
If validated Then
MessageBox.Show("Login Successful!")
Else
MessageBox.Show("Login Failed!")
End If
If this is a CSV file, as seems to be the case, then the easiest way to read it will be with the TextFieldParser class. The MSDN already provides an excellent example for how to use it to read a CSV file, so I won't bother reproducing it here.

My List(OF Strings) are being saved as system.string (Empty)

I'm trying to delete a selected row, then save the rest into a file. However, when I save it, it totally empties the file.
Console.Write("Please eneter the first name of the student you wish to search for: ")
searchfname = Console.ReadLine
searchfname = StrConv(searchfname, VbStrConv.ProperCase)
Console.Write("Please enter the second name of the student you wish to search for: ")
searchsname = Console.ReadLine
searchsname = StrConv(searchsname, VbStrConv.ProperCase)
Dim foundItem() As String = Nothing
Dim foundline As String = Nothing
Dim fnsearch As String = String.Join(searchfname, searchsname)
Dim lines As New List(Of String)(File.ReadAllLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv"))
For Each line As String In lines
If searchfname = item(3) And searchsname = item(4) Then
Console.WriteLine(line)
Console.WriteLine()
Console.WriteLine("Are you sure you wish to delete this record? (y/n)")
End If
Dim answer As String
answer = Console.ReadLine
If answer = "y" Or answer = "Y" Then
Console.Clear()
lines.Remove(line)
Using sw As New StreamWriter("F:\Computing\Spelling Bee\stdnt&staffdtls.csv")
sw.WriteLine(lines.ToString)
End Using
ElseIf answer = "n" Or answer = "N" Then
staffmenu()
End If
Next
Look at this line in your code:
sw.WriteLine(lines.ToString)
Extract the lines.ToString expression from that statement. The result of that expression is "System.String". You are telling your stream writer to write the text "System.String" to the file.
To fix it, you need something more like this:
Using sw As New StreamWriter("F:\Computing\Spelling Bee\stdnt&staffdtls.csv")
For Each line As String In lines
sw.WriteLine(line)
Next line
End Using
The method List(Of T).ToString does not produce a value that includes the elements of the collection. Instead it will just return the type name.
The API you are looking for is File.WriteAllLines. Using this instead of StreamWriter and the Using block
File.WriteAllLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv", lines)
I can see that this issue can be resolved from the given answers and comment, but I would like to add an alternative to use Join function in writing to a file. Try like this may be of help:
Using sw As New StreamWriter(.....)
sw.WriteLine(Join(lines.ToArray(), Environment.NewLine))
End Using
Since using VB.Net, this is a vb.net specific solution can not be used in C#. For C#, use string.join instead.
Hope it helps too!