Dynamically Adding a Column to existing DataTable in Vb.net - vb.net

I am Working with Vb.Net Project, through Web Service call method I get the result in DataTable's Object , now I need to add more columns after local calculations, I m doing all in loops and adding one by column's data through loop or modifying it, for a larger DataTable its too time taking.
Is there any logic that I add those columns in one go rather traversing each DataRow?
Suppose I have a DataTable with 4 columns, (Name = dt)
I need to add two more into it.
for 2000 rows I have to go for each row to initialize the value of newly added columns.
****Suppose I have calculations of new tentative columns into a Temp table.
Is There any way so I can update the values of newly added columns (added into dt)by joins The tables (inside VB.NET code) on the bases of a common column (Primary Key Column)****

Suppose I have calculations of new tentative columns into a Temp
table. Is There any way so I can update the values of newly added
columns (added into dt)by joins The tables (inside VB.NET code) on the
bases of a common column (Primary Key Column)
If the tempTbl is within the same DataSet as your primary Table (containing the Data), and you've got a 1:1 matching key relationship: yes, you can.
Add a DataRelation between your two tables within the DataSet and use it to retrieve a combined DataRow, containing the columns of all related tables.
' the variables
Dim DSet As DataSet = New DataSet("DSet")
Dim DTbl1 As DataTable = New DataTable("One")
Dim DTbl2 As DataTable = New DataTable("Two")
Dim DRelation As DataRelation
' setting up sample tables
DTbl1.Columns.Add("SaleID", GetType(Integer))
DTbl1.Columns.Add("ProductName", GetType(String))
DTbl1.Columns.Add("AmountSold", GetType(Double))
DTbl1.Columns.Add("ItemPrice", GetType(Double))
DTbl2.Columns.Add("SaleID", GetType(Integer))
DTbl2.Columns.Add("Turnover", GetType(Double))
' host this DataTables in the DataSet
DSet.Tables.Add(DTbl1)
DSet.Tables.Add(DTbl2)
' this is the exiting part: adding primary keys...
' the DataTable.PrimaryKey-property is an Array of DataRow, so I just initialize a new array containing the one column I would like to set as primary key for this table.
DTbl1.PrimaryKey = {DTbl1.Columns("SaleID")}
DTbl2.PrimaryKey = {DTbl2.Columns("SaleID")}
' ...and the DataRelation
DRelation = New DataRelation("SaleIDRelation", DSet.Tables("One").Columns(0), DSet.Tables("Two").Columns(0))
DSet.Relations.Add(DRelation)
' populate Tbl1 with some sample data
DTbl1.Rows.Add(1, "Eggs", 4, 0.2)
DTbl1.Rows.Add(2, "Apples", 5, 0.5)
DTbl1.Rows.Add(3, "Milk", 5, 1)
' do the calculation
For Each DRow As DataRow In DSet.Tables("One").Rows
' I personally prefer to keep iteration variables scope inside the loops, so the variable can get catched by the GarbegeCollector as soon as the loop is left
Dim tPrice As Double = 0
' I also prefer not to rely on implicit conversion
tPrice = Convert.ToDouble(DRow("AmountSold")) * Convert.ToDouble(DRow("ItemPrice"))
' for each row processed by the loop, add a row to the second table to store the calculations result
' this row should have the same SaleID, so the DataReleation will be able to relate the two rows together later on
DTbl2.Rows.Add(DRow("SaleID"), tPrice)
Next
' so now you'll be able to get the according DataRow(s) of the second table by retriving the depending ChildRows through the DataRelation
For Each DRow As DataRow In DSet.Tables("One").Rows
Console.WriteLine(String.Format("Product {0} in SaleID {1} has made a total turnover of {2}", DRow("ProductName"), DRow("SaleID"), DRow.GetChildRows("SaleIDRelation")(0)("Turnover")))
Next
Output:
Product Eggs in SaleID 1 has made a total turnover of 0,8
Product Apples in SaleID 2 has made a total turnover of 2,5
Product Milk in SaleID 3 has made a total turnover of 5
The real magic is happening within the loop for the output. I'm accessing the desired value of the first child row, because due to the 1:1 DataRelation, I have made sure that each DataRow in Tbl1 has a pedant in Tbl2 that has the same SaleID.
So what I do is DRow.GetChildRows("SaleIDRelation")(0)("Turnover"):
For DRow (this DataRow)
Get the related ChildRows, using the DataRelation named "SaleIDRelation"
Use the first ChildRow that is found, indicated by (0)
And of that DataRow, I would like to have the value of the column ("Turnover")

Related

DataTable And Two Row Sorting

So the boss comes to me and says "I want the value of each agent and the project on one line and the average of all the other agents on the next line so I can easily see if they are above or below average."
the table looks like this:
dt.Columns.Add("AGENT", GetType(String))
dt.Columns.Add("PROJECT", GetType(String))
dt.Columns.Add("Sales", GetType(Integer))
dt.Columns.Add("Declines", GetType(Integer))
dt.Columns.Add("Margin", GetType(Integer))
Ok its all good. One row in the datatable is the agent and project. The next row is the average of all the other agents and project like so:
row 1:
John Smith,
ProjectName,
(other column values)
row 2:
John Smith,
ProjectName & " AVERAGE/TOTAL",
(other column values)
The project name is removed in the SSRS report on the AVERAGE/TOTAL line because of space constraints on the piece of paper it is printed on.
I do the sorting by our standard way of sorting a datatable.
Dim dataView As New DataView(dt1)
dataView.Sort = "AGENT,PROJECT"
dt1 = dataView.ToTable
Return dt1
But now the boss has a new requirement later on. He wants to be able to sort by other columns in the table but keep the two rows the (agent/project and the agent/project AVERAGE/TOTAL) together. So in essence he wants to be able to sort not by one row but the two rows together but the sort value could be "AGENT,Margin". Obviously to keep the two rows together I have to find a way to sort the Project value too.
So I am stumped and would appreciate any thoughts you might have. C# ideas are welcome as well.LINQ is fine but it is going to have to become a datatable.
so you create two tables. One with the row values one one with the average values. Loop through the row values and then do another loop inside that loop to match project names. Its a hack but it worked.
If SortValue = "Default" Then
dt1.Merge(dt)
Dim dataView As New DataView(dt1)
dataView.Sort = "AGENT,PROJECT"
dt1 = dataView.ToTable
Else
Dim dataView As New DataView(dt)
dataView.Sort = SortValue
dt = dataView.ToTable
Dim dtCopy As New DataTable
dtCopy = dt.Clone
For Each row As DataRow In dt.Rows
dtCopy.ImportRow(row)
For i = 0 To dt1.Rows.Count - 1
If dt1.Rows(i).Item("PROJECT").ToString.Replace(" AVERAGE/TOTAL", "") = row.Item("PROJECT") And dt1.Rows(i).Item("AGENT") = row.Item("AGENT") Then
dtCopy.Rows.Add(dt1.Rows(i).Item("AGENT"), dt1.Rows(i).Item("PROJECT"), dt1.Rows(i).Item("SALES"), dt1.Rows(i).Item("Declines"), dt1.Rows(i).Item("Margin"))
End If
Next
Next
dt1 = dtCopy
End If

How to filter a datagridview when using data from datatable? VB.net

I have created a textbox and want it to search through a database of customers by name. Most of the questions are using an external dataset but this is just using a table created in the program using a csv file.
You could take advantage from BindingSource, to be used as DataSource of your DataGridView. That way, acting on the BindingSource Filter property, you could set any type of filters, based on you columns name.
Please check the following snippet:
Dim dt As New DataTable("Sample")
dt.Columns.Add("Id")
dt.Columns.Add("TimeStamp")
For i As Int32 = 0 To 9999
dt.Rows.Add(New Object() {i, DateTime.Now})
Next
Dim bs As New BindingSource
bs.DataSource = dt
bs.Filter = "Id > 10 AND Id < 20"
DataGridView1.DataSource = bs
As you can see, i've defined a DataTable with two columns, namely "Id" and "TimeStamp". Then, with a simple loop i've populated my DataTable with some random records, for Id = 0 to Id = 9999.
After that, we declare a BindingSource, specifying its DataSource is our DataTable. On the Bindinf Source, we could set any filter, using the Filter property, the columns names, and the common logical operators.
In my example, i've requested the filter to be on the only Id column, to visualize those record whose Id is between 11 and 19.
Then, we could use the BindingSource as our DataGridView DataSource.
And note that filters doesn't need to be apply before assigning the DataGridView DataSource: in fact, after the binding, each filter application will reflect immediately on the visualized rows.
Hope this helps

Checking duplicate Values on DataGrid

I have a DataGrid which is bound with a DataTable having two columns which store sequences, in my DataGrid these sequence columns are bound with DataGridViewComboBoxes. User is able to set sequence from ComboBoxes. Default values in sequence columns is 0.
I just want to check duplicacy in both the columns on button click, user should not be able select any duplicate value in both the columns.
If i implement it by using ToTable method of DataView to find distinct values it also takes rows with value "0"
if i implement unique constraint on column on DataTable it also checks for 0.
If try to remove values with 0 it also changes DataGrid As DataGrid is bound with DataTable
If i try to declare a new DataTable from existing dataTable it also gets bound to DataGrid Automatically.
Please help me.
Here is an example of how you can check for duplicate values in a DataTable:
Option Strict On
Module Module1
Sub Main()
Dim dt As New DataTable
dt.Columns.Add("mycolumn", GetType(Integer))
dt.Rows.Add({"1"})
dt.Rows.Add({"2"})
dt.Rows.Add({"2"})
dt.Rows.Add({"4"})
dt.Rows.Add({"7"})
Dim duplicateDictionary As New Dictionary(Of Integer, Integer) 'value, count
For Each row As DataRow In dt.Rows
Dim count As Integer = 0
Dim value As Integer = CInt(row("mycolumn"))
duplicateDictionary.TryGetValue(value, count)
duplicateDictionary(value) = count + 1
Next
For Each kv As KeyValuePair(Of Integer, Integer) In duplicateDictionary
If kv.Value > 1 Then 'we have a duplicate
Debug.WriteLine("{0} is a duplicated value, encountered {1} times", kv.Key, kv.Value)
End If
Next
End Sub
End Module
Adding a UniqueConstraint is possible as well, but I find it too intrusive at times, depending on how your editing works. For direct in-grid editing, you may want the user to save a non-valid record in memory, and allow to fix the error, showing validation errors instead of constraint violation exception. Of course you never save invalid data to the database.

navigating through records on a database

Simplest way how to loop and display through records using textbox, combo box and datetimepicker.
Below is a code but still cant figure it out
Dim dr As DataRow
Dim ds As Dataset
Dim dt As DataTable
<code to fill the dataset>
dt = ds.Tables(0)
For Each dr In dt.Rows
Console.WriteLine (dr("ColName"))
Next
ds.Dispose()
You need two loops to do this - an outer loop for the number of rows in the table, and an inner loop for the columns in each row.
You have the For Each for the rows already, but you need to know how many columns are in the DataRow, and print out the value in each column. You can get the count of columns from the DataTable.
Dim cols As Integer
cols = dt.Columns.Count - 1
For Each dr in dt.Rows
For i As Integer = 0 To cols
Console.WriteLine(dr(i).ToString())
Next
Next
Notice that I call ToString() on the value returned from each column, and reference the column by it's ordinal. When you access a specific column in the DataRow, it returns an Object, so you'll need to cast that value to the correct data type for use in your program.
The code you posted would have only printed the value for the column that had "ColName" as it's column name for each row. If you didn't have a column named "ColName" then you would see an error.

Get the BindingSource position based on DataTable row

I have a datatable that contains the rows of a database table. This table has a primary key formed by 2 columns.
The components are assigned this way: datatable -> bindingsource -> datagridview. What I want is to search a specific row (based on the primary key) to select it on the grid. I cant use the bindingsource.Find method because you only can use one column.
I have access to the datatable, so I do manually search on the datatable, but how can I get bindingsource row position based on the datatable row? Or there is another way to solve this?
Im using Visual Studio 2005, VB.NET.
I am attempting to add an answer for this 2-year old question. One way to solve this is by appending this code after the UpdateAll method(of SaveItem_Click):
Me.YourDataSet.Tables("YourTable").Rows(YourBindingSource.Position).Item("YourColumn") = "YourNewValue"
Then call another UpdateAll method.
Well, I end up iterating using bindingsource.List and bindingsource.Item. I didnt know but these properties contains the data of the datatable applying the filter and sorting.
Dim value1 As String = "Juan"
Dim value2 As String = "Perez"
For i As Integer = 0 To bsData.Count - 1
Dim row As DataRowView = bsData.Item(i)
If row("Column1") = value1 AndAlso row("Column2") = value2 Then
bsData.Position = i
Return
End If
Next