How to use a Sub value in a second Sub - vb.net

I am new to VB.net and really need bigger brains for this:
(all code added in one module)
I have a random function (that is giving me a random text value).
This is how I call the random function:
Dim IpAddresses As String() = My.Resources.BrainAnswer.Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
Dim RandomIpAddress As String = IpAddresses(GetRandom(IpAddresses.Length))
Now, I have a Sub that takes the Random text value and displays that in a Richtextbox, with a typewriter effect:
Sub type()
Dim thread As New Thread(AddressOf voice)
thread.Start()
Form1.RichTextBox1.Refresh()
Form1.count_ = 1
Form1.RichTextBox1.Text = Form1.str_
Form1.RichTextBox1.Clear()
Form1.str_ = RandomIpAddress
Form1.Timer1.Enabled = True
End Sub
I also have a Thread that I want to call in Sub Type()
Private Sub voice()
Dim TheSpeaker As New Speech.Synthesis.SpeechSynthesizer()
TheSpeaker.SelectVoiceByHints(Synthesis.VoiceGender.Female)
TheSpeaker.Speak(RandomIpAddress)
End Sub
My problem is: how to get the RandomIpAddress in both Sub type() and Private Sub voice?
If I'm using the:
Dim IpAddresses As String() = My.Resources.BrainAnswer.Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
Dim RandomIpAddress As String = IpAddresses(GetRandom(IpAddresses.Length))
inside the Module, then my code is running ONCE correctly. After that the Random code is not working any more (it's loading the same text) - never changing the result (no random).
If I am going to move the "Dim" code inside SUB and Thread, then I will have a random text added in richtextbox and another in Thread. So is doing a random result for both. I just want to get the same random result in both!
Here is my full code:
Imports System.Threading
Imports System.Speech
Imports System.Speech.Recognition
Module brain
Public str_ As String
Private rdm As New Random
Private Function GetRandom(max As Integer) As Integer
If InStr(UCase(Form1.TextBox1.Text), "HELLO MOTHER") Then
Dim theTime As DateTime
theTime = Now.ToLongTimeString
If theTime >= #6:00:00 AM# AndAlso theTime <= #9:59:59 AM# Then
Return rdm.Next(0, 3)
Else
Return rdm.Next(3, 6)
End If
End If
If InStr(UCase(Form1.TextBox1.Text), "HOW ARE YOU") Then
Return rdm.Next(6, 8)
End If
If InStr(UCase(Form1.TextBox1.Text), "WHO ARE YOU") Then
Return rdm.Next(8, 11)
End If
If InStr(UCase(Form1.TextBox1.Text), "YOUR NAME") Then
Return rdm.Next(11, 13)
End If
If InStr(UCase(Form1.TextBox1.Text), "WHAT ARE YOU") Then
Return rdm.Next(13, 16)
End If
If InStr(UCase(Form1.TextBox1.Text), "WHAT DO YOU DO") Then
Return rdm.Next(16, 18)
End If
If InStr(UCase(Form1.TextBox1.Text), "WHAT CAN YOU DO") Then
Return rdm.Next(16, 18)
End If
If InStr(UCase(Form1.TextBox1.Text), "HELP ME") Then
Return rdm.Next(16, 18)
End If
If InStr(UCase(Form1.TextBox1.Text), "YOUR MISSION") Then
Return rdm.Next(18, 19)
End If
End Function
Dim IpAddresses As String() = My.Resources.BrainAnswer.Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
Dim RandomIpAddress As String = IpAddresses(GetRandom(IpAddresses.Length))
Sub type()
Dim thread As New Thread(AddressOf voice)
thread.Start()
Form1.RichTextBox1.Refresh()
Form1.count_ = 1
Form1.RichTextBox1.Text = Form1.str_
Form1.RichTextBox1.Clear()
Form1.str_ = RandomIpAddress
Form1.Timer1.Enabled = True
End Sub
Private Sub voice()
Dim TheSpeaker As New Speech.Synthesis.SpeechSynthesizer()
TheSpeaker.SelectVoiceByHints(Synthesis.VoiceGender.Female)
Dim cleanString As String = Replace(RandomIpAddress, ".", " ")
TheSpeaker.Speak(cleanString)
End Sub
End Module

It seems either you are not getting your task clear or not getting us clear about it.
There is a handful of remarks to pay for this strip of code
Your variable max isn't used in your function GetRandom, that is not a foretelling sign in favor of same function's results.
I believe you are missing Return rdm.Next(19, max) somewhere in your GetRandom(max) function, just a prediction that has a strong likelihood to be applicable
RandomIpAddress is declared a static variable, while you are using it as a function.
Public Delegate Function newfunction() as string
Public RandomIpAddress As newfunction = Function() IpAddresses(GetRandom(IpAddresses.Length))
Thus the use of it would differ to:
Form1.str_ = RandomIpAddress()
And
Dim cleanString As String = Replace(RandomIpAddress(), ".", " ")
Threads are independant entities, they dont have access to other forms' ressources unless you share them.
Declaration of your textbox must be:
Friend Shared WithEvents TextBox1 As TextBox .

Related

Parse custom language syntax

I am developing a server-side scripting language which I intend to use on my private server. It is similar to PHP, and I know that I could easily use PHP instead but I'm just doing some programming for fun.
The syntax of basic commands in my language is as follows:
command_name "parameter1" : "parameter2" : "parameter3"
But it can also be like this when I want to join values for a parameter:
command_name "parameter1" : "param" & "eter2" : "par" & "amet" & "er3"
How would I go about parsing a string like the ones shown above (it will be perfectly typed, no syntax errors) to an object that has these properties
Custom class "Request"
Property "Command" as String, should be the "command_name" part
Property "Parameters" as String(), should be an array of Parameter objects
Shared Function FromString(s As String) as Request, this should accept a string in the language above and parse it to a Request object
Custom class "Parameter"
Property "Segments" as String(), for example "para", "mete", and "r3"
Sub New(ParamArray s as String()), this is how it should be generated from the code
It should be done in VB.NET and I am a moderate level programmer, so even if you just have an idea of how to attack this then please share it with me. I am very new to parsing complex data like this so I need a lot of help. Thanks so much!
Here is another method that is simpler.
Module Module1
Sub Main()
Dim inputs As String() = {"command_name ""parameter1"" : ""parameter2"" : ""parameter3""", "command_name ""parameter1"" : ""param"" & ""eter2"" : ""par"" & ""amet"" & ""er3"""}
For Each _input As String In inputs
Dim commandStr As String = _input.Substring(0, _input.IndexOf(" ")).Trim()
Dim parameters As String = _input.Substring(_input.IndexOf(" ")).Trim()
Dim parametersA As String() = parameters.Split(":".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Select(Function(x) x.Trim()).ToArray()
Dim parametersB As String()() = parametersA.Select(Function(x) x.Split("&".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Select(Function(y) y.Trim(" """.ToCharArray())).ToArray()).ToArray()
Dim newCommand As New Command() With {.name = commandStr, .parameters = parametersB.Select(Function(x) New Parameter(x)).ToArray()}
Command.commands.Add(newCommand)
Next (_input)
Dim z = Command.commands
End Sub
End Module
Public Class Command
Public Shared commands As New List(Of Command)
Public name As String
Public parameters As Parameter()
End Class
Public Class Parameter
Sub New()
End Sub
Sub New(names As String())
Me.names = names
End Sub
Public names As String()
End Class
I figured it out myself
Module Module1
Sub Main()
Dim r As Request = Request.Parse(Console.ReadLine())
Console.WriteLine("The type of request is " & r.Name)
For Each p As Parameter In r.Parameters
Console.WriteLine("All segments inside of parameter " & r.Parameters.IndexOf(p).ToString)
For Each s As String In p.Segments
Console.WriteLine(" Segment " & p.Segments.IndexOf(s).ToString & " is " & s)
Next
Next
Main()
End Sub
Public Class Request
Public Name As String
Public Parameters As New List(Of Parameter)
Public Shared Function Parse(line As String)
Dim r As New Request
r.Name = line.Split(" ")(0)
Dim u As String = line.Substring(line.IndexOf(" "), line.Length - line.IndexOf(" "))
Dim p As String() = u.Split(":")
For Each n As String In p
Dim b As String() = n.Split("&")
Dim e As New List(Of String)
For Each m As String In b
Dim i As Integer = 0
Do Until i > m.Length - 1
If m(i) = ControlChars.Quote Then
Dim s As String = ""
i += 1
Do Until i > m.Length - 1 Or m(i) = ControlChars.Quote
s &= m(i)
i += 1
Loop
e.Add(s)
End If
i += 1
Loop
Next
r.Parameters.Add(New Parameter(e.ToArray))
Next
Return r
End Function
End Class
Public Class Parameter
Public Segments As New List(Of String)
Public Sub New(ParamArray s As String())
Segments = s.ToList
End Sub
End Class
End Module

Delete duplicates from list

I have the following class :
Public Class titlesclass
Public Property Link As String
Public Property Title As String
Public Function Clear()
Link.Distinct().ToArray()
Title.Distinct().ToArray()
End Function
End Class
And the following code :
For Each title As Match In (New Regex(pattern).Matches(content)) 'Since you are only pulling a few strings, I thought a regex would be better.
Dim letitre As New titlesclass
letitre.Link = title.Groups("Data").Value
letitre.Title = title.Groups("Dataa").Value
lestitres.Add(letitre)
'tempTitles2.Add(title.Groups("Dataa").Value)
Next
I tried to delete the duplicated strings using the simple way
Dim titles2 = lestitres.Distinct().ToArray()
And calling the class function :
lestitres.Clear()
But the both propositions didn't work , i know that i'm missing something very simple but still can't find what it is
Easier to use a class that already implements IComparable:
Dim query = From title In Regex.Matches(content, pattern).Cast(Of Match)
Select Tuple.Create(title.Groups("Data").Value, title.Groups("Dataa").Value)
For Each letitre In query.Distinct
Debug.Print(letitre.Item1 & ", " & letitre.Item2)
Next
or Anonymous Types:
Dim query = From title In Regex.Matches(content, pattern).Cast(Of Match)
Select New With {Key .Link = title.Groups("Data").Value,
Key .Title = title.Groups("Dataa").Value}
For Each letitre In query.Distinct
Debug.Print(letitre.Link & ", " & letitre.Title)
Next
Ok, Since I notice you are using a ClassHere is one option you can do in order to not add duplicate items to your List within a class.I'm using a console Application to write this example, it shouldn't be too hard to understand and convert to a Windows Form Application if need be.
Module Module1
Sub Main()
Dim titlesClass = New Titles_Class()
titlesClass.addNewTitle("myTitle") ''adds successfully
titlesClass.addNewTitle("myTitle") '' doesn't add
End Sub
Public Class Titles_Class
Private Property Title() As String
Private Property TitleArray() As List(Of String)
Public Sub New()
TitleArray = New List(Of String)()
End Sub
Public Sub addNewTitle(title As String)
Dim added = False
If Not taken(title) Then
Me.TitleArray.Add(title)
added = True
End If
Console.WriteLine(String.Format("{0}", If(added, $"{title} has been added", $"{title} already exists")))
End Sub
Private Function taken(item As String) As Boolean
Dim foundItem As Boolean = False
If Not String.IsNullOrEmpty(item) Then
foundItem = Me.TitleArray.Any(Function(c) -1 < c.IndexOf(item))
End If
Return foundItem
End Function
End Class
End Module
Another option would be to use a HashSet, It will never add a duplicate item, so even if you add an item with the same value, it wont add it and wont throw an error
Sub Main()
Dim titlesClass = New HashSet(Of String)
titlesClass.Add("myTitle") ''adds successfully
titlesClass.Add("myTitle") '' doesn't add
For Each title As String In titlesClass
Console.WriteLine(title)
Next
End Sub
With all of that aside, have you thought about using a Dictionary so that you could have the title as the key and the link as the value, that would be another way you could not have a list (dictionary) contain duplicate items

Multi-Threading IP Address Pings Causing Application Crash

Boy, learning something new can be a real headache if you can't find a solid source. I have been designing applications in a linear fashion for some time now and want to step up into a more powerful approach. I have been reading up on threading, and perhaps have gone to an larger level than I should. However, one usually steps up when the application calls for it and no better time than the present to learn something new.
My program is designed to do something that seems rather simple, but has become extremely difficult to create in a smooth running manor. The original design created object of each device on the network it wished to ping, in my real world environment they are Kindles. The goal was to ensure they were still connected to the network by Pining them. I used a For Loop and Obj Array to do this set on a Timer. This had unexpected results causing the ListView to flicker and load slowly after the ListView1.Items.Clear. I evolved into updating the List Items rather than clearing them and the flicker remained.
I assumed this was due to the slow process of the array and pings so I started hunting for solutions and came across Multi-Threading. I have known about this for some time, but have yet to dive into the practice. My program seemed to need more speed and smoother operation so I took a stab at it. The below code in its complete form is the result, however it crashes and throws errors. Clearly I have not used Threading as it was intended. Using it in simpler functions works fine and I feel I have the grasp. That is if i want my program to pointlessly run counters.
I don't know what to do next in my steps for getting this task done, and figure I am combining several different methods into a mush of dead program. I could really use some help getting back on track with this. All comments welcome and thank you for checking out my code.
Form1 Code
Public Class Form1
'Obj Array
Public Shared objDevice As New List(Of kDevice)
'Thread Array for each Obj
Public Shared thread() As System.Threading.Thread
Private Sub ipRefresh(objID, itemPos)
Dim objDev As kDevice = objID
If My.Computer.Network.Ping(objDev.kIP) Then
objDev.kStatus = "Online"
objDev.kPings = 0
Else
objDev.kPings += 1
End If
If objDev.kPings >= 8 Then
objDev.kStatus = "Offline"
objDev.kPings = 0
ListView1.Items(itemPos).BackColor = Color.Red
End If
Dim str(4) As String
Dim itm As ListViewItem
str(0) = objDev.kName
str(1) = objDev.kIP
str(2) = objDev.kStatus
str(3) = objDev.kPings
itm = New ListViewItem(str)
ListView1.Items(itemPos) = itm
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.CheckForIllegalCrossThreadCalls = False
' Adding ListView Columns
ListView1.Columns.Add("Device", 100, HorizontalAlignment.Left)
ListView1.Columns.Add("IP Address", 150, HorizontalAlignment.Left)
ListView1.Columns.Add("Status", 60, HorizontalAlignment.Left)
ListView1.Columns.Add("Pings", 60, HorizontalAlignment.Left)
Dim ipList As New List(Of String)
Dim nameList As New List(Of String)
Using MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser("kDevices.csv")
MyReader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
MyReader.Delimiters = New String() {","}
Dim currentRow As String()
Dim rowP As Integer = 1
While Not MyReader.EndOfData
Try
currentRow = MyReader.ReadFields()
Dim cellP As Integer = 0
Dim nTemp As String = ""
For Each currentField As String In currentRow
Select Case cellP
Case 0
nameList.Add(currentField.Replace("""", ""))
Case 1
ipList.Add(currentField.Replace("""", ""))
End Select
cellP += 1
Next
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message & " is invalid. Skipping")
End Try
rowP += 1
End While
End Using
Dim nameLAR As String() = nameList.ToArray
Dim ipLAR As String() = ipList.ToArray
ReDim Preserve thread(nameLAR.Length)
For i As Integer = 0 To nameLAR.Length - 1
Dim newDevice As New kDevice
Dim objNum = i
objDevice.Add(newDevice)
newDevice.kName = nameLAR(i)
newDevice.kIP = ipLAR(i)
If My.Computer.Network.Ping(newDevice.kIP) Then
newDevice.kStatus = "Online"
Else
newDevice.kStatus = "Loading"
End If
Dim str(4) As String
Dim itm As ListViewItem
str(0) = newDevice.kName
str(1) = newDevice.kIP
str(2) = newDevice.kStatus
str(3) = newDevice.kPings
itm = New ListViewItem(str)
If newDevice.kStatus = "Loading" Then
itm.BackColor = Color.Yellow
End If
ListView1.Items.Add(itm)
thread(objNum) = New System.Threading.Thread(Sub() Me.ipRefresh(objDevice(objNum), objNum))
Next
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
For i As Integer = 0 To objDevice.Count - 1
thread(i).Start()
Next
End Sub
End Class
kDevice Class
Public Class kDevice
Private strkName As String
Private strkIP As String
Private strkStatus As String
Private strkLastStatus As String
Private strkPings As Integer = 0
Public Property kName As String
Get
Return strkName
End Get
Set(value As String)
strkName = value
End Set
End Property
Public Property kIP As String
Get
Return strkIP
End Get
Set(value As String)
strkIP = value
End Set
End Property
Public Property kStatus As String
Get
Return strkStatus
End Get
Set(value As String)
strkStatus = value
End Set
End Property
Public Property kPings As Integer
Get
Return strkPings
End Get
Set(value As Integer)
strkPings = value
End Set
End Property
End Class
The Error / Crash on Line 32 of my code which is when it tries to pass the update to the ListView Item
An unhandled exception of type 'System.ArgumentException'
occurred in Microsoft.VisualBasic.dll
Additional information: InvalidArgument=Value of '18'
is not valid for 'index'.
or
An unhandled exception of type 'System.NullReferenceException'
occurred in Microsoft.VisualBasic.dll
Additional information: Object reference not set to an instance
of an object.
If my code does not make sense, or at lease the idea of what I was trying to make it do, please let me know and I will explain whichever parts are unclear. Again thank you for looking over my issue.
Just a possible issue I noticed:
Dim str(4) As String
Dim itm As ListViewItem
str(0) = newDevice.kName
str(1) = newDevice.kIP
str(2) = newDevice.kStatus
str(3) = newDevice.kPings
itm = New ListViewItem(str)
If newDevice.kStatus = "Loading" Then
itm.BackColor = Color.Yellow
End If
ListView1.Items.Add(itm)
In this bit here, you declare str(4) which would be 5 possible indexes (remember it starts at zero), where you should have 4 (str(3)) . I don't think this is the whole issue, but just a small bit you should probably fix. You also may want to look into other ways to update the listview without setting
Me.CheckForIllegalCrossThreadCalls = False
Here's an awesome guide that helped me when I did my first multi threaded application: http://checktechno.blogspot.com/2012/11/multi-thread-for-newbies.html

Threading Problems (I don't understand it)

There's lots and lots of pages on the internet regarding threading but I can't seem to get my head around it.
I have a Form, which on the click of a button, loops through a file and reads it line by line. Each line is the login details for different FTP sites.
When it reads a line, it Dim's a variable as a new instance of a class named CallFTP using the login details.
It then Dim's a variable as a new Thread using a function in CallFTP named PerformFTP.
PerformFTP returns a string with the results of the FTP and I want to add this to a ListBox on the form that began it all.
The code for the button goes like this...
Private Sub cmdRun_Click(sender As Object, e As EventArgs) Handles cmdRun.Click
For Each _FTPLine As String In Split(_FTPDetails, vbNewLine)
Dim _Active As Boolean = CBool(Split(_FTPLine, "|")(7))
If _Active Then
_CurNum += 1
_ID = Format(Now.Year, "0000") & Format(Now.Month, "00") & Format(Now.Day, "00") & Format(Now.Hour, "00") & Format(Now.Minute, "00") & Format(Now.Second, "00") & Format(Now.Millisecond, "000") & Format(_CurNum, "00000")
Dim _FTP As New CallFTP(_ID, Split(_FTPLine, "|")(0), Split(_FTPLine, "|")(1), Split(_FTPLine, "|")(2), Split(_FTPLine, "|")(3), Split(_FTPLine, "|")(4), Split(_FTPLine, "|")(5), Split(_FTPLine, "|")(6))
Dim _Thread = New Thread(New ThreadStart(AddressOf _FTP.PerformFTP))
With _Thread
.IsBackground = True
.Start()
End With
End If
Next _FTPLine
End Sub
The class is as below (not quite but you don't need the rest of the code lol)
Public Class CallFTP
Private _ID As String = ""
Private _Response As String = ""
Private _IPAddress As String = ""
Private _Port As String = ""
Private _User As String = ""
Private _Pass As String = ""
Private _Remote As String = ""
Private _Local As String = ""
Private _InOut As String = ""
Public Sub New(ID As String, Server As String, PortNum As String, Username As String, Password As String, RemoteDir As String, LocalDir As String, InOrOut As String)
_ID = ID
_IPAddress = Server
_Port = PortNum
_User = Username
_Pass = Password
_Remote = RemoteDir
_Local = LocalDir
_InOut = InOrOut
End Sub
Public Function PerformFTP() As String
Return "This is a test"
End Function
End Class
Could anyone explain how I would call a sub named LogMessage on a module named modMisc (which adds a string to a ListBox on the main form)?
I've read that you need to invoke it but everything I read seems to give me a headache and make me need to lie down in a dark room for a few hours.
Is anyone capable of explaining as though you're speaking to a 2 year old? :)
Any help would be much appreciated.
You need to invoke a delegate to update your GUI if you're going to update it from another thread that from where it was created.
1º Your delegate must match (have the same signature) than the method you'll use:
Delegate Sub LogMessageExampleDelegate(ByVal x As Integer, ...)
Signature means that the delegate must return and receive the same types than your function/method.
2º Call your function to update GUI using delegate. This for example inside your update GUI function:
If yourListBox.InvokeRequired Then
yourListBox.Invoke(New LogMessageExampleDelegate(AddressOf THE_FUNCTION_WHICH_UPDATES_THE_GUI_NAME), parameter_value)
Else
'Just call your function
End If
With, as example:
sub addToListBox(byval text as string)
myListBox.Items.add(text)
end sub
So your invoke would be:
If yourListBox.InvokeRequired Then
yourListBox.Invoke(New LogMessageExampleDelegate(AddressOf addToListBox), "Item 1")
Else
'Just call your function
addToListBox("Item 1")
End If
PS: I wrote it two times so hope I didn't mess up with something without noticing it.

Appending a csv file

Dim NumberOfRecords As Integer
Sub Main()
Call ListTowns()
End Sub
Sub ListTowns()
Dim FileName As String
Dim MyFormat As String = "{0, -22} {1, -16} {2, -8} {3, -8}"
FileName = "Towns.csv"
Dim AllRecords As String() = System.IO.File.ReadAllLines(FileName)
Dim TownList = From record In AllRecords
Let field = record.Split(",")
Select New With {.Name = field(0), .County = field(1), .Population = field(2), .Area = field(3)}
For Each Town In TownList
Console.WriteLine(String.Format(MyFormat, Town.Name, Town.County, Town.Population, Town.Area))
Next
NumberOfRecords = TownList.Count
Console.ReadLine()
End Sub
Sub AddRecord()
Dim FileName As String
FileName = "C:\Users\Omar\Desktop\Towns.csv"
FileOpen(1, FileName, OpenMode.Random)
Dim NewRecord As String
Console.WriteLine("Enter the record you want add")
NewRecord = Console.ReadLine()
FilePut(1, NewRecord, NumberOfRecords + 1)
FileClose(1)
Console.WriteLine("The record has been added")
Console.ReadLine()
End Sub
At the moment the program can list the contents of the csv file however with regard to the AddRecord() Sub, when I input the data Test,Test,Test,Test it is adding this record to the file properly and is overwriting the first record.
How do I fix this?
OpenMode.Random is used for reading/writing files that have a fixed width record. It is unclear from your post if you actually have fixed width records (my hunch is you don't). At any rate, to properly read/write in random mode you'd have to declare a structure that defines the length of each record and also tell the system the length of the record when you open it (so that it can move that many bytes to the desired record position you want to read/write!). Follow the links listed in this page titled Random File Access to learn how to do this.
If you don't actually have fixed width records, but instead have variable length records (one record per line, and the lines are different lengths), then you can simply store all the lines in a List(Of String) and add the new record to the end of the List. Now you simply overwrite the entire file with System.IO.File.WriteAllLines(), similar to what you did with ReadAllLines(). With this approach, you can modify any of the records in the List and then simply overwrite the entire file to update the physical file.
Here's a quick example of what the second approach might look like:
Module Module1
Public AllRecords As New List(Of String)
Public FileName As String = "C:\Users\Omar\Desktop\Towns.csv"
Public Sub Main()
LoadTowns()
ListTowns()
AddRecord()
ListTowns()
End Sub
Public Sub LoadTowns()
AllRecords.Clear()
AllRecords.AddRange(System.IO.File.ReadAllLines(FileName))
End Sub
Public Sub ListTowns()
Dim MyFormat As String = "{0, -22} {1, -16} {2, -8} {3, -8}"
Dim TownList = From record In AllRecords
Let field = record.Split(",")
Select New With {.Name = field(0), .County = field(1), .Population = field(2), .Area = field(3)}
For Each Town In TownList
Console.WriteLine(String.Format(MyFormat, Town.Name, Town.County, Town.Population, Town.Area))
Next
Console.ReadLine()
End Sub
Public Sub AddRecord()
Console.WriteLine("Enter the record you want add")
Dim NewRecord As String = Console.ReadLine()
AllRecords.Add(NewRecord)
System.IO.File.WriteAllLines(FileName, AllRecords.ToArray)
Console.WriteLine("The record has been added")
Console.ReadLine()
End Sub
End Module