DTName is a DataTable which returns rows in the code below...when I iterate it through the loop from 0 to its count. Only the data in first row is displayed.
How to get all the rows of the datatable displayed in the result ?
DTName = GetClientNames()
If Not DTName Is Nothing Then
For i = 0 to DTName.Rows.count
strName = DTName.Rows(i).Item("Client Name").Tostring()
Next i
End if
For i = 0 to DTName.Rows.count would eventually throw a IndexOutOfRangeException error when the value of i equals to DTName.Rows.count, the limit should be DTName.Rows.count - 1 .
To get all the values from all datarows, store them in a List :
Dim strName As New List(Of String)
For i = 0 to DTName.Rows.count - 1
strName.Add(DTName.Rows(i)("Client Name").Tostring())
Next i
Alternatively you could use Foreach like this :
For Each DR As DataRow In DTName.Rows
strName.Add(DR("Client Name").Tostring())
Next
I also suggest you remove the redundant check if DTName.Rows.Count > 0
EDIT : You could Declare strName as string and append row values to it :
For i = 0 to DTName.Rows.count - 1
strName &= (DTName.Rows(i)("Client Name").Tostring() & ",")
Next i
Response.Write(strName)
Double to check the actual ColumnName of the Column.
For Each item As DataRow In dataTable.Rows
strName = item("Client Name").ToString()
Console.WriteLine(strName)
Next
Related
I am fetching distinct words in a string column of a DataTable (.dt) and then replacing the unique values with another value, so essentially changing words to other words. Both approaches listed below work, however, for 90k records, the process is not very fast. Is there a way to speed up either approach?
The first approach, is as follows:
'fldNo is column number in dt
For Each Word As String In DistinctWordList
Dim myRow() As DataRow
myRow = dt.Select(MyColumnName & "='" & Word & "'")
For Each row In myRow
row(fldNo) = dicNewWords(Word)
Next
Next
A second LINQ-based approach is as follows, and is actually not very fast either:
Dim flds as new List(of String)
flds.Add(myColumnName)
For Each Word As String In DistinctWordsList
Dim rowData() As DataRow = dt.AsEnumerable().Where(Function(f) flds.Where(Function(el) f(el) IsNot DBNull.Value AndAlso f(el).ToString = Word).Count = flds.Count).ToArray
ReDim foundrecs(rowData.Count)
Cnt = 0
For Each row As DataRow In rowData
Dim Index As Integer = dt.Rows.IndexOf(row)
foundrecs(Cnt) = Index + 1 'row.RowId
Cnt += 1
Next
For i = 0 To Cnt
dt(foundrecs(i))(fldNo) = dicNewWords(Word)
Next
Next
So you have your dictionary of replacements:
Dim d as New Dictionary(Of String, String)
d("foo") = "bar"
d("baz") = "buf"
You can apply them to your table's ReplaceMe column:
Dim rep as String = Nothing
For Each r as DataRow In dt.Rows
If d.TryGetValue(r.Field(Of String)("ReplaceMe"), rep) Then r("ReplaceMe") = rep
Next r
On my machine it takes 340ms for 1 million replacements. I can cut that down to 260ms by using column number rather than name - If d.TryGetValue(r.Field(Of String)(0), rep) Then r(0) = rep
Timing:
'setup, fill a dict with string replacements like "1" -> "11", "7" -> "17"
Dim d As New Dictionary(Of String, String)
For i = 0 To 9
d(i.ToString()) = (i + 10).ToString()
Next
'put a million rows in a datatable, randomly assign dictionary keys as row values
Dim dt As New DataTable
dt.Columns.Add("ReplaceMe")
Dim r As New Random()
Dim k = d.Keys.ToArray()
For i = 1 To 1000000
dt.Rows.Add(k(r.Next(k.Length)))
Next
'what range of values do we have in our dt?
Dim minToMaxBefore = dt.Rows.Cast(Of DataRow).Min(Function(ro) ro.Field(Of String)("ReplaceMe")) & " - " & dt.Rows.Cast(Of DataRow).Max(Function(ro) ro.Field(Of String)("ReplaceMe"))
'it's a crappy way to time, but it'll prove the point
Dim start = DateTime.Now
Dim rep As String = Nothing
For Each ro As DataRow In dt.Rows
If d.TryGetValue(ro.Field(Of String)("ReplaceMe"), rep) Then ro("ReplaceMe") = rep
Next
Dim ennd = DateTime.Now
'what range of values do we have now
Dim minToMaxAfter = dt.Rows.Cast(Of DataRow).Min(Function(ro) ro.Field(Of String)("ReplaceMe")) & " - " & dt.Rows.Cast(Of DataRow).Max(Function(ro) ro.Field(Of String)("ReplaceMe"))
MessageBox.Show($"min to max before of {minToMaxBefore} became {minToMaxAfter} proving replacements occurred, it took {(ennd - start).TotalMilliseconds} ms for 1 million replacements")
I want to choose non-duplicate elements in DataTable
Where DataTable contains data as follows
TABLE A
COLUMN A
AM1
AM5
AM6
AM5
AM1
AM1
AM1
Where the final output is datatable= AM6
MY CODE
Public Function RemoveDuplicateRowsG(ByVal dTable As DataTable) As DataTable
For intI = dTable.Rows.Count - 1 To 0 Step -1
For intJ = intI - 1 To 0 Step -1
If dTable.Rows(intI)(0) = dTable.Rows(intJ)(0) Then
dTable.Rows.RemoveAt(intI)
dTable.Rows.RemoveAt(intJ)
Exit For
End If
Next
Next
dTable.AcceptChanges()
Return dTable
End Function
Maybe if you iterate the datatable first and select the row(s) which contain the value only once, put it inside a new datatable and return the newly created datatable.
Dim dtToReturn As New DataTable
For Each row As DataRow in dTable.Rows
'Select all rows from original datatable with the same value
Dim datarow() As DataRow = dTable.Select("COLUMN A = " & row.Item(0))
'Insert to the new datatable if returned datarow collection only has 1 row
If datarow.Count = 1 Then
dtToReturn.Rows.Add(datarow)
End If
Next
Return dtToReturn
I have code that produces a csv file (with headers) that contain fields identifying pixel locations of points of interest in selected images. Unfortunately, there are occasional duplicates that cause issues later in my production process. My plan to solve this is to open the csv file in the midst of the application, read the data into a data table, sort the data table with a data view using 4 sort keys (I am using the default Column1, Column2 etc) as i cannot figure out ho to use the real column header names contained in the first row. I have attempted to write the resulting rows to a new file, and I get the correct number of rows in the output csv file, but the data in the row is missing and i get a text string ' System.Data.DataRowView, not the 12 fields i was expecting.
In the code, my most recent attempt is to create a writeOutPutLine containing the concatenated contents of the row, in my desired sort order.
I have attempted to use CSVHelper with no success, and also tried about 10 other code sets posted on the various web sites.
Here is my code
Sub New_Csv_Sort()
Dim linecount As Integer = 1
Dim dt As DataTable = New DataTable
Dim dgv As DataGridView = New DataGridView
Dim TextLine As String = ""
Dim SplitLine() As String
Dim objReader As New System.IO.StreamReader(TargetFileName, Encoding.ASCII)
Dim ColumnCount As Integer = 0
For ColumnCount = 1 To 13 Step 1
dt.Columns.Add()
Next
Dim firstline As Boolean = True
Do While objReader.Peek() <> -1
TextLine = objReader.ReadLine()
SplitLine = Split(TextLine, ",")
dt.Rows.Add(SplitLine)
If FirstTime = True Then
' Here I was trying to use the first line to set the column labels but no joy
' For ColumnCount = 1 To 12 Step 1
' dt.datacolumn.
' Next
End If
Loop
' This next is commentted out in the sort statement because I could not get the column names to be recognised
'.Sort = "Datum ASC, Picture ASC, Y_Loc ASC, X_Loc, ASC"
Dim dv As New DataView(dt) With {
.Sort = "Column5 ASC, Column1 ASC, Column12 ASC, Column11 ASC"
}
FileOpen(SortedTargetFileNumber, SortedTargetFileName, OpenMode.Output)
'I have looked that the data and it is read in correctly
But my output line is trash!
For Each Rowview As DataRowView In dv
'WriteOutPutLine = dv.row
For Each DataColumn In dt.Columns
WriteOutPutLine = WriteOutPutLine & Row[col].tostring() & ","
Next
WriteOutPutLine = Rowview.ToString
PrintLine(SortedTargetFileNumber, WriteOutPutLine)
linecount = linecount + 1
Next
FileClose(SortedTargetFileNumber)
MsgBox("Sorted Lines = " & linecount)
End Sub
Sub New_Csv_Sort()
Dim dt As DataTable = New DataTable
Dim TextLine As String = ""
Dim SplitLine() As String
Dim objReader As New System.IO.StreamReader(TargetFileName, Encoding.ASCII)
Dim ColumnCount As Integer = 0
'Create columns for the data -
For ColumnCount = 1 To 13 Step 1
dt.Columns.Add()
Next
'Load the datatable
Do While objReader.Peek() <> -1
TextLine = objReader.ReadLine()
SplitLine = Split(TextLine, ",")
dt.Rows.Add(SplitLine)
Loop
'This is the sort order based on the header titles, but is translated the the default column name
'.Sort = "Datum ASC, Picture ASC, Y_Loc ASC, X_Loc ASC"
Dim dv As New DataView(dt) With {
.Sort = "Column5 ASC, Column1 ASC, Column12 ASC, Column11 ASC"
}
'Open the output file
FileOpen(SortedTargetFileNumber, SortedTargetFileName, OpenMode.Output)
'Create a string of all the rows in the dataview separated by commas
Dim DataLine As String = ""
For Each r As DataRowView In dv
DataLine &= String.Join(",", r.Row.ItemArray) & Environment.NewLine
Next
' Write the data to a file
WriteOutPutLine = DataLine
PrintLine(SortedTargetFileNumber, WriteOutPutLine)
FileClose(SortedTargetFileNumber)
' and we are done
End Sub
try this function
Private Function ConvertToCSV(ByVal dt As DataTable) As String
Dim sb As New Text.StringBuilder()
For Each row As DataRow In dt.Rows
sb.AppendLine(String.Join(",", (From i As Object In row.ItemArray Select i.ToString().Replace("""", """""").Replace(",", "\,").Replace(Environment.NewLine, "\" & Environment.NewLine).Replace("\", "\\")).ToArray()))
Next
Return sb.ToString()
End Function
When I go to add data in first row there is empty lines that appear below my code, why do these lines appear? I need only to add data in one row and save it.
Dim pringdata As String = "SELECT * FROM itemInfo "
Dim sqlconload As New SqlConnection(sqlcon)
Try
sqlconload.Open()
Dim da As New SqlDataAdapter(pringdata, sqlconload)
ds.Clear()
da.Fill(ds, "itemInfo")
Dim rowcount As Integer
rowcount = ds.Tables("itemInfo").Rows.Count
If rowcount >= 1 Then
DGVorders.Rows.Add(rowcount)
For i = 0 To rowcount - 1
If DGVorders.CurrentRow.Cells(0).Value = ds.Tables("itemInfo").Rows(i).Item("itemCode") Then
DGVorders(1, e.RowIndex).Value = ds.Tables("itemInfo").Rows(i).Item("itemName")
DGVorders(2, e.RowIndex).Value = ds.Tables("itemInfo").Rows(i).Item("Uint1")
DGVorders(4, e.RowIndex).Value = ds.Tables("itemInfo").Rows(i).Item("price1")
End If
Next
End If
sqlconload.Close()
Catch ex As Exception
End Try
End Sub
Modify the "AllowUsersToAddRows" property to remove that blank line.
Example:
DataGridView1.AllowUserToAddRows = False
DGVorders.Rows.Add(rowcount) will add rowcount amount of empty rows to your DataGridView. I don't know why you are doing that, it's not as if you are adding values to the cells in those new rows in your for loop.
updated
If dataGridView1.CurrentRow.Cells(0).Value = ds.Tables("itemInfo").Rows(i)("itemCode") Then
Dim newRow As DataGridViewRow = TryCast(dataGridView1.CurrentRow.Clone(), DataGridViewRow)
newRow.Cells(1).Value = ds.Tables("itemInfo").Rows(i)("itemName")
newRow.Cells(2).Value = ds.Tables("itemInfo").Rows(i)("Uint1")
newRow.Cells(3).Value = ds.Tables("itemInfo").Rows(i)("price1")
dataGridView1.Rows.Add(newRow)
End If
I want to find a particular ID in a DataTable, I am using a DataView to filter the results, but how do I know which row in the original table the filter view corresponds to? Any ideas? In know I could use LINQ but I don't think this would help either?
Dim dt As New DataTable
Dim dv As New DataView(dt)
dv.RowFilter = "ID = 123"
If dv.Count = 1 Then
'which datarow in the original datatable is this?
End If
EDIT
I want to avoid having to loop through the DataTable to find this:
For r As Integer = 0 To dt.Rows.Count - 1
If CInt(dt.Rows(r).Item("ID")) = 123 Then
Debug.WriteLine("Found it at row " + r.ToString)
Exit For
End If
Next
Nothing could be easier:
Dim dr As DataRow = dv(0).Row
http://msdn.microsoft.com/en-us/library/system.data.datarowview.row%28v=VS.100%29.aspx
Edit: According to your comment, you could use following to get the index of the row
Dim rowIndex As Int32 = -1
For i As Int32 = 0 To dr.Table.Rows.Count - 1
If dr.Table.Rows(i)("ID").Equals(dr("ID")) Then
rowIndex = i
Exit For
End If
Next
Or in this shorter way:
Dim rowIndex As Int32 = dr.Table.Rows.IndexOf(dr)
http://msdn.microsoft.com/en-us/library/system.data.datarowcollection.indexof.aspx