Update DataView based on the column value in VB.NET - vb.net

I have a dataview as below:
Id | GroupName | Count
1 DummyName 1
2 DummyName 1
3 StubName 1
4 DummyName 1
I need to update the Count column value for each row based on total number of rows with the same GroupName for that row. The desired output is below:
Id | GroupName | Count
1 DummyName 3
2 DummyName 3
3 StubName 1
4 DummyName 3
The logic that I tried to do this with is:
Step 1: Update the Count column value for each row
For Each row As DataRow In tbl.Rows
row("Count") = From r in tbl _
Group r By key = tbl.Columns("sites_siteid") into Group _
where Group.Count() > 1
Select Group.Count()
Next
But it seems like I am messing up with LINQ or ....
I need to do this in VB.Net, I know how to do this in SQL but I am struggling with getting this done in Vb.Net code.
Any help or insight is highly appreciated.
Thanks in advance :)

First, create a Dictionary mapping sites_siteid to the count of rows with the same sites_siteid:
Dim countMap = (From r In tbl.Rows Group r By Key = r.Field(Of String)("sites_siteid") Into Group, Count() Select New With { .SiteId = Key, .Count = Group.Count }) _
.ToDictionary(Function(ic) ic.SiteId, Function(ic) ic.Count)
Then, update each row with the desired count:
For Each row As DataRow In tbl.Rows
row("Count") = countMap(row.Field(Of String)("sites_siteid"))
Next

Related

linq filter columns rather than data

Firstly, I'm not sure if what I'm asking is possible or not so apologies if I'm asking a stupid question.
So I am able to filter a DataTable using linq to get the data I need, I'm wondering if it's possible to filter the columns using a simlar statement.
For example if I have the below datatable dtMyData
ID
Name
1
2
3
4
1
Conor
100
87
3
0
2
Frank
35
70
0
0
3
Jeff
35
13
0
57
I can filter it to the below using the following statement
dtMyData = dtMyData.AsEnumerable().Where(Function (f) f("Name").ToString().Equals("Frank")).CopyToDataTable
ID
Name
1
2
3
4
2
Frank
35
70
0
0
What I'm wanting to do (If it's possible) is filter the columns in a similar way so that I can select all of the columsn > 2 plus the first 2 columns. Giving me the following columns
ID
Name
3
4
1
Conor
3
0
2
Frank
0
0
3
Jeff
0
57
Take a look at this method:
Private Function CopyTable(source As DataTable, columnsToKeep As IEnumerable(Of String)) As DataTable
Dim copiedTable As DataTable = source.Clone()
Dim columnsToRemove() As DataColumn = copiedTable.Columns.Cast(Of DataColumn).Where(Function(column) Not columnsToKeep.Contains(column.ColumnName)).ToArray()
For i As Integer = 0 To columnsToRemove.Length - 1
copiedTable.Columns.Remove(columnsToRemove(i))
Next
For Each row As DataRow In source.Rows
Dim values As New List(Of Object)
For Each column As DataColumn In copiedTable.Columns
values.Add(row.Item(column.ColumnName))
Next
copiedTable.Rows.Add(values.ToArray())
Next
Return copiedTable
End Function
What this does is
Clone the DataTable
Loop over the copied DataTable and remove the columns that are not in the columnsToKeep
Loop over the original DataTable and add the rows to the copied DataTable without the cells that are not in the columnsToKeep
Fiddle: https://dotnetfiddle.net/2l6wk9
Edit
It would actually be easier to use DataTable.Copy over DataTable.Clone, my apologies:
Private Function CopyTable(source As DataTable, columnsToKeep As IEnumerable(Of String)) As DataTable
Dim copiedTable As DataTable = source.Copy()
Dim columnsToRemove() As DataColumn = copiedTable.Columns.Cast(Of DataColumn).Where(Function(column) Not columnsToKeep.Contains(column.ColumnName)).ToArray()
For i As Integer = 0 To columnsToRemove.Length - 1
copiedTable.Columns.Remove(columnsToRemove(i))
Next
Return copiedTable
End Function
What this updated code does is:
Copy the DataTable with its data
Loop over the copied DataTable and remove the columns that are not in the columnsToKeep
Fiddle: https://dotnetfiddle.net/NEIm2t

Find and sum value of a datagridview column in vb.net

I want to find and sum qty value of searched id in data grid view column am using this code
Dim tqty As Double
For Each row As DataGridViewRow In dgv.Rows
If row.Cells.Item(0).Value = cmbItemCode.Text Then
tqty += row.Cells.Item(4).Value
Textbox1.text=tqty
Exit For
End If
Next
The problem is that Textbox1 shows only one top searched row value. For example
id item name qty
1 abc 4
2 xyz 10
1 abc 10
Textbox1 shows the Result only 4.
As soon as you hit the first value, you exit the for statement. Therefore you never get pass the first value. Erase the Exit For it should work.
If DataGridView2.RowCount > 1 Then
Dim tqty As Integer = 0
'if you have the other column to get the result you could add a new one like these above
For index As Integer = 0 To DataGridView2.RowCount - 1
amount += Convert.ToInt32(DataGridView2.Rows(index).Cells(2).Value)
'if you have the other column to get the result you could add a new one like these above (just change Cells(2) to the one you added)
Next
TextBox1.Text = tqty

Colouring datagrid rows

I was wondering how to colour the first 8 rows of a datagridview. I have managed to sort the values in descending order and I wish to have the first 8 rows coloured to highlight the top 8 to the user, and I'm not sure how to go about doing this.
Dim count As Integer
For count = 0 To datagridsort.RowCount - 1
Do
datagridsort.Rows(0).Cells(0).Style.BackColor = Color.Coral
datagridsort.Rows(0).Cells(1).Style.BackColor = Color.Coral
Loop Until count = 8
Next
In the code you posted in your comment, you were never using the count variable. You were only updated the first row every time. Try it like this:
For i As Integer = 0 To Math.Min(datagridsort.RowCount - 1, 7)
For j As Integer = 0 To datagridsort.ColumnCount - 1
datagridsort.Rows(i).Cells(j).Style.BackColor = Color.Coral
Next
Next

SELECT Unique rows from Datagridview using LINQ

I am trying to SELECT ALL rows\columns from a datagridview where the first column is unique using LINQ.
Datagridview:
1 Blue 1111
1 Blue 1111
2 Green 1234
3 Orange 3211
2 Green 1234
4 Red 2222
Trying to get this Output:
1 Blue 1111
2 Green 1234
3 Orange 3211
4 Red 2222
I was able to use the following code which pulls all unique records from the first column but I am not sure how to get the remaining columns:
Dim unique() As String = (From row As DataGridViewRow In dgvMaestro.Rows.Cast(Of DataGridViewRow)() _
Where Not row.IsNewRow _
Select CStr(row.Cells(0).Value)).Distinct.ToArray
For Each a As String In unique
Debug.Print(a)
Next
Output:
1
2
3
4
Thanks
First you need import 2 namespaces for distinct with linq to use AsEnumerable() method in DataTables and Field() method in DataRows
Imports System.Data.DataTableExtensions
Imports System.Data.DataRowExtensions
Declare new datatable
Dim NewTbl As New System.Data.DataTable
Add columns in you scenario
NewTbl.Columns.Add("ID", GetType(Integer))
NewTbl.Columns.Add("Color", GetType(String))
NewTbl.Columns.Add("Value", GetType(Integer))
Linq use Table 'TblValues' as you datasource
Dim results = (From row in TblValues.AsEnumerable() select col1 = row(Of Integer)("ID"), col2 = row(Of String)("Color"), col3 = row(Of Integer)("Value")).Distinct().ToList()
Iterate elements in results with for each, the reason is because results is an object datarow collection and isn't convert auto to table
For each r in results
Dim Row as System.Data.DataRow = NewTbl.NewRow
Row("ID") = r.col1
Row("Color") = r.col2
Row("Value") = r.col3
NewTbl.Rows.Add(Row)
next
Now you have a DataTable 'NewTbl' with distinct values inside
The best way to solve this is to write a comparer to compare the entire row.
Dim noduplicates = dgvMaestro.Rows.Cast(Of DataGridViewRow).Distinct(New RowComparer())
There are some examples of comparers on msdn

How to merge certain datarows in a dataset with multiple unique values vb

The title might be difficult to understand so here's a short explanation :
I have to create a method :
MergeDataset(byval ds as Dataset) as dataset
The datatable has multiple rows
The columns : startDate, endDate, and multiple others
The dataset is ordered by startDate
What I do now :
I create a clone of the dataset, which is empty ofcourse
I loop through every datarow in the datatable
If the datarow has a value in the clone dataset which equals all columns(except startdate and endate)
and the enddate of the clone equals the startdate of the datarow - 1 day
else the row is added to the clone
This now is done correctly, but takes a lot of time.
When I have a dataset of 100 000 rows, it takes multiple houres to merge them all.
Here some code :
Dim mergeSet As DataSet = dsSubscriptions.Clone()
Dim dr() As DataRow = ds.Tables("resultTable").Select("","startDate")
For Each sourceRow As DataRow In dr
If mergeSet.Tables("resultTable").Rows.Count > 0 Then
Dim foundRows As DataRow() = mergeSet.Tables("resultTable").Select(endDate=startDate-1 and value1 = value1 and value2 = value2 and value3 = value3)
'If nothing in foundRows -> Add row
For Each resultrow As DataRow In foundRows
resultrow("endDate") = CDate(sourceRow("endDate"))
next
else
'Add row
Next
A lot of time gets lost in the select of the mergeSet, if I check timespans they're increasing a lot. The select has 5 unique values, and rows can be merged if all values equal eachother, and the dates can be merged into one period.
Small example :
id startDate endDate value1 value2 value3
1 1-11-2012 30-11-2012 A B C Add to Merge
2 1-12-2012 31-12-2012 A B C Merge with 1
3 1-1-2013 31-1-2013 A B B Add to Merge(not same values as 2)
Any help is welcome!
Kind regards