i have a dataTable contains:
ID POCount POTotal
A 1 10
A 2 20
B 4 10
I want to get a result of a new data table as bellow:
ID POCount POTotal
A 3 30
B 4 10
How can i do this using a datatable?
My project is in VB.NET 2005 and i cannot use LINQ method.
What is the best way to do this?
I found a link that kinda near what i want. But it just skip the rows instead of summing up the columns when the id is similar.
http://www.dotnetfunda.com/forums/show/2603/how-to-remove-duplicate-records-from-a-datatable
LINQ is probably better - upgrade to later VS Express - its free!
Here is one approach using a class and a Dictionery
Public Class POSummary
Public Property ID As String
Public Property Count As Integer
Public Property Total As Integer
Sub New(POid As String, POcount As Integer, POtotal As Integer)
ID = POid
Count = POcount
Total = POtotal
End Sub
End Class
Private Sub Button12_Click(sender As Object, e As EventArgs) Handles Button12.Click
Dim pos As New List(Of POSummary)
Dim po As New POSummary("A", 1, 10)
pos.Add(po)
po = New POSummary("A", 2, 20)
pos.Add(po)
po = New POSummary("B", 4, 10)
pos.Add(po)
Debug.Print("--data--")
For Each p As POSummary In pos
Debug.Print(p.ID & " " & p.Count & " " & p.Total)
Next
Dim pd As New Dictionary(Of String, POSummary)
For Each p As POSummary In pos
If Not pd.ContainsKey(p.ID) Then
pd.Add(p.ID, p)
Else
pd(p.ID).Count += p.Count
pd(p.ID).Total += p.Total
End If
Next
Debug.Print("--totals--")
For Each kvp As KeyValuePair(Of String, POSummary) In pd
po = kvp.Value
Debug.Print(po.ID & " " & po.Count & " " & po.Total)
Next
Stop
End Sub
Related
data table with 3 columns ( Quantity - SOP_Type - Item_Number)
I want to compute sum of column Quantity for the item with number "309-032-SHU" and SOP_Type = 3
I tried this code and didn't work
Dim b As String
b = "309-032-SHU"
dim c as integer
c = 3
DGV1.Rows(0).Cells(0).Value = NAJRNDataSet.vwSalesLineItems.Compute("SUM(Quantity)", "Item_Number = " & b & " ", "SOP_Type = " & c & " ")
Since DataTable class does not implement IEnumerable it provides an extension method to get an enumerable. (.AsEnumerable) We can then use a linq syntax to get the Sum.
Private Sub OpCode()
Dim dt As New DataTable
'Fill the datatable
Dim b = "309-032-SHU"
Dim c = 3
Dim Total As Integer
Total = (From r As DataRow In dt.AsEnumerable
Where r.Field(Of String)("Item_Number") = b And r.Field(Of Integer)("SOP_Type") = c
Select r.Field(Of Integer)("Quantity")).Sum
DGV1.Rows(0).Cells(0).Value = Total
End Sub
So I've used visual basics (vb.net) for a bit now and understand some stuff. Right now I want to make a maths quiz that when I click a button it takes me to a new form and starts the quiz. When the quiz starts I want it so it gives the user random numbers and the user needs to answer it in a textbox and if correct it moves on to the next question (Basic, I should be able to do). IMPORTANT - my question is, there's a maths rule called BODMAS (Bracket.Order.Division.Multiply.Add.Subtract) and I want to add this rule into my coding instead of doing regular simple maths...
EXAMPLE question is 2 x (2+3) - 1 = ?
2 x 5 - 1 = ?
10 - 1 = ?
9 = 9
person writes answer to textbox and moves to next similar question
This is my first time using this but I wanted to write in-depth so people can understand. Please help me if you find a video explaining what I'm looking for or if someone has a file with a similar code I could download would be greatly appreciated!
Basically,you need to determine the range of numbers you use, and then match them randomly among '*', '/', '+', '-'. Then randomly insert brackets into it.
Private codeStr As String
Private Function GenerateMathsQuiz() As String
Dim r As Random = New Random()
Dim builder As StringBuilder = New StringBuilder()
'The maximum number of operations is five, and you can increase the number [5] to increase the difficulty
Dim numOfOperand As Integer = r.[Next](1, 5)
Dim numofBrackets As Integer = r.[Next](0, 2)
Dim randomNumber As Integer
For i As Integer = 0 To numOfOperand - 1
'All numbers will be random between 1 and 10
randomNumber = r.[Next](1, 10)
builder.Append(randomNumber)
Dim randomOperand As Integer = r.[Next](1, 4)
Dim operand As String = Nothing
Select Case randomOperand
Case 1
operand = "+"
Case 2
operand = "-"
Case 3
operand = "*"
Case 4
operand = "/"
End Select
builder.Append(operand)
Next
randomNumber = r.[Next](1, 10)
builder.Append(randomNumber)
If numofBrackets = 1 Then
codeStr = InsertBrackets(builder.ToString())
Else
codeStr = builder.ToString()
End If
Return codeStr
End Function
Public Function InsertBrackets(ByVal source As String) As String
Dim rx As Regex = New Regex("\d+", RegexOptions.Compiled Or RegexOptions.IgnoreCase)
Dim matches As MatchCollection = rx.Matches(source)
Dim count As Integer = matches.Count
Dim r As Random = New Random()
Dim numIndexFirst As Integer = r.[Next](0, count - 2)
Dim numIndexLast As Integer = r.[Next](1, count - 1)
While numIndexFirst >= numIndexLast
numIndexLast = r.[Next](1, count - 1)
End While
Dim result As String = source.Insert(matches(numIndexFirst).Index, "(")
result = result.Insert(matches(numIndexLast).Index + matches(numIndexLast).Length + 1, ")")
Return result
End Function
When you finish this, you will get a math quiz, then you need to know how to compile and run code at runtime.
Private Function GetResult(ByVal str As String) As String
Dim sb As StringBuilder = New StringBuilder("")
sb.Append("Namespace calculator" & vbCrLf)
sb.Append("Class calculate " & vbCrLf)
sb.Append("Public Function Main() As Integer " & vbCrLf)
sb.Append("Return " & str & vbCrLf)
sb.Append("End Function " & vbCrLf)
sb.Append("End Class " & vbCrLf)
sb.Append("End Namespace" & vbCrLf)
Dim CompilerParams As CompilerParameters = New CompilerParameters()
CompilerParams.GenerateInMemory = True
CompilerParams.TreatWarningsAsErrors = False
CompilerParams.GenerateExecutable = False
CompilerParams.CompilerOptions = "/optimize"
Dim references As String() = {"System.dll"}
CompilerParams.ReferencedAssemblies.AddRange(references)
Dim provider As VBCodeProvider = New VBCodeProvider()
Dim compile As CompilerResults = provider.CompileAssemblyFromSource(CompilerParams, sb.ToString())
If compile.Errors.HasErrors Then
Dim text As String = "Compile error: "
For Each ce As CompilerError In compile.Errors
text += "rn" & ce.ToString()
Next
Throw New Exception(text)
End If
Dim Instance = compile.CompiledAssembly.CreateInstance("calculator.calculate")
Dim type = Instance.GetType
Dim methodInfo = type.GetMethod("Main")
Return methodInfo.Invoke(Instance, Nothing).ToString()
End Function
Finally, you can use these methods like:
Private Sub GetMathQuizBtn_Click(sender As Object, e As EventArgs) Handles GetMathQuizBtn.Click
Label1.Text = GenerateMathsQuiz()
End Sub
Private Sub ResultBtn_Click(sender As Object, e As EventArgs) Handles ResultBtn.Click
If TextBox1.Text = GetResult(Label1.Text) Then
MessageBox.Show("bingo!")
TextBox1.Text = ""
Label1.Text = GenerateMathsQuiz()
Else
MessageBox.Show("result is wrong")
End If
End Sub
Result:
The code below displays "1" for each year and should be "1" to "5"
Public Class Form1
Private Sub btnDisplay_Click(sender As Object, e As EventArgs) Handles btnDisplay.Click
Dim cost As Double
Dim life As Double = CDbl(ListBox1.SelectedItem)
Dim salvage As Double
Dim numberperiod As Integer
Dim period As Integer
Dim depreciation1 As Double
Dim depreciation2 As Double
Dim isconverted1 As Boolean
Dim isconverted2 As Boolean
Dim isconverted3 As Boolean
Dim year As Integer = 0
isconverted1 = Double.TryParse(textbox1.Text, cost)
isconverted2 = Double.TryParse(textbox2.Text, salvage)
isconverted3 = Integer.TryParse(ListBox1.SelectedItem, period)
lstDCB.Items.Add("Year Depreciation")
lstSOTY.Items.Add("Year Depreciation")
year = Val(year) + 1
For numberperiod = 1 To period Step 1
depreciation1 = Financial.DDB(cost, salvage, life, numberperiod)
depreciation2 = Financial.SYD(cost, salvage, life, numberperiod)
lstDCB.Items.Add(year & " " & Math.Round(depreciation1, 2, MidpointRounding.AwayFromZero))
lstSOTY.Items.Add(year & " " & Math.Round(depreciation2, 2, MidpointRounding.AwayFromZero))
Next numberperiod
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.Close()
End Sub
End Class
It should display 1 to 5 under year of both DDB and SYD.
If you look at the code you posted, you never update the variable year in the routine after it is initialized as Zero and then updated with the statement year = Val(year) + 1.
I believe you meant to put that statement inside the loop body (after the calculation) so that it is incremented in each iteration of the loop.
Something like this:
Module VBModule
Sub Main()
Dim cost As Double = 100
Dim life As Double = 12
Dim salvage As Double = 3
Dim numberperiod As Integer
Dim period As Integer = 3
Dim depreciation1 As Double
Dim depreciation2 As Double
Dim year As Integer = 0
For numberperiod = 1 To period Step 1
depreciation1 = Financial.DDB(cost, salvage, life, numberperiod)
depreciation2 = Financial.SYD(cost, salvage, life, numberperiod)
Console.WriteLine(year & " " & Math.Round(depreciation1, 2, MidpointRounding.AwayFromZero))
Console.WriteLine(year & " " & Math.Round(depreciation2, 2, MidpointRounding.AwayFromZero))
year += 1
Next numberperiod
End Sub
End Module
I am trying to retrieve all of the distinct values from a particular column in a datatable. The column name in the datatable is "Count". I have 2240 rows and I have 6 distinct values in the "Count" column. The problem is, when I execute the following code, it is giving me the number of rows rather than the 6 distinct values.
Dim counts = (From row In loadedData
Select row.Item("Count")).Distinct()
For Each i In counts
MsgBox(i)
Next
How can I modify this to retrieve the 6 distinct values, rather than it giving me the total number of rows?
You just have to select the column and use Enumerable.Distinct:
Dim distinctCounts As IEnumerable(Of Int32) = loadedData.AsEnumerable().
Select(Function(row) row.Field(Of Int32)("Count")).
Distinct()
In query syntax(i didn't know that even Distinct is supported directly in VB.NET):
distinctCounts = From row In loadedData
Select row.Field(Of Int32)("Count")
Distinct
You can use ToTable(distinct As Boolean, ParamArray columnNames As String()) method for this.
loadedData.DefaultView.ToTable(True, "Count")
This will return distinct Users for you. You can add multiple column names if you want.
Here is the msdn documentation.
https://msdn.microsoft.com/en-us/library/wec2b2e6(v=vs.110).aspx
you can also apply this logic if you want ,
first sort datatable through columName ,
then apply this logic
dtRecords.DefaultView.Sort = "columnName"
dtRecords = dtRecords.DefaultView.ToTable
Dim totalRecords As Integer = 0
Dim thNameStr As String = filter(dtRecords, "columnName", totalRecords )
Public Shared Function filter(ByVal dtRecords As DataTable, ByVal columnName As String, ByRef totalRecords As Integer) As String
Dim FilterStr As String = ""
Dim eachTotal As Integer = 0
totalRecords = 0
Dim lastName As String = ""
For rCount = 0 To dtRecords.Rows.Count - 1
If lastName <> "" And lastName <> dtRecords.Rows(rCount)("" & columnName) Then
FilterStr &= lastName & " - [" & eachTotal & "]"
eachTotal = 0
totalRecords += 1
End If
lastName = dtRecords.Rows(rCount)("" & columnName)
eachTotal += 1
Next
FilterStr &= lastName & " - [" & eachTotal & "]"
totalRecords += 1
Return FilterStr
End Function
I am iterating through columns in a datagridview in vb net and passing the
values to a textbox. I need to be able to filter out the emails which are in Cell(4), so that there are no duplicate emails for any single customer.
I have no idea of how to do this using a dataset.
EmailTableAdapter.Fill(Me.EmailDataset.Email)
Dim r As String = String.Empty
For i As Integer = 0 To Me.EmailDataGridView.RowCount - 1
r = r & EmailDataGridView.Rows(i).Cells(7).Value.ToString & " - " & EmailDataGridView.Rows(i).Cells(4).Value.ToString & vbNewLine
Next
TextBox2.Text = (r)
One way to filter out rows with duplicate values in Cells(4) would be to iterate through the grid rows, stuffing items into a Dictionary using Cells(4) values as the Key, and then iterate through the Dictionary to build your "r" string. Such a solution would look something like this:
EmailTableAdapter.Fill(Me.EmailDataset.Email)
Dim EmailDict As New Dictionary(Of String, String)
For i As Integer = 0 To Me.EmailDataGridView.RowCount - 1
If Not EmailDict.ContainsKey(EmailDataGridView.Rows(i).Cells(4).Value.ToString) Then
EmailDict.Add(EmailDataGridView.Rows(i).Cells(4).Value.ToString, EmailDataGridView.Rows(i).Cells(7).Value.ToString)
End If
Next
Dim EmailPair As KeyValuePair(Of String, String)
Dim r As String = String.Empty
For Each EmailPair In EmailDict
r &= EmailPair.Value & " - " & EmailPair.Key & vbNewLine
Next
TextBox2.Text = (r)