Loading object names from a text file (Visual Basic) - vb.net

I have a procedure that saves the name of all of the labels that are clicked to a text file, I then need to load these names later on so that I can change the colour of them to red. This is the procedure that should load the names of the labels from the file:
Sub LoadSeats()
If My.Computer.FileSystem.FileExists("Seats.txt") = True Then 'Checks if the seats.txt file is present
FileReader = New StreamReader("Seats.txt")
NumOfBookedSeats = FileReader.ReadLine() 'Finds out how many seats have been booked
For intCounter = 1 To NumOfBookedSeats
SeatList.Add(FileReader.ReadLine)
BookedSeat.Name = SeatList(intCounter)
BookedSeat.BackColor = Color.Red
BookedSeat.ForeColor = Color.Red
Next
Else
FileWriter = New StreamWriter("Seats.txt")
FileWriter.WriteLine(0)
FileWriter.Close()
End If
End Sub
An error occurs on the this line:
BookedSeat.Name = SeatList(intCounter)
The error says "NullReferenceException was unhandled. Object reference not set to an instance of an object." Im not sure why this is occuring, any help is appreciated.
The 'Seats.txt' file contains this:
4 'This is the number of names in the file
lblG1 'This line and every one following it will contain the name of a label
lblH1
lblI1
lblJ1

It sounds like the variable BookedSeat is null and when you try to access/set the .Name property, this is why you get the error. Can you set a breakpoint and try to check BookedSeat?
EDIT - As per comment
Again you can't call properties on a null object, if you want to create a new BookedSeat then do so before hand. I only know some VB but something like Dim bSeat As New BookedSeat()

Related

'A generic error occurred in GDI+.' saving image to anywhere not Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)

Hoping someone here can help me. I've read the many other similar questions on StackOverflow but haven't found an answer that works for me...
I have code that exports data into an excel report. Part of that code copies an image and places it into a folder just created on the desktop. Then also inserts that image into the excel report. There are two different ways data is exported. Users can export one item at a time, or an entire program of items. When exporting one Item a folder is created on the Desktop with the ItemID, and the image is saved in that folder. When exporting a program a folder is craeted on the desktop for the Program, another folder is created inside that folder for vendor, and anther inside the vendor forlder for the item; Then the image is saved in that item folder. The code works just fine When exporting only an item, but gives an error...
A generic error occurred in GDI+
...on the first image save when exporting a program.
The code to Call the method when exporting one Item is...
Rprt_ItemRFQ_Class.ExportRFQ(Itm_ItemIDCmb.Text, ItmKey, Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), ProgKey)
The Code to Export a group of Items is...
Dim SaveFold As String = IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), ProgName, VendName)
My.Computer.FileSystem.CreateDirectory(SaveFold)
For Each RFQRow As DataRow In DS.RFQRequestForm.Rows()
Rprt_ItemRFQ_Class.ExportRFQ(RFQRow.Item("ItemID"), RFQRow.Item("ItmKey"), SaveFold, ProgKey)
Next
The Code being called is... (SaveFold is a class variable)
Public Shared Sub ExportRFQ(ItemID As String, ItmKey As Integer, StartPath As String, ProgKey As Integer)
SaveFold = IO.Path.Combine(StartPath, ItemID)
My.Computer.FileSystem.CreateDirectory(SaveFold)
"I have cut out all the code for creating and formatting the excel sheet as it is not relevent"
ImgLoad(ItmKey, ItemID)
End Sub
Public Shared Sub ImgLoad(ItmKey As Integer, ItemID As String)
GetPrimImg.Fill(DS.GetPrimImage, ItmKey)
Dim FileStr As String = DS.GetPrimImage.Rows(0).Item(0)
Dim NewPath As String = IO.Path.Combine(SaveFold, ItemID & ".jpg")
Dim fs As IO.FileStream
fs = New IO.FileStream(FileStr, IO.FileMode.Open, IO.FileAccess.ReadWrite)
Dim RFQImg As System.Drawing.Image = System.Drawing.Image.FromStream(fs)
RFQImg.Save(NewPath)
Dim Wid As Integer = IIf(RFQImg.Width = 450, RFQImg.Width * 0.53333, RFQImg.Width * 0.24)
Dim Hgt As Integer = IIf(RFQImg.Height = 450, RFQImg.Height * 0.53333, RFQImg.Height * 0.24)
RFQImg.Dispose()
fs.Close()
xlWorksheet.Range("T1").Select()
Dim P As Object = xlWorksheet.Pictures.Insert(NewPath)
With P
.Left = xlWorksheet.Range("T1").Left
.Top = xlWorksheet.Range("T1").Top
.Placement = ExcelVB.XlPlacement.xlMoveAndSize
.PrintObject = True
With P.ShapeRange
.LockAspectRatio = False
.Width = Wid
.Height = Hgt
.IncrementTop(3.333228)
.IncrementLeft(102.1872441)
End With
End With
End Sub
The Error Occurs on the line
RFQImg.Save(NewPath)
I have tried modifying what gets passed in as SaveFold from the program export, it works just fine if I pass in Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), but any other file path I pass in causes the error.
Ok, I'm kind of an idiot here. Someone saved the vendor name which was the VendName variable with a space character at the end. That is why I was getting the error. I added a trim to the variables and all is good now.

VB.net load controls and content from textfile to textboxes

...Hopefully this question will be readable...
I have 27 textboxes.
The controlname and the text in the textboxes are written to a textfile like this:
System.DateTime.Now.ToString("yyyyMMdd") & "_Names_Config.txt"
Dim objWriter As New System.IO.StreamWriter(configfile, True)
'Textboxes
objwriter.Writeline("tbmax1") 'Control name
objwriter.Writeline("tbmax1.text) 'The text in the textbox
objWriter.WriteLine("tbname1") 'Control name
objWriter.WriteLine(tbname1.Text) 'The text in the textbox
objWriter.WriteLine("tbext1") 'Control name
objWriter.WriteLine(tbext1.Text) 'The text in the textbox
'And so on for all the the controls
This goes on for all the textboxes and controls, so 54 lines in total.
Works great. The textfile looks like this:
Alright, now the issue. There will be a load button that should search the textfile -> find the control matching the form's control -> use the line below and fill that spesific line in the control's textbox -> then find next control and do the same.
Load button: This is #1 attempt;
'Openfiledialog, then:
Using reader As New StreamReader(OpenFileDialog1.FileName.ToString)
Dim currentTextBox As TextBox = Nothing
While reader.Peek > -1
Dim line As String = reader.ReadLine()
If Not String.IsNullOrEmpty(line) Then
Dim tmpTextbox = Controls.Find(line, True) 'Try to find text according to line
If tmpTextbox.Any() Then 'It´s a textbox name
currentTextBox = DirectCast(tmpTextbox(0), TextBox)
Else
'?
End If
End If
End While
End Using
Here comes what I don't understand at all. See before and after picture of what happens to the 27 textboxes after I load the textfile.
What it SHOULD look like:
What it will look like:
"Edit channels" is actually the title of the form itself. I'm speechless. Because I totally don't understand why this happens and the load code, I moved on to another attempt.
#2 attempt:
Using reader As New StreamReader(OpenFileDialog1.FileName)
Dim Line As String = reader.ReadLine()
Dim Current As Integer = 0
Dim TB As TextBox = Nothing
While Not IsNothing(Line) 'It will be Nothing when file is over
'__________________________________________________________________1
If Line.StartsWith("tbext1") Then
'We will increment CurrentChannel, as we changed the section
Current += 1
For onetonine = 1 To 9
tbext1.Text = Line
Next
End If
If Line.StartsWith("tbname1") Then
'We will increment CurrentChannel, as we changed the section
Current += 1
For onetonine = 1 To 9
tbname1.Text = Line
Next
End If
If Line.StartsWith("tbmax1") Then
'We will increment CurrentChannel, as we changed the section
Current += 1
For onetonine = 1 To 9
tbmax1.Text = Line
Next
End If
'__________________________________________________________________2
'Then I guess this would go on for all the 27 textboxes (probably a really bad attempt)
End While
End Using
However, this just goes into break mode.
Your first approach works already if you fill the Else part:
If tmpTextbox.Any() Then
currentTextBox = DirectCast(tmpTextbox(0), TextBox)
ElseIf currentTextBox IsNot Nothing Then
currentTextBox.Text = line
End If
But you should not use it in production code:
Control-names are a very bad key for a database record or file entry:
They can change in future and you won't notice it
They are GUI related and not supposed to be identifiers for properties
is not fail-safe because there could be multiple controls with the same name
don't store key-value pairs on different lines, that makes it difficult, less readable and more error-prone to put them together afterwards
If you want to use one line you need a delimiter that a user never enters, it can be a combination of multiple characters like |::| or something similar. Then you can later use String.Split({"|::|"}, StringSplitOptions.None) to get both tokens back.
However, this is still not a good approach and also not 100% safe. So better approaches were
serialize/deserialize a List(Of String).
If you want to store it in a way that a human can read you should prefer XML.
Here's an example how you can write/read xml easily:
' write all TextBoxes to a file '
Dim allTextBoxes = TextBoxPanel.Controls.OfType(Of TextBox)()
Dim doc As New XDocument(New XElement("Channels"))
For Each txt In allTextBoxes
doc.Root.Add(New XElement(txt.Name, txt.Text.Trim()))
Next
doc.Save(OpenFileDialog1.FileName)
' later read it ... '
Dim xml As XDocument = XDocument.Load(OpenFileDialog1.FileName)
For Each element As XElement In xml.Descendants("Channels").Descendants()
Dim txt = allTextBoxes.FirstOrDefault(function(t) t.Name = element.Name)
If txt IsNot nothing
txt.Text = element.Value
End If
Next

Null Reference Exception when reading file vb.NET

So I am creating a program that needs to be able to read line by line from a .cfg (config) file, it can open it happily; here is the code:
OpenConfig.ShowDialog()
file = OpenConfig.FileName()
fileReader()
However when it tries to read the file, using this code:
Function fileReader()
Dim reader As New StreamReader(file)
Dim vLb As ListBox = shopTabs.SelectedTab.Controls.Item(10) 'Listbox Variable
For i = 0 To reader.Peek
textline(i) = reader.ReadLine()
vLb.Items.Add(i)
Next
Return True
End Function
It throws an exception at the line:
textline(i) = reader.ReadLine()
Any help would be greatly appreciated as I can't work out why it does so.
Your code could be simplified into the following code:
Using openConfig As New OpenFileDialog()
If openConfig.ShowDialog(Me) = DialogResult.OK Then
For Each s As String In File.ReadAllLines(openConfig.FileName)
ListBox1.Items.Add(s)
Next
End If
End Using
As I commented, your code does some things that are highly questionable and undoubtedly difficult to maintain, such as referencing a control by the index property.
I suspect that your project would benefit from using UserControls too, since I'm guessing you have the same controls placed in every tab (a ListBox is always control index #10?).

How to reference controls located on different Tabs (VB.NET)

I have an application written in VB.NET that reads data from a file and displays the data on the screen.
Depending on the data in the file, the program has a TabControl with up to 3 tabs and each tab in turn has a DataGridView for displaying data. For example I have a TabControl that has a tab called "Saturday" and a tab called "Sunday".
The problem I am having is that when I read data from a file, the program displays all the data on the Saturday's tab grid because I am not sure how to reference the Grid on the Sunday tab.
To add the DataGridView I am using the following code:
Grid = New DataGridView
Grid.Dock = DockStyle.Fill
Grid.Name = "Grid" & TabControl.SelectedIndex
Grid.Tag = "Grid" & TabControl.SelectedIndex
And this is how I am reading the data in:
If reader.GetAttribute("controltype") = "Tab" Then
SelectedTab = reader.Name
End If
If reader.Name = "cell" Then
y = y + 1
Grid.Rows(i).Cells(y).Style.BackColor = Color.FromName(reader.ReadElementString("cell"))
End If
What I almost want to do is something like (pseudocode):
SelectedTab.Grid.Rows(i).Cells(y).Style.BackColor = Color.FromName(reader.ReadElementString("cell"))
However when I use the above code it complains:
'Grid' is not a member of 'String'
I hope you understand the issue. Let me know if you need clarification
Your code is a little unclear. However, it appears to me that the following line:
If reader.GetAttribute("controltype") = "Tab" Then
SelectedTab = reader.Name
End If
is creating at least one problem. It looks like you are attempting to refer to a Tabpage control by the string representation of its name, but unless I missed something, what that line is actually doing is trying to make a tabpage control type("SelectedTab") refer to a string type. If that is the case, then you will want to try this instead:
If reader.GetAttribute("controltype") = "Tab" Then
TabControl1.SelectedTab = TabControl1.TabPages(reader.name)
End If
It is a little hard to tell from the code you have posted, but that might get you headed down the right path.
++++++++++++
UPDATE: It appears from your code that you are naming each DGV control by appending the index of the tab on which it is located to the string "grid." I am going to assume that you are using a class member variable named "SelectedTab" to represent the current tab selected in the control. I will assume that at the top of your class you have done something like this:
'Form-or-class scoped memebr variables:
Private SelectedTab As TabPage
Private SelectedGrid As DataGridView
You should be able to refer to the active grid control using something like this:
Private Sub TabControl1_SelectedIndexChanged(sender As Object, e As System.EventArgs) Handles TabControl1.SelectedIndexChanged
' Set SelectedTab member variable to refer to the new selected tab page:
SelectedTab = TabControl1.SelectedTab
' Set the SelectedGrid to refer to the grid control hosted on the selected tab page:
SelectedGrid = TabControl1.SelectedTab.Controls("Grid" & TabControl1.SelectedIndex.ToString())
End Sub
From here, you should be able to use the member variable for SelectedGrid to refer to the grid present on which ever tab page is selected in your tab control.
It is challenging to address your concerns with only fragments of your code. If you have additional difficulties, please post more of your code, so we can better see what else is going on.
Hope that helps!
Okay, I would go about something like this. Maybe you can simply use a DataSet to load the XML data in one line (if they have been saved with DataSet.WriteXML before).
Dim ds As New DataSet
Dim p As TabPage
Dim gv As DataGridView
ds.ReadXml("F:\testdata.xml")
For i As Integer = TabControl1.TabPages.Count - 1 To 0 Step -1
TabControl1.TabPages.RemoveAt(i)
Next
For Each dt As DataTable In ds.Tables
p = New TabPage(dt.TableName)
gv = New DataGridView
' ... configure the gv here...
gv.AutoGenerateColumns = True
gv.Dock = DockStyle.Fill
' ...
gv.DataSource = dt
TabControl1.TabPages.Add(p)
p.Controls.Add(gv)
Next

Why does combo-box return the wrong value?

When I run my program and get it to give me the value (Yes, I do have the items in the drop down list selected) in the combo-box all I get is this,
System.Windows.Forms.ComboBox+ObjectCollection
This is the code I am using
Dim name As String
name = cmbworld.Text
MsgBox(name)
Any ideas?
P.S. The code I used to insert the values is
cmbworld.Items.Clear()
If File.Exists(root + "\setting\world.txt") Then
For Each line As String In File.ReadLines(root + "\setting\world.txt")
If line.Length <> 0 Then
cmbworld.Items.Add(line)
End If
Next line
Else
This code would reproduce the problem:
Dim name As String
name = cmbworld.Items.ToString()
MsgBox(name)
You have some other code somewhere that is assigning the value of the Text property incorrectly. You need to index the Items collection. For example:
cmbworld.Text = cmbWorld.Items(0)
The code you are posting can't be what is not working in your code.
Taking your example, I get a clean message with a line of data from my text file.
The only way I get your message is when I do the following:
MessageBox.Show(cmbworld.Items.ToString)
I would put a stop debugger on that MsgBox line and check the values.
You are using the wrong property, use SelectedText.
cmbworld.SelectedText