Import CSV file with comma and multiline text in quotes in a DataGridView - vb.net

I'm trying to import a CSV file into a DataGridView but I'm running in some issues when I try to import multiline text.
What I'm trying to import is this:
ID;RW;Name;Description;Def;Unit;Min;Max
0;R;REG_INFO;"state of the
machine";0;ms;0;0xFFFF
1;R/W;REG_NUMBER;current number;0;days;0;65,535
This is what it should like when imported:
What I've implemented till now:
Private Sub btnOpen_Click(sender As Object, e As EventArgs) Handles btnOpen.Click
Using ofd As OpenFileDialog = New OpenFileDialog() With {.Filter = "Text file|*.csv"}
If ofd.ShowDialog() = DialogResult.OK Then
Dim lines As List(Of String) = File.ReadAllLines(ofd.FileName).ToList()
Dim list As List(Of Register) = New List(Of Register)
For i As Integer = 1 To lines.Count - 1
Dim data As String() = lines(i).Split(";")
list.Add(New Register() With {
.ID = data(0),
.RW = data(1),
.Name = data(2),
.Description = data(3),
.Def = data(4),
.Unit = data(5),
.Min = data(6),
.Max = data(7)
})
Next
DataGridView1.DataSource = list
End If
End Using
End Sub
But I run in some problems with multiline text when I try to load the CSV, as "state of the machine" in the example.

An example, using the TextFieldParser class.
(This class is available in .Net 5)
The TextFieldParser object provides methods and properties for parsing
structured text files. Parsing a text file with the TextFieldParser is
similar to iterating over a text file, while using the ReadFields
method to extract fields of text is similar to splitting the strings
Your source of data is a delimited (not fixed-length) structure, the header/fields values are separated by a symbol, so you can specify TextFieldType = FieldType.Delimited
The delimiter is not a comma (the C in CSV), so you need to pass the delimiter symbol(s) to the SetDelimiters() method.
Call the ReadFields() to extract each line as an array of String, representing the Fields' values (=> here, no conversion is performed, all values are returned as strings. Make your own Type converter in case it's needed.)
Imports Microsoft.VisualBasic.FileIO
Public Class RegisterParser
Private m_FilePath As String = String.Empty
Private m_delimiters As String() = Nothing
Public Sub New(sourceFile As String, delimiters As String())
m_FilePath = sourceFile
m_delimiters = delimiters
End Sub
Public Function ReadData() As List(Of Register)
Dim result As New List(Of Register)
Using tfp As New TextFieldParser(m_FilePath)
tfp.TextFieldType = FieldType.Delimited
tfp.SetDelimiters(m_delimiters)
tfp.ReadFields()
Try
While Not tfp.EndOfData
result.Add(New Register(tfp.ReadFields()))
End While
Catch fnfEx As FileNotFoundException
MessageBox.Show($"File not found: {fnfEx.Message}")
Catch exIDX As IndexOutOfRangeException
MessageBox.Show($"Invalid Data format: {exIDX.Message}")
Catch exIO As MalformedLineException
MessageBox.Show($"Invalid Data format at line {exIO.Message}")
End Try
End Using
Return result
End Function
End Class
Pass the path of the CSV file and the set of delimiters to use (here, just ;).
The ReadData() method returns a List(Of Register) objects, to assign to the DataGridView.DataSource.
DefaultCellStyle.WrapMode is set to True, so multiline text can actually wrap in the Cell (otherwise it would be clipped).
After that, call AutoResizeRows(), so the wrapped text can be seen.
Dim csvPath = [The CSV Path]
Dim csvParser = New RegisterParser(csvPath, {";"})
DataGridView1.DataSource = csvParser.ReadData()
DataGridView1.Columns("Description").DefaultCellStyle.WrapMode = DataGridViewTriState.True
DataGridView1.AutoResizeRows()
Register class:
Added a constructor that accepts an array of strings. You could change it to Object(), then add a converter to the class to parse and convert the values to another Type.
Public Class Register
Public Sub New(ParamArray values As String())
ID = values(0)
RW = values(1)
Name = values(2)
Description = values(3)
Def = values(4)
Unit = values(5)
Min = values(6)
Max = values(7)
End Sub
Public Property ID As String
Public Property RW As String
Public Property Name As String
Public Property Description As String
Public Property Def As String
Public Property Unit As String
Public Property Min As String
Public Property Max As String
End Class

Related

Split a string array problems vb.net

I am new to VB.NET and would like to split a string into an array.
I have a string like:
613,710,200,127,127,'{\"js\":{\"\":\"16\",\"43451\":\"16\",\"65815\":\"16\",\"43452\":\"16\",\"41147\":\"16\",\"43449\":\"16\",\"43467\":\"16\",\"1249\":\"16\",\"43462\":\"16\",\"43468\":\"48\",\"43438\":\"64\",\"43439\":\"80\"}}','rca',95,2048000,3,1,'AABBCCDDEEFFGGHHIIJJKKLL=','xx.xx.xx.xx',NULL
I want to split this into a array at ",".
I tried:
Dim variable() As String
Dim stext As String
stext = "mystringhere"
variable = Split(stext, ",")
My problem is the part of
'{\"js\":{\"\":\"16\",\"43451\":\"16\",\"65815\":\"16\",\"43452\":\"16\",\"41147\":\"16\",\"43449\":\"16\",\"43467\":\"16\",\"1249\":\"16\",\"43462\":\"16\",\"43468\":\"48\",\"43438\":\"64\",\"43439\":\"80\"}}',
is split too. I want this to get all together in variable(5). Is this posible?
thank you for help
What you need is a CSV parser in which you can set the field quote character. Unfortunately the TexFieldParser which comes with VB.NET doesn't have that facility. Fortunately, other ones do - here I have used the LumenWorksCsvReader, which is available as a NuGet package *.
Option Strict On
Option Infer On
Imports System.IO
Imports LumenWorks.Framework.IO.Csv
Module Module1
Sub Main()
Dim s = "613,710,200,127,127,'{\""js\"":{\""\"":\""16\"",\""43451\"":\""16\"",\""65815\"":\""16\"",\""43452\"":\""16\"",\""41147\"":\""16\"",\""43449\"":\""16\"",\""43467\"":\""16\"",\""1249\"":\""16\"",\""43462\"":\""16\"",\""43468\"":\""48\"",\""43438\"":\""64\"",\""43439\"":\""80\""}}','rca',95,2048000,3,1,'AABBCCDDEEFFGGHHIIJJKKLL=','xx.xx.xx.xx',NULL"
Using sr As New StringReader(s)
Using csvReader = New CsvReader(sr, delimiter:=","c, quote:="'"c, escape:="\"c, hasHeaders:=False)
Dim nFields = csvReader.FieldCount
While csvReader.ReadNextRecord()
For i = 0 To nFields - 1
Console.WriteLine(csvReader(i))
Next
End While
End Using
End Using
Console.ReadLine()
End Sub
End Module
which outputs
613
710
200
127
127
{"js":{"":"16","43451":"16","65815":"16","43452":"16","41147":"16","43449":"16","43467":"16","1249":"16","43462":"16","43468":"48","43438":"64","43439":"80"}}
rca
95
2048000
3
1
AABBCCDDEEFFGGHHIIJJKKLL=
xx.xx.xx.xx
NULL
Note that the double-quotes are doubled up in the literal string as that is the way to enter a single double-quote in VB.
If you really want the backslashes to remain, remove the escape:="\"c parameter.
If you are reading from a file then use the appropriate StreamReader instead of the StringReader.
Using the above, perhaps you have a Windows Forms program where you wanted to populate a RichTextBox with the data from, say, a text file named "C:\temp\CsvFile.txt" with the content
613,710,200,127,127,'{\""js\"":{\""\"":\""16\"",\""43451\"":\""16\"",\""65815\"":\""16\"",\""43452\"":\""16\"",\""41147\"":\""16\"",\""43449\"":\""16\"",\""43467\"":\""16\"",\""1249\"":\""16\"",\""43462\"":\""16\"",\""43468\"":\""48\"",\""43438\"":\""64\"",\""43439\"":\""80\""}}','rca',95,2048000,3,1,'AABBCCDDEEFFGGHHIIJJKKLL=','xx.xx.xx.xx',NULL
614,710,200,127,127,'{\""js\"":{\""\"":\""16\"",\""43451\"":\""16\"",\""65815\"":\""16\"",\""43452\"":\""16\"",\""41147\"":\""16\"",\""43449\"":\""16\"",\""43467\"":\""16\"",\""1249\"":\""16\"",\""43462\"":\""16\"",\""43468\"":\""48\"",\""43438\"":\""64\"",\""43439\"":\""80\""}}','din',95,2048000,3,1,'AABBCCDDEEFFGGHHIIJJKKLL=','yy.yy.yy.yy',NULL
615,710,200,127,127,'{\""js\"":{\""\"":\""16\"",\""43451\"":\""16\"",\""65815\"":\""16\"",\""43452\"":\""16\"",\""41147\"":\""16\"",\""43449\"":\""16\"",\""43467\"":\""16\"",\""1249\"":\""16\"",\""43462\"":\""16\"",\""43468\"":\""48\"",\""43438\"":\""64\"",\""43439\"":\""80\""}}','jst',95,2048000,3,1,'AABBCCDDEEFFGGHHIIJJKKLL=','zz.zz.zz.zz',NULL
you could use the above to come up with
Imports System.IO
Imports LumenWorks.Framework.IO.Csv
Public Class Form1
Public Class Datum
Property A As Integer
Property B As Integer
Property C As Integer
Property D As Integer
Property E As Integer
Property JsonData As String
Property SocketType As String
Property F As Integer
Property G As Integer
Property H As Integer
Property I As Integer
Property Base64Data As String
Property IpAddy As String
Property J As String
Public Overrides Function ToString() As String
Return $"{A}, {SocketType}, {IpAddy}, {B} ,{C}, {D}, {E}, {F}, {G}, {H}, {I}, {JsonData}, {Base64Data}, {J}"
End Function
End Class
Public Function GetData(filename As String) As List(Of Datum)
Dim data As New List(Of Datum)
Using sr As New StreamReader(filename)
Using csvReader = New CsvReader(sr, hasHeaders:=False, delimiter:=","c, quote:="'"c, escape:="\"c, comment:=Nothing, trimmingOptions:=ValueTrimmingOptions.UnquotedOnly)
Dim nFields = csvReader.FieldCount
If nFields <> 14 Then
Throw New MalformedCsvException("Did not find 14 fields in the file " & filename)
End If
While csvReader.ReadNextRecord()
Dim d As New Datum()
d.A = Integer.Parse(csvReader(0))
d.B = Integer.Parse(csvReader(1))
d.C = Integer.Parse(csvReader(2))
d.D = Integer.Parse(csvReader(3))
d.E = Integer.Parse(csvReader(4))
d.JsonData = csvReader(5)
d.SocketType = csvReader(6)
d.F = Integer.Parse(csvReader(7))
d.G = Integer.Parse(csvReader(8))
d.H = Integer.Parse(csvReader(9))
d.I = Integer.Parse(csvReader(10))
d.Base64Data = csvReader(11)
d.IpAddy = csvReader(12)
d.J = csvReader(13)
data.Add(d)
End While
End Using
End Using
Return data
End Function
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim srcFile = "C:\temp\CsvData.txt"
Dim dat = GetData(srcFile)
For Each d In dat
RichTextBox1.AppendText(d.ToString() & vbCrLf)
Next
End Sub
End Class
It might be necessary to perform more checks on the data when trying to parse it. Note that I made a function for the .ToString() method of the Datum class and put the properties in a different order just to demonstrate its use.
* Tools -> NuGet Package Manager -> Manage NuGet Packages for Solution... Choose the "Browse" tab -> type in LumenWorksCsvReader -> select the one by Sébastien Lorion et al., -> tick your project name in the pane to the right -> click Install.
I am new to VB.NET and would like to split a string into an array.
...
variable = Split(stext,",")
Instead of
variable = Split(stext,",")
use
variable = stext.split(",")
If you want to get a bit more complicated on your split you would create an array of char data as such
dim data(3) as char
data(0) = ","c
data(1) = vbcrlf
data(2) = chr(34)
data(3) = vbtab
... and so on
variable = stext.split(data)

how to write to/read from a "settings" text file

I'm working on a Timer program, that allows the user to set up a timer for each individual user account on the computer. I'm having some trouble writing the settings to a text file and reading from it. I want to know if it's possible to write it in this fashion --> username; allowedTime; lastedLoggedIn; remainingTime; <-- in one line for each user, and how would I go about doing that? I also wanted to know if it's possible to alter the text file in this way, in the case that there's already an entry for a user, only change the allowedTime, or the remainingTime, kinda just updating the file?
Also I'm also having trouble being able to read from the text file. First of all I can't figure out how to determine if a selected user is in the file or not. Form there, if the user is listed in the file, how can access the rest of the line, like only get the allowedTime of that user, or the remaining time?
I tried a couple of ways, but i just can't get it to do how I'm imaging it, if that makes sense.
here's the code so far:
Public Sub saveUserSetting(ByVal time As Integer)
Dim hash As HashSet(Of String) = New HashSet(Of String)(File.ReadAllLines("Settings.txt"))
Using w As StreamWriter = File.AppendText("Settings.txt")
If Not hash.Contains(selectedUserName.ToString()) Then
w.Write(selectedUserName + "; ")
w.Write(CStr(time) + "; ")
w.WriteLine(DateTime.Now.ToLongDateString() + "; ")
Else
w.Write(CStr(time) + "; ")
w.WriteLine(DateTime.Now.ToLongDateString() + "; ")
End If
End Using
End Sub
Public Sub readUserSettings()
Dim currentUser As String = GetUserName()
Dim r As List(Of String) = New List(Of String)(System.IO.File.ReadLines("Settings.txt"))
'For Each i = 0 to r.lenght - 1
'Next
'check to see if the current user is in the file
MessageBox.Show(r(0).ToString())
If r.Contains(selectedUserName) Then
MessageBox.Show(selectedUserName + " is in the file.")
'Dim allowedTime As Integer
Else
MessageBox.Show("the user is not in the file.")
End If
'if the name is in the file then
'get the allowed time and the date
'if the date is older than the current date return the allowed time
'if the date = the current date then check thhe remaning time and return that
'if the date is ahead of the current date return the reamining and display a messgae that the current date needs to be updated.
End Sub
edit: I just wanted to make sure if I'm doing the serialization right and the same for the deserialization.
this is what i got so far:
Friend userList As New List(Of Users)
Public Sub saveUserSetting()
Using fs As New System.IO.FileStream("Settings.xml", IO.FileMode.OpenOrCreate)
Dim bf As New BinaryFormatter
bf.Serialize(fs, userList)
End Using
End Sub
Public Sub readUserSettings()
Dim currentUser As String = GetUserName()
Dim useList As New List(Of Users)
Using fs As New System.IO.FileStream("Settings.xml", IO.FileMode.OpenOrCreate)
Dim bf As New BinaryFormatter
useList = bf.Deserialize(fs)
End Using
MessageBox.Show(useList(0).ToString)
End Sub
<Serializable>
Class Users
Public userName As String
Public Property allowedTime As Integer
Public Property lastLoggedInDate As String
Public Property remainingTime As Integer
Public Overrides Function ToString() As String
Return String.Format("{0} ({1}, {2}, {3})", userName, allowedTime, lastLoggedInDate, remainingTime)
End Function
End Class
edit 2:
I'm not too familiar with try/catch but would this work instead?
Public Sub readUserSettings()
If System.IO.File.Exists("Settings") Then
Using fs As New System.IO.FileStream("Settings", FileMode.Open, FileAccess.Read)
Dim bf As New BinaryFormatter
userList = bf.Deserialize(fs)
End Using
Else
MessageBox.Show("The setting file doesn't exists.")
End If
End Sub
You have a few typos and such in your code, but it is pretty close for your first try:
Friend userList As New List(Of Users)
Public Sub saveUserSetting()
' NOTE: Using the BINARY formatter will write a binary file, not XML
Using fs As New System.IO.FileStream("Settings.bin", IO.FileMode.OpenOrCreate)
Dim bf As New BinaryFormatter
bf.Serialize(fs, userList)
End Using
End Sub
Public Sub readUserSettings()
' this doesnt seem needed:
Dim currentUser As String = GetUserName()
' do not want the following line - it will create a NEW
' useRlist which exists only in this procedure
' you probably want to deserialize to the useRlist
' declared at the module/class level
' Dim useList As New List(Of Users)
' a) Check if the filename exists and just exit with an empty
' useRlist if not (like for the first time run).
' b) filemode wass wrong - never create here, just read
Using fs As New System.IO.FileStream("Settings.bin",
FileMode.Open, FileAccess.Read)
Dim bf As New BinaryFormatter
' user list is declared above as useRList, no useList
useList = bf.Deserialize(fs)
End Using
' Console.WriteLine is much better for this
MessageBox.Show(useList(0).ToString)
End Sub
<Serializable>
Class Users
' I would make this a property also
Public userName As String
Public Property allowedTime As Integer
Public Property lastLoggedInDate As String
Public Property remainingTime As Integer
Public Overrides Function ToString() As String
Return String.Format("{0} ({1}, {2}, {3})", userName, allowedTime, lastLoggedInDate, remainingTime)
End Function
End Class
ToDo:
a) decide whether you want XML or binary saves. With XML, users can read/edit the file.
b) Use a file path created from Environment.GetFolder(); with a string literal it may end up in 'Program Files' when deployed, and you cannot write there.
c) when reading/loading the useRlist, use something like
FileStream(myUserFile, FileMode.Open, FileAccess.Read)
It wont exist the first time run, so check if it does and just leave the list empty. After that, you just need to open it for reading. For saving use something like:
FileStream(myUserFile, FileMode.OpenOrCreate, FileAccess.Write)
You want to create it and write to it. You might put the Load/Save code inside a Try/Catch so if there are file access issues you can trap and report them, and so you know the list did not get saved or read.
Using a serializer, the entire contents of the list - no matter how long - will get saved with those 3-4 lines of code, and the entire list read back in the 2-3 lines to load/read the file.
I don't have the answer to all your questions however I've been also working on a timer application and just recently started using text file to read and write information. The method I'm using has proven itself fairly easy to use and not very confusing. Here is an extract of my code:
Dim startup As String = "C:\Users\DigiParent\Desktop\Project data\Digitimeinfo.txt"
Dim reader As New System.IO.StreamReader(startup, Encoding.Default)
Dim data As String = reader.ReadToEnd
Dim aryTextFile(6) As String
aryTextFile = data.Split(",")
This will read everything in the text file and in sort separate everything in between the , and store them individual in the array. To put the code back in one line use
Dim LineOfText As String
LineOfText = String.Join(",", aryTextFile)
so you could write someting like this to write your info to a text file:
Dim startup As String = "C:\Users\DigiParent\Desktop\Project data\Digitimeinfo.txt"
Dim objWriter As New System.IO.StreamWriter(startup, False)
Dim aryTextFile(2) As String
aryTextFile(0) = pasword
aryTextFile(1) = user
aryTextFile(2) = remainingtime
LineOfText = String.Join(",", aryTextFile)
objWriter.WriteLine(LineOfText)
objWriter.Close()
and to read it you could use steam reader.

request.querystring in vb.net

I have this url that i need to decode:
http://gistest:54321/default.aspx?data=%7B%22id%22:%2269403%22,%22longitude%22:%22-143.406417%22,%22latitude%22:%2232.785834%22,%22timestamp%22:%2223-10%2010:12%22%7D
This code changes every time
I use this code:
<%Response.Write(Request.QueryString.Item("data") )%><br/>
<%Response.Write(Request.QueryString.Item("id") )%><br/>
<%Response.Write(Request.QueryString.Item("longitude") )%><br/>
<%Response.Write(Request.QueryString.Item("latitude") )%><br/>
<%Response.Write(Request.QueryString.Item("timestamp") )%><br/>
But i only get this as output, maybe there is an option where to check if data is not null, and then i request.querystring the other parts in data:
{"id"="69403","longitude"="-143.406417","latitude"="32.785834","timestamp"="23-10 10:12"}
This is from
<%Response.Write(Request.QueryString.Item("data") )%>
I really hope I understood the problem correctly. I am assuming you require the values of each key within the query string key called Data? To do so I used the code below:
Dim values() As String = Server.UrlDecode(Request.QueryString("data")).Replace("{", "").Replace("}", "").Split(New Char() {","}, StringSplitOptions.RemoveEmptyEntries)
For Each value As String In values
Dim keyValue() As String = value.Split(New Char() {":"}, StringSplitOptions.RemoveEmptyEntries)
Response.Write(keyValue(0).Replace("""", "") & " : " & keyValue(1).Replace("""", "") & "<br/>")
Next
In a nutshell, I decode the QueryString("data"), replace the braces and split the string into an array by using the comma as the first split character. We then end up with an array containing values in the following format "id":"649403".
Thereafter I iterate through the values and split one final time for each value based on the semi-colon (:) character.
With this method you can build and manipulate the data dynamically.
Code Edit
I replaced all references of ":" with "=" to ensure that the time stamp will be correctly retrieved and then split the key values based on =. You can use a select case to assign variables to values if necessary. (Obviously make sure your variable is not declared within the select as it will not be in the right scope for later use!)
If Request.QueryString("data") IsNot Nothing Then
Dim values() As String = Request.QueryString("data").Replace("{", "").Replace("}", "").Replace(""":""", """=""").Split(New Char() {","}, StringSplitOptions.RemoveEmptyEntries)
For Each value As String In values
Dim keyValue() As String = value.Split(New Char() {"="}, StringSplitOptions.RemoveEmptyEntries)
Response.Write(keyValue(0).Replace("""", "") & " : " & keyValue(1).Replace("""", "") & "<br/>")
Select Case keyValue(0).ToLower()
Case "id"
Dim id As String = keyValue(1)
End Select
Next
End If
Reflection Edit
Create an instance of your object then retrieve all its properties (Dim properties() As PropertyInfo = myObj.GetType().GetProperties()). Iterate through the properties and set the value where the name is equal to the key. Don't forget to import the System.Reflection library.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim data As String = "%7B%22id%22:%2269403%22,%22longitude%22:%22-143.406417%22,%22latitude%22:%2232.785834%22,%22timestamp%22:%2223-10%2010:12%22%7D"
If data IsNot Nothing Then
Dim myObj As New MyObject
Dim properties() As PropertyInfo = myObj.GetType().GetProperties()
Dim values() As String = Server.UrlDecode(data).Replace("{", "").Replace("}", "").Replace(""":""", """=""").Split(New Char() {","}, StringSplitOptions.RemoveEmptyEntries)
For Each value As String In values
Dim keyValue() As String = value.Split(New Char() {"="}, StringSplitOptions.RemoveEmptyEntries)
For Each prop As PropertyInfo In properties
If prop.Name.ToLower = keyValue(0).ToLower.Replace("""", "") Then
prop.SetValue(myObj, keyValue(1), Nothing)
End If
Next
Next
myObj.Save()
End If
End Sub
Public Class MyObject
Private _ID As String
Private _Longitude As String
Private _Latitude As String
Private _Timestamp As String
Public Property ID As String
Get
Return _ID
End Get
Set(value As String)
_ID = value
End Set
End Property
Public Property Longitude As String
Get
Return _Longitude
End Get
Set(value As String)
_Longitude = value
End Set
End Property
Public Property Latitude As String
Get
Return _Latitude
End Get
Set(value As String)
_Latitude = value
End Set
End Property
Public Property Timestamp As String
Get
Return _Timestamp
End Get
Set(value As String)
_Timestamp = value
End Set
End Property
Public Sub Save()
'Save logic here
End Sub
End Class
I think the problem you are running into is that there only is one querystring parameter in the URL you posted, and that is data. The rest of the information is encoded in the data querystring value. The value stored in data almost looks like a JSON/Javascript object, except with an = in between the property names and values instead of a :.
So, basically you won't be able to use Request.QueryString to get the values of id, longitude, latitude, etc. I think your options are to either write some code to parse the value of data yourself or replace the = with : and use a JSON parser for .NET (i.e., the JavascriptSerializer class or JSON.net).
Personally, I would write a method in the codebehind that would return a Dictionary(Of String, Object). In that method just I would just change every "=" to a ":" and then use the JavaScriptSerializer provided with .NET to parse the string. I don't have an ASP.NET instance handy right now, but the following sample I threw together in LinqPad should illustrate the idea:
Sub Main
Dim url = "http://gistest:54321/default.aspx?data=%7B%22id%22=%2269403%22,%22longitude%22=%22-143.406417%22,%22latitude%22=%2232.785834%22,%22timestamp%22=%2223-10%2010:12%22%7D"
Dim uri = New Uri(url)
Dim data = System.Web.HttpUtility.ParseQueryString(uri.Query)("data")
Dim o = ParseData(data)
Console.WriteLine(o("id"))
Console.WriteLine(o("longitude"))
Console.WriteLine(o("latitude"))
Console.WriteLine(o("timestamp"))
End Sub
Function ParseData(data As String) As Dictionary(Of String, Object)
Dim js = new System.Web.Script.Serialization.JavaScriptSerializer()
Dim o = js.DeserializeObject(data.Replace("""=""", """:"""))
ParseData = DirectCast(o, Dictionary(Of String, Object))
End Function
One thing to note about this approach is that I am expecting the url to be in the same format as what you posted. You may need to modify this method to make it more robust to handle different inputs.
If you drop the ParseData function into your codebehind, then something like the following code in your front page should give you the output you are looking for (again, sorry I don't have an ASP.NET instance to test with right now):
<%
Dim o = ParseData(Request.QueryString.Item("data"))
Response.Write(o("id"))
Response.Write("<br />")
Response.Write(o("longitude"))
Response.Write("<br />")
Response.Write(o("latitude"))
Response.Write("<br />")
Response.Write(o("timestamp"))
Response.Write("<br />")
%>

Referencing an Unbound DataGridView Without Specifically Naming It?

I am using 3 unbound DataGridView controls to display certain information. To load the information into those DGVs, I am pulling the information from an encrypted file, decrypting it, parsing the information, then trying to fill the DGVs with that information. The loading from the file is called by the menu item click. Here is what I have so far:
Private Sub miCLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles miCLoad.Click
Dim FilePath As String = "C:\FList\CList.clt"
Dim LoadFile As New SaveandLoad.SaveAndLoad
Dim FileRead As New Simple3Des("MyPassword")
Dim FileString As String = FileRead.ReadFile(FilePath)
With LoadFile
.WhichList = dgCourses
.FilePath = FilePath
.DecryptedString = FileRead.DecryptData(FileString)
.dgList = dgCourses
End With
Call LoadFile.LoadFile()
End Sub
Public Class SaveandLoad
Public Property WhichList As New DataGridView
Public Property FilePath As String
Public Property DecryptedString As String
Public Property EncryptedString As String
Public Property dgList As Control
Public Sub LoadFile()
Dim dgRow As DataGridViewRow
Dim dgCell As DataGridViewTextBoxCell
Dim Lines() As String = DecryptedString.Split(vbLf)
Dim LinesList As List(Of String) = Lines.ToList
LinesList.RemoveAt(Lines.Length - 1)
For Each Line As String In LinesList
Dim Fields() As String = Line.Split(",")
dgRow = New DataGridViewRow
For x = 0 To (WhichList.Columns.Count - 1) Step 1
dgCell = New DataGridViewTextBoxCell
dgCell.Value = Fields(x).ToString
dgRow.Cells.Add(dgCell)
Next
WhichList.Rows.Add(dgRow)
Next
Select Case WhichList.Name
Case "dgCourses"
frmFacultyList.dgCourses = WhichList
frmFacultyList.dgCourses.Refresh()
WhichList.Dispose()
Case "dgFList"
frmFacultyList.dgFList = WhichList
frmFacultyList.dgFList.Refresh()
WhichList.Dispose()
Case "dgSList"
frmFacultyList.dgSList = WhichList
frmFacultyList.dgSList.Refresh()
WhichList.Dispose()
End Select
MsgBox("List Successfully Loaded", vbOKOnly, "Load")
End Sub
I want to be able to reference (or fill) a DGV without using 'select case' or 'if-then' statements. This will be too inefficient once I start adding the many other DGVs, that will be added in the future. Therefore, the title is the main question. I am using VS Express 2010.
I don't know VB too much, however, I'll post my solution in C# (may be helpfull in some way....)
DataGridView myDGV;
foreach (var item in this.Controls)
{
if (item.GetType() == typeof(DataGridView))
{
if (((DataGridView)item).Name == WhichList.Name)
{
//Cannot assing to 'item' here, because it is a 'foreach iteration variable'
//However you can save the variable for later use.
myDGV = (DataGridView)item;
}
}
}
myDGV = WhichList;
// different approach
DataGridView myDGV = (DataGridView)this.Controls.Find(WhichList.Name, false).First();
myDGV = WhichList;
Here is what worked for me in VB.NET:
Dim FormControls As New frmFacultyList.ControlCollection(frmFacultyList)
For Each DGV As DataGridView In FormControls
If WhichList.Name = DGV.Name Then
DGV = WhichList
DGV.Refresh()
End If
Next
Make an instance of the control collection then search specifically for DGVs using For Each. Simple and efficient.

compare and merge multiple files the text file using VB.NET

I have a multiple text files that I need to merge. but I need to compare the reference number before merge it.
below is the text file
Text 1
001Email
002Video
003SocialNetwork
Text 2
001Gmail
001Yahoo
002Youtube
002Metacafe
003Facebook
003Myspace
Text 3
www.gmail.com001
www.yahoo.com001
www.youtube.com002
www.myspace.com002
www.facebook.com003
www.myspace.com003
Output
001Email
001Gmail
www.gmail.com001
001Yahoo
wwww.yahoo.com001
002Video
002Youtube
www.youtube.com002
002Metacafe
www.metacafe.com002
003SocialNetwork
003Facebook
www.facebook.com003
003Myspace
www.myspace.com003
What will be the fastest way to deal it read line by line to compare. the text file consist of thousand of line
Here's what might possibly be an overly complex solution. The comments in the code should explain everything hopefully. The output doesn't match exactly what you have because I don't know how much order is important for everything. It sorts everything first by the reference number and then by the text portion of the string (excluding www.). The results you posted were in reference number order and then file parsing order and then alphabetical (002Metacafe came after 002Video). Let me know if that's important.
Option Explicit On
Option Strict On
Imports System.IO
Imports System.Text.RegularExpressions
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
''//List of files to process
Dim Files As New List(Of String)
Files.Add(Path.Combine(My.Computer.FileSystem.SpecialDirectories.Desktop, "Text1.txt"))
Files.Add(Path.Combine(My.Computer.FileSystem.SpecialDirectories.Desktop, "Text2.txt"))
Files.Add(Path.Combine(My.Computer.FileSystem.SpecialDirectories.Desktop, "Text3.txt"))
''//Will hold the current line being read
Dim Line As String
''//Holds our main collection of data
Dim MyData As New List(Of Data)
''//Loop through each file
For Each F In Files
''//Open the file for reading
Using FS As New FileStream(F, FileMode.Open, FileAccess.Read, FileShare.Read)
Using SR As New StreamReader(FS)
''//Read each line
Line = SR.ReadLine()
Do While Line IsNot Nothing
''//The data constructor handles parsing of the line
MyData.Add(New Data(Line))
''//Read next line
Line = SR.ReadLine()
Loop
End Using
End Using
Next
''//Our data implements IComparable(Of Data) so we can just sort the list
MyData.Sort()
''//Output our data
For Each D In MyData
Trace.WriteLine(D)
Next
Me.Close()
End Sub
End Class
Public Class Data
Implements IComparable(Of Data)
''//Our RegEx pattern for looking for a string that either starts or ends with numbers
Private Shared ReadOnly Pattern As String = "^(?<RefStart>\d+)?(?<Text>.*?)(?<RefEnd>\d+)?$"
Public Text As String ''//The _text_ portion of the data
Public Reference As String ''//The reference number stored as text
Public ReferenceAtStart As Boolean ''//Whether the reference number was found at the start or end of the line
Public ReadOnly Property ReferenceAsNum() As Integer ''//Numeric version of the reference number for sorting
Get
Return Integer.Parse(Me.Reference)
End Get
End Property
Public ReadOnly Property TextComparable() As String ''//Remove the www for sorting
Get
Return Me.Text.Replace("www.", "")
End Get
End Property
Public Sub New(ByVal line As String)
''//Sanity check
If String.IsNullOrEmpty(line) Then Throw New ArgumentNullException("line")
''//Parse the line
Dim M = Regex.Match(line, Pattern)
If M Is Nothing Then Throw New ArgumentException("Line does not conform to expected pattern")
''//If the RefStart has a value then the number is at the beginning of the string
If M.Groups("RefStart").Success Then
Me.ReferenceAtStart = True
Me.Reference = M.Groups("RefStart").Value
Else ''//Otherwise its at the end
Me.ReferenceAtStart = False
Me.Reference = M.Groups("RefEnd").Value
End If
Me.Text = M.Groups("Text").Value
End Sub
Public Function CompareTo(ByVal other As Data) As Integer Implements System.IComparable(Of Data).CompareTo
''//Compare the reference numbers first
Dim Ret = Me.ReferenceAsNum.CompareTo(other.ReferenceAsNum)
''//If they are the same then compare the strings
If Ret = 0 Then Ret = String.Compare(Me.TextComparable, other.TextComparable, StringComparison.InvariantCultureIgnoreCase)
Return Ret
End Function
Public Overrides Function ToString() As String
''//Reproduce the original string
If Me.ReferenceAtStart Then
Return String.Format("{0}{1}", Me.Reference, Me.Text)
Else
Return String.Format("{1}{0}", Me.Reference, Me.Text)
End If
End Function
End Class