How to Serialize or Save Multiple Forms to Single File - vb.net

Essentially I'm creating a D&D character sheet with 9 forms, 6 of which will be saved. I need to save every TextBox in each of those 6 forms. I haven't tried Serialization yet as I haven't found an especially good guide that clarifies exactly what I need to do yet, and at this point it's fairly confusing to me. I have, however, tried saving to a file and writing back when the file is opened. This works for one form, but I'm almost certain that it won't work for multiple forms given the way that the code is written.
Dim SaveCharacter As StreamWriter
If txtName.Text = "" Then
MessageBox.Show("In order to save, you must at least enter a name for your character.", "Error: No Name Entered")
Else
SaveCharacterAs.ShowDialog()
System.IO.File.WriteAllText(SaveCharacterAs.FileName, "")
Try
For Each cnt In Me.Controls.OfType(Of TextBox)
SaveCharacter = File.AppendText(SaveCharacterAs.FileName)
SaveCharacter.WriteLine(cnt.Text)
SaveCharacter.Close()
Next
For Each cnt In frmAttributeRoller.Controls.OfType(Of TextBox)
SaveCharacter = File.AppendText(SaveCharacterAs.FileName)
SaveCharacter.WriteLine(cnt.Text)
SaveCharacter.Close()
Next
The above code is what I have for writing to a file. I was thinking of trying to save the file to a .txt file with the name of the character that's entered in the form, and for each subform that I'm saving, create a separate .txt file with the character name concatenated with the form name, then write code to open all of those files in the correct forms, but that could get messy if the user selects the wrong file to start with. Is there a better way to save multiple forms to one file without serializing? Is serializing my best bet?
Thanks for the help!

Here's a suggestion. Create a DataSet with tables that describe your character sheet fields. Then create an instance of that DataSet and add a record with default (mostly blank) values to the table.
Now you can bind the columns to text boxes like this. (I'm doing this from memory, so forgive me if it doesn't compile - it should at least point you in the right direction
Dim ds As New CharacterDataSet ' Whatever you call your dataset
Dim bs As New BindingSource(ds, ds.CharacterTable.TableName)
bs.MoveFirst()
' Note, if you end up having more than one record, you can use bs.Filter
' to select which record the BindingSource points to.
txtCharacterName.DataBindings.Add("Text", bs, "CharacterName") ' Where CharacterName is the name of the column in the table
cboCharacterRace.DataBindings.Add("SelectedValue", bs, "Race") ' For a ComboBox
Also, if you want to be more robust with your column names in the DataBindings.Add, you can do something like ds.CharacterTable.CharacterNameColumn.ColumnName. That way, you can't accidentally misspell the column name in the binding.
Now you can use DataSet.WriteXML to write out the the whole dataset in one shot.

Related

VB.NET write/read data from text file

This might be something that I am overlooking, as I am currently reading a book on VB.NET. I canceled a course in VB.Net recently because I was stuck on a problem and the lecturer did not get back to me with my questions that I had.
The objective was to create a business application with VB.NET that writes data from text boxes to a text file, seperated by a comma or a pipe. The user of the application must be able to select the directory where they want the file to be saved.
So I have for example 2 forms, one that captures the data for a client, and another form where you can select from a drop-down control, Now I know that streamwriter allows for the user to select self where they want the file to be saved, but how do I make the second form intelligent to know where the user saved the form and then reads the client_id, and fills the other data associated with the client_id to the text boxes in the form. I know streamreader is the one to use when you want to read data from a file, but how will streamreader know where the user will save the file to?
I am not doing the course any more, but I will keep on thinking what I could have done to actually get the project to work.
For writing to file
// Write single line to new file.
Using writer As New StreamWriter("C:\log.txt", True)
writer.WriteLine("Important data line 1")
End Using
For reading from file
// read from a file
Dim line As String
Using reader As New StreamReader("file.txt")
line = reader.ReadLine()
End Using
Console.WriteLine(line)

VB 2010: ScrollToCaret won't work on plain textbox but will with rich text box

I have written an application in VB 2010 that generates log files, and I wanted to add a feature to view the log files without leaving the app. This was done, naturally, by adding a form with a text box and loading in the file.
Sometimes these files get plenty big, so I was looking for a way to just show the most recent entries -- i.e., the last few lines. I got that figured out (using a pretty cool method that works really fast without iterating through all the lines of text).
Just to make it convenient, I wanted to make it display the very bottom of the text box, so ScrollToCaret() was employed. However, in this particular text box, the ScrollToCaret() function didn't work, no matter how I tried to implement it. If I use a RichTextBox, it works fine, and if that's what I need to do, that's how I'll do it. But I have to know why it wouldn't work in a regular text box.
Here's my code:
Dim intLineCount As Int64 = IO.File.ReadAllLines(strFileName).Length
Dim intStartPosition As Int64 = intLineCount - 1000
Dim intPositionLoop As Int64
Try
Dim strAllLines() As String = File.ReadAllLines(strFileName)
For intPositionLoop = intStartPosition To intLineCount
txtViewLogs.AppendText(strAllLines(intPositionLoop - 1) & vbNewLine)
Next
Catch ex As Exception
End Try
txtViewLogs.Focus()
txtViewLogs.ScrollToCaret()
As this shows, this will display the last 1000 lines of the log file. When the file is completely loaded, the caret is already at the end of the file, so there was no need to set the SelectionStart point to the end of the file, but I even tried that, and no luck.
In order to eliminate the possibility that some property of the text box could have been accidentally changed, I deleted the text box and added another one, taking care not to make any accidental changes to the properties.
Anyone have any idea why it's like this? As I said, if I have to stick with a rich text box, that's what I'll do, but it kills me not knowing why this is doing that. I know I've used this in other applications, but I can't see why it won't work with this one.

A way to save a specific My.Settings Variable in VB.NET

in My.Settings i've alot of variables including a 36000 records Datatable and Couple Large Array Lists, now when i call My.Settings.Save() it saves all the variables which takes alot of time and it saves variables that haven't been changed, is there a way make it Save only a Specific Datatable or ArrayList?
My.Setting.Save()
'but what i want for example is something like
My.Settings.SomeDatatable.Save()
These settings are stored in an XML file. Since XML files do not store data in a fixed-width record format, there is no way to update a single node in an XML file without rewriting the whole thing. If it is too slow, I would recommend either:
Store these settings in multiple XML files, so that you only have to save the applicable file, but not the rest
Store the settings in the database where each row can be saved individually without rewriting the whole file
Databases store their data in fixed-width "pages" so that only the modified pages need to be rewritten, rather than the whole file.
What about saving your dataTable not within your Settings. You could make use of DataTable.WriteXml(). this would keep your settings much smaller and you can access them separately!
' save table
DataTable.WriteXml("yourFile.xml")
' load table
Dim newTable As New DataTable
newTable.ReadXml(fileName)
But if there is no other possibility this solution from SLaks will work too
' save table
Dim writer As New StringWriter()
table.WriteXml(writer)
My.MySettings.Default.TableXml = writer.ToString()
' load table
Dim reader As New StringReader(My.MySettings.Default.TableXml)
table.ReadXml(reader)

SSIS custom script: loop over columns to concatenate values

I'm trying to create a custom script in SSIS 2008 that will loop over the selected input columns and concatenate them so they can be used to create a SHA1 hash. I'm aware of the available custom components but I'm not able to install them on our system at work.
Whilst the example posed here appears to work fine http://www.sqlservercentral.com/articles/Integration+Services+(SSIS)/69766/ when I've tested this selected only a few and not all columns I get odd results. The script only seems to work if columns selected are in sequential order. Even when they are in order, after so many records or perhaps the next buffer different MD5 hashes are generated despite the rows being exactly the same throughout my test data.
I've tried to adapt the code from the previous link along with these articles but have had no joy thus far.
http://msdn.microsoft.com/en-us/library/ms136020.aspx
http://agilebi.com/jwelch/2007/06/03/xml-transformations-part-2/
As a starting point this works fine to display the column names that I have selected to be used as inputs
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
For Each inputColumn As IDTSInputColumn100 In Me.ComponentMetaData.InputCollection(0).InputColumnCollection
MsgBox(inputColumn.Name)
Next
End Sub
Building on this I try to get the values using the code below:
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
Dim column As IDTSInputColumn100
Dim rowType As Type = Row.GetType()
Dim columnValue As PropertyInfo
Dim testString As String = ""
For Each column In Me.ComponentMetaData.InputCollection(0).InputColumnCollection
columnValue = rowType.GetProperty(column.Name)
testString += columnValue.GetValue(Row, Nothing).ToString()
Next
MsgBox(testString)
End Sub
Unfortunately this does not work and I receive the following error:
I'm sure what I am trying to do is easily achievable though my limited knowledge of VB.net and in particular VB.net in SSIS, I'm struggling. I could define the column names individually as shown here http://timlaqua.com/2012/02/slowly-changing-dimensions-with-md5-hashes-in-ssis/ though I'd like to try out a dynamic method.
Your problem is trying to run ToString() on a NULL value from your database.
Try Convert.ToString(columnValue) instead, it just returns an empty string.
The input columns are not guaranteed to be in the same order each time. So you'll end up getting a different hash any time the metadata in the dataflow changes. I went through the same pain when writing exactly the same script.
Every answer on the net I've found states to build a custom component to be able to do this. No need. I relied on SSIS to generate the indexes to column names when it builds the base classes each time the script component is opened. The caveat is that any time the metadata of the data flow changes, the indexes may change and need to be updated by re-opening and closing the SSIS script component.
You will need to override ProcessInput() to get store a reference to PipelineBuffer, which isn't exposed in ProcessInputRow, where you actually need to use it to access the columns by their index rather than by name.
The list of names and associated indexes are stored in ComponentMetaData.InputCollection[0].InputColumnCollection, which needs to be iterated over and sorted to guarantee same HASH every time.
PS. I posted the answer last year but it vanished, probably because it was in C# rather than VB (kind of irrelevant in SSIS). You can find the code with all ugly details here https://gist.github.com/danieljarolim/e89ff5b41b12383c60c7#file-ssis_sha1-cs

An item with the same key has already been added - csvreader.fieldcount

I'm trying to create an import program from CSV.
My code is
csv = New CsvReader(New StreamReader("CSVFileLocation"), True)
Dim fieldCount As Integer = csv.FieldCount
The error message "An item with the same key has already been added." on the second line.
If I changed "HasReaders" to "False", there's no such error. But, I'm not able to get the Headers.
Could somebody help me on this, please?
FYI: I'm using Visual Studio 2010 version.
Regards,
Richard
Check that your CSV file may have duplicate column names, or multiple empty cells, in the header row?
If that's the case, try to loop through your csv object, and try rename the headers in code before calling the property FieldCount.
My guess is that the CsvReader class is going through the first row adding strings to a dictionary, and the header row has two cells with the same value (so two identically named fields). Take a look at your data and see if this is the case. Alternately, if you have access to the source code for CsvReader, you could have it handle this case by naming the second field something slightly different (e.g., by appending a "1" onto the end of its name).