Join two data tables having common fields - asp.net

I have 2 datatable objects (dt1,dt2), which have a common filed called "File_Name". I want to create a datatable (dtFinal), combining the two datatables to be used in gridview of asp.net
Each of the tables (dt1,dt2) can have overlapping column header names, meaning if dt1 has a header as "plant_code" dt2 can also have the header as "plant_Code" but not mandatory.
My objective is to have a common datatable (dtFinal) with all the headers from all the individual datatables.
I tried something like this
Dt1.PrimaryKey = New DataColumn() {Dt1.Columns(System.AppDomain.CurrentDomain.BaseDirectory & "\resources\files\" & "GRN" & ".csv")}
Dt2.PrimaryKey = New DataColumn() {Dt1.Columns(System.AppDomain.CurrentDomain.BaseDirectory & "\resources\files\" & "Payment Data" & ".csv")}
Dt1 = CsvToDataTable(System.AppDomain.CurrentDomain.BaseDirectory & "\resources\files\" & "GRN" & ".csv")
Dt2 = CsvToDataTable(System.AppDomain.CurrentDomain.BaseDirectory & "\resources\files\" & "Payment Data" & ".csv")
ds.Tables.Add(Dt1)
ds.Tables.Add(Dt2)
Dim drel As New DataRelation("EquiJoin", Dt2.Columns("File_Name"), Dt1.Columns("File_Name"))
ds.Relations.Add(drel)
Dim jt As New DataTable("Joinedtable")
ds.Tables.Add(jt)
For Each dr As DataRow In ds.Tables("Table1").Rows
Dim parent As DataRow = dr.GetParentRow("EquiJoin")
Dim current As DataRow = jt.NewRow()
' Just add all the columns' data in "dr" to the New table.
For i As Integer = 0 To ds.Tables("Table1").Columns.Count - 1
current(i) = dr(i)
Next
' Add the column that is not present in the child, which is present in the parent.
current("Dname") = parent("Dname")
jt.Rows.Add(current)
Next
DtFinal = ds.Tables("Joinedtable")
Creating a dataset and a relation between dt1 and dt2 ...But this doesn't seem to work and giving me an error in line 1 instance of object to be declared using New.
Has someone tried something like this in Vb ? Or can my code be edited to make it work.
Further info: each datatable tb1 and tb2 have unique values in the File_Name column which is the first column. and hence can be selected as the primary key.

When you say, "Merge" it may mean one thing or another. For example, I may think of this method.
This is Working Code:
Public Sub MergeTables()
Dim t1 As New DataTable("T1")
t1.Columns.Add("C1", GetType(String))
t1.Columns.Add("C2", GetType(String))
t1.Columns.Add("C3", GetType(String))
Dim t2 As New DataTable("T2")
t2.Columns.Add("C1", GetType(String)) 'same column
t2.Columns.Add("C2", GetType(Integer)) ' same column, different data type
t2.Columns.Add("C4", GetType(String)) ' different column
Dim map As New Dictionary(Of String, String)
Dim t3 As New DataTable("T4")
MergeColumns(t3, t1, map)
MergeColumns(t3, t2, map)
Debug.WriteLine("Should be 5 columns and reality is: " & t3.Columns.Count)
' Add some data
t1.Rows.Add({"data from t1 c1", "data from t1 c2", "data from t1 c3"})
t2.Rows.Add({"data from t2 c1", 55, "data from t2 c3"})
MergeRows(t3, t1, map)
MergeRows(t3, t2, map)
t3.AcceptChanges()
For Each row As DataRow In t3.Rows
Debug.WriteLine(String.Join(";", row.ItemArray.Select(Function(o) o.ToString()).ToArray()))
Next
End Sub
Private Sub MergeColumns(totbl As DataTable, fromtbl As DataTable, map As Dictionary(Of String, String))
For Each c As DataColumn In fromtbl.Columns
If Not totbl.Columns.Contains(c.ColumnName) Then
totbl.Columns.Add(c.ColumnName, c.DataType)
map.Add(c.Table.TableName & "_" & c.ColumnName, c.ColumnName)
ElseIf Not totbl.Columns(c.ColumnName).DataType.Equals(c.DataType) Then
totbl.Columns.Add(c.Table.TableName & "_" & c.ColumnName, c.DataType)
map.Add(c.Table.TableName & "_" & c.ColumnName, c.Table.TableName & "_" & c.ColumnName)
Else
map.Add(c.Table.TableName & "_" & c.ColumnName, c.ColumnName)
End If
Next
End Sub
Private Sub MergeRows(totbl As DataTable, fromtbl As DataTable, map As Dictionary(Of String, String))
For Each row As DataRow In fromtbl.Rows
Dim newRow As DataRow = totbl.NewRow()
For Each c As DataColumn In fromtbl.Columns
newRow(map(fromtbl.TableName & "_" & c.ColumnName)) = row(c.ColumnName)
Next
totbl.Rows.Add (newRow)
Next
End Sub
Result:
data from t1 c1 ; data from t1 c2 ; data from t1 c3 ; ;
data from t2 c1 ; ; ; 55 ; data from t2 c3
But may be, you need something else. However, this is good example how to do thing like this

You could try the DataTable Merge.
dt3 = new DataTable();
dt3 .Merge(dtOne);
dt3 .Merge(dtTwo);
Look at this post for more info/solutions. Merge 2 DataTables and store in a new one

Related

Unable to use macro for pivot table for more than 65500 rows

I am Using Macro for pivot table in Excel...
when i am trying to put pivot table for a data of around 80,000 rows my pivot table is not appearing but if i take only 65000 rows than its working can anyone help me in debugging this error.
These are the VBA Codes that i am using
Option Explicit
Sub Macro1()
'Declare Variables
Dim PSheet As Worksheet
Dim DSheet As Worksheet
Dim PCache As PivotCache
Dim PTable As PivotTable
Dim PRange As Range
Dim LastRow As Long
Dim LastCol As Long
'Delete Preivous Pivot Table Worksheet & Insert a New Blank Worksheet With Same Name
On Error Resume Next
Application.DisplayAlerts = False
Worksheets("PivotTable").Delete
Sheets.Add Before:=ActiveSheet
ActiveSheet.Name = "PivotTable"
Application.DisplayAlerts = True
Set PSheet = Worksheets("PivotTable")
Set DSheet = Worksheets("Data")
'Define Data Range
LastRow = DSheet.Cells(Rows.Count, 1).End(xlUp).Row
LastCol = DSheet.Cells(1, Columns.Count).End(xlToLeft).Column
Set PRange = DSheet.Cells(1, 1).Resize(LastRow, LastCol)
'Define Pivot Cache
Set PCache = ActiveWorkbook.PivotCaches.Create _
(SourceType:=xlDatabase, SourceData:=PRange). _
CreatePivotTable(TableDestination:=PSheet.Cells(2, 2), _
TableName:="EmployeePivotTable")
'Insert Blank Pivot Table
Set PTable = PCache.CreatePivotTable _
(TableDestination:=PSheet.Cells(1, 1), TableName:="EmployeePivotTable")
'Insert Row Fields
With ActiveSheet.PivotTables("EmployeePivotTable").PivotFields("FilePeriod")
.Orientation = xlRowField
.Position = 1
End With
With ActiveSheet.PivotTables("EmployeePivotTable").PivotFields("ProjectNumber")
.Orientation = xlRowField
.Position = 2
End With
'Insert Column Fields
With ActiveSheet.PivotTables("EmployeePivotTable").PivotFields("EffectiveFTE")
.Orientation = xlColumnField
.Position = 1
End With
'Format Pivot Table
ActiveSheet.PivotTables("EmployeePivotTable").ShowTableStyleRowStripes = True
ActiveSheet.PivotTables("EmployeePivotTable").TableStyle2 = "PivotStyleMedium9"
End Sub

Creating SQL query in VB.net from a Checkboxlist

I have a checkboxlist and I populate it dynamically from a database. For example after i populate the checkboxlist is like that:
Los Angeles
New York
London
Berlin
Amsterdam
I want to create a SQL query according to the checkboxes are checked. If i want to choose only one city (e.g. only New York) i want the result to be:
(City = 2)
Thats works properly but when i have multiple cities (e.g. New York, London and Amsterdam) i want the result to be for example:
(City = 2) OR (City = 3) OR (City = 5)
Or if i choose Los Angeles and Berlin I want the result to be like this:
(City = 1) OR (City = 4)
How can i achieve this? That's my code below but I am stacked. Any ideas?
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim var As String = ""
Dim counter As Integer = 0
Dim myList As New List(Of String)()
For i As Integer = 0 To CheckBoxList1.Items.Count - 1
If CheckBoxList1.Items(i).Selected Then
myList.Add(i + 1)
counter = counter + 1
If counter = 1 Then
var = "(City =" & i + 1 & ")"
Else
Console.WriteLine(myList(1))
Dim myArray As String() = myList.ToArray()
For j As Integer = 1 To myArray.Length
Dim var2 As String = " OR (City =" & counter & ")"
var = "(City =" & myArray(0) & ")" & var2
Next
End If
End If
Next
SQL = "SELECT * FROM Data1 WHERE (" & var & ") ORDER BY [ID]"
Session("Search") = SQL
Server.Transfer("Data_Form.aspx")
End Sub
What I recommend most strongly is to look into Table-value Parameters:
http://msdn.microsoft.com/en-us/library/bb675163(v=vs.110).aspx
This will fix your issue and help you avoid sql injection vulnerabilities.
But if you really insist on using string concatenation, try using an IN() condition, where you end up with something more like CITY IN (1,2) instead of (City = 1 OR City = 2). You can make this a bit easier to write by leading with an unused ID, like so:
Dim cityClause As String = " CITY IN (-1{0})" 'start with a valid clause
Dim cityIDs As String = ""
For Each box As ListItem In CheckBoxList1.Items.Where(Function(b) b.Selected)
'Try storing the ID for each city in the value part of each listitem,
' rather than using the index order
cityIDs = cityIDs & "," & box.Value
Next box
cityClause = string.Format(cityClause, cityIDs)
You can use City IN(2,3,5) instead of (City = 2) OR (City = 3) OR (City = 5):
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim condition As String = ""
For i As Integer = 0 To CheckBoxList1.Items.Count - 1
If CheckBoxList1.Items(i).Selected Then
condition = condition & "," & (i + 1)
End If
Next
SQL = "SELECT * FROM Data1 WHERE (" & condition.SubString(1) & ") ORDER BY [ID]"
Session("Search") = SQL
Server.Transfer("Data_Form.aspx")
End Sub

loop multiple table from dataset

i have 2 table in my dataset, what i trying to achieve is convert 2 table item into string
Public Shared Function mtdCDsToStr(ByVal pDataSet As DataSet) As String
Dim sDs As String
Dim sb As New System.Text.StringBuilder
Dim drRow As DataRow
Dim dcColumn As DataColumn
Dim dtTable As DataTable
Dim x As Integer = 0
For Each dtTable In pDataSet.Tables
For Each drRow In pDataSet.Tables(x).Rows
Dim colName(pDataSet.Tables(x).Columns.Count) As String
Dim i As Integer = 0
For Each dcColumn In pDataSet.Tables(0).Columns
colName(i) = dcColumn.ColumnName
sb.Append(colName(i) + "," + drRow(colName(i)).ToString + ",")
i += 1
Next
sb.Append("|")
Next
x += 1
sb.Append("$")
Next
sDs = sb.ToString
Return sDs
End Function
code explanation
the function is to pass in a dataset and convert the dataset into a string
what i trying to achieve is convert multiple datatable into a string but i can only loop one table in my code above, what should i do in order to loop multi table? =(
change as below
For Each dtTable As DataTable In dataSet.Tables
For Each dr As DataRow In dtTable.Rows
For Each column As DataColumn In dtTable.Columns
sb.Append(column.ColumnName + "," & dr(column.ColumnName).ToString() & ",")
Next
sb.Append("|")
Next
sb.Append("$")
Next
But rather than converting DataSet to string you may try to get XML from DataSet. I'm Not sure What is the exact requirement you converting to sting, but XML will be good way to communicate Data.
xmlString =lpDataSet.GetXml()

how to count the record in the database?

i have this database table called people
People
peopleID peopleName relationship customerID
1 A aunty 1
2 B aunty 1
3 C second uncle 1
4 D aunty 2
how am i going to count the number of people where the customerID = 1 and if the relationship is the same, it is counted as 1
so from the database table above, i should get the result of 3 and put the result of 3 in Label1 in gridview?
i can get the count value for the only where the customerID =1 but i can't figure out how am i going to count if the relationship part
Protected Sub GridView2_RowDataBound(sender As Object, e As
System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView2.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
'Do your processing here...
Dim txt As TextBox = DirectCast(e.Row.FindControl("Label1"), TextBox)
Dim adapter As New SqlDataAdapter
Dim ds As New DataSet
'Dim sql As String
Dim connectionString = ConfigurationManager.ConnectionStrings("ProjData").ConnectionString
Dim myConn As New SqlConnection(connectionString)
Dim cmd = "Select * From People Where customerID='" & Session("customerID") & "' "
' Dim myCmd As New SqlCommand(cmd, myConn)
Try
myConn.Open()
Dim myCmd As New SqlCommand(cmd, myConn)
adapter.SelectCommand = myCmd
adapter.Fill(ds, "People")
adapter.Dispose()
myCmd.Dispose()
txt.Text = ds.Tables(0).Rows.Count
Catch ex As Exception
MsgBox("Can not open connection ! ")
End Try
End If
End Sub
You should wrap your SqlConnection in a using statement (not sure how you do that in VB). In your example you don't close the connection, the using statement does this for you automatically (the alternative is to close the connection in a finally block)
When i correctly understand your question, the following SQL Statement should give you the count as you need it.
Select count(peopleID)
From People
Where customerID = 1
Group by relationship, customerID
If this answer didn't solve your problem please add further information to your question.
In your code, you fetch all the rows and then count them. You can also execute a query that will count the number of rows on the server. This will perform much better!
string sql = "SELECT COUNT(*) FROM People Where customerID='" & Session("customerID") & "' "
...
int rowCount = myCmd.ExecuteScalar();
If you want to count the number of rows with the same relationship, you have to use a group by.
You have to change your sql to:
string sql = 'SELECT COUNT(peopleId) FROM People Where customerID='" & Session("customerID") & "' "GROUP BY relationship, customerId"

Merging the table from 3 dataset to 1

I am loading three dataset from the database which has
Dataset 1 > Table 1 > 10 rows
Dataset 2 > Table 1 > 3 rows
Dataset 3 > Table 1 > 5 rows
(All dataset has same column name, same datatype) actually they contains the data based on different select condition)
now I want to merge all three dataset into one like this
Dataset 4 > Table 1 > 18 rows
Please help how can I do it
Try the DataSet.Merge Method (DataSet) method. Something like this (not tested):
C#:
dataset1.Merge(dataset2);
DataSet dataset4 = dataset1.Merge(dataset3);
VB.NET:
dataset1.Merge(dataset2)
Dim dataset4 As New DataSet = dataset1.Merge(dataset3)
You can use Tim's suggestion if you're looking to merge the two datasets and all of the containing tables, or you can do something like this for specific tables.
DataTable table1 = new DataTable();
DataTable table2 = new DataTable();
DataTable table3 = new DataTable();
table1.Merge(table2);
table1.Merge(table3);
One (flexible) way is using Enumerable.Union.
In VB.NET:
Dim tblMerged = tbl1.AsEnumerable _
.Union(tbl2.AsEnumerable) _
.Union(tbl3.AsEnumerable) _
.CopyToDataTable()
Tested with:
Dim tbl1 As New DataTable
Dim tbl2 As New DataTable
Dim tbl3 As New DataTable
Dim col1_1 As New DataColumn("Col1", GetType(String))
Dim col2_1 As New DataColumn("Col1", GetType(String))
Dim col3_1 As New DataColumn("Col1", GetType(String))
tbl1.Columns.Add(col1_1)
tbl2.Columns.Add(col2_1)
tbl3.Columns.Add(col3_1)
For i As Int32 = 1 To 10
Dim row = tbl1.NewRow
row(0) = "Tbl1_Value" & i
tbl1.Rows.Add(row)
Next
For i As Int32 = 1 To 20
Dim row = tbl2.NewRow
row(0) = "Tbl2_Value" & i
tbl2.Rows.Add(row)
Next
For i As Int32 = 1 To 50
Dim row = tbl3.NewRow
row(0) = "Tbl3_Value" & i
tbl3.Rows.Add(row)
Next
Dim tblMerged = tbl1.AsEnumerable.Union(tbl2.AsEnumerable).Union(tbl3.AsEnumerable).CopyToDataTable

Resources