I have the following code which selects some rows using LINQ depending on some conditions.
Dim cname
Dim Category
Dim cprice
Try
For i = 0 To mainDatatable.Rows.Count - 1
cname = mainDatatable.Rows(i)("cname")
Category = mainDatatable.Rows(i)("ccategory")
cprice = mainDatatable.Rows(i)("cprice")
Dim nameparts() As String = cname.Split(New String() {" "}, StringSplitOptions.None)
Dim query = From products In mainDatatable.AsEnumerable()
Where products.Field(Of Integer)("ccategory") = Category And products.Field(Of Double)("cprice") = cprice And products.Field(Of String)("cname").Contains(nameparts(0)) And products.Field(Of String)("cname").Contains(nameparts(1))
Select products
If query.Count > 1 Then
'then i want to do some changes to those rows
End If
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
The code is working perfectly but I need to do changes on the selected rows. I'm not sure how to do it, for example i have a column called gprice and I want it to set it to some value for all the selected rows and save changes to mainDatatable ,would aprreciate your help.
To make it clear, suppose the row count in the query is 6 then I want to make all the values for some column in the query = 1 and then update the values of the selected rows in the mainDatatable
------update
If you don't get it forget the above code and here is what I am trying to do
-Ii have a datatable it only have 2 columns product name and product price, now there are products with same name but different colors
-I want to group those products by pharsing the string name and check for other products with identical words in the name, only one word is allowed to differ which is the color,
-Also the price have to be the same between the products in that group and this is what the above LINQ code does and it does it perfectly
-My problem is i have added a third column called groupnumber, I want to add 1 for each product in the 1st group, 2 for each product in group 2nd and so on.
Related
I have an API that accepts a list of objects(Object contains ProductID and Quantity). I want to determine whether there are duplicate product ID on the passed list. If duplicates are found, I'll merge them by adding the Quantity of duplicate product ID. To do this, I created my own algorithm that loops the list one-by-one then store it to another list (the verified one). The code goes like this.
For Each passedVoucher As VoucherInfo In VouchersToRelease
indexofduplicate = 0
sumQuantity = 0
hasDuplicate = False
If VerifiedReleasedVouchers.Count() > 0 Then
'for loop that checks if productID exists in the VerifiedReleasedVouchers
For Each finalList As VoucherInfo In VerifiedReleasedVouchers
If passedVoucher.ProductID = finalList.ProductID Then
indexofduplicate = VerifiedReleasedVouchers.IndexOf(finalList)
'if true, adds the Quantity of duplicate to the existing quantity at the VerifiedReleasedVouchers
sumQuantity = Convert.ToInt32(VerifiedReleasedVouchers(indexofduplicate).Quantity) + Convert.ToInt32(passedVoucher.Quantity)
VerifiedReleasedVouchers(indexofduplicate).Quantity = sumQuantity.ToString
hasDuplicate = True
Exit For
End If
Next
End If
'adds the voucher to verified released voucher if no duplicate was found
If hasDuplicate = False Then
VerifiedReleasedVouchers.Add(passedVoucher)
End If
Next
So what I did is, I ForEach looped the passed list. Inside the loop, I compared the current object from the passedList into every object in the verifiedList(w/c is empty by default) to determine whether their are duplicate product ID. If no duplicate was found, i'll just add the current object to the verifiedList. If duplicate was found, ill just update the object from the verified list with the same ProductID by storing the sum of the Quantity of both objects.
The code above works perfectly as intended but the thing is, it performs a lot of tasks. Is there any way to simplify what I did above?
P.S. List.Distinct() is not a solution for this
You could use Linq to easily achieve what you want. First you must GroupBy ProductID and then Select all the groups with a sum of the quantity. Finally, we get a list:
Dim VerifiedReleasedVouchers As List(Of VoucherInfo) = VouchersToRelease.GroupBy(Function(x) x.ProductID).[Select](Function(y) New VoucherInfo() With {
.ProductID = y.Key,
.Quantity = y.Sum(Function(z) z.Quantity),
.Denom = y.First().Denom
}).ToList()
I have a project where I connected an Access Database through a DataGridView. I've made some queries based on info inputed by the user through textboxes and comboboxes. Now I need to find a way to count the Average of the records found after the query from one specific column. Is there a way to do that ?
Store the counts from your queries...
Dim lstCounts As New List(Of Integer)
'Your database retrieval method: SELECT COUNT(*) FROM table WHERE field = 'Blah'
lstCounts.Add(<above result>)
'Your database retrieval method: SELECT COUNT(*) FROM table WHERE field = 'Blah1'
lstCounts.Add(<above result>)
'Your database retrieval method: SELECT COUNT(*) FROM table WHERE field = 'Blah2'
lstCounts.Add(<above result>)
'etc.
Find the average...
Dim nTotal As Integer = 0
Dim dAverage As Decimal = 0.0
For i As Integer = 0 to lstCounts.Count - 1
nTotal += lstCounts(i)
Next
'Make sure you aren't dividing by zero
If lstCounts.Count > 0
dAverage = nTotal / lstCounts.Count
End If
You could also simply just add the total as you perform each query and not bother using a List, but then you need to track how many queries you ran.
I don't know what i doing wrong. I have been on several forums trying to figure out how to sort a table in visual basic.
I have treid with and with out a dataview, but noting seams to work.
I have a logg that the user can do new inserts in. It has 3 columns. "Date", "Tool", "Comment".
When my VB application loads the program reads the table from a Access database and i get my sorting just fine by the sql phrase:
"select * from Logg ORDER BY Logg.Datum DESC"
After a user have uppdated the table i whant to sort it again. I have treid the following, but nothing happens. The order is the same whatever i do.
DS is my Dataset and dw my dataview, and "Datum" the column i whant to sort
DS.Tables("hela").DefaultView.Sort = "Datum DESC"
dw = DS.Tables("hela").DefaultView
For i = 0 To antal_poss - 1
LOGG(i, 0) = dw.Table.Rows(i).Item(3)
LOGG(i, 1) = dw.Table.Rows(i).Item(1)
LOGG(i, 2) = dw.Table.Rows(i).Item(4)
Next i
What am i doing wrong?
In your code you use the DataView to retrieve the Table and then the DataRows, but you extract them following the order on the DataTable.
You need to loop following the order of the DataView.
Something like this
Dim i As Integer = 0
For Each row As DataRowView in dw
LOGG(i, 0) = row.Item(3)
LOGG(i, 1) = row.Item(1)
LOGG(i, 2) = row.Item(4)
i += 1
Next i
Of course this assume that your LOGG array contains enough entries to accomodate every row retrieved. It is the same number of the rows in the DataTable
How do I get a field of a datatable when I know column name and a row ID, without looping?
For instance; I want the “Total Sold” value when Region = City and Product = Legos. This is something I have struggled with for a long time, probably because I think in SQL so looping through everything all the time doesn’t always seem like the correct way to go. BUT if I just need to learn to think like a VB developer and always loop to get something out of a list or table, please let me know.
I have a series of asserts comparing two datatables, one that has one row with a named column for each cell (from XML produced by SSRS), and another datatable that has one row for each unique value in a region (produced from a SQL query).
Table from SQL (mockup dataset):
Region Prod Total Sold
City Legos 68
State Legos 90
Nat. Legos 200
City ToyB 20
State ToyB 30
Nat. ToyB 40
City ToyC 450
State ToyC 600
Nat. ToyC 900
Table from XML (dataset returned from SSRS):
City_Legos State_Legos Nat_Legos City_ToyB State_ToyB Nat_ToyB City_ToyC State_ToyC
68 90 200 20 30 40 450 600
The part of the assert statement that gets data from the XML based datatable is easy, because there is only one row (index 0), and I can just name the column I want:
Dim xmlRow As DataRow = xmlDatatable.Rows(0)
Assert.AreEqual(“my SQL cell goes here”, xmlRow.Field(Of Integer)(“City_Legos”))
And I can do one assert for each of the specified columns. Many of the columns won’t be tested, and they have specific names, so I can’t simply loop through the columns. So what do I put in “my SQL cell goes here” to return the Total Sold for City and Legos? Obviously in SQL it would be easy: SELECT TOP 1 Total_Sold WHERE Region = City and Prod = Legos.
I am currently looping through the SQL datatable and testing each cell for my criteria, but that logic gets huge because I have to wrap each like in If…Then, like this:
For Each m As DataRow In mySqlTable.Rows
If m.Field(Of String)("Prod") = "Legos" Then
If m.Field(Of String)("Region") = "City" Then
Assert.AreEqual(m.Field(Of Integer)("TotalSold"), xmlRow.Field(Of Integer)(“City_Legos”))
End If
If m.Field(Of String)("Region") = "State" Then
Assert.AreEqual(m.Field(Of Integer)("TotalSold"), xmlRow.Field(Of Integer)(“State_Legos”))
End If
If m.Field(Of String)("Region") = "Nat" Then
Assert.AreEqual(m.Field(Of Integer)("TotalSold"), xmlRow.Field(Of Integer)(“Nat_Legos”))
End If
End If
Next
I’m hoping I can do something like a select or LINQ or Function?
Something like this would be nice:
Dim result as Integer = mySqlTable.Select.First(“Region = City and Prod = Legos“)
Or:
Assert.AreEqual(mySqlTable.Select.First(“Region = City and Prod = Legos“), xmlRow.Field(Of Integer)(“City_Legos”))
This is a unit test, so I will always know the column and field names returned by SSRS.
Getting the cell by Column name and row identifier has always been something I’ve struggled with, so hopefully I can finally get this solved.
Thanks!
You could use the Datatable Compute method. Replace (“my SQL cell goes here” with
CInt(mySqlTable.Compute("SUM([Total Sold])", "[Region] = 'City' and [Prod] = 'Legos'"))
This is assuming that the rows are unique and no null values.
I'm trying to loop through a data table that has multiple values for my constraint. How can I keep the first value and add together all the other values that match my constraint.
For i = 0 To ds.Tables(0).Rows.Count - 1
If ds.Tables(0).Rows(i).Item("TEND_POS_ID") = 8 Then
'This only returns the last value
'Value 1 = 2
'Value 2 = 7.5
'should = 9.5 but it is showing 7.5
tmpCoupon = ds.Tables(0).Rows(i).Item("TENDER_AMT")
End If
Next
txtCoupon.Text = tmpCoupon
If I understand your question correctly, you need to add the values of TENDER_AMT where the value in TEND_POS_ID is 8. If this is the case you could use the Select method of the DataTable
Dim rows = ds.Tables(0).Select("TEND_POS_ID = 8")
for each r in rows
tmpCoupon += Convert.ToDecimal(r("TENDER_AMD"))
Next
However, rembember that this kind of work (SUM a column grouping by another column) is usually better resolved by the query that you submit to the database. Something like this:
SELECT TEND_POS_ID, SUM(TENDER_AMD) FROM Table1 GROUP BY TEND_POS_ID