Using CSV .txt files with arrays in VB.NET to edit data? - arrays

I'm a beginner trying to learn VB.NET and I'm not quite sure how I'll explain this, but I'll give it a shot. Basically, I've written a txt file with about 10 lines of data in CSV form.
For example:
John, 10, 14
Michael, 14, 27
Billy, 13, 45
etc, etc....
I just want to be able to read and edit particular lines - not necessarily add new lines.
Just wondering if someone could just outline how I'd go about this - not asking anyone to write the program for me. I just don't know what to do and I couldn't understand other answers I've found on SO that attempted to solve the same problem. I don't know if I'm just a bit dense or something so it'd be great if someone could perhaps give a simple, 'dumbed-down' outline of what I need to do.
Thank you.

as stated in the comments you usually read all the file into memory, manipulate it and write it all back.
dotnet has a method that puts a file content in an array (line by line)
if you need to access individual cells in the CSV you probably want to run the split method on each line and join to merge them back together.
the split/join methods are either an method of the string/array object or its in the Strings namespace
a method for writing the file back is also in the System.IO Namespace

You don't asking to write the code for you, I can understand you but I think there is no way to show how can you do that. I used split/join methods as #weberik mentioned. It is a simple console application:
Public Class Sample
Public Shared Sub Main()
CreateExampleFileIfNotExists()
'lines variable is an "Array"
Dim lines() As String = IO.File.ReadAllLines("Example.txt")
'write items to the console
ShowItems(lines, "Values before edit:")
'edit the items
EditItems(lines)
'write edited items to the console
ShowItems(lines, "Values after edit:")
'save changes?
Save(lines)
'finish
Console.WriteLine("Press any key to exit.")
Console.ReadKey()
End Sub
Public Shared Sub ShowItems(lines() As String, header As String)
Console.WriteLine(header)
Dim headers() As String = {"Name:", "Value1:", "Value2:"}
WriteItems(headers)
For Each line In lines
WriteItems(line.Split(","))
Next
End Sub
Public Shared Sub EditItems(lines() As String)
For i As Integer = 0 To lines.Length - 1
Dim line As String = lines(i)
Dim values() As String = line.Split(",")
'edit the item
values(0) = "Edited " & values(0)
values(1) += i
values(2) *= i
lines(i) = String.Join(",", values)
Next
Console.WriteLine() 'empty line
End Sub
Public Shared Sub WriteItems(itemValues() As String)
Dim line As String = ""
For Each item In itemValues
line &= item & vbTab & vbTab
Next
Console.WriteLine(line)
End Sub
Public Shared Sub CreateExampleFileIfNotExists()
If Not IO.File.Exists("Example.txt") Then
IO.File.WriteAllLines("Example.txt", {"John,10,14", "Michael,14,27", "Billy,13,45"})
End If
End Sub
Public Shared Sub Save(lines() As String)
Console.WriteLine(vbCrLf & "Do you want to save the changes? Y/N")
Dim result = Console.ReadKey()
Console.WriteLine()
Select Case result.Key
Case ConsoleKey.Y
IO.File.WriteAllLines("Example.txt", lines)
Console.WriteLine("The changes has been saved.")
End Select
End Sub
End Class

Related

Bad file name or number (VB.NET)

I am attempting to try and write everything in the file just into console, but I keep getting Error 52: "Bad file name or number" and I'm not sure what im doing wrong. This is in VB16 in visual studio. The name of the file that is being read is "example1.txt".
Imports System
Imports System.IO
Module Program
Sub Main()
Dim name() As String = {}
Dim i As Integer = 0
FileOpen(1, "example1.txt", OpenMode.Input)
While Not EOF(1)
name(i) = LineInput(i)
Console.WriteLine(name(i))
i += 1
End While
FileClose(1)
Console.ReadLine()
End Sub
End Module
The specific issue here is that you specify a file number of 1 when you open the file:
FileOpen(1, "example1.txt", OpenMode.Input)
but then you use different file numbers when you read the lines:
name(i) = LineInput(i)
You're not telling LineInput to read a specific line. You're telling it to read the next line from a specific file. That should be:
name(i) = LineInput(1)
This is an example of why you should not use magic numbers in your code. It's too easy to mess them up. If you want to use the same value for the same reason in multiple places, assign it to a variable or even a constant and then use that each time:
Dim fileNumber = 1
FileOpen(fileNumber, "example1.txt", OpenMode.Input)
While Not EOF(fileNumber)
name(i) = LineInput(fileNumber)
EDIT:
To achieve equivalent functionality with good VB.NET code, you would do something like this:
Imports System.IO
Module Module1
Sub Main()
Dim names As New List(Of String)
Using inputFile As New StreamReader("example1.txt")
While Not inputFile.EndOfStream
Dim name = inputFile.ReadLine()
names.Add(name)
Console.WriteLine(name)
End While
End Using
Console.ReadLine()
End Sub
End Module
or this:
Imports System.IO
Module Module1
Sub Main()
Dim names As New List(Of String)
For Each name In File.ReadLines("example1.txt")
names.Add(name)
Console.WriteLine(name)
Next
Console.ReadLine()
End Sub
End Module
or this:
Imports System.IO
Module Module1
Sub Main()
Dim names = File.ReadAllLines("example1.txt")
For Each name In names
Console.WriteLine(name)
Next
Console.ReadLine()
End Sub
End Module
Note that the last example is slightly different because names is an array rather than a collection and the entire file is read first, before each name is output to the console. It would appear the same from the user's perspective though. Once they are populated, you can pretty much use an array and a collection in exactly the same way.

array of arrays visual basic

I'm developing a module for capture Attlogs from a ZKSoftware Fingerprint Biometric and send it to MySQL database using the SDK that came with the CD, so far I manage to connect successfully to the clock, display the logs on a listview, but I got stuck pushing the values on a multidimensional array, i'm sure it's a matter of declaration but I better ask for help... the code is as follows:
Dim thisLog(1) As String
Dim allLogs()() As String = New String()() {}
afterwards where the iteration (i) load the Attlogs in the listview I got:
thisLog = {sdwEnrollNumber, idwYear.ToString() & "-" + idwMonth.ToString() & "-" & idwDay.ToString() & " " & idwHour.ToString() & ":" & idwMinute.ToString() & ":" & idwSecond.ToString()}
allLogs(i) = {thisLog(0), thisLog(1)}
The error I'm getting is related to the size of the array, so the question can be resumed in how can I create a rectangular array (2)(n) with every row of the captured data. Thanks in advance
I would highly suggest you create a class to store the data in. Have a List(Of LogEntry) afterward. This would make your code a lot easier to read.
Class LogEntry
Public Property EnrollNumber As String
Public Property EntryDate As DateTime
Public Sub New(ByVal enrollNumber As String, ByVal entryDate As DateTime)
Me.EnrollNumber = enrollNumber
Me.EntryDate = entryDate
End Sub
End Class
For adding a new record, you just need to create an instance of that class and add it to the list.
Dim allLogs As New List(Of LogEntry)
allLogs.Add(New LogEntry(sdwEnrollNumber, New DateTime(idwYear, idwMonth, idwDay, idwHour, idwMinute, idwSecond)))
Since you'll now have a valid date instead of a concatenation of string, it'll be easy to do manipulation afterward.
Console.WriteLine(allLogs(0).EnrollNumber)
Console.WriteLine(allLogs(0).EntryDate.ToString("yyyy-MM-dd HH:mm:ss"))
how can I create a rectangular array (2)(n) with every row of the captured data?
Use a List:
Dim allLogs As New List(Of String())()
allLogs.Add(New String(1) {sdwEnrollNumber, _
String.Format("{0}-{1}-{2} {3}:{4}:{5}", _
idwYear, idwMonth, idwDay, idwHour, idwMinute, idwSecond)} )
I might also use the appropriate DateTime constructor and format string to format that 2nd part, depending on how you get those idw variables in the first place.

How to convert a text file to an array in Visual Basic 2008 line by line?

I am newer to Visual Basic and I am trying to get into file reading. From what I've found online I haven't found anything that wasn't entirely confusing to me.
I am trying to make a simple game to test some dialogue things and I want the options of what you can say to be predetermined. Right now I have a few sentences in arrays, but what I really want to do is just type everything into a text file with a different item on each line and then convert each line to a separate item of an array.
What I have right now is:
Dim convoStarters() As String = {"Hello", "Who are you?", "Who the hell are you?"}
What I want to do is take information from a text file organized like so:
Hello
Who are you?
Who the hell are you?
and put each line into an array that looks exactly like the one I have above (except of course, I'd add more things to the text file).
Thank you for helping a new guy out, have a nice day.
First of all you have to find out, how many elements are necessary for your array.
By counting the numbers of '","' + 1 you have the numbers of elements existing in your string.
Please have a look in string methods like instr(), mid(), left(), rtrim(), ltrim() ..
With the number of elements you found you can REDIM array, or REDIM PRESERVER array
for your example REDIM strArr(nrElements) or if you need to add some elements without
loosing content use REDIM PRESERVE strArr(nrElements).
Then you can fill it up:
for x = LBound(strArr,1) to Ubound(strArr,1)
strArr(x) = Stringpart(x)
next x
Always open your "direct window" in VBA Editor under menu "view" and use debupg.print strArr(x)
Assuming you meant VB.NET and not VBA (both for the tag to Visual Studio and for the purpose of development a game), you can use a StreamReader to read the file line by line and adding the elements to the string then:
VB.NET SOLUTION
Note: if you didn't do yet, to interact with any file (input or output) you need to import the IO of the system, which means state this on top of your code:
Imports System.IO
...then...
GLOBAL VARIABLES (on top of the module, out of any sub/function)
Dim myStringElements As Integer
Dim convoStarters() As String
SUB CODE
Public Sub yourSub()
myStringElements = 0
Dim sr As StreamReader = New StreamReader(path) 'this object will read the text file
Do While sr.Peek() >= 0 'this will loop through the lines until the end
AddElementToStringArray(sr.ReadLine()) 'this will add the single line to the string array
Loop
sr.Close()
End Sub
PUBLIC FUNCTION BODY (another sub that makes the adding job)
Public Sub AddElementToStringArray(ByVal stringToAdd As String)
ReDim Preserve convoStarters(myStringElements)
convoStarters(myStringElements) = stringToAdd
myStringElements += 1
End Sub
VBA SOLUTION
But if as of your comment you rather meant VBA, then the logic is the same but the syntax is slightly different:
GLOBAL VARIABLES
Dim myStringElements As Integer
Dim convoStarters() As String
SUB CODE
myStringElements = 0
Open "C:\Users\Matteo\Desktop\Test.txt" For Input As #1
While Not EOF(1)
Line Input #1, DataLine ' read in data 1 line at a time
AddElementToStringArray (DataLine) 'this will add the single line to the string array
Wend
PUBLIC FUNCTION BODY
Public Sub AddElementToStringArray(ByVal stringToAdd As String)
ReDim Preserve convoStarters(myStringElements)
convoStarters(myStringElements) = stringToAdd
myStringElements += 1
End Sub

How to have a global Dictionary in VB.NET/WPF application to save data from different windows?

I am new to VB.NET and WPF.
I am building a "Questionnaire" app. Users will be presented sequentially with different questions/tasks (windows). After they respond on each question/task and press a "submit" button a new window will open with a new question/task, and previous window will close. After each question, when the button is pressed, I need to store data to some global object. After all questions are answered the data of this object should be written out to the output file.
I figured out that Dictionary will be the best to store the results after each window.
I am not sure how, where to create this global Dictionary and how to access it. Should I use View Model? If yes, can you give an example? Or, should it be just a simple class with shared property? (something like this)
EDIT 2: I tried many different ways recommended online
GlobalModule:
Module GlobalModule
Public Foo As String
End Module
GlobalVariables:
Public Class GlobalVariables
Public Shared UserName As String = "Tim Johnson"
Public Shared UserAge As Integer = 39
End Class
Global properties:
Public Class Globals
Public Shared Property One As String
Get
Return TryCast(Application.Current.Properties("One"), String)
End Get
Set(ByVal value As String)
Application.Current.Properties("One") = value
End Set
End Property
Public Shared Property Two As Integer
Get
Return Convert.ToInt32(Application.Current.Properties("Two"))
End Get
Set(ByVal value As Integer)
Application.Current.Properties("Two") = value
End Set
End Property
End Class
Here is where I save the data to global variables/properties in the first window. I need to store data in this subroutine before closing an old window and opening a new window. I use MessageBox just for testing.
Private Sub btnEnter_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnEnter.Click
Dim instructionWindow As InstructionsWindow
instructionWindow = New InstructionsWindow()
Application.Current.Properties("number") = textBoxValue.Text
Globals.One = "2"
Globals.Two = 3
MessageBox.Show("GlobalVariables: UserName=" & GlobalVariables.UserName & " UserAge=" & GlobalVariables.UserAge)
GlobalVariables.UserName = "Viktor"
GlobalVariables.UserAge = 34
GlobalModule.Foo = "Test Foo"
'testing if it saved tha value
'MessageBox.Show(Application.Current.Properties("number"))
Application.Current.MainWindow.Close()
instructionWindow.ShowDialog()
End Sub
Next subroutine is where I am trying to retrieve the value from global Properties/variables in the second window, but message boxes come out empty. There might also the case that I am assigning values in a wrong way, or not reading them in a right way (casting?) :
Private Sub FlowDocReader_Initialized(ByVal sender As Object, ByVal e As System.EventArgs) Handles FlowDocReader.Initialized
' Get a reference to the Application base class instance.
Dim currentApplication As Application = Application.Current
MessageBox.Show(currentApplication.Properties("number"))
MessageBox.Show("One = " & Globals.One & " Two = " & Globals.Two)
MessageBox.Show("GlobalVariables: UserName=" & GlobalVariables.UserName & " UserAge=" & GlobalVariables.UserAge)
MessageBox.Show("GlobalModule.Foo = " & GlobalModule.Foo)
Dim filename As String = My.Computer.FileSystem.CurrentDirectory & "\instructions.txt"
Dim paragraph As Paragraph = New Paragraph()
paragraph.Inlines.Add(System.IO.File.ReadAllText(filename))
Dim document As FlowDocument = New FlowDocument(paragraph)
FlowDocReader.Document = document
End Sub
Thanks.
You can make public Dictionary property for form and put your dictionry to this property or make constructor with Dictionary argument.
You already have this dictionary Application.Properties
Look here, please.
First, you can define a dictionary (list of lists) as follows at the beginning of a form or in a module
Dim dic As New Dictionary(Of String, List(Of String))
As the user completes questions on a form, write the partucular form number and query results to a single record in the dic before going to the next form (place this code into the "Next" button):
'Assume q1response=3, q2response=4,..., qpresponse="text", etc.
Dim myValues As New List(Of String)
myValues.Add(formname)
myValues.Add(q1response)
myValues.Add(q2response)
.
.
myValues.Add(qpresponse)
dic.Add(username, myValues)
When a user is done, there will be multiple records in the dictionary, each of which starts with their name and is followed by question responses. You can loop through multiple dictionary records, where each record is for a user using the following:
For Each DictionaryEntry In dic 'this loops through dic entries
Dim str As List(Of String) = DictionaryEntry.Value
'here you can do whatever you want with results while you read through dic records
'username will be = str(0)
'formname will be str(1)
'q1 response on "formname" will be str(2)
'q2 response on "formname" will be str(3)
'q3 response on "formname" will be str(4)
...
Next
The trick is that there will be multiple dictionary records with results for one user, where record one can have results like "John Doe,page1,q1,q2,q3" and record 2 will be "John Doe,page2,q4,q5,q6." Specifically, the "str" in the above loop will be an array of string data containing all the items within each dictionary record, that is, in str(0), str(1), str(2),... This is the information you need to work with or move, save, analyze, etc.
You can always put all the code I provided in a class (which will be independent of any form) and dimension the sic is a Sub New in this class, with the updating .Add values lines in their own sub in this same class). Then just Dim Updater As New MyNewClassName. Call the Updater in each continue button using Call Updater.SubNameWithAddValues(q1,q2,...qp). It won't matter where you are in your program since you using a specific class. The one thing I noticed with my code is that you can only use the line that adds the "key" or the username once, so use it after the last query -so put it in a Sub Finished in your new class and call as Call Updater.Finished(username,q30,q31,last)

Reading comma-separated lines from textbox

I've been reading and reading tons of answers, modifying the code, and still i cant figure out how to solve this problem.
I have a textbox that receives multiline comma-separated information from a .txt or .csv file. Example:
Pearl Harbour;Ticonderoga CG-45;300;1000 Everett;Ticonderoga
CG-46;310;1200 Pearl Harbour;Burke DDG-110;215;800
Now there will be a combobox to chose a port (in this example the options will be Pearl Harbour and Everett). After choosing "Pearl Harbour", another multiline textbox will show only the lines which have "Pearl Harbour" as the first element.
Now goes what I was able to write:
Public Sub Readfile()
TextBox1.Text = System.IO.File.ReadAllText("libro1.csv")<br>
Dim lines() As String<br>
lines = Split(TextBox1.Text, vbCrLf)<br>
Dim strline0 As String = lines(0)<br>
Dim strArray0() As String = strline0.Split(";")<br>
Dim strline1 As String = lines(1)<br>
Dim strArray1() As String = strline1.Split(";")<br>
...
End Sub
The first problem I find is that for every line the .csv has, I must write that two lines of code to have an array with all the information. But I cant do that because I cant know how many lines the .csv is going to have.
Im kind of lost here. Im not asking anyone to do magic and give me a code I can copy and paste, but I would be grateful if someone can guide me through this.
First off, you'd do better to use a List than an array. Particularly for a collection of strings, they're much easier to work with. With that, you're correct that you can't go individually naming your lines because you don't know how many there will be. That's why you need to create a list of lines and loop through them, like ...
Public Sub Readfile()
TextBox1.Text = System.IO.File.ReadAllText("libro1.csv")
Dim lines As List(of String)
Dim allResults As New List(of List(of String))
lines = Split(TextBox1.Text, vbCrLf)
For Each line In lines
Dim result As List(Of String) = line.Split(CChar(";"))
allResults.Add(result)
Next
End Sub
This will allow you to essentially say, "For each line in the file, take each semi-colon-separated part and put it into a list called 'result'. Then put 'result' into another list of results called 'allResults'."
Behold! The power of loops!

Resources